diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/.classpath b/memory/org.eclipse.cdt.debug.ui.memory.search/.classpath new file mode 100644 index 00000000000..751c8f2e504 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/.project b/memory/org.eclipse.cdt.debug.ui.memory.search/.project new file mode 100644 index 00000000000..7d2db578ea9 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/.project @@ -0,0 +1,17 @@ + + + org.eclipse.cdt.debug.ui.memory.search + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.search/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..6cb83b26de9 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Memory Search +Bundle-SymbolicName: org.eclipse.cdt.debug.ui.memory.search;singleton:=true +Bundle-Version: 1.1.0.qualifier +Bundle-Localization: plugin +Require-Bundle: org.eclipse.debug.core, + org.eclipse.debug.ui, + org.eclipse.core.runtime, + org.eclipse.swt, + org.eclipse.jface, + org.eclipse.ui, + org.eclipse.search;bundle-version="3.4.0" +Eclipse-LazyStart: true +Bundle-Activator: org.eclipse.cdt.debug.ui.memory.search.MemorySearchPlugin +Bundle-Vendor: Eclipse.org +Import-Package: org.eclipse.debug.ui.memory diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/about.html b/memory/org.eclipse.cdt.debug.ui.memory.search/about.html new file mode 100644 index 00000000000..cb740ae8bc8 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/about.html @@ -0,0 +1,24 @@ + + + + +About +

About This Content

+ +

June 5, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/build.properties b/memory/org.eclipse.cdt.debug.ui.memory.search/build.properties new file mode 100644 index 00000000000..bbc45d3cdc8 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/build.properties @@ -0,0 +1,9 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + plugin.properties,\ + .,\ + plugin.xml,\ + about.html,\ + icons/ + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/plugin.xml b/memory/org.eclipse.cdt.debug.ui.memory.search/plugin.xml new file mode 100644 index 00000000000..084932a3e20 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/plugin.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/FindAction.java b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/FindAction.java new file mode 100644 index 00000000000..9aad2e62874 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/FindAction.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.search; + +import java.util.Properties; + +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.internal.ui.views.memory.MemoryView; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +public class FindAction implements IViewActionDelegate { + + private MemoryView fView; + + private static Properties fSearchDialogProperties = new Properties(); + + public void init(IViewPart view) { + if (view instanceof MemoryView) + fView = (MemoryView) view; + } + + public void run(IAction action) { + ISelection selection = fView.getSite().getSelectionProvider() + .getSelection(); + + if (selection instanceof IStructuredSelection) { + IStructuredSelection strucSel = (IStructuredSelection) selection; + + // return if current selection is empty + if (strucSel.isEmpty()) + return; + + Object obj = strucSel.getFirstElement(); + + if (obj == null) + return; + + IMemoryBlock memBlock = null; + + if (obj instanceof IMemoryRendering) { + memBlock = ((IMemoryRendering) obj).getMemoryBlock(); + } else if (obj instanceof IMemoryBlock) { + memBlock = (IMemoryBlock) obj; + } + + Shell shell = DebugUIPlugin.getShell(); + FindReplaceDialog dialog = new FindReplaceDialog(shell, (IMemoryBlockExtension) memBlock, + fView, (Properties) fSearchDialogProperties); + if(action.getText().equalsIgnoreCase("Find Next")) + { + if(fSearchDialogProperties.getProperty(FindReplaceDialog.SEARCH_ENABLE_FIND_NEXT, "false").equals("true")) + { + dialog.performFindNext(); + } + return; + } + else + { + dialog.open(); + + Object results[] = dialog.getResult(); + } + } + + } + + public void selectionChanged(IAction action, ISelection selection) { + if(action.getText().equalsIgnoreCase("Find Next")) + { + action.setEnabled(fSearchDialogProperties.getProperty(FindReplaceDialog.SEARCH_ENABLE_FIND_NEXT, "false") + .equals("true")); + } + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/FindReplaceDialog.java b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/FindReplaceDialog.java new file mode 100644 index 00000000000..0f9da6806be --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/FindReplaceDialog.java @@ -0,0 +1,1198 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.search; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.util.Properties; +import java.util.StringTokenizer; +import java.util.Vector; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.internal.ui.views.memory.MemoryView; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; +import org.eclipse.debug.ui.memory.IRepositionableMemoryRendering; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.search.ui.ISearchQuery; +import org.eclipse.search.ui.ISearchResult; +import org.eclipse.search.ui.NewSearchUI; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.SelectionDialog; + +public class FindReplaceDialog extends SelectionDialog +{ + + private IMemoryBlockExtension fMemoryBlock; + + final static int preFetchSize = 10 * 1024; + + private Text fFindText; + private Text fReplaceText; + + private Combo fStartText; + private Combo fEndText; + + private Button fFindButton; + private Button fFindAllButton; + private Button fReplaceButton; + private Button fReplaceFindButton; + private Button fReplaceAllButton; + private Button fCloseButton; + + private MemoryView fMemoryView; + + private Button fFormatAsciiButton; + private Button fFormatHexButton; + private Button fFormatOctalButton; + private Button fFormatBinaryButton; + private Button fFormatDecimalButton; + private Button fFormatByteSequenceButton; + + private Button fCaseInSensitiveCheckbox; + + private Button fWrapCheckbox; + + private Button fForwardButton; + + private Properties fProperties; + + protected final static String SEARCH_FIND = "SEARCH_FIND"; //$NON-NLS-1$ + protected final static String SEARCH_REPLACE = "SEARCH_REPLACE"; //$NON-NLS-1$ + protected final static String SEARCH_START = "SEARCH_START"; //$NON-NLS-1$ + protected final static String SEARCH_END = "SEARCH_END"; //$NON-NLS-1$ + protected final static String SEARCH_LAST_FOUND = "SEARCH_LAST_FOUND"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT = "SEARCH_FORMAT"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_ASCII = "SEARCH_FORMAT_ASCII"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_HEX = "SEARCH_FORMAT_HEX"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_OCTAL = "SEARCH_FORMAT_OCTAL"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_BINARY = "SEARCH_FORMAT_BINARY"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_DECIMAL = "SEARCH_FORMAT_DECIMAL"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_BYTESEQUENCE = "SEARCH_FORMAT_BYTESEQUENCE"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_CASEINSENSTIVE = "SEARCH_FORMAT_CASEINSENSTIVE"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_FORWARD = "SEARCH_FORMAT_FORWARD"; //$NON-NLS-1$ + protected final static String SEARCH_FORMAT_WRAP = "SEARCH_FORMAT_WRAP"; //$NON-NLS-1$ + protected final static String SEARCH_ENABLE_FIND_NEXT = "SEARCH_ENABLE_FIND_NEXT"; //$NON-NLS-1$ + + public FindReplaceDialog(Shell parent, IMemoryBlockExtension memoryBlock, MemoryView memoryView, Properties properties) + { + super(parent); + super.setTitle(Messages.getString("FindReplaceDialog.Title")); //$NON-NLS-1$ + setShellStyle(getShellStyle() | SWT.RESIZE); + + fMemoryBlock = memoryBlock; + fMemoryView = memoryView; + fProperties = properties; + this.setBlockOnOpen(false); + } + + private BigInteger getUserStart() + { + String start = fStartText.getText(); + if(start.toUpperCase().startsWith("0X")) //$NON-NLS-1$ + start = start.substring(2); + return new BigInteger(start, 16); + } + + private BigInteger getUserEnd() + { + String end = fEndText.getText(); + if(end.toUpperCase().startsWith("0X")) //$NON-NLS-1$ + end = end.substring(2); + return new BigInteger(end, 16); + } + + private boolean getIsDirectionForward() + { + return fForwardButton.getSelection(); + } + + private SearchPhrase getSearchPhrase() + { + SearchPhrase phrase = null; + + if(fFormatAsciiButton.getSelection()) + { + phrase = new AsciiSearchPhrase(fFindText.getText(), fCaseInSensitiveCheckbox.getSelection()); + } + else if(fFormatHexButton.getSelection()) + { + phrase = new BigIntegerSearchPhrase(new BigInteger(fFindText.getText().toUpperCase().startsWith("0X") //$NON-NLS-1$ + ? fFindText.getText().substring(2) : fFindText.getText(), 16), 16); + } + else if(fFormatOctalButton.getSelection()) + { + phrase = new BigIntegerSearchPhrase(new BigInteger(fFindText.getText().startsWith("0") //$NON-NLS-1$ + ? fFindText.getText().substring(1) : fFindText.getText(), 8), 8); + } + else if(fFormatBinaryButton.getSelection()) + { + phrase = new BigIntegerSearchPhrase(new BigInteger(fFindText.getText().toUpperCase().startsWith("0B") //$NON-NLS-1$ + ? fFindText.getText().substring(2) : fFindText.getText(), 2), 2); + } + else if(fFormatDecimalButton.getSelection()) + { + phrase = new BigIntegerSearchPhrase(new BigInteger(fFindText.getText(), 10), 10); + } + else if(fFormatByteSequenceButton.getSelection()) + { + phrase = new ByteSequenceSearchPhrase(fFindText.getText()); + } + + return phrase; + } + + protected byte[] parseByteSequence(String s) + { + Vector sequence = new Vector(); + StringTokenizer st = new StringTokenizer(s, " "); //$NON-NLS-1$ + while(st.hasMoreElements()) + { + String element = ((String) st.nextElement()).trim(); + if(element.length() > 0) + { + BigInteger value; + if(element.toUpperCase().startsWith("0X")) //$NON-NLS-1$ + value = new BigInteger(element.substring(2), 16); + else if(element.toUpperCase().startsWith("0B")) //$NON-NLS-1$ + value = new BigInteger(element.substring(2), 2); + else if(element.toUpperCase().startsWith("0")) //$NON-NLS-1$ + value = new BigInteger(element.substring(1), 8); + else + value = new BigInteger(element, 10); + Byte b = new Byte(value.byteValue()); + + if(value.compareTo(BigInteger.valueOf(255)) > 0) + return null; + + sequence.addElement(b); + } + } + Byte seq[] = sequence.toArray(new Byte[sequence.size()]); + byte[] bytes = new byte[seq.length]; + for(int i = 0; i < seq.length; i++) + bytes[i] = seq[i].byteValue(); + return bytes; + } + + private byte[] getReplaceData() + { + if(fFormatAsciiButton.getSelection()) + return fReplaceText.getText().getBytes(); + else if(fFormatHexButton.getSelection()) + return removeZeroPrefixByte(new BigInteger(fReplaceText.getText().toUpperCase().startsWith("0X") ? fReplaceText.getText().substring(2) : fReplaceText.getText(), 16).toByteArray()); //$NON-NLS-1$ + else if(fFormatOctalButton.getSelection()) + return removeZeroPrefixByte(new BigInteger(fReplaceText.getText().startsWith("0") ? fReplaceText.getText().substring(1) : fReplaceText.getText(), 8).toByteArray()); //$NON-NLS-1$ + else if(fFormatBinaryButton.getSelection()) + return removeZeroPrefixByte(new BigInteger(fReplaceText.getText().toUpperCase().startsWith("0B") ? fReplaceText.getText().substring(2) : fReplaceText.getText(), 2).toByteArray()); //$NON-NLS-1$ + else if(fFormatDecimalButton.getSelection()) + return removeZeroPrefixByte(new BigInteger(fReplaceText.getText(), 10).toByteArray()); + else if(fFormatByteSequenceButton.getSelection()) + return parseByteSequence(fReplaceText.getText()); + + return new byte[0]; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) + */ + protected void createButtonsForButtonBar(Composite parent) { + + fFindButton = createButton(parent, 10, Messages.getString("FindReplaceDialog.ButtonFind"), true); //$NON-NLS-1$ + fFindButton.addSelectionListener(new SelectionListener() + { + public void widgetDefaultSelected(SelectionEvent e) { } + + public void widgetSelected(SelectionEvent e) { + performFind(getUserStart(), getUserEnd(), getSearchPhrase(), getIsDirectionForward(), null, false, false); + cancelPressed(); + } + }); + + fFindAllButton = createButton(parent, 10, Messages.getString("FindReplaceDialog.ButtonFindAll"), true); //$NON-NLS-1$ + fFindAllButton.addSelectionListener(new SelectionListener() + { + public void widgetDefaultSelected(SelectionEvent e) { } + + public void widgetSelected(SelectionEvent e) { + performFind(getUserStart(), getUserEnd(), getSearchPhrase(), getIsDirectionForward(), null, true, false); + cancelPressed(); + } + }); + + fReplaceFindButton = createButton(parent, 11, Messages.getString("FindReplaceDialog.ButtonReplaceFind"), false); //$NON-NLS-1$ + fReplaceFindButton.addSelectionListener(new SelectionListener() + { + public void widgetDefaultSelected(SelectionEvent e) { } + + public void widgetSelected(SelectionEvent e) { + performFind(getUserStart(), getUserEnd(), getSearchPhrase(), getIsDirectionForward(), getReplaceData(), false, true); + cancelPressed(); + } + }); + + fReplaceButton = createButton(parent, 12, Messages.getString("FindReplaceDialog.ButtonReplace"), false); //$NON-NLS-1$ + fReplaceButton.addSelectionListener(new SelectionListener() + { + public void widgetDefaultSelected(SelectionEvent e) { } + + public void widgetSelected(SelectionEvent e) { + performFind(getUserStart(), getUserEnd(), getSearchPhrase(), getIsDirectionForward(), getReplaceData(), false, false); + cancelPressed(); + } + }); + + fReplaceAllButton = createButton(parent, 13, Messages.getString("FindReplaceDialog.ButtonReplaceAll"), false); //$NON-NLS-1$ + fReplaceAllButton.addSelectionListener(new SelectionListener() + { + public void widgetDefaultSelected(SelectionEvent e) { } + + public void widgetSelected(SelectionEvent e) { + performFind(getUserStart(), getUserEnd(), getSearchPhrase(), getIsDirectionForward(), getReplaceData(), true, false); + cancelPressed(); + } + }); + + fCloseButton = createButton(parent, IDialogConstants.CANCEL_ID, Messages.getString("FindReplaceDialog.Close"), false); //$NON-NLS-1$ + + ((GridLayout) parent.getLayout()).numColumns = 2; + + validate(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.SelectionDialog#getResult() + */ + public Object[] getResult() { + + Object[] results = super.getResult(); + + if (results != null) + { + return results; + } + return new Object[0]; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#cancelPressed() + */ + protected void cancelPressed() { + + fProperties.setProperty(SEARCH_FIND, fFindText.getText()); + fProperties.setProperty(SEARCH_REPLACE, fReplaceText.getText()); + fProperties.setProperty(SEARCH_START, fStartText.getText()); + fProperties.setProperty(SEARCH_END, fEndText.getText()); + if(fFormatAsciiButton.getSelection()) + fProperties.setProperty(SEARCH_FORMAT, SEARCH_FORMAT_ASCII); + else if(fFormatBinaryButton.getSelection()) + fProperties.setProperty(SEARCH_FORMAT, SEARCH_FORMAT_BINARY); + else if(fFormatByteSequenceButton.getSelection()) + fProperties.setProperty(SEARCH_FORMAT, SEARCH_FORMAT_BYTESEQUENCE); + else if(fFormatDecimalButton.getSelection()) + fProperties.setProperty(SEARCH_FORMAT, SEARCH_FORMAT_DECIMAL); + else if(fFormatHexButton.getSelection()) + fProperties.setProperty(SEARCH_FORMAT, SEARCH_FORMAT_HEX); + else if(fFormatOctalButton.getSelection()) + fProperties.setProperty(SEARCH_FORMAT, SEARCH_FORMAT_OCTAL); + + fProperties.setProperty(SEARCH_FORMAT_FORWARD, "" + fForwardButton.getSelection()); + + fProperties.setProperty(SEARCH_FORMAT_CASEINSENSTIVE, "" + fCaseInSensitiveCheckbox.getSelection()); + + fProperties.setProperty(SEARCH_FORMAT_WRAP, "" + fWrapCheckbox.getSelection()); + + fProperties.setProperty(SEARCH_ENABLE_FIND_NEXT, "false"); + + setResult(null); + + super.cancelPressed(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + protected void okPressed() { + setSelectionResult(new Object[]{ fProperties }); + + super.okPressed(); + } + + public BigInteger getEndAddress() + { + String text = fEndText.getText(); + boolean hex = text.startsWith("0x"); //$NON-NLS-1$ + BigInteger endAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return endAddress; + } + + public BigInteger getStartAddress() + { + String text = fStartText.getText(); + boolean hex = text.startsWith("0x"); //$NON-NLS-1$ + BigInteger startAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return startAddress; + } + + private void validate() + { + boolean valid = false; + boolean replaceValid = false; + + try + { + BigInteger endAddress = getEndAddress(); + BigInteger startAddress = getStartAddress(); + + /* + * The end-address must be larger that the start-address. + */ + if ( startAddress.compareTo(endAddress) == -1 ) { + /* + * Validate the search phrase. + */ + if(getSearchPhrase() != null && getSearchPhrase().getByteLength() > 0) { + valid = true; + } + + /* + * Validate the replacement phrase. + */ + if(getReplaceData() != null && getReplaceData().length > 0) { + replaceValid = true; + } + } + } + catch(Throwable ex) + { + // do nothing + } + + fFindButton.setEnabled(valid); + fFindAllButton.setEnabled(valid); + fReplaceButton.setEnabled(replaceValid); + fReplaceFindButton.setEnabled(replaceValid); + fReplaceAllButton.setEnabled(replaceValid); + } + + private String pad(int characterCount, String value) + { + StringBuffer sb = new StringBuffer(value); + for(int i = 0; i < characterCount - value.length(); i++) + sb.insert(0, "0"); //$NON-NLS-1$ + return sb.toString(); + } + + private String[] removeNullElements(String strings[]) + { + Vector nonNullStrings = new Vector(); + for(String string : strings) + if(string != null) + nonNullStrings.addElement(string); + return (String[]) nonNullStrings.toArray(new String[0]); + } + + private String getMemoryBlockBaseAddress() + { + BigInteger base = null; + try + { + base = fMemoryBlock.getBigBaseAddress(); + } + catch(DebugException de) + { + // do nothing + } + + if(base == null) + base = BigInteger.ZERO; + + return "0x" + pad(getAddressSize() * 2, base.toString(16).toUpperCase()); //$NON-NLS-1$ + } + + private String getViewportStart() + { + ISelection selection = fMemoryView.getViewPane(IDebugUIConstants.ID_RENDERING_VIEW_PANE_1).getSelectionProvider().getSelection(); + if(selection instanceof StructuredSelection) + { + if(((StructuredSelection) selection).getFirstElement() instanceof IRepositionableMemoryRendering) + { + ((IRepositionableMemoryRendering) ((StructuredSelection) selection).getFirstElement()).getSelectedAddress(); + } + } + return null; + } + + private String getStart() + { + BigInteger start = null; + try + { + start = fMemoryBlock.getMemoryBlockStartAddress(); + } + catch(DebugException de) + { + // do nothing + } + + if(start == null) + start = BigInteger.ZERO; + + return "0x" + pad(getAddressSize() * 2, start.toString(16).toUpperCase()); //$NON-NLS-1$ + } + + private String getEnd() + { + BigInteger end = null; + + try + { + end = fMemoryBlock.getMemoryBlockEndAddress(); + } + catch(DebugException de) + { + // do nothing + } + + if(end == null) + { + end = BigInteger.ZERO; + + for(int i = getAddressSize(); i > 0; i--) + { + end = end.shiftLeft(8); + end = end.or(BigInteger.valueOf(255)); + } + } + + return "0x" + pad(getAddressSize() * 2, end.toString(16).toUpperCase()); //$NON-NLS-1$ + } + + private int getAddressSize() + { + int addressSize; + try + { + addressSize = fMemoryBlock.getAddressSize(); + } + catch(DebugException de) + { + addressSize = 4; // default to 32bit? + } + return addressSize; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + protected Control createDialogArea(Composite parent) { + + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, MemorySearchPlugin.getUniqueIdentifier() + ".MemorySearchDialog_context"); //$NON-NLS-1$ + Composite composite = new Composite(parent, SWT.NONE); + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + + // find + + Label findLabel = new Label(composite, SWT.NONE); + Label replaceLabel = new Label(composite, SWT.NONE); + fReplaceText = new Text(composite, SWT.BORDER); + + findLabel.setText(Messages.getString("FindReplaceDialog.LabelFind")); //$NON-NLS-1$ + + fFindText = new Text(composite, SWT.BORDER); + FormData data = new FormData(); + data.left = new FormAttachment(fReplaceText, 0, SWT.LEFT); + data.width = 260; + fFindText.setLayoutData(data); + fFindText.setText(fProperties.getProperty(SEARCH_FIND, "")); + + data = new FormData(); + data.top = new FormAttachment(fFindText, 0, SWT.CENTER); + findLabel.setLayoutData(data); + + // replace + + replaceLabel.setText(Messages.getString("FindReplaceDialog.LabelReplaceWith")); //$NON-NLS-1$ + data = new FormData(); + data.top = new FormAttachment(fFindText); + replaceLabel.setLayoutData(data); + + data = new FormData(); + data.top = new FormAttachment(replaceLabel, 0, SWT.CENTER); + data.left = new FormAttachment(replaceLabel); + data.width = 260; + fReplaceText.setLayoutData(data); + fReplaceText.setText(fProperties.getProperty(SEARCH_REPLACE, "")); + + // group direction + + Group directionGroup = new Group(composite, SWT.NONE); + Group formatGroup = new Group(composite, SWT.NONE); + Group rangeGroup = new Group(composite, SWT.NONE); + directionGroup.setText(Messages.getString("FindReplaceDialog.LabelDirection")); //$NON-NLS-1$ + + GridLayout layout = new GridLayout(); + layout.numColumns = 1; + directionGroup.setLayout(layout); + + fForwardButton = new Button(directionGroup, SWT.RADIO); + fForwardButton.setText(Messages.getString("FindReplaceDialog.ButtonForward")); //$NON-NLS-1$ + final Button backwardButton = new Button(directionGroup, SWT.RADIO); + backwardButton.setText(Messages.getString("FindReplaceDialog.ButtonBackward")); //$NON-NLS-1$ + final boolean isForward = fProperties.getProperty(SEARCH_FORMAT_FORWARD, "true").equalsIgnoreCase("true"); + fForwardButton.setSelection(isForward); + backwardButton.setSelection(!isForward); + + data = new FormData(); + data.top = new FormAttachment(fReplaceText); + data.right = new FormAttachment(formatGroup, 0, SWT.RIGHT); + data.left = new FormAttachment(formatGroup, 0, SWT.LEFT); + data.bottom = new FormAttachment(rangeGroup, 0, SWT.BOTTOM); + directionGroup.setLayoutData(data); + + // group range + + rangeGroup.setText(Messages.getString("FindReplaceDialog.LabelRange")); //$NON-NLS-1$ + + layout = new GridLayout(); + layout.numColumns = 2; + layout.makeColumnsEqualWidth = false; + rangeGroup.setLayout(layout); + + // group range - start address + + Label startLabel = new Label(rangeGroup, SWT.NONE); + startLabel.setText(Messages.getString("FindReplaceDialog.LabelStartAddress")); //$NON-NLS-1$ + + fStartText = new Combo(rangeGroup, SWT.BORDER); + GridData gridData = new GridData(); + gridData.widthHint = 200; + gridData.grabExcessHorizontalSpace = true; + fStartText.setLayoutData(gridData); + + // group range - end address + + Label endLabel = new Label(rangeGroup, SWT.NONE); + endLabel.setText(Messages.getString("FindReplaceDialog.LabelEndAddress")); //$NON-NLS-1$ + fEndText = new Combo(rangeGroup, SWT.BORDER); + gridData = new GridData(); + gridData.widthHint = 200; + gridData.grabExcessHorizontalSpace = true; + fEndText.setLayoutData(gridData); + + data = new FormData(); + data.left = new FormAttachment(directionGroup); + data.top = new FormAttachment(directionGroup, 0, SWT.TOP); + data.right = new FormAttachment(fFindText, 0, SWT.RIGHT); + rangeGroup.setLayoutData(data); + + fStartText.setItems(removeNullElements(new String[] { getViewportStart(), getStart(), getEnd(), getMemoryBlockBaseAddress() })); + fEndText.setItems(removeNullElements(new String[] { getEnd(), getStart(), getMemoryBlockBaseAddress(), getViewportStart() })); + if(fProperties.getProperty(SEARCH_START) != null) + fStartText.add(fProperties.getProperty(SEARCH_START), 0); + if(fProperties.getProperty(SEARCH_END) != null) + fEndText.add(fProperties.getProperty(SEARCH_END), 0); + fStartText.select(0); + fEndText.select(0); + + // format group + + formatGroup.setText(Messages.getString("FindReplaceDialog.LabelFormat")); //$NON-NLS-1$ + layout = new GridLayout(); + layout.numColumns = 1; + formatGroup.setLayout(layout); + + fFormatAsciiButton = new Button(formatGroup, SWT.RADIO); + fFormatAsciiButton.setText(Messages.getString("FindReplaceDialog.ButtonASCII")); //$NON-NLS-1$ + + fFormatHexButton = new Button(formatGroup, SWT.RADIO); + fFormatHexButton.setText(Messages.getString("FindReplaceDialog.ButtonHexadecimal")); //$NON-NLS-1$ + + fFormatOctalButton = new Button(formatGroup, SWT.RADIO); + fFormatOctalButton.setText(Messages.getString("FindReplaceDialog.ButtonOctal")); //$NON-NLS-1$ + + fFormatBinaryButton = new Button(formatGroup, SWT.RADIO); + fFormatBinaryButton.setText(Messages.getString("FindReplaceDialog.ButtonBinary")); //$NON-NLS-1$ + + fFormatDecimalButton = new Button(formatGroup, SWT.RADIO); + fFormatDecimalButton.setText(Messages.getString("FindReplaceDialog.ButtonDecimal")); //$NON-NLS-1$ + + fFormatByteSequenceButton = new Button(formatGroup, SWT.RADIO); + fFormatByteSequenceButton.setText(Messages.getString("FindReplaceDialog.ButtonByteSequence")); //$NON-NLS-1$ + + final String format = fProperties.getProperty(SEARCH_FORMAT, FindReplaceDialog.SEARCH_FORMAT_ASCII); + + fFormatAsciiButton.setSelection(format.equals(SEARCH_FORMAT_ASCII)); + fFormatOctalButton.setSelection(format.equals(SEARCH_FORMAT_OCTAL)); + fFormatBinaryButton.setSelection(format.equals(SEARCH_FORMAT_BINARY)); + fFormatDecimalButton.setSelection(format.equals(SEARCH_FORMAT_DECIMAL)); + fFormatHexButton.setSelection(format.equals(SEARCH_FORMAT_HEX)); + fFormatByteSequenceButton.setSelection(format.equals(SEARCH_FORMAT_BYTESEQUENCE)); + + + data = new FormData(); + data.top = new FormAttachment(rangeGroup); + formatGroup.setLayoutData(data); + + // options group + + Group optionsGroup = new Group(composite, SWT.NONE); + optionsGroup.setText(Messages.getString("FindReplaceDialog.LabelOptions")); //$NON-NLS-1$ + + data = new FormData(); + data.left = new FormAttachment(formatGroup); + data.top = new FormAttachment(rangeGroup); + data.bottom = new FormAttachment(formatGroup, 0, SWT.BOTTOM); + data.right = new FormAttachment(rangeGroup, 0, SWT.RIGHT); + optionsGroup.setLayoutData(data); + + layout = new GridLayout(); + layout.numColumns = 1; + optionsGroup.setLayout(layout); + + + // wrap + + fWrapCheckbox = new Button(optionsGroup, SWT.CHECK); + fWrapCheckbox.setText(Messages.getString("FindReplaceDialog.ButtonWrapSearch")); //$NON-NLS-1$ + fWrapCheckbox.setEnabled(false); // TODO implement wrap + + fCaseInSensitiveCheckbox = new Button(optionsGroup, SWT.CHECK); + fCaseInSensitiveCheckbox.setText(Messages.getString("FindReplaceDialog.ButtonCaseInsensitive")); //$NON-NLS-1$ + + fFormatAsciiButton.addSelectionListener(new SelectionListener() + { + public void widgetDefaultSelected(SelectionEvent e) { } + + public void widgetSelected(SelectionEvent e) { + fCaseInSensitiveCheckbox.setEnabled(true); + } + }); + + SelectionListener nonAsciiListener = new SelectionListener() + { + public void widgetDefaultSelected(SelectionEvent e) { } + + public void widgetSelected(SelectionEvent e) { + fCaseInSensitiveCheckbox.setEnabled(false); + validate(); + } + }; + fFormatHexButton.addSelectionListener(nonAsciiListener); + fFormatOctalButton.addSelectionListener(nonAsciiListener); + fFormatBinaryButton.addSelectionListener(nonAsciiListener); + fFormatDecimalButton.addSelectionListener(nonAsciiListener); + fFormatByteSequenceButton.addSelectionListener(nonAsciiListener); + + fStartText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + boolean valid = true; + try + { + getStartAddress(); + } + catch(Exception ex) + { + valid = false; + } + + fStartText.setForeground(valid ? Display.getDefault().getSystemColor(SWT.COLOR_BLACK) : + Display.getDefault().getSystemColor(SWT.COLOR_RED)); + + validate(); + } + + }); + + fEndText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + try + { + getEndAddress(); + fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + } + catch(Exception ex) + { + fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + } + + validate(); + } + + }); + + fFindText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) + { + validate(); + } + }); + + fReplaceText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) + { + validate(); + } + }); + + composite.setTabList(new Control[] { + fFindText, + fReplaceText, + directionGroup, + rangeGroup, + formatGroup, + optionsGroup, + }); + + fFindText.setFocus(); + + return composite; + } + + + class FindReplaceMemoryCache + { + BigInteger memoryCacheStartAddress = BigInteger.ZERO; + MemoryByte memoryCacheData[] = new MemoryByte[0]; + } + + MemoryByte[] getBytesFromAddress(final BigInteger address, final int length, FindReplaceMemoryCache cache) + throws DebugException + { + if(! (address.compareTo(cache.memoryCacheStartAddress) >= 0 + && address.add(BigInteger.valueOf(length)).compareTo(cache.memoryCacheStartAddress + .add(BigInteger.valueOf(cache.memoryCacheData.length))) < 0)) + { + BigInteger fetchAddress = address.subtract(BigInteger.valueOf(preFetchSize)); + if(fetchAddress.compareTo(BigInteger.ZERO) < 0) // TODO replace ZERO with address space start + fetchAddress = BigInteger.ZERO; + + MemoryByte bytes[] = fMemoryBlock.getBytesFromAddress(fetchAddress, preFetchSize * 2); + + cache.memoryCacheStartAddress = fetchAddress; + cache.memoryCacheData = bytes; + } + + MemoryByte bytes[] = new MemoryByte[length]; + System.arraycopy(cache.memoryCacheData, address.subtract(cache.memoryCacheStartAddress).intValue(), + bytes, 0, length); + return bytes; + } + + private BigInteger parseHexBigInteger(String s) + { + if(s.toUpperCase().startsWith("0X")) + return new BigInteger(s.substring(2), 16); + else + return new BigInteger(s, 16); + } + + protected void performFindNext() + { + try + { + BigInteger start = parseHexBigInteger(fProperties.getProperty(SEARCH_LAST_FOUND)); + BigInteger end = parseHexBigInteger(fProperties.getProperty(SEARCH_END)); + boolean searchForward = fProperties.getProperty(SEARCH_FORMAT_FORWARD, "false").equals("true"); + boolean caseInSensitive = fProperties.getProperty(SEARCH_FORMAT_CASEINSENSTIVE, "false").equals("true"); + if(searchForward) + start = start.add(BigInteger.ONE); + else + start = start.subtract(BigInteger.ONE); + SearchPhrase phrase = null; + String findText = fProperties.getProperty(SEARCH_FIND); + + if(fProperties.getProperty(SEARCH_FORMAT).equals(SEARCH_FORMAT_ASCII)) + phrase = new AsciiSearchPhrase(findText, caseInSensitive); + else if(fProperties.getProperty(SEARCH_FORMAT).equals(SEARCH_FORMAT_HEX)) + phrase = new BigIntegerSearchPhrase(new BigInteger(findText.toUpperCase().startsWith("0X") //$NON-NLS-1$ + ? findText.substring(2) : findText, 16), 16); + else if(fProperties.getProperty(SEARCH_FORMAT).equals(SEARCH_FORMAT_OCTAL)) + phrase = new BigIntegerSearchPhrase(new BigInteger(findText.startsWith("0") //$NON-NLS-1$ + ? findText.substring(1) : findText, 8), 8); + else if(fProperties.getProperty(SEARCH_FORMAT).equals(SEARCH_FORMAT_BINARY)) + phrase = new BigIntegerSearchPhrase(new BigInteger(findText.toUpperCase().startsWith("0B") //$NON-NLS-1$ + ? findText.substring(2) : findText, 2), 2); + else if(fProperties.getProperty(SEARCH_FORMAT).equals(SEARCH_FORMAT_DECIMAL)) + phrase = new BigIntegerSearchPhrase(new BigInteger(findText, 10), 10); + else if(fProperties.getProperty(SEARCH_FORMAT).equals(SEARCH_FORMAT_BYTESEQUENCE)) + phrase = new ByteSequenceSearchPhrase(findText); + + performFind(start, end, phrase, searchForward, null, false, false); + + } + catch(Exception e) + { + MemorySearchPlugin.logError(Messages.getString("FindReplaceDialog.MemorySearchFailure"), e); + } + } + + private void performFind(final BigInteger start, final BigInteger end, final SearchPhrase searchPhrase, + final boolean searchForward, final byte[] replaceData, final boolean all, final boolean replaceThenFind) + { + final ISearchQuery query = new IMemorySearchQuery() + { + private ISearchResult fSearchResult = null; + + public boolean canRerun() { + return false; + } + + public boolean canRunInBackground() { + return true; + } + + public String getLabel() { + return Messages.getString("FindReplaceDialog.SearchingMemoryFor") + searchPhrase; //$NON-NLS-1$ + } + + public ISearchResult getSearchResult() { + if(fSearchResult == null) + fSearchResult = new MemorySearchResult(this, Messages.getString("FindReplaceDialog.SearchingMemoryFor") + searchPhrase); //$NON-NLS-1$ + return fSearchResult; + } + + public IStatus run(IProgressMonitor monitor) + throws OperationCanceledException { + + final BigInteger searchPhraseLength = BigInteger.valueOf(searchPhrase.getByteLength()); + BigInteger range = start.subtract(end); + //BigInteger range = searchForward ? end.subtract(start) : start.subtract(end); + //BigInteger currentPosition = start; + BigInteger currentPosition = searchForward ? start : end.subtract(searchPhraseLength); + + if ( range.compareTo(searchPhraseLength) >= 0 ) { + return Status.OK_STATUS; + } + + boolean isReplace = replaceData != null; + + BigInteger jobs = range; + BigInteger factor = BigInteger.ONE; + if(jobs.compareTo(BigInteger.valueOf(0x07FFFFFF)) > 0) + { + factor = jobs.divide(BigInteger.valueOf(0x07FFFFFF)); + jobs = jobs.divide(factor); + } + + BigInteger jobCount = BigInteger.ZERO; + + BigInteger replaceCount = BigInteger.ZERO; + + FindReplaceMemoryCache cache = new FindReplaceMemoryCache(); + + monitor.beginTask(Messages.getString("FindReplaceDialog.SearchingMemoryFor") + searchPhrase, jobs.intValue()); //$NON-NLS-1$ + + boolean matched = false; + while(((searchForward && currentPosition.compareTo(end.subtract(searchPhraseLength)) < 0) + || (!searchForward && currentPosition.compareTo(start) > 0)) && !monitor.isCanceled()) + { + try + { + MemoryByte bytes[] = getBytesFromAddress(currentPosition, searchPhraseLength.intValue(), cache); + matched = searchPhrase.isMatch(bytes); + if(matched) + { + if(all && !isReplace) + ((MemorySearchResult) getSearchResult()).addMatch(new MemoryMatch(currentPosition, searchPhraseLength)); + + if(isReplace) + { + try + { + fMemoryBlock.setValue(currentPosition.subtract(fMemoryBlock.getBigBaseAddress()), replaceData); + } + catch(DebugException de) + { + MemorySearchPlugin.logError(Messages.getString("FindReplaceDialog.MemoryReadFailed"), de); //$NON-NLS-1$ + } + + replaceCount = replaceCount.add(BigInteger.ONE); + } + + if(isReplace && replaceThenFind && replaceCount.compareTo(BigInteger.ONE) == 0) + { + isReplace = false; + matched = false; + } + + if(matched && !all) + { + final BigInteger finalCurrentPosition = currentPosition; + Display.getDefault().asyncExec(new Runnable(){ + + public void run() { + IMemoryRenderingContainer containers[] = getMemoryView().getMemoryRenderingContainers(); + for(int i = 0; i < containers.length; i++) + { + IMemoryRendering rendering = containers[i].getActiveRendering(); + if(rendering instanceof IRepositionableMemoryRendering) + { + try { + ((IRepositionableMemoryRendering) rendering).goToAddress(finalCurrentPosition); + } catch (DebugException e) { + MemorySearchPlugin.logError(Messages.getString("FindReplaceDialog.RepositioningMemoryViewFailed"), e); //$NON-NLS-1$ + } + } + if(rendering != null) + { + // Temporary, until platform accepts/adds new interface for setting the selection + try { + Method m = rendering.getClass().getMethod("setSelection", new Class[] { BigInteger.class, BigInteger.class } ); + if(m != null) + m.invoke(rendering, finalCurrentPosition, finalCurrentPosition.add(searchPhraseLength)); + } catch (Exception e) { + // do nothing + } + } + } + } + + }); + + fProperties.setProperty(SEARCH_ENABLE_FIND_NEXT, "true"); + fProperties.setProperty(SEARCH_LAST_FOUND, "0x" + finalCurrentPosition.toString(16)); + return Status.OK_STATUS; + } + } + + matched = false; + + if(searchForward) + currentPosition = currentPosition.add(BigInteger.ONE); + else + currentPosition = currentPosition.subtract(BigInteger.ONE); + + } + catch(DebugException e) + { + MemorySearchPlugin.logError(Messages.getString("FindReplaceDialog.MemorySearchFailure"), e); //$NON-NLS-1$ + return Status.CANCEL_STATUS; + } + + jobCount = jobCount.add(BigInteger.ONE); + if(jobCount.compareTo(factor) == 0) + { + jobCount = BigInteger.ZERO; + monitor.worked(1); + } + } + + if(monitor.isCanceled()) + return Status.CANCEL_STATUS; + + return Status.OK_STATUS; + } + + public MemoryView getMemoryView() { + return fMemoryView; + } + }; + + if(all && replaceData == null) + { + Display.getDefault().asyncExec(new Runnable() { + public void run() + { + NewSearchUI.activateSearchResultView(); + NewSearchUI.runQueryInBackground(query); + } + }); + } + else + { + Job job = new Job("Searching memory for " + searchPhrase){ //$NON-NLS-1$ + public IStatus run(IProgressMonitor monitor) { + return query.run(monitor); + } + }; + job.schedule(); + } + + } + + interface SearchPhrase + { + boolean isMatch(MemoryByte[] bytes); + int getByteLength(); + String toString(); + } + + class AsciiSearchPhrase implements SearchPhrase + { + private String fPhrase; + private boolean fIsCaseInsensitive; + + public AsciiSearchPhrase(String phrase, boolean isCaseInsensitive) + { + fPhrase = phrase; + fIsCaseInsensitive = isCaseInsensitive; + } + + public int getByteLength() + { + return fPhrase.length(); + } + + public String toString() + { + return fPhrase; + } + + public boolean isMatch(MemoryByte[] bytes) + { + byte[] targetBytes = new byte[bytes.length]; + for(int i = 0; i < bytes.length; i++) + targetBytes[i] = bytes[i].getValue(); + + String searchString = fPhrase; + String targetString = new String(targetBytes); + + if(fIsCaseInsensitive) + { + searchString = searchString.toUpperCase(); + targetString = targetString.toUpperCase(); + } + + return searchString.equals(targetString); + } + } + + class ByteSequenceSearchPhrase implements SearchPhrase + { + private byte[] fBytes = null; + + public ByteSequenceSearchPhrase(String phrase) + { + fBytes = parseByteSequence(phrase); + } + + public int getByteLength() + { + if ( fBytes != null ) { + return fBytes.length; + } + else { + return 0; + } + } + + public String toString() + { + if(fBytes == null) + return ""; //$NON-NLS-1$ + StringBuffer buf = new StringBuffer(); + for(int i = 0; i < fBytes.length; i++) + buf.append(BigInteger.valueOf(fBytes[i]).toString(16) + " "); //$NON-NLS-1$ + return buf.toString(); + } + + public boolean isMatch(MemoryByte[] bytes) + { + if ( fBytes == null ) + return false; + for(int i = 0; i < bytes.length; i++) + if(bytes[i].getValue() != fBytes[i]) + return false; + return true; + } + } + + class BigIntegerSearchPhrase implements SearchPhrase + { + private BigInteger fPhrase; + private int fRadix; + + public BigIntegerSearchPhrase(BigInteger phrase, int radix) + { + fPhrase = phrase; + fRadix = radix; + } + + public int getByteLength() + { + return removeZeroPrefixByte(fPhrase.toByteArray()).length; + } + + public String toString() + { + return fPhrase.toString(fRadix); + } + + public boolean isMatch(MemoryByte[] bytes) + { + byte[] targetBytes = new byte[bytes.length + 1]; + targetBytes[0] = 0; + for(int i = 0; i < bytes.length; i++) + targetBytes[i + 1] = bytes[i].getValue(); + + // TODO endian? + BigInteger targetBigInteger = new BigInteger(targetBytes); + + return fPhrase.equals(targetBigInteger); + } + } + + private byte[] removeZeroPrefixByte(byte[] bytes) + { + if(bytes[0] != 0 || bytes.length == 1) + return bytes; + + byte[] processedBytes = new byte[bytes.length - 1]; + System.arraycopy(bytes, 1, processedBytes, 0, processedBytes.length); + return processedBytes; + } + + interface IMemorySearchQuery extends ISearchQuery + { + public MemoryView getMemoryView(); + }; + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemoryMatch.java b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemoryMatch.java new file mode 100644 index 00000000000..31ef6887ae9 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemoryMatch.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2008-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.search; + +import java.math.BigInteger; + +public class MemoryMatch +{ + BigInteger fStartAddress; + + public BigInteger getStartAddress() { + return fStartAddress; + } + + public void setStartAddress(BigInteger startAddress) { + fStartAddress = startAddress; + } + + public BigInteger getLength() { + return fLength; + } + + public void setLength(BigInteger length) { + fLength = length; + } + + BigInteger fLength; + + public MemoryMatch(BigInteger startAddress, BigInteger length) + { + fStartAddress = startAddress; + fLength = length; + } + + public BigInteger getEndAddress() + { + return getStartAddress().add(getLength()); + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchPlugin.java b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchPlugin.java new file mode 100644 index 00000000000..be7a3f44aea --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchPlugin.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.search; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +public class MemorySearchPlugin extends AbstractUIPlugin +{ + private static final String PLUGIN_ID = "org.eclipse.cdt.debug.ui.memory.search"; //$NON-NLS-1$ + + private static MemorySearchPlugin plugin; + + public MemorySearchPlugin() + { + super(); + plugin = this; + } + + /** + * Returns the shared instance. + */ + public static MemorySearchPlugin getDefault() { + return plugin; + } + + /** + * Returns the unique identifier for this plugin. + */ + public static String getUniqueIdentifier() { + return PLUGIN_ID; + } + + protected static void logError(String message, Exception e) + { + Status status = new Status(IStatus.ERROR, PLUGIN_ID, + DebugException.INTERNAL_ERROR, message, e); + + getDefault().getLog().log(status); + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchResult.java b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchResult.java new file mode 100644 index 00000000000..2f1f52e5abd --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchResult.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.search; + +import java.util.Enumeration; +import java.util.Vector; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.search.ui.ISearchQuery; +import org.eclipse.search.ui.ISearchResult; +import org.eclipse.search.ui.ISearchResultListener; +import org.eclipse.search.ui.SearchResultEvent; + +public class MemorySearchResult implements ISearchResult +{ + private ISearchQuery fQuery; + private String fLabel; + + private Vector listeners = new Vector(); + + private Vector fMatches = new Vector(); + + public MemorySearchResult(ISearchQuery query, String label) + { + fQuery = query; + fLabel = label; + } + + public ImageDescriptor getImageDescriptor() { + + return null; + } + + public String getLabel() { + return fLabel; + } + + public ISearchQuery getQuery() { + return fQuery; + } + + public String getTooltip() { + + return fLabel; + } + + public MemoryMatch[] getMatches() + { + MemoryMatch matches[] = new MemoryMatch[fMatches.size()]; + for(int i = 0; i < matches.length; i++) + matches[i] = (MemoryMatch) fMatches.elementAt(i); + return matches; + } + + public void addMatch(MemoryMatch address) + { + fMatches.addElement(address); + fireChange(); + } + + private void fireChange() + { + Enumeration en = listeners.elements(); + while(en.hasMoreElements()) + ((ISearchResultListener) en.nextElement()).searchResultChanged(new SearchResultEvent(this) {} ); + } + + public void addListener(ISearchResultListener l) { + listeners.addElement(l); + + } + + public void removeListener(ISearchResultListener l) { + listeners.removeElement(l); + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchResultsPage.java b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchResultsPage.java new file mode 100644 index 00000000000..14706c447b2 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/MemorySearchResultsPage.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.search; + +import java.lang.reflect.Method; +import java.math.BigInteger; + +import org.eclipse.cdt.debug.ui.memory.search.FindReplaceDialog.IMemorySearchQuery; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; +import org.eclipse.debug.ui.memory.IRepositionableMemoryRendering; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.search.ui.IQueryListener; +import org.eclipse.search.ui.ISearchQuery; +import org.eclipse.search.ui.ISearchResult; +import org.eclipse.search.ui.ISearchResultListener; +import org.eclipse.search.ui.ISearchResultPage; +import org.eclipse.search.ui.ISearchResultViewPart; +import org.eclipse.search.ui.NewSearchUI; +import org.eclipse.search.ui.SearchResultEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.part.Page; +import org.eclipse.ui.part.PageBook; + +public class MemorySearchResultsPage extends Page implements ISearchResultPage, IQueryListener { + + private TreeViewer fTreeViewer; + private PageBook fPagebook; + private Composite fViewerContainer; + private IQueryListener fQueryListener; + + private ISearchResultViewPart fPart; + + public void queryAdded(ISearchQuery query) { + + } + + public void queryFinished(ISearchQuery query) { + + } + + public void queryRemoved(ISearchQuery query) { + + } + + public void queryStarting(ISearchQuery query) { + + } + + public String getID() { + + return MemorySearchPlugin.getUniqueIdentifier(); + } + + public String getLabel() { + if(fQuery == null) + return Messages.getString("MemorySearchResultsPage.LabelMemorySearch"); //$NON-NLS-1$ + else + return fQuery.getLabel(); + } + + public Object getUIState() { + + return fTreeViewer.getSelection(); + } + + public void restoreState(IMemento memento) { + + + } + + public void saveState(IMemento memento) { + + + } + + public void setID(String id) { + + + } + + public void setInput(ISearchResult search, Object uiState) { + if(search instanceof MemorySearchResult) + ((MemorySearchResult) search).addListener(new ISearchResultListener() + { + + public void searchResultChanged(SearchResultEvent e) { + Display.getDefault().asyncExec(new Runnable() { + public void run() + { + fTreeViewer.refresh(); + } + }); + + } + + }); + + } + + public void setViewPart(ISearchResultViewPart part) { + fPart = part; + } + + public void createControl(Composite parent) { + fViewerContainer = new Composite(parent, SWT.NULL); + fViewerContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); + fViewerContainer.setSize(100, 100); + fViewerContainer.setLayout(new FillLayout()); + + fTreeViewer = new TreeViewer(fViewerContainer, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + + fTreeViewer.setContentProvider(new ITreeContentProvider() { + + public void dispose() { + + + } + + public void inputChanged(Viewer viewer, Object oldInput, + Object newInput) { + viewer.refresh(); + } + + public Object[] getChildren(Object parentElement) { + return new Object[0]; + } + + public Object getParent(Object element) { + return null; + } + + public boolean hasChildren(Object element) { + return false; + } + + public Object[] getElements(Object inputElement) { + + if(fQuery == null) + return new Object[0]; + else + { + return ((MemorySearchResult) fQuery.getSearchResult()).getMatches(); + } + } + + }); + + fTreeViewer.setInput(new Object()); + fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener(){ + + public void selectionChanged(final SelectionChangedEvent event) { + if( event.getSelection() instanceof StructuredSelection) + { + IMemoryRenderingContainer containers[] = ((IMemorySearchQuery) fQuery).getMemoryView().getMemoryRenderingContainers(); + MemoryMatch match = (MemoryMatch) ((StructuredSelection) event.getSelection()).getFirstElement(); + for(int i = 0; i < containers.length; i++) + { + IMemoryRendering rendering = containers[i].getActiveRendering(); + if(rendering instanceof IRepositionableMemoryRendering) + { + try { + ((IRepositionableMemoryRendering) rendering).goToAddress(match.getStartAddress()); + } catch (DebugException e) { + MemorySearchPlugin.logError(Messages.getString("MemorySearchResultsPage.RepositioningMemoryViewFailed"), e); //$NON-NLS-1$ + } + } + + if(rendering != null) + { + // Temporary, until platform accepts/adds new interface for setting the selection + try { + Method m = rendering.getClass().getMethod("setSelection", new Class[] { BigInteger.class, BigInteger.class } ); //$NON-NLS-1$ + if(m != null) + m.invoke(rendering, match.getStartAddress(), match.getEndAddress()); + } catch (Exception e) { + // do nothing + } + } + } + } + } + + }); + fTreeViewer.setLabelProvider(new ILabelProvider() { + + public Image getImage(Object element) { + + return null; + } + + public String getText(Object element) { + if(element instanceof MemoryMatch) + return "0x" + ((MemoryMatch) element).getStartAddress().toString(16); //$NON-NLS-1$ + + return element.toString(); + } + + public void addListener(ILabelProviderListener listener) { + + + } + + public void dispose() { + + + } + + public boolean isLabelProperty(Object element, String property) { + + return false; + } + + public void removeListener(ILabelProviderListener listener) { + + + } + + }); + + fQueryListener = createQueryListener(); + + NewSearchUI.addQueryListener(fQueryListener); + } + + private ISearchQuery fQuery; + + private IQueryListener createQueryListener() { + return new IQueryListener() { + public void queryAdded(ISearchQuery query) { + // ignore + } + + public void queryRemoved(ISearchQuery query) { + queryStarting(query); + } + + public void queryStarting(final ISearchQuery query) { + fQuery = query; + + Display.getDefault().asyncExec(new Runnable() { + public void run() + { + fPart.updateLabel(); + + if(!fTreeViewer.getControl().isDisposed()) + fTreeViewer.refresh(); + } + }); + } + + public void queryFinished(final ISearchQuery query) { + + } + }; + } + + public void dispose() { + fTreeViewer.getControl().dispose(); + fViewerContainer.dispose(); + } + + public Control getControl() { + return fViewerContainer; + } + + public void setActionBars(IActionBars actionBars) { + + + } + + public void setFocus() { + + + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/Messages.java b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/Messages.java new file mode 100644 index 00000000000..915c0905605 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/Messages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.search; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class Messages { + private static final String BUNDLE_NAME = "org.eclipse.cdt.debug.ui.memory.search.messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private Messages() { + } + + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/messages.properties b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/messages.properties new file mode 100644 index 00000000000..e6a16833af8 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/src/org/eclipse/cdt/debug/ui/memory/search/messages.properties @@ -0,0 +1,31 @@ +FindReplaceDialog.Title=Find / Replace Memory +FindReplaceDialog.ButtonFind=Find +FindReplaceDialog.ButtonFindAll=Find All +FindReplaceDialog.ButtonReplaceFind=Replace/Find +FindReplaceDialog.ButtonReplace=Replace +FindReplaceDialog.ButtonReplaceAll=Replace All +FindReplaceDialog.Close=Close +FindReplaceDialog.LabelFind=Find: +FindReplaceDialog.LabelReplaceWith=Replace With: +FindReplaceDialog.LabelDirection=Direction +FindReplaceDialog.ButtonForward=Forward +FindReplaceDialog.ButtonBackward=Backward +FindReplaceDialog.LabelRange=Range +FindReplaceDialog.LabelStartAddress=Start address: +FindReplaceDialog.LabelEndAddress=End address: +FindReplaceDialog.LabelFormat=Format +FindReplaceDialog.ButtonASCII=ASCII String +FindReplaceDialog.ButtonHexadecimal=Hexadecimal +FindReplaceDialog.ButtonOctal=Octal +FindReplaceDialog.ButtonBinary=Binary +FindReplaceDialog.ButtonDecimal=Decimal +FindReplaceDialog.ButtonByteSequence=Byte Sequence +FindReplaceDialog.LabelOptions=Options +FindReplaceDialog.ButtonWrapSearch=Wrap Search +FindReplaceDialog.ButtonCaseInsensitive=Case Insensitive +FindReplaceDialog.MemoryReadFailed=Memory Read Failed +FindReplaceDialog.MemorySearchFailure=Memory Search Failure +FindReplaceDialog.RepositioningMemoryViewFailed=Repositioning Memory View Failed +FindReplaceDialog.SearchingMemoryFor=Searching memory for +MemorySearchResultsPage.LabelMemorySearch=Memory Search +MemorySearchResultsPage.RepositioningMemoryViewFailed=Repositioning Memory View Failed diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/.classpath b/memory/org.eclipse.cdt.debug.ui.memory.traditional/.classpath new file mode 100644 index 00000000000..751c8f2e504 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/.project b/memory/org.eclipse.cdt.debug.ui.memory.traditional/.project new file mode 100644 index 00000000000..5777fb24f47 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/.project @@ -0,0 +1,28 @@ + + + org.eclipse.cdt.debug.ui.memory.traditional + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..efca372f9e2 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF @@ -0,0 +1,16 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Traditional Memory Rendering +Bundle-SymbolicName: org.eclipse.cdt.debug.ui.memory.traditional;singleton:=true +Bundle-Version: 1.1.0.qualifier +Bundle-Localization: plugin +Require-Bundle: org.eclipse.debug.core, + org.eclipse.debug.ui, + org.eclipse.core.runtime, + org.eclipse.swt, + org.eclipse.jface, + org.eclipse.ui, + org.eclipse.search;bundle-version="3.4.0" +Eclipse-LazyStart: true +Bundle-Activator: org.eclipse.cdt.debug.ui.memory.traditional.TraditionalRenderingPlugin +Bundle-Vendor: Eclipse.org diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/about.html b/memory/org.eclipse.cdt.debug.ui.memory.traditional/about.html new file mode 100644 index 00000000000..cb740ae8bc8 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/about.html @@ -0,0 +1,24 @@ + + + + +About +

About This Content

+ +

June 5, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/build.properties b/memory/org.eclipse.cdt.debug.ui.memory.traditional/build.properties new file mode 100644 index 00000000000..bbc45d3cdc8 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/build.properties @@ -0,0 +1,9 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + plugin.properties,\ + .,\ + plugin.xml,\ + about.html,\ + icons/ + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/plugin.properties b/memory/org.eclipse.cdt.debug.ui.memory.traditional/plugin.properties new file mode 100644 index 00000000000..3f960bac63c --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/plugin.properties @@ -0,0 +1 @@ +TraditionalRenderingPreferenceActionName=Traditional Rendering Preferences... \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/plugin.xml b/memory/org.eclipse.cdt.debug.ui.memory.traditional/plugin.xml new file mode 100644 index 00000000000..9db0d7c8060 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/plugin.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AbstractPane.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AbstractPane.java new file mode 100644 index 00000000000..59ee0cda2a4 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AbstractPane.java @@ -0,0 +1,759 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.math.BigInteger; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Caret; + +public abstract class AbstractPane extends Canvas +{ + protected Rendering fRendering; + + // selection state + protected boolean fSelectionStarted = false; + protected boolean fSelectionInProgress = false; + + protected BigInteger fSelectionStartAddress = null; + + protected int fSelectionStartAddressSubPosition; + + // caret + protected Caret fCaret = null; + + // character may not fall on byte boundary + protected int fSubCellCaretPosition = 0; + protected int fOldSubCellCaretPosition = 0; + + protected boolean fCaretEnabled = false; + + protected BigInteger fCaretAddress = null; + + // storage + protected int fRowCount = 0; + + protected boolean fPaneVisible = true; + + class AbstractPaneMouseListener implements MouseListener + { + public void mouseUp(MouseEvent me) + { + positionCaret(me.x, me.y); + + fCaret.setVisible(true); + + if(fSelectionInProgress && me.button == 1) + { + endSelection(me.x, me.y); + } + + fSelectionInProgress = fSelectionStarted = false; + } + + public void mouseDown(MouseEvent me) + { + AbstractPane.this.forceFocus(); + + positionCaret(me.x, me.y); + + fCaret.setVisible(false); + + if(me.button == 1) + { + // if shift is down and we have an existing start address, + // append selection + if((me.stateMask & SWT.SHIFT) != 0 + && fRendering.getSelection().getStart() != null) + { + + // if the pane doesn't have a selection start (the + // selection was created in a different pane) + // then initialize the pane's selection start to the + // rendering's selection start + if(AbstractPane.this.fSelectionStartAddress == null) + AbstractPane.this.fSelectionStartAddress = fRendering + .getSelection().getStart(); + + AbstractPane.this.fSelectionStarted = true; + + AbstractPane.this.appendSelection(me.x, me.y); + + } + else + { + // start a new selection + + AbstractPane.this.startSelection(me.x, me.y); + } + } + } + + public void mouseDoubleClick(MouseEvent me) + { + handleMouseDoubleClick(me); + } + + } + + class AbstractPaneMouseMoveListener implements MouseMoveListener + { + public void mouseMove(MouseEvent me) + { + if(fSelectionStarted) + { + fSelectionInProgress = true; + appendSelection(me.x, me.y); + } + } + } + + class AbstractPaneKeyListener implements KeyListener + { + public void keyPressed(KeyEvent ke) + { + fOldSubCellCaretPosition = fSubCellCaretPosition; + if((ke.stateMask & SWT.SHIFT) != 0) + { + switch(ke.keyCode) + { + case SWT.ARROW_RIGHT: + case SWT.ARROW_LEFT: + case SWT.ARROW_UP: + case SWT.ARROW_DOWN: + case SWT.PAGE_DOWN: + case SWT.PAGE_UP: + if(fRendering.getSelection().getStart() == null) + { + fRendering.getSelection().setStart(fCaretAddress.add(BigInteger.valueOf( + fRendering.getAddressesPerColumn())), fCaretAddress); + } + break; + } + } + + if(ke.keyCode == SWT.ARROW_RIGHT) + { + handleRightArrowKey(); + } + else if(ke.keyCode == SWT.ARROW_LEFT || ke.keyCode == SWT.BS) + { + handleLeftArrowKey(); + } + else if(ke.keyCode == SWT.ARROW_DOWN) + { + handleDownArrowKey(); + } + else if(ke.keyCode == SWT.ARROW_UP) + { + handleUpArrowKey(); + } + else if(ke.keyCode == SWT.PAGE_DOWN) + { + handlePageDownKey(); + } + else if(ke.keyCode == SWT.PAGE_UP) + { + handlePageUpKey(); + } + else if(ke.keyCode == SWT.ESC) + { + fRendering.getViewportCache().clearEditBuffer(); + } + else if(ke.character == '\r') + { + fRendering.getViewportCache().writeEditBuffer(); + } + else if(Rendering.isValidEditCharacter(ke.character)) + { + if(fRendering.getSelection().hasSelection()) + { + setCaretAddress(fRendering.getSelection().getLow()); + fSubCellCaretPosition = 0; + } + + editCell(fCaretAddress, fSubCellCaretPosition, ke.character); + } + + if((ke.stateMask & SWT.SHIFT) != 0) + { + switch(ke.keyCode) + { + case SWT.ARROW_RIGHT: + case SWT.ARROW_LEFT: + case SWT.ARROW_UP: + case SWT.ARROW_DOWN: + case SWT.PAGE_DOWN: + case SWT.PAGE_UP: + fRendering.getSelection().setEnd(fCaretAddress.add(BigInteger.valueOf( + fRendering.getAddressesPerColumn())), + fCaretAddress); + break; + } + } + else if(ke.keyCode != SWT.SHIFT) + // if shift key, keep selection, we might add to it + { + fRendering.getSelection().clear(); + } + } + + public void keyReleased(KeyEvent ke) + { + // do nothing + } + } + + class AbstractPanePaintListener implements PaintListener + { + public void paintControl(PaintEvent pe) + { + AbstractPane.this.paint(pe); + } + } + + public AbstractPane(Rendering rendering) + { + super(rendering, SWT.DOUBLE_BUFFERED); + + fRendering = rendering; + + try + { + fCaretAddress = rendering.getBigBaseAddress(); + } + catch(Exception e) + { + // do nothing + } + + // pref + + this.setFont(fRendering.getFont()); + + GC gc = new GC(this); + gc.setFont(this.getFont()); + fCaret = new Caret(this, SWT.NONE); + fCaret.setSize(1, gc.stringExtent("|").y); //$NON-NLS-1$ + gc.dispose(); + + this.addPaintListener(createPaintListener()); + + this.addMouseListener(createMouseListener()); + + this.addMouseMoveListener(createMouseMoveListener()); + + this.addKeyListener(createKeyListener()); + + this.addFocusListener(new FocusListener() + { + public void focusLost(FocusEvent fe) + { + IPreferenceStore store = TraditionalRenderingPlugin.getDefault().getPreferenceStore(); + if(TraditionalRenderingPreferenceConstants.MEM_EDIT_BUFFER_SAVE_ON_ENTER_ONLY + .equals(store.getString(TraditionalRenderingPreferenceConstants.MEM_EDIT_BUFFER_SAVE))) + { + fRendering.getViewportCache().clearEditBuffer(); + } + else + { + fRendering.getViewportCache().writeEditBuffer(); + } + + // clear the pane local selection start + AbstractPane.this.fSelectionStartAddress = null; + } + + public void focusGained(FocusEvent fe) + { + } + }); + } + + protected MouseListener createMouseListener(){ + return new AbstractPaneMouseListener(); + } + + protected MouseMoveListener createMouseMoveListener(){ + return new AbstractPaneMouseMoveListener(); + } + + protected KeyListener createKeyListener(){ + return new AbstractPaneKeyListener(); + } + + protected PaintListener createPaintListener(){ + return new AbstractPanePaintListener(); + } + + protected void handleRightArrowKey() + { + fSubCellCaretPosition++; + if(fSubCellCaretPosition >= getCellCharacterCount()) + { + fSubCellCaretPosition = 0; + // Ensure that caret is within the addressable range + BigInteger newCaretAddress = fCaretAddress.add(BigInteger + .valueOf(getNumberOfBytesRepresentedByColumn() / fRendering.getAddressableSize())); + if(newCaretAddress.compareTo(fRendering.getMemoryBlockEndAddress()) > 0) + { + fSubCellCaretPosition = getCellCharacterCount(); + } + else + { + setCaretAddress(newCaretAddress); + } + } + updateCaret(); + ensureCaretWithinViewport(); + } + + protected void handleLeftArrowKey() + { + fSubCellCaretPosition--; + if(fSubCellCaretPosition < 0) + { + fSubCellCaretPosition = getCellCharacterCount() - 1; + // Ensure that caret is within the addressable range + BigInteger newCaretAddress = fCaretAddress.subtract(BigInteger + .valueOf(getNumberOfBytesRepresentedByColumn() / fRendering.getAddressableSize())); + if(newCaretAddress.compareTo(fRendering.getMemoryBlockStartAddress()) < 0) + { + fSubCellCaretPosition = 0; + } + else + { + setCaretAddress(newCaretAddress); + } + + } + updateCaret(); + ensureCaretWithinViewport(); + } + + protected void handleDownArrowKey() + { + // Ensure that caret is within the addressable range + BigInteger newCaretAddress = fCaretAddress.add(BigInteger + .valueOf(fRendering.getAddressableCellsPerRow())); + setCaretAddress(newCaretAddress); + + updateCaret(); + ensureCaretWithinViewport(); + } + + protected void handleUpArrowKey() + { + // Ensure that caret is within the addressable range + BigInteger newCaretAddress = fCaretAddress.subtract(BigInteger + .valueOf(fRendering.getAddressableCellsPerRow())); + setCaretAddress(newCaretAddress); + + updateCaret(); + ensureCaretWithinViewport(); + } + + protected void handlePageDownKey() + { + // Ensure that caret is within the addressable range + BigInteger newCaretAddress = fCaretAddress.add(BigInteger + .valueOf(fRendering.getAddressableCellsPerRow() + * (fRendering.getRowCount() - 1))); + + setCaretAddress(newCaretAddress); + + updateCaret(); + ensureCaretWithinViewport(); + } + + protected void handlePageUpKey() + { + // Ensure that caret is within the addressable range + BigInteger newCaretAddress = fCaretAddress.subtract(BigInteger + .valueOf(fRendering.getAddressableCellsPerRow() + * (fRendering.getRowCount() - 1))); + setCaretAddress(newCaretAddress); + + updateCaret(); + ensureCaretWithinViewport(); + } + + protected void handleMouseDoubleClick(MouseEvent me) + { + try + { + BigInteger address = getViewportAddress(me.x / getCellWidth(), me.y + / getCellHeight()); + + fRendering.getSelection().clear(); + fRendering.getSelection().setStart(address.add(BigInteger + .valueOf(fRendering.getAddressesPerColumn())), address); + fRendering.getSelection().setEnd(address.add(BigInteger + .valueOf(fRendering.getAddressesPerColumn())), address); + } + catch(DebugException de) + { + // do nothing + } + } + + protected boolean isPaneVisible() + { + return fPaneVisible; + } + + protected void setPaneVisible(boolean visible) + { + fPaneVisible = visible; + this.setVisible(visible); + } + + protected int getNumberOfBytesRepresentedByColumn() + { + return fRendering.getBytesPerColumn(); + } + + protected void editCell(BigInteger address, int subCellPosition, + char character) + { + // do nothing + } + + // Set the caret address + protected void setCaretAddress(BigInteger caretAddress) + { + // Ensure that caret is within the addressable range + if((caretAddress.compareTo(fRendering.getMemoryBlockStartAddress()) >= 0) && + (caretAddress.compareTo(fRendering.getMemoryBlockEndAddress()) <= 0)) + { + fCaretAddress = caretAddress; + } + else if(caretAddress.compareTo(fRendering.getMemoryBlockStartAddress()) < 0) + { + // calculate offset from the beginning of the row + int cellOffset = fCaretAddress.subtract(fRendering.getViewportStartAddress()).intValue(); + int row = cellOffset / (fRendering.getBytesPerRow() / fRendering.getBytesPerCharacter()); + + cellOffset -= row * fRendering.getBytesPerRow() / fRendering.getBytesPerCharacter(); + + fCaretAddress = fRendering.getMemoryBlockStartAddress().add( + BigInteger.valueOf(cellOffset / fRendering.getAddressableSize())); + } + else if(caretAddress.compareTo(fRendering.getMemoryBlockEndAddress()) > 0) + { + // calculate offset from the end of the row + int cellOffset = fCaretAddress.subtract(fRendering.getViewportEndAddress()).intValue() + 1; + int row = cellOffset / (fRendering.getBytesPerRow() / fRendering.getBytesPerCharacter()); + + cellOffset -= row * fRendering.getBytesPerRow()/ fRendering.getBytesPerCharacter(); + + fCaretAddress = fRendering.getMemoryBlockEndAddress().add( + BigInteger.valueOf(cellOffset / fRendering.getAddressableSize())); + } + + fRendering.setCaretAddress(fCaretAddress); + } + + protected boolean isOdd(int value) + { + return (value / 2) * 2 == value; + } + + protected void updateCaret() + { + try + { + if(fCaretAddress != null) + { + Point cellPosition = getCellLocation(fCaretAddress); + if(cellPosition != null) + { + fCaret.setLocation(cellPosition.x + fSubCellCaretPosition + * getCellCharacterWidth(), cellPosition.y); + } + } + } + catch(Exception e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_POSITION_CURSOR"), e); //$NON-NLS-1$ + } + } + + protected void ensureCaretWithinViewport() // TODO getAddressableSize() > 1 ? + { + // determine if caret is before the viewport start + // if so, scroll viewport up by appropriate rows + if(fCaretAddress.compareTo(fRendering.getViewportStartAddress()) < 0) + { + BigInteger difference = fRendering.getViewportStartAddress() + .subtract(fCaretAddress); + BigInteger rows = difference.divide(BigInteger.valueOf(fRendering.getBytesPerRow())); + if(rows.multiply( + BigInteger.valueOf(fRendering.getBytesPerRow())).compareTo(difference) != 0) + rows = rows.add(BigInteger.valueOf(1)); + + fRendering.setViewportStartAddress(fRendering.getViewportStartAddress() + .subtract(rows.multiply(BigInteger.valueOf(fRendering.getBytesPerRow())))); + fRendering.ensureViewportAddressDisplayable(); + fRendering.gotoAddress(fRendering.getViewportStartAddress()); + } + // determine if caret is after the viewport end + // if so, scroll viewport down by appropriate rows + else if(fCaretAddress.compareTo(fRendering.getViewportEndAddress()) >= 0) + { + BigInteger difference = fCaretAddress.subtract(fRendering + .getViewportEndAddress().subtract(BigInteger.valueOf(1))); + BigInteger rows = difference.divide(BigInteger.valueOf(fRendering.getBytesPerRow())); + if(rows.multiply( + BigInteger.valueOf(fRendering.getBytesPerRow())).compareTo(difference) != 0) + rows = rows.add(BigInteger.valueOf(1)); + + fRendering.setViewportStartAddress(fRendering.getViewportStartAddress().add( + rows.multiply(BigInteger.valueOf(fRendering.getBytesPerRow())))); + fRendering.ensureViewportAddressDisplayable(); + fRendering.gotoAddress(fRendering.getViewportStartAddress()); + } + + fRendering.setCaretAddress(fCaretAddress); + } + + protected void advanceCursor() + { + fSubCellCaretPosition++; + if(fSubCellCaretPosition >= getCellCharacterCount()) + { + fSubCellCaretPosition = 0; + fCaretAddress = fCaretAddress.add(BigInteger + .valueOf(getNumberOfBytesRepresentedByColumn() / fRendering.getAddressableSize())); + + } + updateCaret(); + ensureCaretWithinViewport(); + } + + protected void positionCaret(int x, int y) + { + // do nothing + } + + protected int getRowCount() + { + return fRowCount; + } + + protected void setRowCount() + { + fRowCount = getBounds().height / getCellHeight(); + } + + protected void settingsChanged() + { + fSubCellCaretPosition = 0; + } + + protected void startSelection(int x, int y) + { + try + { + BigInteger address = getViewportAddress(x / getCellWidth(), y + / getCellHeight()); + + if(address != null) + { + this.fSelectionStartAddress = address; + Point cellPosition = getCellLocation(address); + + if(cellPosition != null) + { + int offset = x - cellPosition.x; + fSelectionStartAddressSubPosition = offset + / getCellCharacterWidth(); + } + fRendering.getSelection().clear(); + fRendering.getSelection().setStart(address.add(BigInteger.valueOf( + fRendering.getBytesPerColumn() / fRendering.getAddressableSize())), address); + + fSelectionStarted = true; + + new CopyAction(fRendering, DND.SELECTION_CLIPBOARD).run(); + } + } + catch(DebugException e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_START_SELECTION"), e); //$NON-NLS-1$ + } + } + + protected void endSelection(int x, int y) + { + appendSelection(x, y); + + fSelectionInProgress = false; + } + + protected void appendSelection(int x, int y) + { + try + { + if(this.fSelectionStartAddress == null) + return; + + BigInteger address = getViewportAddress(x / getCellWidth(), y + / getCellHeight()); + + if(address.compareTo(this.fSelectionStartAddress) == 0) + { + // deal with sub cell selection + Point cellPosition = getCellLocation(address); + int offset = x - cellPosition.x; + int subCellCharacterPosition = offset / getCellCharacterWidth(); + + if(Math.abs(subCellCharacterPosition + - this.fSelectionStartAddressSubPosition) > this + .getCellCharacterCount() / 4) + { + fRendering.getSelection().setEnd(address.add(BigInteger + .valueOf(fRendering.getAddressesPerColumn())), address); + } + else + { + fRendering.getSelection().setEnd(null, null); + } + } + else + { + fRendering.getSelection().setEnd(address.add(BigInteger + .valueOf(fRendering.getAddressesPerColumn())), address); + } + + if(fRendering.getSelection().getEnd() != null) + { + this.fCaretAddress = fRendering.getSelection().getEnd(); + this.fSubCellCaretPosition = 0; + } + + updateCaret(); + + new CopyAction(fRendering, DND.SELECTION_CLIPBOARD).run(); + } + catch(DebugException e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_APPEND_SELECTION"), e); //$NON-NLS-1$ + } + } + + protected void paint(PaintEvent pe) + { + fRowCount = getBounds().height / getCellHeight(); + + if(fRendering.isDirty()) + { + fRendering.setDirty(false); + fRendering.refresh(); + } + } + + abstract protected BigInteger getViewportAddress(int col, int row) + throws DebugException; + + protected Point getCellLocation(BigInteger address) + { + return null; + } + + protected String getCellText(MemoryByte bytes[]) + { + return null; + } + + abstract protected int getCellWidth(); + + abstract protected int getCellCharacterCount(); + + public void setFont(Font font) + { + super.setFont(font); + fCharacterWidth = -1; + fCellHeight = -1; + fTextHeight = -1; + } + + private int fCellHeight = -1; // called often, cache + + protected int getCellHeight() + { + if(fCellHeight == -1) + { + fCellHeight = getCellTextHeight() + + (fRendering.getCellPadding() * 2); + } + + return fCellHeight; + } + + private int fCharacterWidth = -1; // called often, cache + + protected int getCellCharacterWidth() + { + if(fCharacterWidth == -1) + { + GC gc = new GC(this); + gc.setFont(fRendering.getFont()); + fCharacterWidth = gc.getAdvanceWidth('F'); + gc.dispose(); + } + + return fCharacterWidth; + } + + private int fTextHeight = -1; // called often, cache + + protected int getCellTextHeight() + { + if(fTextHeight == -1) + { + GC gc = new GC(this); + gc.setFont(fRendering.getFont()); + FontMetrics fontMetrics = gc.getFontMetrics(); + fTextHeight = fontMetrics.getHeight(); + gc.dispose(); + } + return fTextHeight; + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AddressPane.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AddressPane.java new file mode 100644 index 00000000000..afb20eaa404 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/AddressPane.java @@ -0,0 +1,256 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.math.BigInteger; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; + +public class AddressPane extends AbstractPane +{ + public AddressPane(Rendering parent) + { + super(parent); + } + + protected BigInteger getViewportAddress(int col, int row) + throws DebugException + { + BigInteger address = fRendering.getViewportStartAddress(); + address = address.add(BigInteger.valueOf((row + * fRendering.getColumnCount() + col) + * fRendering.getAddressesPerColumn())); + + return address; + } + + protected void appendSelection(int x, int y) + { + try + { + if(this.fSelectionStartAddress == null) + return; + + BigInteger address = getViewportAddress(x / getCellWidth(), y + / getCellHeight()); + + if(address.compareTo(this.fSelectionStartAddress) == 0) + { + fRendering.getSelection().setEnd(null, null); + } + else + { + fRendering.getSelection().setEnd(address.add(BigInteger + .valueOf(fRendering.getAddressesPerColumn() * fRendering.getColumnCount())), address); + } + } + catch(DebugException e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_APPEND_SELECTION"), e); //$NON-NLS-1$ + } + } + + public Point computeSize(int wHint, int hHint) + { + return new Point(getCellWidth() + fRendering.getRenderSpacing(), 100); + } + + protected int getCellCharacterCount() + { + // two characters per byte of hex address + + return fRendering.getAddressBytes() * 2 + + 2; // 0x + } + + protected int getCellWidth() + { + GC gc = new GC(this); + StringBuffer buf = new StringBuffer(); + for(int i = 0; i < getCellCharacterCount(); i++) + buf.append("0"); + int width = gc.textExtent(buf.toString()).x; + gc.dispose(); + return width; + } + + private int getColumnCount() + { + return 0; + } + + private BigInteger getCellAddressAt(int x, int y) throws DebugException + { + BigInteger address = fRendering.getViewportStartAddress(); + + int col = x / getCellWidth(); + int row = y / getCellHeight(); + + if(col > getColumnCount()) + return null; + + address = address.add(BigInteger.valueOf(row + * fRendering.getColumnCount() * fRendering.getAddressesPerColumn() + / fRendering.getBytesPerCharacter())); + + address = address.add(BigInteger.valueOf(col + * fRendering.getAddressesPerColumn())); + + return address; + } + + protected Point getCellLocation(BigInteger cellAddress) + { + try + { + BigInteger address = fRendering.getViewportStartAddress(); + + int cellOffset = cellAddress.subtract(address).intValue(); + + cellOffset *= fRendering.getAddressableSize(); + + if(fRendering.getColumnCount() == 0) // avoid divide by zero + return new Point(0,0); + + int row = cellOffset + / (fRendering.getColumnCount() * fRendering.getBytesPerColumn() / fRendering + .getBytesPerCharacter()); + + cellOffset -= row * fRendering.getColumnCount() + * fRendering.getBytesPerColumn() + / fRendering.getBytesPerCharacter(); + + int col = cellOffset / fRendering.getBytesPerColumn() + / fRendering.getBytesPerCharacter(); + + int x = col * getCellWidth() + fRendering.getCellPadding(); + int y = row * getCellHeight() + fRendering.getCellPadding(); + + return new Point(x, y); + } + catch(Exception e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_DETERMINE_CELL_LOCATION"), e); //$NON-NLS-1$ + return null; + } + } + + protected int getNumberOfBytesRepresentedByColumn() + { + return fRendering.getBytesPerRow(); + } + + protected void positionCaret(int x, int y) + { + try + { + BigInteger cellAddress = getCellAddressAt(x, y); + if(cellAddress != null) + { + Point cellPosition = getCellLocation(cellAddress); + + int offset = x - cellPosition.x; + int x2 = offset / getCellCharacterWidth(); + + if(x2 >= this.getCellCharacterCount()) + { + cellAddress = cellAddress.add(BigInteger.valueOf(this + .getNumberOfBytesRepresentedByColumn())); + x2 = 0; + cellPosition = getCellLocation(cellAddress); + } + + fCaret.setLocation(cellPosition.x + x2 + * getCellCharacterWidth(), cellPosition.y); + + this.fCaretAddress = cellAddress; + this.fSubCellCaretPosition = x2; + setCaretAddress(fCaretAddress); + } + } + catch(Exception e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_POSITION_CURSOR"), e); //$NON-NLS-1$ + } + } + + protected void paint(PaintEvent pe) + { + super.paint(pe); + + GC gc = pe.gc; + + FontMetrics fontMetrics = gc.getFontMetrics(); + int textHeight = fontMetrics.getHeight(); + int cellHeight = textHeight + (fRendering.getCellPadding() * 2); + + try + { + BigInteger start = fRendering.getViewportStartAddress(); + + for(int i = 0; i < this.getBounds().height / cellHeight; i++) + { + gc.setForeground(fRendering.getTraditionalRendering().getColorText()); + BigInteger lineAddress = start.add(BigInteger.valueOf(i + * fRendering.getColumnCount() + * fRendering.getAddressesPerColumn())); + + if(fRendering.getSelection().isSelected(lineAddress)) + { + gc.setBackground(fRendering.getTraditionalRendering().getColorSelection()); + gc.fillRectangle(fRendering.getCellPadding() * 2, + cellHeight * i, getCellWidth(), cellHeight); + + gc.setForeground(fRendering.getTraditionalRendering().getColorBackground()); + } + else + { + gc.setBackground(fRendering.getTraditionalRendering().getColorBackground()); + + gc.fillRectangle(fRendering.getCellPadding() * 2, + cellHeight * i, getCellWidth(), cellHeight); + + // Allow subclass to override this method to do its own coloring + applyCustomColor(gc); + } + + gc.drawText(fRendering.getAddressString(lineAddress), + fRendering.getCellPadding() * 2, cellHeight * i + + fRendering.getCellPadding()); + } + } + catch(Exception e) + { + fRendering.logError(TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_PAINT"), e); //$NON-NLS-1$ + } + } + + // Allow subclass to override this method to do its own coloring + protected void applyCustomColor(GC gc) + { + gc.setForeground(fRendering.getTraditionalRendering().getColorText()); + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/DataPane.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/DataPane.java new file mode 100644 index 00000000000..551cbc1522f --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/DataPane.java @@ -0,0 +1,381 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.math.BigInteger; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; + +public class DataPane extends AbstractPane +{ + public DataPane(Rendering parent) + { + super(parent); + } + + protected String getCellText(MemoryByte bytes[]) + { + return fRendering.getRadixText(bytes, fRendering.getRadix(), fRendering + .isTargetLittleEndian()); + } + + protected void editCell(BigInteger address, int subCellPosition, + char character) + { + try + { + MemoryByte bytes[] = fRendering.getBytes(fCaretAddress, fRendering + .getBytesPerColumn()); + + String cellText = getCellText(bytes); + if(cellText == null) + return; + + StringBuffer cellTextBuffer = new StringBuffer(cellText); + cellTextBuffer.setCharAt(subCellPosition, character); + BigInteger value = new BigInteger(cellTextBuffer.toString().trim(), + fRendering.getNumericRadix(fRendering.getRadix())); + final boolean isSignedType = fRendering.getRadix() == Rendering.RADIX_DECIMAL_SIGNED; + final boolean isSigned = isSignedType + && value.compareTo(BigInteger.valueOf(0)) < 0; + + int bitCount = value.bitLength(); + if(isSignedType) + bitCount++; + if(bitCount > fRendering.getBytesPerColumn() * 8) + return; + + int byteLen = fRendering.getBytesPerColumn(); + byte[] byteData = new byte[byteLen]; + for(int i = 0; i < byteLen; i++) + { + int bits = 255; + if(isSignedType && i == byteLen - 1) + bits = 127; + + byteData[i] = (byte) (value.and(BigInteger.valueOf(bits)) + .intValue() & bits); + value = value.shiftRight(8); + } + + if(isSigned) + byteData[byteLen - 1] |= 128; + + if(!fRendering.isDisplayLittleEndian()) + { + byte[] byteDataSwapped = new byte[byteData.length]; + for(int i = 0; i < byteData.length; i++) + byteDataSwapped[i] = byteData[byteData.length - 1 - i]; + byteData = byteDataSwapped; + } + + if(byteData.length != bytes.length) + return; + + TraditionalMemoryByte bytesToSet[] = new TraditionalMemoryByte[bytes.length]; + + for(int i = 0; i < byteData.length; i++) + { + bytesToSet[i] = new TraditionalMemoryByte(byteData[i]); + bytesToSet[i].setBigEndian(bytes[i].isBigEndian()); + + // for embedded, the user wants feedback that the change will be sent to the target, + // even if does not change the value. eventually, maybe we need another color to + // indicate change. + //if(bytes[i].getValue() != byteData[i]) + { + bytesToSet[i].setEdited(true); + } + //else + { +// if(bytes[i] instanceof TraditionalMemoryByte) +// bytesToSet[i].setEdited(((TraditionalMemoryByte) bytes[i]).isEdited()); + bytesToSet[i].setChanged(bytes[i].isChanged()); + } + } + + fRendering.getViewportCache().setEditedValue(address, bytesToSet); + + advanceCursor(); + + redraw(); + } + catch(Exception e) + { + // do nothing + } + } + + protected int getCellWidth() + { + return getCellCharacterCount() * getCellCharacterWidth() + + (fRendering.getCellPadding() * 2); + } + + protected int getCellCharacterCount() + { + return fRendering.getRadixCharacterCount(fRendering.getRadix(), + fRendering.getBytesPerColumn()); + } + + public Point computeSize(int wHint, int hHint) + { + return new Point(fRendering.getColumnCount() * getCellWidth() + + fRendering.getRenderSpacing(), 100); + } + + private BigInteger getCellAddressAt(int x, int y) throws DebugException + { + BigInteger address = fRendering.getViewportStartAddress(); + + int col = x / getCellWidth(); + int row = y / getCellHeight(); + + if(col >= fRendering.getColumnCount()) + return null; + + address = address.add(BigInteger.valueOf(row + * fRendering.getColumnCount() * fRendering.getAddressesPerColumn())); + + address = address.add(BigInteger.valueOf(col + * fRendering.getAddressesPerColumn())); + + return address; + } + + protected Point getCellLocation(BigInteger cellAddress) + { + try + { + BigInteger address = fRendering.getViewportStartAddress(); + + int cellOffset = cellAddress.subtract(address).intValue(); + cellOffset *= fRendering.getAddressableSize(); + + int row = cellOffset + / (fRendering.getColumnCount() * fRendering.getBytesPerColumn()); + cellOffset -= row * fRendering.getColumnCount() + * fRendering.getBytesPerColumn(); + + int col = cellOffset / fRendering.getBytesPerColumn(); + + int x = col * getCellWidth() + fRendering.getCellPadding(); + int y = row * getCellHeight() + fRendering.getCellPadding(); + + return new Point(x, y); + } + catch(Exception e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_DETERMINE_CELL_LOCATION"), e); //$NON-NLS-1$ + return null; + } + } + + protected void positionCaret(int x, int y) + { + try + { + BigInteger cellAddress = getCellAddressAt(x, y); + if(cellAddress != null) + { + Point cellPosition = getCellLocation(cellAddress); + int offset = x - cellPosition.x; + int subCellCharacterPosition = offset / getCellCharacterWidth(); + + if(subCellCharacterPosition == this.getCellCharacterCount()) + { + cellAddress = cellAddress.add(BigInteger.valueOf(fRendering + .getAddressesPerColumn())); + subCellCharacterPosition = 0; + cellPosition = getCellLocation(cellAddress); + } + + fCaret.setLocation(cellPosition.x + subCellCharacterPosition + * getCellCharacterWidth(), cellPosition.y); + + this.fCaretAddress = cellAddress; + this.fSubCellCaretPosition = subCellCharacterPosition; + setCaretAddress(fCaretAddress); + } + } + catch(Exception e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_POSITION_CURSOR"), e); //$NON-NLS-1$ + } + } + + protected BigInteger getViewportAddress(int col, int row) + throws DebugException + { + BigInteger address = fRendering.getViewportStartAddress(); + address = address.add(BigInteger.valueOf((row + * fRendering.getColumnCount() + col) + * fRendering.getAddressesPerColumn())); + + return address; + } + + protected void paint(PaintEvent pe) + { + super.paint(pe); + + // Allow subclasses to override this method to do their own painting + doPaintData(pe); + + } + + // Allow subclasses to override this method to do their own painting + protected void doPaintData(PaintEvent pe) + { + GC gc = pe.gc; + gc.setFont(fRendering.getFont()); + + int cellHeight = getCellHeight(); + int cellWidth = getCellWidth(); + + int columns = fRendering.getColumnCount(); + + try + { + BigInteger start = fRendering.getViewportStartAddress(); + + for(int i = 0; i < this.getBounds().height / cellHeight; i++) + { + for(int col = 0; col < columns; col++) + { + if(isOdd(col)) + gc.setForeground(fRendering.getTraditionalRendering().getColorText()); + else + gc.setForeground(fRendering.getTraditionalRendering().getColorTextAlternate()); + + BigInteger cellAddress = start.add(BigInteger.valueOf((i + * fRendering.getColumnCount() + col) + * fRendering.getAddressesPerColumn())); + + TraditionalMemoryByte bytes[] = fRendering.getBytes(cellAddress, + fRendering.getBytesPerColumn()); + + if(fRendering.getSelection().isSelected(cellAddress)) + { + gc.setBackground(fRendering.getTraditionalRendering().getColorSelection()); + gc.fillRectangle(cellWidth * col + + fRendering.getCellPadding(), cellHeight * i, + cellWidth, cellHeight); + + gc.setForeground(fRendering.getTraditionalRendering().getColorBackground()); + } + else + { + gc.setBackground(fRendering.getTraditionalRendering().getColorBackground()); + gc.fillRectangle(cellWidth * col + + fRendering.getCellPadding(), cellHeight * i, + cellWidth, cellHeight); + + // Allow subclasses to override this method to do their own coloring + applyCustomColor(gc, bytes, col); + } + + gc.drawText(getCellText(bytes), cellWidth * col + + fRendering.getCellPadding(), cellHeight * i + + fRendering.getCellPadding()); + + BigInteger cellEndAddress = cellAddress.add(BigInteger + .valueOf(fRendering.getAddressesPerColumn())); + cellEndAddress = cellEndAddress.subtract(BigInteger + .valueOf(1)); + + if(fCaretEnabled) + { + if(cellAddress.compareTo(fCaretAddress) <= 0 + && cellEndAddress.compareTo(fCaretAddress) >= 0) + { + int x = cellWidth * col + + fRendering.getCellPadding() + + fSubCellCaretPosition + * this.getCellCharacterWidth(); + int y = cellHeight * i + + fRendering.getCellPadding(); + fCaret.setLocation(x, y); + } + } + + if(fRendering.isDebug()) + gc.drawRectangle(cellWidth * col + + fRendering.getCellPadding(), cellHeight * i + + fRendering.getCellPadding(), cellWidth, + cellHeight); + } + } + } + catch(Exception e) + { + fRendering.logError(TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_PAINT"), e); //$NON-NLS-1$ + } + + } + + // Allow subclasses to override this method to do their own coloring + protected void applyCustomColor(GC gc, TraditionalMemoryByte bytes[], int col) + { + // TODO consider adding finer granularity? + boolean anyByteEditing = false; + for(int n = 0; n < bytes.length && !anyByteEditing; n++) + if(bytes[n] instanceof TraditionalMemoryByte) + if(((TraditionalMemoryByte) bytes[n]).isEdited()) + anyByteEditing = true; + + if(isOdd(col)) + gc.setForeground(fRendering.getTraditionalRendering().getColorText()); + else + gc.setForeground(fRendering.getTraditionalRendering().getColorTextAlternate()); + gc.setBackground(fRendering.getTraditionalRendering().getColorBackground()); + + if(anyByteEditing) + { + gc.setForeground(fRendering.getTraditionalRendering().getColorEdit()); + } + else + { + boolean isColored = false; + for(int i = 0; i < fRendering.getHistoryDepth() && !isColored; i++) + { + // TODO consider adding finer granularity? + for(int n = 0; n < bytes.length; n++) + { + if(bytes[n].isChanged(i)) + { + if(i == 0) + gc.setForeground(fRendering.getTraditionalRendering().getColorsChanged()[i]); + else + gc.setBackground(fRendering.getTraditionalRendering().getColorsChanged()[i]); + isColored = true; + break; + } + } + } + } + + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IMemoryByte.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IMemoryByte.java new file mode 100644 index 00000000000..650edbbca28 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IMemoryByte.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +public interface IMemoryByte { + + public boolean isEdited(); + + public void setEdited(boolean edited); +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IMemorySelection.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IMemorySelection.java new file mode 100644 index 00000000000..ff1c104a8fa --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IMemorySelection.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.math.BigInteger; + +public interface IMemorySelection +{ + public boolean hasSelection(); + + public boolean isSelected(BigInteger address); + + public BigInteger getStart(); + + public BigInteger getEnd(); + + public BigInteger getStartLow(); + + public void setStart(BigInteger high, BigInteger low); + + public void setEnd(BigInteger high, BigInteger low); + + public BigInteger getHigh(); + + public BigInteger getLow(); + + public void clear(); +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IViewportCache.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IViewportCache.java new file mode 100644 index 00000000000..3c3973f19b1 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/IViewportCache.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.math.BigInteger; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.MemoryByte; + +public interface IViewportCache { + + public void dispose(); + public void refresh(); + public TraditionalMemoryByte[] getBytes(BigInteger address, int bytesRequested) throws DebugException; + public void archiveDeltas(); + public void setEditedValue(BigInteger address, TraditionalMemoryByte[] bytes); + public void clearEditBuffer(); + public void writeEditBuffer(); + public boolean containsEditedCell(BigInteger address); + // private void queueRequest(BigInteger startAddress, BigInteger endAddress); +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java new file mode 100644 index 00000000000..72272adb37c --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java @@ -0,0 +1,2104 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugEvent; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.IDebugEventSetListener; +import org.eclipse.debug.core.model.IDebugElement; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; +import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil; +import org.eclipse.debug.internal.ui.views.memory.renderings.GoToAddressComposite; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.Text; + +public class Rendering extends Composite implements IDebugEventSetListener +{ + // the IMemoryRendering parent + private TraditionalRendering fParent; + + // controls + + protected AddressPane fAddressPane; + + protected DataPane fBinaryPane; + + protected TextPane fTextPane; + + private GoToAddressComposite fAddressBar; + + private Control fAddressBarControl; // FIXME why isn't there a getControl() ? + + private Selection fSelection = new Selection(); + + // storage + + BigInteger fViewportAddress = null; // default visibility for performance + + BigInteger fMemoryBlockStartAddress = null; + BigInteger fMemoryBlockEndAddress = null; + + protected BigInteger fBaseAddress = null; // remember the base address + + private int fColumnCount = 0; // auto calculate can be disabled by user, + // making this user settable + + private int fBytesPerRow = 0; // current number of bytes per row are displayed + + private int fCurrentScrollSelection = 0; // current scroll selection; + + private BigInteger fCaretAddress = BigInteger.valueOf(0); // -1 ? + + // user settings + + private int fTextMode = 1; // ASCII default, TODO make preference? + + private int fBytesPerColumn = 4; // 4 byte cell width default + + private int fRadix = RADIX_HEX; + + private int fColumnsSetting = COLUMNS_AUTO_SIZE_TO_FIT; + + private boolean fIsTargetLittleEndian = false; + + private boolean fIsDisplayLittleEndian = false; + + // constants used to identify radix + public final static int RADIX_HEX = 1; + + public final static int RADIX_DECIMAL_SIGNED = 2; + + public final static int RADIX_DECIMAL_UNSIGNED = 3; + + public final static int RADIX_OCTAL = 4; + + public final static int RADIX_BINARY = 5; + + // constants used to identify panes + public final static int PANE_ADDRESS = 1; + + public final static int PANE_BINARY = 2; + + public final static int PANE_TEXT = 3; + + // constants used to identify text, maybe java should be queried for all available sets + public final static int TEXT_ISO_8859_1 = 1; + public final static int TEXT_USASCII = 2; + public final static int TEXT_UTF8 = 3; + protected final static int TEXT_UTF16 = 4; + + // internal constants + public final static int COLUMNS_AUTO_SIZE_TO_FIT = 0; + + // view internal settings + private int fCellPadding = 2; + + private int fPaneSpacing = 16; + + private String fPaddingString = "?"; //$NON-NLS-1$ + + // flag whether the memory cache is dirty + private boolean fCacheDirty = false; + + public Rendering(Composite parent, TraditionalRendering renderingParent) + { + super(parent, SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.H_SCROLL + | SWT.V_SCROLL); + + this.setFont(JFaceResources + .getFont(IInternalDebugUIConstants.FONT_NAME)); // TODO internal? + + this.fParent = renderingParent; + + // initialize the viewport start + if(fParent.getMemoryBlock() != null) + { + fViewportAddress = fParent.getMemoryBlockStartAddress(); + + // this will be null if memory may be retrieved at any address less than + // this memory block's base. if so use the base address. + if (fViewportAddress == null) + fViewportAddress = fParent.getBigBaseAddress(); + fBaseAddress = fViewportAddress; + } + + // instantiate the panes, TODO default visibility from state or + // plugin.xml? + this.fAddressPane = createAddressPane(); + this.fBinaryPane = createDataPane(); + this.fTextPane = createTextPane(); + + fAddressBar = new GoToAddressComposite(); + fAddressBarControl = fAddressBar.createControl(parent); + Button button = fAddressBar.getButton(IDialogConstants.OK_ID); + if (button != null) + { + button.addSelectionListener(new SelectionAdapter() { + + public void widgetSelected(SelectionEvent e) { + doGoToAddress(); + } + }); + + button = fAddressBar.getButton(IDialogConstants.CANCEL_ID); + if (button != null) + { + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + setVisibleAddressBar(false); + }}); + } + } + + fAddressBar.getExpressionWidget().addSelectionListener(new SelectionAdapter() { + public void widgetDefaultSelected(SelectionEvent e) { + doGoToAddress(); + }}); + + fAddressBar.getExpressionWidget().addKeyListener(new KeyAdapter() { + + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.ESC) + setVisibleAddressBar(false); + super.keyPressed(e); + } + }); + + this.fAddressBarControl.setVisible(false); + + getHorizontalBar().addSelectionListener(new SelectionListener() + { + public void widgetSelected(SelectionEvent se) + { + Rendering.this.layout(); + } + + public void widgetDefaultSelected(SelectionEvent se) + { + // do nothing + } + }); + + getVerticalBar().addSelectionListener( + new SelectionListener() + { + public void widgetSelected(SelectionEvent se) + { + int addressableSize = getAddressableSize(); + + switch(se.detail) + { + case SWT.ARROW_DOWN: + handleDownArrow(); + break; + case SWT.PAGE_DOWN: + handlePageDown(); + break; + case SWT.ARROW_UP: + handleUpArrow(); + break; + case SWT.PAGE_UP: + handlePageUp(); + break; + case SWT.SCROLL_LINE: + // See: BUG 203068 selection event details broken on GTK < 2.6 + default: + if(getVerticalBar().getSelection() == getVerticalBar().getMinimum()) + { + // Set view port start address to the start address of the Memory Block + fViewportAddress = Rendering.this.getMemoryBlockStartAddress(); + } + else if(getVerticalBar().getSelection() == getVerticalBar().getMaximum()) + { + // The view port end address should be less or equal to the the end address of the Memory Block + // Set view port address to be bigger than the end address of the Memory Block for now + // and let ensureViewportAddressDisplayable() to figure out the correct view port start address + fViewportAddress = Rendering.this.getMemoryBlockEndAddress(); + } + else + { + // Figure out the delta + int delta = getVerticalBar().getSelection() - fCurrentScrollSelection; + fViewportAddress = fViewportAddress.add(BigInteger.valueOf( + getAddressableCellsPerRow() * delta)); + } + ensureViewportAddressDisplayable(); + // Update tooltip + // FIXME conversion from slider to scrollbar + // getVerticalBar().setToolTipText(Rendering.this.getAddressString(fViewportAddress)); + + // Update the addresses on the Address pane. + if(fAddressPane.isPaneVisible()) + { + fAddressPane.redraw(); + } + redrawPanes(); + break; + } + + } + + public void widgetDefaultSelected(SelectionEvent se) + { + // do nothing + } + }); + + this.addPaintListener(new PaintListener() + { + public void paintControl(PaintEvent pe) + { + pe.gc.setBackground(Rendering.this.getTraditionalRendering().getColorBackground()); + pe.gc.fillRectangle(0, 0, Rendering.this.getBounds().width, + Rendering.this.getBounds().height); + } + }); + + setLayout(); + + this.addControlListener(new ControlListener() + { + public void controlMoved(ControlEvent ce) + { + } + + public void controlResized(ControlEvent ce) + { + packColumns(); + } + }); + + DebugPlugin.getDefault().addDebugEventListener(this); + } + + protected void setLayout() + { + this.setLayout(new Layout() + { + public void layout(Composite composite, boolean changed) + { + int xOffset = 0; + if(Rendering.this.getHorizontalBar().isVisible()) + xOffset = Rendering.this.getHorizontalBar().getSelection(); + + int x = xOffset * -1; + int y = 0; + + if(fAddressBarControl.isVisible()) + { + fAddressBarControl.setBounds(0, 0, + Rendering.this.getBounds().width, fAddressBarControl + .computeSize(100, 30).y); // FIXME + //y = fAddressBarControl.getBounds().height; + } + + if(fAddressPane.isPaneVisible()) + { + fAddressPane.setBounds(x, y, + fAddressPane.computeSize(0, 0).x, Rendering.this + .getBounds().height + - y); + x = fAddressPane.getBounds().x + + fAddressPane.getBounds().width; + } + + if(fBinaryPane.isPaneVisible()) + { + fBinaryPane.setBounds(x, y, + fBinaryPane.computeSize(0, 0).x, Rendering.this + .getBounds().height + - y); + x = fBinaryPane.getBounds().x + + fBinaryPane.getBounds().width; + } + + if(fTextPane.isPaneVisible()) + { + fTextPane.setBounds(x, y, + Math.max(fTextPane.computeSize(0, 0).x, Rendering.this.getClientArea().width + - x - xOffset), Rendering.this.getBounds().height - y); + } + + if(getClientArea().width >= fTextPane.getBounds().x + fTextPane.getBounds().width + xOffset) + { + Rendering.this.getHorizontalBar().setVisible(false); + } + else + { + ScrollBar horizontal = Rendering.this.getHorizontalBar(); + + horizontal.setVisible(true); + horizontal.setMinimum(0); + horizontal.setMaximum(fTextPane.getBounds().x + + fTextPane.getBounds().width + xOffset); + horizontal.setThumb(getClientArea().width); + horizontal.setPageIncrement(40); // TODO ? + horizontal.setIncrement(20); // TODO ? + } + } + + protected Point computeSize(Composite composite, int wHint, + int hHint, boolean flushCache) + { + return new Point(100, 100); // dummy data + } + }); + } + + protected void handleDownArrow() + { + fViewportAddress = fViewportAddress.add(BigInteger + .valueOf(getAddressableCellsPerRow())); + ensureViewportAddressDisplayable(); + redrawPanes(); + } + + protected void handleUpArrow() + { + fViewportAddress = fViewportAddress.subtract(BigInteger + .valueOf(getAddressableCellsPerRow())); + ensureViewportAddressDisplayable(); + redrawPanes(); + } + + protected void handlePageDown() + { + fViewportAddress = fViewportAddress.add(BigInteger + .valueOf(getAddressableCellsPerRow() + * (Rendering.this.getRowCount() - 1))); + ensureViewportAddressDisplayable(); + redrawPanes(); + } + + protected void handlePageUp() + { + fViewportAddress = fViewportAddress.subtract(BigInteger + .valueOf(getAddressableCellsPerRow() + * (Rendering.this.getRowCount() - 1))); + ensureViewportAddressDisplayable(); + redrawPanes(); + } + + protected AddressPane createAddressPane() + { + return new AddressPane(this); + } + + protected DataPane createDataPane() + { + return new DataPane(this); + } + + protected TextPane createTextPane() + { + return new TextPane(this); + } + + public TraditionalRendering getTraditionalRendering() // TODO rename + { + return fParent; + } + + protected void setCaretAddress(BigInteger address) + { + fCaretAddress = address; + } + + protected BigInteger getCaretAddress() + { + return fCaretAddress; + } + + private void doGoToAddress() { + try { + BigInteger address = fAddressBar.getGoToAddress(this.getMemoryBlockStartAddress(), this.getCaretAddress()); + getTraditionalRendering().gotoAddress(address); + setVisibleAddressBar(false); + } catch (NumberFormatException e1) + { + // FIXME log? + } + } + + // Ensure that all addresses displayed are within the addressable range + protected void ensureViewportAddressDisplayable() + { + if(fViewportAddress.compareTo(Rendering.this.getMemoryBlockStartAddress()) < 0) + { + fViewportAddress = Rendering.this.getMemoryBlockStartAddress(); + } + else if(getViewportEndAddress().compareTo(getMemoryBlockEndAddress().add(BigInteger.ONE)) > 0) + { + fViewportAddress = getMemoryBlockEndAddress().subtract(BigInteger.valueOf(getAddressableCellsPerRow() + * getRowCount() - 1)); + } + + setCurrentScrollSelection(); + } + + public IMemorySelection getSelection() + { + return fSelection; + } + + protected int getHistoryDepth() + { + return fViewportCache.getHistoryDepth(); + } + + protected void setHistoryDepth(int depth) + { + fViewportCache.setHistoryDepth(depth); + } + + public void logError(String message, Exception e) + { + Status status = new Status(IStatus.ERROR, fParent.getRenderingId(), + DebugException.INTERNAL_ERROR, message, e); + + DebugUIPlugin.getDefault().getLog().log(status); + } + + public void handleFontPreferenceChange(Font font) + { + setFont(font); + + Control controls[] = this.getRenderingPanes(); + for(int i = 0; i < controls.length; i++) + controls[i].setFont(font); + + packColumns(); + layout(true); + } + + public void setPaddingString(String padding) + { + fPaddingString = padding; + + refresh(); + } + + public char getPaddingCharacter() + { + return fPaddingString.charAt(0); // use only the first character + } + + static int suspendCount = 0; + + public void handleDebugEvents(DebugEvent[] events) + { + if(this.isDisposed()) + return; + + boolean isChangeOnly = false; + boolean isSuspend = false; + + for(int i = 0; i < events.length; i++) + { + if(events[0].getSource() instanceof IDebugElement) + { + final int kind = events[i].getKind(); + final int detail = events[i].getDetail(); + final IDebugElement source = (IDebugElement) events[i] + .getSource(); + + if(source.getDebugTarget() == getMemoryBlock() + .getDebugTarget()) + { + if(kind == DebugEvent.SUSPEND) + { + handleSuspendEvent(detail); + isSuspend = true; + } + else if(kind == DebugEvent.CHANGE) + { + handleChangeEvent(); + isChangeOnly = true; + } + } + } + } + + if(isSuspend) + handleSuspend(); + else if(isChangeOnly) + handleChange(); + } + + protected void handleSuspend() + { + Display.getDefault().asyncExec(new Runnable() + { + public void run() + { + archiveDeltas(); + refresh(); + } + }); + } + + protected void handleChange() + { + Display.getDefault().asyncExec(new Runnable() + { + public void run() + { + refresh(); + } + }); + } + + protected void handleSuspendEvent(int detail) + { + } + + protected void handleChangeEvent() + { + } + + // return true to enable development debug print statements + public boolean isDebug() + { + return false; + } + + protected IMemoryBlockExtension getMemoryBlock() + { + IMemoryBlock block = fParent.getMemoryBlock(); + if(block != null) + return (IMemoryBlockExtension) block + .getAdapter(IMemoryBlockExtension.class); + + return null; + } + + public BigInteger getBigBaseAddress() + { + return fParent.getBigBaseAddress(); + } + + public int getAddressableSize() + { + return fParent.getAddressableSize(); + } + + protected IViewportCache getViewportCache() + { + return fViewportCache; + } + + public TraditionalMemoryByte[] getBytes(BigInteger address, int bytes) + throws DebugException + { + return getViewportCache().getBytes(address, bytes); + } + + // default visibility for performance + ViewportCache fViewportCache = new ViewportCache(); + + private interface Request + { + } + + class ViewportCache extends Thread implements IViewportCache + { + class ArchiveDeltas implements Request + { + + } + + class AddressPair implements Request + { + BigInteger startAddress; + + BigInteger endAddress; + + public AddressPair(BigInteger start, BigInteger end) + { + startAddress = start; + endAddress = end; + } + + @Override + public boolean equals(Object obj) { + if(obj == null) + return false; + if(obj instanceof AddressPair) + { + return ((AddressPair) obj).startAddress.equals(startAddress) + && ((AddressPair) obj).endAddress.equals(endAddress); + } + + return false; + } + + } + + class MemoryUnit + { + BigInteger start; + + BigInteger end; + + TraditionalMemoryByte[] bytes; + + public MemoryUnit clone() + { + MemoryUnit b = new MemoryUnit(); + + b.start = this.start; + b.end = this.end; + b.bytes = new TraditionalMemoryByte[this.bytes.length]; + for(int i = 0; i < this.bytes.length; i++) + b.bytes[i] = new TraditionalMemoryByte(this.bytes[i].getValue()); + + return b; + } + + public boolean isValid() + { + return this.start != null && this.end != null + && this.bytes != null; + } + } + + private HashMap fEditBuffer = new HashMap(); + + private boolean fDisposed = false; + + private Object fLastQueued = null; + + private Vector fQueue = new Vector(); + + protected MemoryUnit fCache = null; + + protected MemoryUnit fHistoryCache[] = new MemoryUnit[0]; + + protected int fHistoryDepth = 0; + + public ViewportCache() + { + start(); + } + + public void dispose() + { + fDisposed = true; + synchronized(this) + { + this.notify(); + } + } + + public int getHistoryDepth() + { + return fHistoryDepth; + } + + public void setHistoryDepth(int depth) + { + fHistoryDepth = depth; + fHistoryCache = new MemoryUnit[fHistoryDepth]; + } + + public void refresh() + { + assert Thread.currentThread().equals( + Display.getDefault().getThread()) : TraditionalRenderingMessages + .getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$ + + if(fCache != null) + { + queueRequest(fViewportAddress, getViewportEndAddress()); + } + } + + public void archiveDeltas() + { + assert Thread.currentThread().equals( + Display.getDefault().getThread()) : TraditionalRenderingMessages + .getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$ + + if(fCache != null) + { + queueRequestArchiveDeltas(); + } + } + + private void queueRequest(BigInteger startAddress, BigInteger endAddress) + { + AddressPair pair = new AddressPair(startAddress, endAddress); + queue(pair); + } + + private void queueRequestArchiveDeltas() + { + ArchiveDeltas archive = new ArchiveDeltas(); + queue(archive); + } + + private void queue(Object element) + { + synchronized(fQueue) + { + if(!(fQueue.size() > 0 && element.equals(fLastQueued))) + { + fQueue.addElement(element); + fLastQueued = element; + } + } + synchronized(this) + { + this.notify(); + } + } + + public void run() + { + while(!fDisposed) + { + AddressPair pair = null; + boolean archiveDeltas = false; + synchronized(fQueue) + { + if(fQueue.size() > 0) + { + Request request = (Request) fQueue.elementAt(0); + Class type = null; + if(request instanceof ArchiveDeltas) + { + archiveDeltas = true; + type = ArchiveDeltas.class; + } + else if(request instanceof AddressPair) + { + pair = (AddressPair) request; + type = AddressPair.class; + } + + while(fQueue.size() > 0 && type.isInstance(fQueue.elementAt(0))) + fQueue.removeElementAt(0); + } + } + if(archiveDeltas) + { + for(int i = fViewportCache.getHistoryDepth() - 1; i > 0; i--) + fHistoryCache[i] = fHistoryCache[i - 1]; + + fHistoryCache[0] = fCache.clone(); + } + else if(pair != null) + { + populateCache(pair.startAddress, pair.endAddress); + } + else + { + synchronized(this) + { + try + { + this.wait(); + } + catch(Exception e) + { + // do nothing + } + } + } + } + } + + // cache memory necessary to paint viewport + // TODO: user setting to buffer +/- x lines + // TODO: reuse existing cache? probably only a minor performance gain + private void populateCache(final BigInteger startAddress, + final BigInteger endAddress) + { + try + { + final IMemoryBlockExtension memoryBlock = getMemoryBlock(); + + final BigInteger lengthInBytes = endAddress.subtract(startAddress); + final BigInteger addressableSize = BigInteger.valueOf(getAddressableSize()); + + final long units = lengthInBytes.divide(addressableSize).add( + lengthInBytes.mod(addressableSize).compareTo(BigInteger.ZERO) > 0 + ? BigInteger.ONE : BigInteger.ZERO).longValue(); + + // CDT (and maybe other backends) will call setValue() on these MemoryBlock objects. + // We don't want this to happen, because it interferes with this rendering's own + // change history. Ideally, we should strictly use the back end change notification + // and history, but it is only guaranteed to work for bytes within the address range + // of the MemoryBlock. + final MemoryByte readBytes[] = memoryBlock + .getBytesFromAddress(startAddress, units); + + TraditionalMemoryByte cachedBytes[] = new TraditionalMemoryByte[readBytes.length]; + for(int i = 0; i < readBytes.length; i++) + cachedBytes[i] = new TraditionalMemoryByte(readBytes[i].getValue(), readBytes[i].getFlags()); + + // derive the target endian from the read MemoryBytes. + if (cachedBytes.length > 0) { + if (cachedBytes[0].isEndianessKnown()) { + setTargetLittleEndian(!cachedBytes[0].isBigEndian()); + } + } + + // reorder bytes within unit to be a sequential byte stream if the endian is already little + if(isTargetLittleEndian()) + { + // there isn't an order when the unit size is one, so skip for performance + if(addressableSize.compareTo(BigInteger.ONE) != 0) + { + int unitSize = addressableSize.intValue(); + TraditionalMemoryByte cachedBytesAsByteSequence[] = new TraditionalMemoryByte[cachedBytes.length]; + for(int unit = 0; unit < units; unit++) + { + for(int unitbyte = 0; unitbyte < unitSize; unitbyte++) + { + cachedBytesAsByteSequence[unit * unitSize + unitbyte] = cachedBytes[unit * unitSize + unitSize - unitbyte]; + } + } + cachedBytes = cachedBytesAsByteSequence; + } + } + + final TraditionalMemoryByte[] cachedBytesFinal = cachedBytes; + Display.getDefault().asyncExec(new Runnable() + { + public void run() + { + // generate deltas + for(int historyIndex = 0; historyIndex < getHistoryDepth(); historyIndex++) + { + if(fHistoryCache[historyIndex] != null && fHistoryCache[historyIndex].isValid()) + { + BigInteger maxStart = startAddress + .max(fHistoryCache[historyIndex].start); + BigInteger minEnd = endAddress + .min(fHistoryCache[historyIndex].end).subtract( + BigInteger.valueOf(1)); + + BigInteger overlapLength = minEnd + .subtract(maxStart); + if(overlapLength.compareTo(BigInteger.valueOf(0)) > 0) + { + // there is overlap + + int offsetIntoOld = maxStart.subtract( + fHistoryCache[historyIndex].start).intValue(); + int offsetIntoNew = maxStart.subtract( + startAddress).intValue(); + + for(int i = overlapLength.intValue(); i >= 0; i--) + { + cachedBytesFinal[offsetIntoNew + i] + .setChanged(historyIndex, cachedBytesFinal[offsetIntoNew + + i].getValue() != fHistoryCache[historyIndex].bytes[offsetIntoOld + + i].getValue()); + } + } + } + } + + fCache = new MemoryUnit(); + fCache.start = startAddress; + fCache.end = endAddress; + fCache.bytes = cachedBytesFinal; + + // If the history does not exist, populate the history with the just populated cache. This solves the + // use case of 1) connect to target; 2) edit memory before the first suspend debug event; 3) paint + // differences in changed color. + if(fHistoryCache[0] == null) + fHistoryCache[0] = fCache.clone(); + + Rendering.this.redrawPanes(); + } + }); + + } + catch(Exception e) + { + logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_READ_MEMORY"), e); //$NON-NLS-1$ + } + } + + // bytes will be fetched from cache + public TraditionalMemoryByte[] getBytes(BigInteger address, int bytesRequested) + throws DebugException + { + assert Thread.currentThread().equals( + Display.getDefault().getThread()) : TraditionalRenderingMessages + .getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$ + + if(containsEditedCell(address)) // cell size cannot be switched during an edit + return getEditedMemory(address); + + boolean contains = false; + if(fCache != null && fCache.start != null) + { + // see if all of the data requested is in the cache + BigInteger dataEnd = address.add(BigInteger.valueOf(bytesRequested)); + + if(fCache.start.compareTo(address) <= 0 + && fCache.end.compareTo(dataEnd) >= 0 + && fCache.bytes.length > 0) + contains = true; + } + + if(contains) + { + int offset = address.subtract(fCache.start).intValue(); + TraditionalMemoryByte bytes[] = new TraditionalMemoryByte[bytesRequested]; + for(int i = 0; i < bytes.length; i++) + { + bytes[i] = fCache.bytes[offset + i]; + } + + return bytes; + } + + TraditionalMemoryByte bytes[] = new TraditionalMemoryByte[bytesRequested]; + for(int i = 0; i < bytes.length; i++) + { + bytes[i] = new TraditionalMemoryByte(); + bytes[i].setReadable(false); + } + + fViewportCache.queueRequest(fViewportAddress, + getViewportEndAddress()); + + return bytes; + } + + public boolean containsEditedCell(BigInteger address) + { + assert Thread.currentThread().equals( + Display.getDefault().getThread()) : TraditionalRenderingMessages + .getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$ + + return fEditBuffer.containsKey(address); + } + + private TraditionalMemoryByte[] getEditedMemory(BigInteger address) + { + assert Thread.currentThread().equals( + Display.getDefault().getThread()) : TraditionalRenderingMessages + .getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$ + + return (TraditionalMemoryByte[]) fEditBuffer.get(address); + } + + public void clearEditBuffer() + { + assert Thread.currentThread().equals( + Display.getDefault().getThread()) : TraditionalRenderingMessages + .getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$ + + fEditBuffer.clear(); + Rendering.this.redrawPanes(); + } + + public void writeEditBuffer() + { + assert Thread.currentThread().equals( + Display.getDefault().getThread()) : TraditionalRenderingMessages + .getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$ + + Set keySet = fEditBuffer.keySet(); + Iterator iterator = keySet.iterator(); + + while(iterator.hasNext()) + { + BigInteger address = (BigInteger) iterator.next(); + TraditionalMemoryByte[] bytes = (TraditionalMemoryByte[]) fEditBuffer + .get(address); + + byte byteValue[] = new byte[bytes.length]; + for(int i = 0; i < bytes.length; i++) + byteValue[i] = bytes[i].getValue(); + + try + { + getMemoryBlock().setValue(address.subtract(fParent.getBigBaseAddress()), byteValue); + } + catch(Exception e) + { + MemoryViewUtil.openError(TraditionalRenderingMessages.getString("TraditionalRendering.FAILURE_WRITE_MEMORY"), "", e); + + logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_WRITE_MEMORY"), e); //$NON-NLS-1$ + } + } + + clearEditBuffer(); + } + + public void setEditedValue(BigInteger address, TraditionalMemoryByte[] bytes) + { + assert Thread.currentThread().equals( + Display.getDefault().getThread()) : TraditionalRenderingMessages + .getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$ + + fEditBuffer.put(address, bytes); + Rendering.this.redrawPanes(); + } + } + + public void setVisibleAddressBar(boolean visible) + { + fAddressBarControl.setVisible(visible); + if(visible) + { + String selectedStr = "0x" + getCaretAddress().toString(16); + Text text = fAddressBar.getExpressionWidget(); + text.setText(selectedStr); + text.setSelection(0, text.getCharCount()); + fAddressBar.getExpressionWidget().setFocus(); + } + + layout(true); + layoutPanes(); + } + + public void setDirty(boolean needRefresh) + { + fCacheDirty = needRefresh; + } + + public boolean isDirty() + { + return fCacheDirty; + } + + public void dispose() + { + DebugPlugin.getDefault().removeDebugEventListener(this); + if(fViewportCache != null) + { + fViewportCache.dispose(); + fViewportCache = null; + } + super.dispose(); + } + + class Selection implements IMemorySelection + { + private BigInteger fStartHigh; + private BigInteger fStartLow; + + private BigInteger fEndHigh; + private BigInteger fEndLow; + + public void clear() + { + fEndHigh = fEndLow = fStartHigh = fStartLow = null; + redrawPanes(); + } + + public boolean hasSelection() + { + return fStartHigh != null && fStartLow != null + && fEndHigh != null && fEndLow != null; + } + + public boolean isSelected(BigInteger address) + { + // do we have valid start and end addresses + if(getEnd() == null || getStart() == null) + return false; + + // if end is greater than start + if(getEnd().compareTo(getStart()) >= 0) + { + if(address.compareTo(getStart()) >= 0 + && address.compareTo(getEnd()) < 0) + return true; + } + // if start is greater than end + else if(getStart().compareTo(getEnd()) >= 0) + { + if(address.compareTo(getEnd()) >= 0 + && address.compareTo(getStart()) < 0) + return true; + } + + return false; + } + + public void setStart(BigInteger high, BigInteger low) + { + if(high == null && low == null) + { + if(fStartHigh != null && fStartLow != null) + { + fStartHigh = null; + fStartLow = null; + redrawPanes(); + } + + return; + } + + boolean changed = false; + + if(fStartHigh == null || !high.equals(fStartHigh)) + { + fStartHigh = high; + changed = true; + } + + if(fStartLow == null || !low.equals(fStartLow)) + { + fStartLow = low; + changed = true; + } + + if(changed) + redrawPanes(); + } + + public void setEnd(BigInteger high, BigInteger low) + { + if(high == null && low == null) + { + if(fEndHigh != null && fEndLow != null) + { + fEndHigh = null; + fEndLow = null; + redrawPanes(); + } + + return; + } + + boolean changed = false; + + if(fEndHigh == null || !high.equals(fEndHigh)) + { + fEndHigh = high; + changed = true; + } + + if(fEndLow == null || !low.equals(fEndLow)) + { + fEndLow = low; + changed = true; + } + + if(changed) + redrawPanes(); + } + + public BigInteger getHigh() + { + if(!hasSelection()) + return null; + + return getStart().max(getEnd()); + } + + public BigInteger getLow() + { + if(!hasSelection()) + return null; + + return getStart().min(getEnd()); + } + + public BigInteger getStart() + { + // if there is no start, return null + if(fStartHigh == null) + return null; + + // if there is no end, return the high address of the start + if(fEndHigh == null) + return fStartHigh; + + // if Start High/Low equal End High/Low, return a low start and high end + if(fStartHigh.equals(fEndHigh) + && fStartLow.equals(fEndLow)) + return fStartLow; + + BigInteger differenceEndToStartHigh = fEndHigh.subtract(fStartHigh).abs(); + BigInteger differenceEndToStartLow = fEndHigh.subtract(fStartLow).abs(); + + // return the start high or start low based on which creates a larger selection + if(differenceEndToStartHigh.compareTo(differenceEndToStartLow) > 0) + return fStartHigh; + else + return fStartLow; + } + + public BigInteger getStartLow() { + return fStartLow; + } + + public BigInteger getEnd() + { + // if there is no end, return null + if(fEndHigh == null) + return null; + + // if Start High/Low equal End High/Low, return a low start and high end + if(fStartHigh.equals(fEndHigh) + && fStartLow.equals(fEndLow)) + return fStartHigh; + + BigInteger differenceStartToEndHigh = fStartHigh.subtract(fEndHigh).abs(); + BigInteger differenceStartToEndLow = fStartHigh.subtract(fEndLow).abs(); + + // return the start high or start low based on which creates a larger selection + if(differenceStartToEndHigh.compareTo(differenceStartToEndLow) >= 0) + return fEndHigh; + else + return fEndLow; + } + } + + public void setPaneVisible(int pane, boolean visible) + { + switch(pane) + { + case PANE_ADDRESS: + fAddressPane.setPaneVisible(visible); + break; + case PANE_BINARY: + fBinaryPane.setPaneVisible(visible); + break; + case PANE_TEXT: + fTextPane.setPaneVisible(visible); + break; + } + + fireSettingsChanged(); + layoutPanes(); + } + + public boolean getPaneVisible(int pane) + { + switch(pane) + { + case PANE_ADDRESS: + return fAddressPane.isPaneVisible(); + case PANE_BINARY: + return fBinaryPane.isPaneVisible(); + case PANE_TEXT: + return fTextPane.isPaneVisible(); + default: + return false; + } + } + + protected void packColumns() + { + int availableWidth = Rendering.this.getSize().x; + + if(fAddressPane.isPaneVisible()) + { + availableWidth -= fAddressPane.computeSize(0, 0).x; + availableWidth -= Rendering.this.getRenderSpacing() * 2; + } + + int combinedWidth = 0; + + if(fBinaryPane.isPaneVisible()) + combinedWidth += fBinaryPane.getCellWidth(); + + if(fTextPane.isPaneVisible()) + combinedWidth += fTextPane.getCellWidth(); + + if(getColumnsSetting() == Rendering.COLUMNS_AUTO_SIZE_TO_FIT) + { + if(combinedWidth == 0) + fColumnCount = 0; + else + { + fColumnCount = availableWidth / combinedWidth; + if(fColumnCount == 0) + fColumnCount = 1; // paint one column even if only part can show in view + } + } + else + { + fColumnCount = getColumnsSetting(); + } + + try + { + // Update the number of bytes per row; + // the max and min scroll range and the current thumb nail position. + fBytesPerRow = getBytesPerColumn() * getColumnCount(); + BigInteger difference = getMemoryBlockEndAddress().subtract(getMemoryBlockStartAddress()).add(BigInteger.ONE); + BigInteger maxScrollRange = difference.divide(BigInteger.valueOf(getAddressableCellsPerRow())); + if(maxScrollRange.multiply(BigInteger.valueOf(getAddressableCellsPerRow())).compareTo(difference) != 0) + maxScrollRange = maxScrollRange.add(BigInteger.ONE); + + // support targets with an addressable size greater than 1 + maxScrollRange = maxScrollRange.divide(BigInteger.valueOf(getAddressableSize())); + + getVerticalBar().setMinimum(1); + getVerticalBar().setMaximum(maxScrollRange.intValue()); + getVerticalBar().setIncrement(1); + getVerticalBar().setPageIncrement(this.getRowCount() -1); + //TW FIXME conversion of slider to scrollbar + // fScrollBar.setToolTipText(Rendering.this.getAddressString(fViewportAddress)); + setCurrentScrollSelection(); + } + catch(Exception e) + { + // FIXME precautionary + } + + Rendering.this.redraw(); + Rendering.this.redrawPanes(); + } + + public AbstractPane[] getRenderingPanes() + { + return new AbstractPane[] { fAddressPane, fBinaryPane, + fTextPane }; + } + + public int getCellPadding() + { + return fCellPadding; + } + + protected int getRenderSpacing() + { + return fPaneSpacing; + } + + public void refresh() + { + if(!this.isDisposed()) + { + if(this.isVisible() && getViewportCache() != null) + { + getViewportCache().refresh(); + } + else + { + setDirty(true); + fParent.updateRenderingLabels(); + } + } + } + + protected void archiveDeltas() + { + this.getViewportCache().archiveDeltas(); + } + + public void gotoAddress(BigInteger address) + { + // Ensure that the GoTo address is within the addressable range + if((address.compareTo(this.getMemoryBlockStartAddress())< 0) || + (address.compareTo(this.getMemoryBlockEndAddress()) > 0)) + { + return; + } + + fViewportAddress = address; // TODO update fCaretAddress + redrawPanes(); + } + + public void setViewportStartAddress(BigInteger newAddress) + { + fViewportAddress = newAddress; + } + + public BigInteger getViewportStartAddress() + { + return fViewportAddress; + } + + public BigInteger getViewportEndAddress() + { + return fViewportAddress.add(BigInteger.valueOf(this.getBytesPerRow() * getRowCount() / getAddressableSize())); + } + + public String getAddressString(BigInteger address) + { + StringBuffer addressString = new StringBuffer(address.toString(16) + .toUpperCase()); + for(int chars = getAddressBytes() * 2 - addressString.length(); chars > 0; chars--) + { + addressString.insert(0, '0'); + } + addressString.insert(0, "0x"); //$NON-NLS-1$ + + return addressString.toString(); + } + + protected int getAddressBytes() + { + return fParent.getAddressSize(); + } + + public int getColumnCount() + { + return fColumnCount; + } + + public int getColumnsSetting() + { + return fColumnsSetting; + } + + public void setColumnsSetting(int columns) + { + if(fColumnsSetting != columns) + { + fColumnsSetting = columns; + fireSettingsChanged(); + layoutPanes(); + } + } + + protected void ensureVisible(BigInteger address) + { + BigInteger viewportStart = this.getViewportStartAddress(); + BigInteger viewportEnd = this.getViewportEndAddress(); + + boolean isAddressBeforeViewportStart = address.compareTo(viewportStart) < 0; + boolean isAddressAfterViewportEnd = address.compareTo(viewportEnd) > 0; + + if(isAddressBeforeViewportStart || isAddressAfterViewportEnd) + gotoAddress(address); + } + + protected int getRowCount() + { + int rowCount = 0; + Control panes[] = getRenderingPanes(); + for(int i = 0; i < panes.length; i++) + { + if(panes[i] instanceof AbstractPane) + rowCount = Math.max(rowCount, + ((AbstractPane) panes[i]).getRowCount()); + } + + return rowCount; + } + + public int getBytesPerColumn() + { + return fBytesPerColumn; + } + + protected int getBytesPerRow() + { + return fBytesPerRow; + } + + protected int getAddressableCellsPerRow() + { + return getBytesPerRow() / getAddressableSize(); + } + + public int getAddressesPerColumn() + { + return this.getBytesPerColumn() / getAddressableSize(); + } + + /** + * @return Set current scroll selection + */ + protected void setCurrentScrollSelection() + { + BigInteger selection = getViewportStartAddress().divide( + BigInteger.valueOf(getAddressableCellsPerRow()).add(BigInteger.ONE)); + getVerticalBar().setSelection(selection.intValue()); + fCurrentScrollSelection = selection.intValue(); + } + + /** + * @return start address of the memory block + */ + protected BigInteger getMemoryBlockStartAddress() + { + if(fMemoryBlockStartAddress == null) + fMemoryBlockStartAddress = fParent.getMemoryBlockStartAddress(); + if(fMemoryBlockStartAddress == null) + fMemoryBlockStartAddress = BigInteger.ZERO; + + return fMemoryBlockStartAddress; + } + + /** + * @return end address of the memory block + */ + protected BigInteger getMemoryBlockEndAddress() + { + if(fMemoryBlockEndAddress == null) + fMemoryBlockEndAddress = fParent.getMemoryBlockEndAddress(); + + return fMemoryBlockEndAddress; + } + + public int getRadix() + { + return fRadix; + } + + protected int getNumericRadix(int radix) + { + switch(radix) + { + case RADIX_BINARY: + return 2; + case RADIX_OCTAL: + return 8; + case RADIX_DECIMAL_SIGNED: + case RADIX_DECIMAL_UNSIGNED: + return 10; + case RADIX_HEX: + return 16; + } + + return -1; + } + + public void setRadix(int mode) + { + if(fRadix == mode) + return; + + fRadix = mode; + fireSettingsChanged(); + layoutPanes(); + } + + public void setTextMode(int mode) + { + fTextMode = mode; + + fireSettingsChanged(); + layoutPanes(); + } + + public int getTextMode() + { + return fTextMode; + } + + protected String getCharacterSet(int mode) + { + switch(mode) + { + case Rendering.TEXT_UTF8: + return "UTF8"; + case Rendering.TEXT_UTF16: + return "UTF16"; + case Rendering.TEXT_USASCII: + return "US-ASCII"; + case Rendering.TEXT_ISO_8859_1: + default: + return "ISO-8859-1"; + } + } + + public int getBytesPerCharacter() + { + if(fTextMode == Rendering.TEXT_UTF16) + return 2; + + return 1; + } + + public boolean isTargetLittleEndian() + { + return fIsTargetLittleEndian; + } + + public void setTargetLittleEndian(boolean littleEndian) + { + if(fIsTargetLittleEndian == littleEndian) + return; + + fParent.setTargetMemoryLittleEndian(littleEndian); + fIsTargetLittleEndian = littleEndian; + Display.getDefault().asyncExec(new Runnable() { + public void run() + { + fireSettingsChanged(); + layoutPanes(); + } + }); + } + + public boolean isDisplayLittleEndian() + { + return fIsDisplayLittleEndian; + } + + public void setDisplayLittleEndian(boolean littleEndian) + { + if(fIsDisplayLittleEndian = littleEndian) + return; + + fIsDisplayLittleEndian = littleEndian; + + fireSettingsChanged(); + Display.getDefault().asyncExec(new Runnable(){ + public void run() + { + layoutPanes(); + } + }); + } + + public void setBytesPerColumn(int byteCount) + { + if(fBytesPerColumn != byteCount) + { + fBytesPerColumn = byteCount; + fireSettingsChanged(); + layoutPanes(); + } + } + + protected void redrawPane(int paneId) + { + if(!isDisposed() && this.isVisible()) + { + AbstractPane pane = null; + if(paneId == Rendering.PANE_ADDRESS) + { + pane = fAddressPane; + } + else if(paneId == Rendering.PANE_BINARY) + { + pane = fBinaryPane; + } + if(paneId == Rendering.PANE_TEXT) + { + pane = fTextPane; + } + if(pane != null && pane.isPaneVisible()) + { + pane.redraw(); + pane.setRowCount(); + if(pane.isFocusControl()) + pane.updateCaret(); + } + + } + + fParent.updateRenderingLabels(); + } + + protected void redrawPanes() + { + if(!isDisposed() && this.isVisible()) + { + if(fAddressPane.isPaneVisible()) + { + fAddressPane.redraw(); + fAddressPane.setRowCount(); + if(fAddressPane.isFocusControl()) + fAddressPane.updateCaret(); + } + + if(fBinaryPane.isPaneVisible()) + { + fBinaryPane.redraw(); + fBinaryPane.setRowCount(); + if(fBinaryPane.isFocusControl()) + fBinaryPane.updateCaret(); + } + + if(fTextPane.isPaneVisible()) + { + fTextPane.redraw(); + fTextPane.setRowCount(); + if(fTextPane.isFocusControl()) + fTextPane.updateCaret(); + } + } + + fParent.updateRenderingLabels(); + } + + private void layoutPanes() + { + packColumns(); + layout(true); + + redraw(); + redrawPanes(); + } + + private void fireSettingsChanged() + { + fAddressPane.settingsChanged(); + fBinaryPane.settingsChanged(); + fTextPane.settingsChanged(); + } + + protected void copyAddressToClipboard() + { + Clipboard clip = null; + try + { + clip = new Clipboard(getDisplay()); + + String addressString = "0x" + getCaretAddress().toString(16); + + TextTransfer plainTextTransfer = TextTransfer.getInstance(); + clip.setContents(new Object[] { addressString }, + new Transfer[] { plainTextTransfer }); + } + finally + { + if(clip != null) + { + clip.dispose(); + } + } + } + + static final char[] hexdigits = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + public String getRadixText(MemoryByte bytes[], int radix, + boolean isLittleEndian) + { + boolean readable = true; + for(int i = 0; i < bytes.length; i++) + if(!bytes[i].isReadable()) + readable = false; + + if(readable) + { + // bytes from the cache are stored as a sequential byte sequence regardless of target endian. + // the endian attribute tells us the recommended endian for display. the user may change this + // from the default. if the endian is little, we must swap the byte order. + boolean needsSwap = false; + if(isDisplayLittleEndian()) + needsSwap = true; + + switch(radix) + { + case Rendering.RADIX_HEX: + case Rendering.RADIX_OCTAL: + case Rendering.RADIX_BINARY: + { + long value = 0; + if(needsSwap) + { + for(int i = 0; i < bytes.length; i++) + { + value = value << 8; + value = value + | (bytes[bytes.length - 1 - i].getValue() & 0xFF); + } + } + else + { + for(int i = 0; i < bytes.length; i++) + { + value = value << 8; + value = value | (bytes[i].getValue() & 0xFF); + } + } + + char buf[] = new char[getRadixCharacterCount(radix, + bytes.length)]; + + switch(radix) + { + case Rendering.RADIX_BINARY: + { + for(int i = buf.length - 1; i >= 0; i--) + { + buf[i] = hexdigits[(int) (value & 1)]; + value = value >>> 1; + } + break; + } + case Rendering.RADIX_OCTAL: + { + for(int i = buf.length - 1; i >= 0; i--) + { + buf[i] = hexdigits[(int) (value & 7)]; + value = value >>> 3; + } + break; + } + case Rendering.RADIX_HEX: + { + for(int i = buf.length - 1; i >= 0; i--) + { + buf[i] = hexdigits[(int) (value & 15)]; + value = value >>> 4; + } + break; + } + } + + return new String(buf); + } + case Rendering.RADIX_DECIMAL_UNSIGNED: + case Rendering.RADIX_DECIMAL_SIGNED: + { + boolean isSignedType = radix == Rendering.RADIX_DECIMAL_SIGNED ? true + : false; + + int textWidth = getRadixCharacterCount(radix, bytes.length); + + char buf[] = new char[textWidth]; + + byte[] value = new byte[bytes.length + 1]; + + if(needsSwap) + { + for(int i = 0; i < bytes.length; i++) + { + value[bytes.length - i] = bytes[i].getValue(); + } + } + else + { + for(int i = 0; i < bytes.length; i++) + { + value[i + 1] = bytes[i].getValue(); + } + } + + BigInteger bigValue; + boolean isNegative = false; + if(isSignedType && (value[1] & 0x80) != 0) + { + value[0] = -1; + isNegative = true; + bigValue = new BigInteger(value).abs(); + } + else + { + value[0] = 0; + bigValue = new BigInteger(value); + } + + for(int i = 0; i < textWidth; i++) + { + BigInteger divideRemainder[] = bigValue.divideAndRemainder( + BigInteger.valueOf(10)); + int remainder = divideRemainder[1].intValue(); + buf[textWidth - 1 - i] = hexdigits[remainder % 10]; + bigValue = divideRemainder[0]; + } + + if(isSignedType) + { + buf[0] = isNegative ? '-' : ' '; + } + + return new String(buf); + } + } + } + + StringBuffer errorText = new StringBuffer(); + for(int i = getRadixCharacterCount(radix, bytes.length); i > 0; i--) + errorText.append(getPaddingCharacter()); + + return errorText.toString(); + } + + public int getRadixCharacterCount(int radix, int bytes) + { + switch(radix) + { + case Rendering.RADIX_HEX: + return bytes * 2; + case Rendering.RADIX_BINARY: + return bytes * 8; + case Rendering.RADIX_OCTAL: + { + switch(bytes) + { + case 1: + return 3; + case 2: + return 6; + case 4: + return 11; + case 8: + return 22; + } + } + case Rendering.RADIX_DECIMAL_UNSIGNED: + { + switch(bytes) + { + case 1: + return 3; + case 2: + return 5; + case 4: + return 10; + case 8: + return 20; + } + } + case Rendering.RADIX_DECIMAL_SIGNED: + { + switch(bytes) + { + case 1: + return 4; + case 2: + return 6; + case 4: + return 11; + case 8: + return 21; + } + } + } + + return 0; + } + + protected static boolean isValidEditCharacter(char character) + { + return (character >= '0' && character <= '9') + || (character >= 'a' && character <= 'z') + || (character >= 'A' && character <= 'Z') || character == '-' + || character == ' '; + } + + public String formatText(MemoryByte[] memoryBytes, + boolean isLittleEndian, int textMode) + { + // check memory byte for unreadable bytes + boolean readable = true; + for(int i = 0; i < memoryBytes.length; i++) + if(!memoryBytes[i].isReadable()) + readable = false; + + // if any bytes are not readable, return ?'s + if(!readable) + { + StringBuffer errorText = new StringBuffer(); + for(int i = memoryBytes.length; i > 0; i--) + errorText.append(getPaddingCharacter()); + return errorText.toString(); + } + + // TODO + // does endian mean anything for text? ah, unicode? + + // create byte array from MemoryByte array + byte bytes[] = new byte[memoryBytes.length]; + for(int i = 0; i < bytes.length; i++) + { + bytes[i] = memoryBytes[i].getValue(); + } + + // replace invalid characters with '.' + // maybe there is a way to query the character set for + // valid characters? + + // replace invalid US-ASCII with '.' + if(textMode == Rendering.TEXT_USASCII) + { + for(int i = 0; i < bytes.length; i++) + { + int byteValue = bytes[i]; + if(byteValue < 0) + byteValue += 256; + + if(byteValue < 0x20 || byteValue > 0x7e) + bytes[i] = '.'; + } + } + + // replace invalid ISO-8859-1 with '.' + if(textMode == Rendering.TEXT_ISO_8859_1) + { + for(int i = 0; i < bytes.length; i++) + { + int byteValue = bytes[i]; + if(byteValue < 0) + byteValue += 256; + + if(byteValue < 0x20 || + (byteValue >= 0x7f && byteValue < 0x9f)) + bytes[i] = '.'; + } + } + + try + { + // convert bytes to string using desired character set + StringBuffer buf = new StringBuffer(new String(bytes, this.getCharacterSet(textMode))); + + // pad string to (byte count - string length) with spaces + for(int i = 0; i < memoryBytes.length - buf.length(); i++) + buf.append(' '); + return buf.toString(); + } + catch(Exception e) + { + // return ?s the length of byte count + StringBuffer buf = new StringBuffer(); + for(int i = 0; i < memoryBytes.length - buf.length(); i++) + buf.append(getPaddingCharacter()); + return buf.toString(); + } + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TextPane.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TextPane.java new file mode 100644 index 00000000000..5b4bbe2253b --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TextPane.java @@ -0,0 +1,326 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.math.BigInteger; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; + +public class TextPane extends AbstractPane +{ + public TextPane(Rendering parent) + { + super(parent); + } + + protected int getCellCharacterCount() + { + return fRendering.getBytesPerColumn() + / fRendering.getBytesPerCharacter(); + } + + protected String getCellText(MemoryByte bytes[]) + { + return fRendering.formatText(bytes, fRendering + .isTargetLittleEndian(), fRendering.getTextMode()); + } + + protected void editCell(BigInteger address, int subCellPosition, + char character) + { + try + { + MemoryByte bytes[] = fRendering.getBytes(fCaretAddress, fRendering + .getBytesPerColumn()); + + String cellText = getCellText(bytes); + if(cellText == null) + return; + + StringBuffer cellTextBuffer = new StringBuffer(cellText); + cellTextBuffer.setCharAt(subCellPosition, character); + + byte byteData[] = cellTextBuffer.toString().getBytes(fRendering.getCharacterSet(fRendering.getTextMode())); + if(byteData.length != bytes.length) + return; + + TraditionalMemoryByte bytesToSet[] = new TraditionalMemoryByte[bytes.length]; + + for(int i = 0; i < byteData.length; i++) + { + bytesToSet[i] = new TraditionalMemoryByte(byteData[i]); + + if(bytes[i].getValue() != byteData[i]) + { + bytesToSet[i].setEdited(true); + } + else + { + bytesToSet[i].setChanged(bytes[i].isChanged()); + } + } + + fRendering.getViewportCache().setEditedValue(address, bytesToSet); + + advanceCursor(); + + redraw(); + } + catch(Exception e) + { + // this is ok + } + } + + protected int getCellWidth() + { + GC gc = new GC(this); + gc.setFont(fRendering.getFont()); + int width = gc.getAdvanceWidth('F'); + gc.dispose(); + + return fRendering.getBytesPerColumn() + / fRendering.getBytesPerCharacter() * width; + } + + public Point computeSize(int wHint, int hHint) + { + return new Point(fRendering.getColumnCount() * getCellWidth() + + fRendering.getRenderSpacing(), 100); + + } + + protected Point getCellLocation(BigInteger cellAddress) + { + try + { + BigInteger address = fRendering.getViewportStartAddress(); + + int cellOffset = cellAddress.subtract(address).intValue(); + cellOffset *= fRendering.getAddressableSize(); + + int row = cellOffset + / (fRendering.getColumnCount() * fRendering.getBytesPerColumn() / fRendering + .getBytesPerCharacter()); + cellOffset -= row * fRendering.getColumnCount() + * fRendering.getBytesPerColumn() + / fRendering.getBytesPerCharacter(); + + int col = cellOffset / fRendering.getBytesPerColumn() + / fRendering.getBytesPerCharacter(); + + int x = col * getCellWidth() + fRendering.getCellPadding(); + int y = row * getCellHeight() + fRendering.getCellPadding(); + + return new Point(x, y); + } + catch(Exception e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_DETERMINE_CELL_LOCATION"), e); //$NON-NLS-1$ + return null; + } + } + + private BigInteger getCellAddressAt(int x, int y) throws DebugException + { + BigInteger address = fRendering.getViewportStartAddress(); + + int col = x / getCellWidth(); + int row = y / getCellHeight(); + + if(col >= fRendering.getColumnCount()) + return null; + + address = address.add(BigInteger.valueOf(row + * fRendering.getColumnCount() * fRendering.getAddressesPerColumn() + / fRendering.getBytesPerCharacter())); + + address = address.add(BigInteger.valueOf(col + * fRendering.getAddressesPerColumn())); + + return address; + } + + protected void positionCaret(int x, int y) + { + try + { + BigInteger cellAddress = getCellAddressAt(x, y); + + if(cellAddress != null) + { + Point cellPosition = getCellLocation(cellAddress); + + int offset = x - cellPosition.x; + int x2 = offset / getCellCharacterWidth(); + + if(x2 == this.getCellCharacterCount()) + { + cellAddress = cellAddress.add(BigInteger.valueOf(fRendering + .getAddressesPerColumn())); + x2 = 0; + cellPosition = getCellLocation(cellAddress); + } + + fCaret.setLocation(cellPosition.x + x2 + * getCellCharacterWidth(), cellPosition.y); + + this.fCaretAddress = cellAddress; + this.fSubCellCaretPosition = x2; + setCaretAddress(fCaretAddress); + } + } + catch(Exception e) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_POSITION_CURSOR"), e); //$NON-NLS-1$ + } + } + + protected BigInteger getViewportAddress(int col, int row) + throws DebugException + { + BigInteger address = fRendering.getViewportStartAddress(); + address = address.add(BigInteger.valueOf((row + * fRendering.getColumnCount() + col) + * fRendering.getAddressesPerColumn() + / fRendering.getBytesPerCharacter())); + + return address; + } + + protected void paint(PaintEvent pe) + { + super.paint(pe); + + GC gc = pe.gc; + gc.setFont(fRendering.getFont()); + + int cellHeight = getCellHeight(); + int cellWidth = getCellWidth(); + + final int columns = fRendering.getColumnCount(); + + final boolean isLittleEndian = fRendering.isTargetLittleEndian(); + + gc.setForeground(fRendering.getTraditionalRendering().getColorBackground()); + gc.fillRectangle(columns * cellWidth, 0, this.getBounds().width, this + .getBounds().height); + + try + { + BigInteger start = fRendering.getViewportStartAddress(); + + for(int i = 0; i < this.getBounds().height / cellHeight; i++) + { + for(int col = 0; col < columns; col++) + { + if(isOdd(col)) + gc.setForeground(fRendering.getTraditionalRendering().getColorText()); + else + gc.setForeground(fRendering.getTraditionalRendering().getColorTextAlternate()); + + BigInteger cellAddress = start.add(BigInteger.valueOf((i + * columns + col) + * fRendering.getAddressesPerColumn())); + + TraditionalMemoryByte bytes[] = fRendering.getBytes(cellAddress, + fRendering.getBytesPerColumn()); + + if(fRendering.getSelection().isSelected(cellAddress)) + { + gc.setBackground(fRendering.getTraditionalRendering().getColorSelection()); + gc.fillRectangle(cellWidth * col, cellHeight * i, + cellWidth, cellHeight); + + gc.setForeground(fRendering.getTraditionalRendering().getColorBackground()); + } + else + { + gc.setBackground(fRendering.getTraditionalRendering().getColorBackground()); + gc.fillRectangle(cellWidth * col, cellHeight * i, + cellWidth, cellHeight); + + applyCustomColor(gc, bytes, col); + } + + gc.drawText(fRendering.formatText(bytes, + isLittleEndian, fRendering.getTextMode()), cellWidth * col, cellHeight * i + + fRendering.getCellPadding()); + + if(fRendering.isDebug()) + gc.drawRectangle(cellWidth * col, cellHeight * i + + fRendering.getCellPadding(), cellWidth, + cellHeight); + } + } + } + catch(Exception e) + { + fRendering.logError(TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_PAINT"), e); //$NON-NLS-1$ + } + + } + + // Allow subclasses to override this method to do their own coloring + protected void applyCustomColor(GC gc, TraditionalMemoryByte bytes[], int col) + { + // TODO consider adding finer granularity? + boolean anyByteEditing = false; + for(int n = 0; n < bytes.length && !anyByteEditing; n++) + if(bytes[n] instanceof TraditionalMemoryByte) + if(((TraditionalMemoryByte) bytes[n]).isEdited()) + anyByteEditing = true; + + if(isOdd(col)) + gc.setForeground(fRendering.getTraditionalRendering().getColorText()); + else + gc.setForeground(fRendering.getTraditionalRendering().getColorTextAlternate()); + gc.setBackground(fRendering.getTraditionalRendering().getColorBackground()); + + if(anyByteEditing) + { + gc.setForeground(fRendering.getTraditionalRendering().getColorEdit()); + } + else + { + boolean isColored = false; + for(int i = 0; i < fRendering.getHistoryDepth() && !isColored; i++) + { + // TODO consider adding finer granularity? + for(int n = 0; n < bytes.length; n++) + { + if(bytes[n].isChanged(i)) + { + if(i == 0) + gc.setForeground(fRendering.getTraditionalRendering().getColorsChanged()[i]); + else + gc.setBackground(fRendering.getTraditionalRendering().getColorsChanged()[i]); + isColored = true; + break; + } + } + } + + } + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalGoToAddressRendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalGoToAddressRendering.java new file mode 100644 index 00000000000..e9ef9bb4941 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalGoToAddressRendering.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.math.BigInteger; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension; +import org.eclipse.debug.internal.ui.DebugUIMessages; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil; +import org.eclipse.debug.internal.ui.views.memory.RenderingViewPane; +import org.eclipse.debug.internal.ui.views.memory.renderings.CreateRendering; +import org.eclipse.debug.ui.memory.AbstractMemoryRendering; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; +import org.eclipse.debug.ui.memory.IMemoryRenderingSite; +import org.eclipse.debug.ui.memory.IRepositionableMemoryRendering; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; + +public class TraditionalGoToAddressRendering extends AbstractMemoryRendering { + + private IMemoryRenderingSite fSite; + private IMemoryRenderingContainer fContainer; + + @Override + public void init(IMemoryRenderingContainer container, IMemoryBlock block) { + super.init(container, block); + fSite = container.getMemoryRenderingSite(); + fContainer = container; + } + + public TraditionalGoToAddressRendering(String renderingId) { + super(renderingId); + } + + private Control fControl; + + public Control createControl(Composite parent) { + + Composite fGotoAddressContainer = parent; + + final GoToAddressWidget fGotoAddress = new GoToAddressWidget(); + Control fGotoAddressControl = fGotoAddress.createControl(fGotoAddressContainer); + + fControl = fGotoAddressControl; + + final Runnable goHandler = new Runnable() + { + public void run() + { + go(fGotoAddress.getExpressionText(), false); + } + }; + + Button button = fGotoAddress.getButton(IDialogConstants.OK_ID); + if (button != null) + { + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + goHandler.run(); + } + }); + } + + button = fGotoAddress.getButton(GoToAddressWidget.ID_GO_NEW_TAB); + if (button != null) + { + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + go(fGotoAddress.getExpressionText(), true); + } + }); + } + + fGotoAddress.getExpressionWidget().addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.CR) + goHandler.run(); + super.keyPressed(e); + } + }); + + + return fControl; + } + + public Control getControl() { + return fControl; + } + + private void go(final String expression, final boolean inNewTab) + { + IMemoryRenderingContainer containers[] = fSite.getMemoryRenderingContainers(); + for(int i = 0; i < containers.length; i++) + { + if(containers[i] instanceof RenderingViewPane) + { + final IMemoryRenderingContainer container = containers[i]; + if(containers[i] != null) + { + final IMemoryRendering activeRendering = containers[i].getActiveRendering(); + if(activeRendering != null) + { + new Thread() { + public void run() + { + IMemoryBlock activeMemoryBlock = activeRendering.getMemoryBlock(); + IMemoryBlockExtension blockExtension = (IMemoryBlockExtension) activeMemoryBlock.getAdapter(IMemoryBlockExtension.class); + + if(inNewTab) + { + try { + final IMemoryRendering rendering = new CreateRendering(container); + IMemoryBlock newBlock = null; + if(activeMemoryBlock.getDebugTarget() instanceof IMemoryBlockRetrievalExtension) + { + newBlock = ((IMemoryBlockRetrievalExtension) activeMemoryBlock.getDebugTarget()) + .getExtendedMemoryBlock(expression, activeMemoryBlock.getDebugTarget()); + + } + else + { + BigInteger newAddress; + if(expression.toUpperCase().startsWith("0X")) + newAddress = new BigInteger(expression.substring(2), 16); + else + newAddress = new BigInteger(expression, 16); + + newBlock = activeMemoryBlock.getDebugTarget().getMemoryBlock(newAddress.longValue(), + activeMemoryBlock.getLength()); + } + + final IMemoryBlock finalNewBlock = newBlock; + Display.getDefault().asyncExec(new Runnable(){ + public void run() + { + rendering.init(container, finalNewBlock); + container.addMemoryRendering(rendering); + } + }); + + } catch (DebugException e) { + MemoryViewUtil.openError(DebugUIMessages.GoToAddressAction_Go_to_address_failed, + DebugUIMessages.GoToAddressAction_Address_is_invalid, e); + } + } + else if(activeRendering instanceof IRepositionableMemoryRendering) + { + try + { + if(activeMemoryBlock.getDebugTarget() instanceof IMemoryBlockRetrievalExtension) + { + IMemoryBlockExtension resolveExpressionBlock = ((IMemoryBlockRetrievalExtension) activeMemoryBlock.getDebugTarget()) + .getExtendedMemoryBlock(expression, activeMemoryBlock.getDebugTarget()); + ((IRepositionableMemoryRendering) activeRendering).goToAddress(resolveExpressionBlock.getBigBaseAddress()); + } + else + { + BigInteger newAddress; + if(expression.toUpperCase().startsWith("0X")) + newAddress = new BigInteger(expression.substring(2), 16); + else + newAddress = new BigInteger(expression, 16); + + ((IRepositionableMemoryRendering) activeRendering).goToAddress(newAddress); + } + } + catch(DebugException de) + { + MemoryViewUtil.openError(DebugUIMessages.GoToAddressAction_Go_to_address_failed, + DebugUIMessages.GoToAddressAction_Address_is_invalid, de); + } + } + + } + }.start(); + } + } + } + } + } +} + +class GoToAddressWidget { + + private Text fExpression; + private Button fOKButton; + private Button fOKNewTabButton; + private Composite fComposite; + + protected static int ID_GO_NEW_TAB = 2000; + + /** + * @param parent + * @return + */ + public Control createControl(Composite parent) + { + fComposite = new Composite(parent, SWT.NONE); + PlatformUI.getWorkbench().getHelpSystem().setHelp(fComposite, DebugUIPlugin.getUniqueIdentifier() + ".GoToAddressComposite_context"); //$NON-NLS-1$ + GridLayout layout = new GridLayout(); + layout.numColumns = 6; + layout.makeColumnsEqualWidth = false; + layout.marginHeight = 0; + layout.marginLeft = 0; + fComposite.setLayout(layout); + + fExpression = new Text(fComposite, SWT.SINGLE | SWT.BORDER); + fExpression.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + fOKButton = new Button(fComposite, SWT.NONE); + fOKButton.setText("Go"); + +// fOKNewTabButton = new Button(fComposite, SWT.NONE); +// fOKNewTabButton.setText("New Tab"); + + return fComposite; + } + + public int getHeight() + { + int height = fComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y; + return height; + } + + public Button getButton(int id) + { + if (id == IDialogConstants.OK_ID) + return fOKButton; + if (id == ID_GO_NEW_TAB) + return fOKNewTabButton; + return null; + } + + public String getExpressionText() + { + return fExpression.getText().trim(); + } + + public Text getExpressionWidget() + { + return fExpression; + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalGoToAddressRenderingTypeDelegate.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalGoToAddressRenderingTypeDelegate.java new file mode 100644 index 00000000000..1e1bd4a2c87 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalGoToAddressRenderingTypeDelegate.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.debug.ui.memory.IMemoryRenderingTypeDelegate; + +public class TraditionalGoToAddressRenderingTypeDelegate + implements IMemoryRenderingTypeDelegate +{ + + public IMemoryRendering createRendering(String id) throws CoreException { + return new TraditionalGoToAddressRendering(id); + } + + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java new file mode 100644 index 00000000000..f9c1b0d7071 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java @@ -0,0 +1,1494 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigInteger; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.core.model.IMemoryBlockRetrieval; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.debug.internal.ui.DebugPluginImages; +import org.eclipse.debug.internal.ui.DebugUIMessages; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; +import org.eclipse.debug.internal.ui.memory.IMemoryBlockConnection; +import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil; +import org.eclipse.debug.internal.ui.views.memory.renderings.GoToAddressAction; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.memory.AbstractMemoryRendering; +import org.eclipse.debug.ui.memory.AbstractTableRendering; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; +import org.eclipse.debug.ui.memory.IRepositionableMemoryRendering; +import org.eclipse.debug.ui.memory.IResettableMemoryRendering; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.IBasicPropertyConstants; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.ui.progress.UIJob; + +/** + * A memory rendering displaying memory in a traditional + * memory view look and feel, optimized for minimal IO traffic. + *

+ * requirements of the debug model implementation: + * - An IMemoryBlockExtension is required. + * + * Since it is not possible to size the memory block to match + * the size of the viewport, memory block change notification + * is not useful. Such events are ignored by this rendering. + */ + +public class TraditionalRendering extends AbstractMemoryRendering implements IRepositionableMemoryRendering, IResettableMemoryRendering +{ + protected Rendering fRendering; + protected Action displayEndianBigAction; + protected Action displayEndianLittleAction; + + private IWorkbenchAdapter fWorkbenchAdapter; + private IMemoryBlockConnection fConnection; + + private final static int MAX_MENU_COLUMN_COUNT = 8; + + public TraditionalRendering(String id) + { + super(id); + + JFaceResources.getFontRegistry().addListener( + new IPropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent event) + { + if(event.getProperty().equals( + IInternalDebugUIConstants.FONT_NAME)) + { + TraditionalRendering.this.fRendering + .handleFontPreferenceChange(JFaceResources + .getFont(IInternalDebugUIConstants.FONT_NAME)); + } + } + }); + + this.addPropertyChangeListener(new IPropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent event) + { + IMemoryRendering sourceRendering = (IMemoryRendering) event + .getSource(); + if(!sourceRendering.getMemoryBlock().equals(getMemoryBlock())) + return; + + Object address = event.getNewValue(); + + if(event.getProperty().equals( + AbstractTableRendering.PROPERTY_SELECTED_ADDRESS) + && address instanceof BigInteger) + { + TraditionalRendering.this.fRendering + .ensureVisible((BigInteger) address); + } + } + }); + + TraditionalRenderingPlugin.getDefault().getPreferenceStore().addPropertyChangeListener( + new IPropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent event) + { + disposeColors(); + allocateColors(); + applyPreferences(); + } + }); + + + DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener( + new IPropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent event) + { + if(event.getProperty().equals(IDebugUIConstants.PREF_PADDED_STR)) + { + if(TraditionalRendering.this.fRendering != null) + { + setRenderingPadding((String) event.getNewValue()); + TraditionalRendering.this.fRendering.redrawPanes(); + } + } + } + }); + + } + + private void setRenderingPadding(String padding) + { + if(padding == null || padding.length() == 0) + padding = "?"; + TraditionalRendering.this.fRendering.setPaddingString(padding); + } + + protected void logError(String message, Exception e) + { + Status status = new Status(IStatus.ERROR, getRenderingId(), + DebugException.INTERNAL_ERROR, message, e); + + DebugUIPlugin.getDefault().getLog().log(status); + } + + private BigInteger fBigBaseAddress; + private BigInteger fStartAddress; + private BigInteger fEndAddress; + private int fAddressableSize; + private int fAddressSize; + + public void init(IMemoryRenderingContainer container, IMemoryBlock block) + { + super.init(container, block); + + try + { + fBigBaseAddress = ((IMemoryBlockExtension) block).getBigBaseAddress(); + } + catch(DebugException de) + { + logError(TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_RETRIEVE_BASE_ADDRESS"), de); //$NON-NLS-1$ // FIXME + } + + try + { + fAddressableSize = ((IMemoryBlockExtension) block).getAddressableSize(); + } + catch(DebugException de) + { + fAddressableSize = 1; + } + + try + { + fStartAddress = ((IMemoryBlockExtension)block).getMemoryBlockStartAddress(); + } + catch (DebugException de) { + fStartAddress = null; + logError(TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_RETRIEVE_START_ADDRESS"), de); //$NON-NLS-1$ + } + + + try + { + fAddressSize = ((IMemoryBlockExtension) block).getAddressSize(); + } + catch(DebugException e) + { + fAddressSize = 0; + } + + BigInteger endAddress; + try + { + endAddress = ((IMemoryBlockExtension) block).getMemoryBlockEndAddress(); + if (endAddress != null) + fEndAddress = endAddress; + } + catch (DebugException e) + { + fEndAddress = null; + } + + if (fEndAddress == null) + { + int addressSize; + try { + addressSize = ((IMemoryBlockExtension) block).getAddressSize(); + } catch (DebugException e) { + addressSize = 4; + } + + endAddress = BigInteger.valueOf(2); + endAddress = endAddress.pow(addressSize*8); + endAddress = endAddress.subtract(BigInteger.valueOf(1)); + fEndAddress = endAddress; + } + + // default to MAX_VALUE if we have trouble getting the end address + if (fEndAddress == null) + fEndAddress = BigInteger.valueOf(Integer.MAX_VALUE); + } + + public BigInteger getBigBaseAddress() + { + return fBigBaseAddress; + } + + public BigInteger getMemoryBlockStartAddress() + { + return fStartAddress; + } + + public BigInteger getMemoryBlockEndAddress() + { + return fEndAddress; + } + + public int getAddressableSize() + { + return fAddressableSize; + } + + public int getAddressSize() + { + return fAddressSize; + } + + public Control createControl(Composite parent) + { + allocateColors(); + + this.fRendering = new Rendering(parent, this); + + applyPreferences(); + + createMenus(); + + return this.fRendering; + } + + // FIXME + private static final String ID_GO_TO_ADDRESS_COMMAND = "org.eclipse.debug.ui.command.gotoaddress"; //$NON-NLS-1$ + private AbstractHandler fGoToAddressHandler; + + public void activated() + { + super.activated(); + + IWorkbench workbench = PlatformUI.getWorkbench(); + ICommandService commandSupport = (ICommandService)workbench.getAdapter(ICommandService.class); + + if(commandSupport != null) + { + Command gotoCommand = commandSupport.getCommand(ID_GO_TO_ADDRESS_COMMAND); + + if(fGoToAddressHandler == null) + { + fGoToAddressHandler = new AbstractHandler() { + public Object execute(ExecutionEvent event) throws ExecutionException { + // TODO + return null; + } + }; + } + gotoCommand.setHandler(fGoToAddressHandler); + } + + } + + public void deactivated() + { + IWorkbench workbench = PlatformUI.getWorkbench(); + ICommandService commandSupport = (ICommandService) workbench.getAdapter(ICommandService.class); + + if(commandSupport != null) + { + // remove handler + Command command = commandSupport.getCommand(ID_GO_TO_ADDRESS_COMMAND); + command.setHandler(null); + } + + super.deactivated(); + } + + public void setSelection(BigInteger start, BigInteger end) + { + fRendering.getSelection().setStart(start, start); + fRendering.getSelection().setEnd(end, end); + } + + public void gotoAddress(final BigInteger address) + { + this.fRendering.gotoAddress(address); + } + + public void updateRenderingLabels() + { + UIJob job = new UIJob("updateLabels"){ //$NON-NLS-1$ + public IStatus runInUIThread(IProgressMonitor monitor) { + + // update tab labels + String fLabel = getLabel(); + firePropertyChangedEvent(new PropertyChangeEvent(TraditionalRendering.this, + IBasicPropertyConstants.P_TEXT, null, fLabel)); + + return Status.OK_STATUS; + }}; + job.setSystem(true); + job.schedule(); + } + + private Color colorBackground; + private Color colorChanged; + private Color colorsChanged[] = null; + private Color colorEdit; + private Color colorSelection; + private Color colorText; + private Color colorTextAlternate; + + public void allocateColors() + { + IPreferenceStore store = TraditionalRenderingPlugin.getDefault().getPreferenceStore(); + + colorBackground = new Color(Display.getDefault(), PreferenceConverter.getColor(store, + TraditionalRenderingPreferenceConstants.MEM_COLOR_BACKGROUND)); + + colorChanged = new Color(Display.getDefault(), PreferenceConverter.getColor(store, + TraditionalRenderingPreferenceConstants.MEM_COLOR_CHANGED)); + + colorEdit = new Color(Display.getDefault(), PreferenceConverter.getColor(store, + TraditionalRenderingPreferenceConstants.MEM_COLOR_EDIT)); + + colorSelection = new Color(Display.getDefault(), PreferenceConverter.getColor(store, + TraditionalRenderingPreferenceConstants.MEM_COLOR_SELECTION)); + + colorText = new Color(Display.getDefault(), PreferenceConverter.getColor(store, + TraditionalRenderingPreferenceConstants.MEM_COLOR_TEXT)); + + // alternate cell color + Color textColor = getColorText(); + int red = textColor.getRed(); + int green = textColor.getGreen(); + int blue = textColor.getBlue(); + + float scale = (float) store.getInt( + TraditionalRenderingPreferenceConstants.MEM_LIGHTEN_DARKEN_ALTERNATE_CELLS); + + red = (int) Math.min(red + ((255 - red) / 10) * scale, 255); + green = (int) Math.min(green + ((255 - green) / 10) * scale, 255); + blue = (int) Math.min(blue + ((255 - blue) / 10) * scale, 255); + + colorTextAlternate = new Color(Display.getDefault(), new RGB(red, green, blue)); + } + + public void disposeColors() + { + if(colorBackground != null) + colorBackground.dispose(); + colorBackground = null; + + if(colorChanged != null) + colorChanged.dispose(); + colorChanged = null; + + if(colorEdit != null) + colorEdit.dispose(); + colorEdit = null; + + if(colorSelection != null) + colorSelection.dispose(); + colorSelection = null; + + if(colorText != null) + colorText.dispose(); + colorText = null; + + if(colorTextAlternate != null) + colorTextAlternate.dispose(); + colorTextAlternate = null; + + disposeChangedColors(); + } + + public void applyPreferences() + { + if(!fRendering.isDisposed()) + { + IPreferenceStore store = TraditionalRenderingPlugin.getDefault().getPreferenceStore(); + + fRendering.setHistoryDepth(store.getInt(TraditionalRenderingPreferenceConstants.MEM_HISTORY_TRAILS_COUNT)); + + fRendering.setBackground(getColorBackground()); + + AbstractPane panes[] = fRendering.getRenderingPanes(); + for(int i = 0; i < panes.length; i++) + panes[i].setBackground(getColorBackground()); + + setRenderingPadding(DebugUIPlugin.getDefault().getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR)); + + fRendering.redrawPanes(); + } + } + + public Color getColorBackground() + { + IPreferenceStore store = TraditionalRenderingPlugin.getDefault().getPreferenceStore(); + + if(store.getBoolean(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_BACKGROUND)) + return Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND); + else + return colorBackground; + } + + public Color getColorChanged() + { + return colorChanged; + } + + private void disposeChangedColors() + { + if(colorsChanged != null) + for(int i = 0; i < colorsChanged.length; i++) + colorsChanged[i].dispose(); + colorsChanged = null; + } + + public Color[] getColorsChanged() + { + if(colorsChanged != null && colorsChanged.length != fRendering.getHistoryDepth()) + { + disposeChangedColors(); + } + + if(colorsChanged == null) + { + colorsChanged = new Color[fRendering.getHistoryDepth()]; + colorsChanged[0] = colorChanged; + int shades = fRendering.getHistoryDepth() + 4; + int red = (255 - colorChanged.getRed()) / shades; + int green = (255 - colorChanged.getGreen()) / shades; + int blue = (255 - colorChanged.getBlue()) / shades; + for(int i = 1; i < fRendering.getHistoryDepth(); i++) + { + colorsChanged[i] = new Color(colorChanged.getDevice(), + colorChanged.getRed() + ((shades - i) * red), + colorChanged.getGreen() + ((shades - i) * green), + colorChanged.getBlue() + ((shades - i) * blue)); + } + } + + return colorsChanged; + } + + public Color getColorEdit() + { + return colorEdit; + } + + public Color getColorSelection() + { + IPreferenceStore store = TraditionalRenderingPlugin.getDefault().getPreferenceStore(); + + if(store.getBoolean(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_SELECTION)) + return Display.getDefault().getSystemColor(SWT.COLOR_LIST_SELECTION); + else + return colorSelection; + } + + public Color getColorText() + { + IPreferenceStore store = TraditionalRenderingPlugin.getDefault().getPreferenceStore(); + + if(store.getBoolean(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_TEXT)) + return Display.getDefault().getSystemColor(SWT.COLOR_LIST_FOREGROUND); + else + return colorText; + } + + public Color getColorTextAlternate() + { + return colorTextAlternate; + } + + public void createMenus() + { + // add the menu to each of the rendering panes + Control[] renderingControls = this.fRendering.getRenderingPanes(); + for(int i = 0; i < renderingControls.length; i++) + super.createPopupMenu(renderingControls[i]); + super.createPopupMenu(this.fRendering); + + // copy + + final Action copyAction = new CopyAction(this.fRendering); + + // copy address + + final Action copyAddressAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.COPY_ADDRESS")) //$NON-NLS-1$ + { + public void run() + { + Display.getDefault().asyncExec(new Runnable() + { + public void run() + { + TraditionalRendering.this.fRendering.copyAddressToClipboard(); + } + }); + } + }; + + // go to address + + final Action gotoAddressAction = new GoToAddressAction(TraditionalRendering.this) + { + public void run() { + TraditionalRendering.this.fRendering + .setVisibleAddressBar(true); + } + }; + + // reset to base address + + final Action gotoBaseAddressAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.RESET_TO_BASE_ADDRESS")) //$NON-NLS-1$ + { + public void run() + { + Display.getDefault().asyncExec(new Runnable() + { + public void run() + { + TraditionalRendering.this.fRendering + .gotoAddress(TraditionalRendering.this.fRendering.fBaseAddress); + } + }); + } + }; + + + // refresh + + final Action refreshAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.REFRESH")) //$NON-NLS-1$ + { + public void run() + { + Display.getDefault().asyncExec(new Runnable() + { + public void run() + { + // For compatibility with DSF update modes (hopefully this will either be replaced by an enhanced + // platform interface or the caching will move out of the data layer + try { + Method m = fRendering.getMemoryBlock().getClass().getMethod("clearCache", new Class[0]); + if(m != null) + m.invoke(fRendering.getMemoryBlock(), new Object[0]); + } + catch (Exception e) + { + } + + TraditionalRendering.this.fRendering.refresh(); + } + }); + } + }; + + // display address + + final Action displayAddressPaneAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.ADDRESS"), //$NON-NLS-1$ + IAction.AS_CHECK_BOX) + { + public void run() + { + TraditionalRendering.this.fRendering.setPaneVisible( + Rendering.PANE_ADDRESS, isChecked()); + } + }; + displayAddressPaneAction.setChecked(this.fRendering + .getPaneVisible(Rendering.PANE_ADDRESS)); + + // display hex + + final Action displayBinaryPaneAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.BINARY"), //$NON-NLS-1$ + IAction.AS_CHECK_BOX) + { + public void run() + { + TraditionalRendering.this.fRendering.setPaneVisible( + Rendering.PANE_BINARY, isChecked()); + } + }; + displayBinaryPaneAction.setChecked(this.fRendering + .getPaneVisible(Rendering.PANE_BINARY)); + + // display text + + final Action displayTextPaneAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.TEXT"), //$NON-NLS-1$ + IAction.AS_CHECK_BOX) + { + public void run() + { + TraditionalRendering.this.fRendering.setPaneVisible( + Rendering.PANE_TEXT, isChecked()); + } + }; + displayTextPaneAction.setChecked(this.fRendering + .getPaneVisible(Rendering.PANE_TEXT)); + + // display size + + final Action displaySize1BytesAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.1_BYTE"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering.setBytesPerColumn(1); + } + }; + displaySize1BytesAction + .setChecked(this.fRendering.getBytesPerColumn() == 1); + + final Action displaySize2BytesAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.2_BYTES"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ + { + public void run() + { + TraditionalRendering.this.fRendering.setBytesPerColumn(2); + } + }; + displaySize2BytesAction + .setChecked(this.fRendering.getBytesPerColumn() == 2); + + final Action displaySize4BytesAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.4_BYTES"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ + { + public void run() + { + TraditionalRendering.this.fRendering.setBytesPerColumn(4); + } + }; + displaySize4BytesAction + .setChecked(this.fRendering.getBytesPerColumn() == 4); + + final Action displaySize8BytesAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.8_BYTES"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ + { + public void run() + { + TraditionalRendering.this.fRendering.setBytesPerColumn(8); + } + }; + displaySize8BytesAction + .setChecked(this.fRendering.getBytesPerColumn() == 8); + + // text / unicode ? + + final Action displayCharactersISO8859Action = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.ISO-8859-1"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering + .setTextMode(Rendering.TEXT_ISO_8859_1); + } + }; + displayCharactersISO8859Action.setChecked(this.fRendering + .getTextMode() == Rendering.TEXT_ISO_8859_1); + + final Action displayCharactersUSASCIIAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.USASCII"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering + .setTextMode(Rendering.TEXT_USASCII); + } + }; + displayCharactersUSASCIIAction.setChecked(this.fRendering + .getTextMode() == Rendering.TEXT_USASCII); + + final Action displayCharactersUTF8Action = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.UTF8"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ + { + public void run() + { + TraditionalRendering.this.fRendering + .setTextMode(Rendering.TEXT_UTF8); + } + }; + displayCharactersUTF8Action.setChecked(this.fRendering + .getTextMode() == Rendering.TEXT_UTF8); + +// final Action displayCharactersUTF16Action = new Action( +// TraditionalRenderingMessages +// .getString("TraditionalRendering.UTF16"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ +// { +// @Override +// public void run() +// { +// TraditionalRendering.this.fRendering +// .setTextMode(Rendering.TEXT_UTF16); +// } +// }; +// displayCharactersUTF16Action.setChecked(this.fRendering +// .getTextMode() == Rendering.TEXT_UTF16); + + // endian + + displayEndianBigAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.BIG"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering + .setDisplayLittleEndian(false); + } + }; + displayEndianBigAction.setChecked(!this.fRendering.isTargetLittleEndian()); + + displayEndianLittleAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.LITTLE"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering + .setDisplayLittleEndian(true); + } + }; + displayEndianLittleAction.setChecked(this.fRendering.isTargetLittleEndian()); + + // radix + + final Action displayRadixHexAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.HEX"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering + .setRadix(Rendering.RADIX_HEX); + } + }; + displayRadixHexAction + .setChecked(this.fRendering.getRadix() == Rendering.RADIX_HEX); + + final Action displayRadixDecSignedAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.DECIMAL_SIGNED"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ + { + public void run() + { + TraditionalRendering.this.fRendering + .setRadix(Rendering.RADIX_DECIMAL_SIGNED); + } + }; + displayRadixDecSignedAction + .setChecked(this.fRendering.getRadix() == Rendering.RADIX_DECIMAL_SIGNED); + + final Action displayRadixDecUnsignedAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.DECIMAL_UNSIGNED"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ + { + public void run() + { + TraditionalRendering.this.fRendering + .setRadix(Rendering.RADIX_DECIMAL_UNSIGNED); + } + }; + displayRadixDecUnsignedAction + .setChecked(this.fRendering.getRadix() == Rendering.RADIX_DECIMAL_UNSIGNED); + + final Action displayRadixOctAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.OCTAL"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering + .setRadix(Rendering.RADIX_OCTAL); + } + }; + displayRadixOctAction + .setChecked(this.fRendering.getRadix() == Rendering.RADIX_OCTAL); + + final Action displayRadixBinAction = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.BINARY"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering + .setRadix(Rendering.RADIX_BINARY); + } + }; + displayRadixBinAction + .setChecked(this.fRendering.getRadix() == Rendering.RADIX_BINARY); + + final Action displayColumnCountAuto = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.COLUMN_COUNT_AUTO"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering.setColumnsSetting(Rendering.COLUMNS_AUTO_SIZE_TO_FIT); + } + }; + displayColumnCountAuto.setChecked(fRendering.getColumnsSetting() == Rendering.COLUMNS_AUTO_SIZE_TO_FIT); + + final Action[] displayColumnCounts = new Action[MAX_MENU_COLUMN_COUNT]; + for(int i = 0, j = 1; i < MAX_MENU_COLUMN_COUNT; i++, j*=2) + { + final int finali = j; + displayColumnCounts[i] = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.COLUMN_COUNT_" + finali), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + TraditionalRendering.this.fRendering.setColumnsSetting(finali); + } + }; + displayColumnCounts[i].setChecked(fRendering.getColumnsSetting() == finali); + } + + final Action displayColumnCountCustomValue = new Action("", IAction.AS_RADIO_BUTTON) + { + public void run() + { + } + }; + + final Action displayColumnCountCustom = new Action( + TraditionalRenderingMessages + .getString("TraditionalRendering.COLUMN_COUNT_CUSTOM"), //$NON-NLS-1$ + IAction.AS_RADIO_BUTTON) + { + public void run() + { + InputDialog inputDialog = new InputDialog( + fRendering.getShell(), + "Set Column Count", //$NON-NLS-1$ + "Please enter column count", //$NON-NLS-1$ + "", //$NON-NLS-1$ + new IInputValidator() { + public String isValid(String input) { + try { + int i= Integer.parseInt(input); + if (i <= 0) + return "Please enter a positive integer"; //$NON-NLS-1$ + if (i > 200) + return "Please enter a positive integer not greater than 200"; //$NON-NLS-1$ + + } catch (NumberFormatException x) { + return "Please enter a positive integer"; //$NON-NLS-1$ + } + return null; + } + } + ); + + if (inputDialog.open() != Window.OK) + { + this.setChecked(false); + int currentColumnSetting = TraditionalRendering.this.fRendering.getColumnsSetting(); + if(currentColumnSetting == Rendering.COLUMNS_AUTO_SIZE_TO_FIT) + displayColumnCountAuto.setChecked(true); + else + { + boolean currentCountIsCustom = true; + for(int i = 0, j = 1; i < MAX_MENU_COLUMN_COUNT && currentCountIsCustom; i++, j*=2) + { + currentCountIsCustom = (j != fRendering.getColumnsSetting()); + if(j == fRendering.getColumnsSetting()) + displayColumnCounts[i].setChecked(true); + } + if(currentCountIsCustom) + displayColumnCountCustomValue.setChecked(true); + } + + return; + } + + int newColumnCount = -1; + try { + newColumnCount = Integer.parseInt(inputDialog.getValue()); + } catch (NumberFormatException x) { assert false; } + + boolean customIsOneOfStandardListChoices = false; + + for(int i = 0, j = 1; i < MAX_MENU_COLUMN_COUNT; i++, j*=2) { + if ( newColumnCount == j ) { + customIsOneOfStandardListChoices = true; + TraditionalRendering.this.fRendering.setColumnsSetting(newColumnCount); + this.setChecked(false); + displayColumnCountCustomValue.setChecked(false); + displayColumnCounts[i].setChecked(true); + break; + } + } + + if ( ! customIsOneOfStandardListChoices ) { + TraditionalRendering.this.fRendering.setColumnsSetting(newColumnCount); + this.setChecked(false); + + displayColumnCountCustomValue.setChecked(true); + displayColumnCountCustomValue.setText(Integer.valueOf( + fRendering.getColumnsSetting()).toString()); + } + } + }; + + getPopupMenuManager().addMenuListener(new IMenuListener() + { + public void menuAboutToShow(IMenuManager manager) + { + manager.add(new Separator()); + + MenuManager sub = new MenuManager( + TraditionalRenderingMessages + .getString("TraditionalRendering.PANES")); //$NON-NLS-1$ + sub.add(displayAddressPaneAction); + sub.add(displayBinaryPaneAction); + sub.add(displayTextPaneAction); + manager.add(sub); + + sub = new MenuManager(TraditionalRenderingMessages + .getString("TraditionalRendering.ENDIAN")); //$NON-NLS-1$ + sub.add(displayEndianBigAction); + sub.add(displayEndianLittleAction); + manager.add(sub); + + sub = new MenuManager(TraditionalRenderingMessages + .getString("TraditionalRendering.TEXT")); //$NON-NLS-1$ + sub.add(displayCharactersISO8859Action); + sub.add(displayCharactersUSASCIIAction); + sub.add(displayCharactersUTF8Action); + //sub.add(displayCharactersUTF16Action); + manager.add(sub); + + sub = new MenuManager(TraditionalRenderingMessages + .getString("TraditionalRendering.CELL_SIZE")); //$NON-NLS-1$ + sub.add(displaySize1BytesAction); + sub.add(displaySize2BytesAction); + sub.add(displaySize4BytesAction); + sub.add(displaySize8BytesAction); + manager.add(sub); + + sub = new MenuManager(TraditionalRenderingMessages + .getString("TraditionalRendering.RADIX")); //$NON-NLS-1$ + sub.add(displayRadixHexAction); + sub.add(displayRadixDecSignedAction); + sub.add(displayRadixDecUnsignedAction); + sub.add(displayRadixOctAction); + sub.add(displayRadixBinAction); + manager.add(sub); + + sub = new MenuManager(TraditionalRenderingMessages + .getString("TraditionalRendering.COLUMN_COUNT")); //$NON-NLS-1$ + sub.add(displayColumnCountAuto); + for(int i = 0; i < displayColumnCounts.length; i++) + sub.add(displayColumnCounts[i]); + + boolean currentCountIsCustom = fRendering.getColumnsSetting() != 0; + for(int i = 0, j = 1; i < MAX_MENU_COLUMN_COUNT && currentCountIsCustom; i++, j*=2) + currentCountIsCustom = (j != fRendering.getColumnsSetting()); + if(currentCountIsCustom) + sub.add(displayColumnCountCustomValue); + + sub.add(displayColumnCountCustom); + manager.add(sub); + manager.add(new Separator()); + + manager.add(copyAction); + manager.add(copyAddressAction); + + // IMemoryGoToAddressProvider interface, called using reflection, waiting on platform acceptance of patch + final IMemoryBlockRetrieval retrieve = MemoryViewUtil.getMemoryBlockRetrieval(TraditionalRendering.this.getMemoryBlock()); + if (retrieve != null) + { + try + { + Method m = retrieve.getClass().getMethod("getGoToAddressRenderingId", new Class[] {}); + m.setAccessible(true); + + if(m != null) + { + String id = (String) m.invoke(retrieve, new Object[] {}); + if(id == null) + manager.add(gotoAddressAction); + } + } + catch(Exception e) + { + // do nothing + } + } + + manager.add(gotoBaseAddressAction); + manager.add(refreshAction); + manager.add(new Separator()); + manager.add(new Separator( + IWorkbenchActionConstants.MB_ADDITIONS)); + } + }); + + } + + public Control getControl() + { + return this.fRendering; + } + + + // selection is terminology for caret position + public BigInteger getSelectedAddress() { + IMemorySelection selection = fRendering.getSelection(); + if (selection == null || selection.getStart() == null) + return fRendering.getCaretAddress(); + + return selection.getStartLow(); + } + + public MemoryByte[] getSelectedAsBytes() { + try + { + // default to the caret address and the cell count size + BigInteger startAddr = fRendering.getCaretAddress(); + int byteCount = fRendering.getBytesPerColumn(); + + // Now see if there's a selection + IMemorySelection selection = fRendering.getSelection(); + if (selection != null && selection.getStart() != null) + { + // The implementation is such that just having a caret somewhere + // (without multiple cells being selected) constitutes a selection, + // except for when the rendering is in its initial state. I.e., + // just because we get here doesn't mean the user has selected more + // than one cell. + + startAddr = getSelectedAddress(); + + if (selection.getHigh() != null) + { + byteCount = selection.getHigh().subtract(selection.getLow()).intValue() * fRendering.getAddressableSize(); + } + } + return fRendering.getViewportCache().getBytes(startAddr, byteCount); + + } + catch(DebugException de) + { + // FIXME log? + return null; + } + } + + public void goToAddress(final BigInteger address) throws DebugException { + Display.getDefault().asyncExec(new Runnable(){ + public void run() + { + fRendering.gotoAddress(address); + } + }); + } + + protected void setTargetMemoryLittleEndian(boolean littleEndian) + { + // once we actually read memory we can determine the + // endianess and need to set these actions accordingly. + displayEndianBigAction.setChecked(!littleEndian); + displayEndianLittleAction.setChecked(littleEndian); + + // when target endian changes, force display endian to track. + // user can then change display endian if desired. + fRendering.setDisplayLittleEndian(littleEndian); + } + + public void dispose() + { + if(this.fRendering != null) + this.fRendering.dispose(); + disposeColors(); + super.dispose(); + } + + public Object getAdapter(Class adapter) + { + if(adapter == IWorkbenchAdapter.class) + { + if(this.fWorkbenchAdapter == null) + { + this.fWorkbenchAdapter = new IWorkbenchAdapter() + { + public Object[] getChildren(Object o) + { + return new Object[0]; + } + + public ImageDescriptor getImageDescriptor(Object object) + { + return null; + } + + public String getLabel(Object o) + { + return TraditionalRenderingMessages + .getString("TraditionalRendering.RENDERING_NAME"); //$NON-NLS-1$ + } + + public Object getParent(Object o) + { + return null; + } + }; + } + return this.fWorkbenchAdapter; + } + + if (adapter == IMemoryBlockConnection.class) + { + if (fConnection == null) + { + fConnection = new IMemoryBlockConnection() + { + public void update() + { + // update UI asynchronously + Display display = DebugUIPlugin.getDefault().getWorkbench().getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + try + { + if(fBigBaseAddress != TraditionalRendering.this.fRendering.getMemoryBlock().getBigBaseAddress()) + { + fBigBaseAddress = TraditionalRendering.this.fRendering.getMemoryBlock().getBigBaseAddress(); + TraditionalRendering.this.fRendering.gotoAddress(fBigBaseAddress); + } + TraditionalRendering.this.fRendering.refresh(); + } + catch (DebugException e) + { + } + } + }); + } + }; + } + return fConnection; + } + + return super.getAdapter(adapter); + } + + public void resetRendering() throws DebugException { + fRendering.gotoAddress(fRendering.fBaseAddress); + } +} + + +class TraditionalMemoryByte extends MemoryByte implements IMemoryByte +{ + private boolean isEdited = false; + + private boolean[] changeHistory = new boolean[0]; + + public TraditionalMemoryByte() + { + super(); + } + + public TraditionalMemoryByte(byte byteValue) + { + super(byteValue); + } + + public TraditionalMemoryByte(byte byteValue, byte byteFlags) + { + super(byteValue, byteFlags); + } + + public boolean isEdited() + { + return isEdited; + } + + public void setEdited(boolean edited) + { + isEdited = edited; + } + + public boolean isChanged(int historyDepth) + { + return changeHistory.length > historyDepth && changeHistory[historyDepth]; + } + + public void setChanged(int historyDepth, boolean changed) + { + if(historyDepth >= changeHistory.length) + { + boolean newChangeHistory[] = new boolean[historyDepth + 1]; + System.arraycopy(changeHistory, 0, newChangeHistory, 0, changeHistory.length); + changeHistory = newChangeHistory; + } + + changeHistory[historyDepth] = changed; + + if(historyDepth == 0) + this.setChanged(changed); + } +} + +class CopyAction extends Action +{ + // TODO for the sake of large copies, this action should probably read in + // blocks on a Job. + + private Rendering fRendering; + private int fType = DND.CLIPBOARD; + + public CopyAction(Rendering rendering) + { + this(rendering, DND.CLIPBOARD); + } + + public CopyAction(Rendering rendering, int clipboardType) + { + super(); + fType = clipboardType; + fRendering = rendering; + setText(DebugUIMessages.CopyViewToClipboardAction_title); + setToolTipText(DebugUIMessages.CopyViewToClipboardAction_tooltip); + setImageDescriptor(DebugPluginImages + .getImageDescriptor(IInternalDebugUIConstants.IMG_ELCL_COPY_VIEW_TO_CLIPBOARD)); + setHoverImageDescriptor(DebugPluginImages + .getImageDescriptor(IInternalDebugUIConstants.IMG_LCL_COPY_VIEW_TO_CLIPBOARD)); + setDisabledImageDescriptor(DebugPluginImages + .getImageDescriptor(IInternalDebugUIConstants.IMG_DLCL_COPY_VIEW_TO_CLIPBOARD)); + } + + public void run() + { + final String PANE_SPACING = " "; //$NON-NLS-1$ + + Clipboard clip = null; + try + { + clip = new Clipboard(fRendering.getDisplay()); + + BigInteger start = fRendering.getSelection().getStart(); + BigInteger end = fRendering.getSelection().getEnd(); + // end will be null when there is nothing selected + if (end == null) + return; + + if(start.compareTo(end) > 0) + { + // swap start and end + + BigInteger bigI = end; + end = start; + start = bigI; + } + + final int radix = fRendering.getRadix(); + final int bytesPerColumn = fRendering.getBytesPerColumn(); + final boolean isLittleEndian = fRendering.isTargetLittleEndian(); + final int bytesPerCharacter = fRendering.getBytesPerCharacter(); + + final int addressWidth = fRendering.getAddressString(start) + .length(); + + final int binaryCellWidth = fRendering.getRadixCharacterCount( + radix, bytesPerColumn) + 1; + + final int asciiCellWidth = fRendering.getBytesPerColumn() + / fRendering.getBytesPerCharacter(); + + final int combindCellWidths = (fRendering + .getPaneVisible(Rendering.PANE_BINARY) ? binaryCellWidth : 0) + + (fRendering.getPaneVisible(Rendering.PANE_TEXT) ? asciiCellWidth + : 0); + + final int columns = fRendering.getColumnCount(); + + BigInteger lengthToRead = end.subtract(start); + + int rows = lengthToRead.divide( + BigInteger.valueOf(columns * bytesPerColumn)).intValue(); + + if(rows * columns * bytesPerColumn < lengthToRead.intValue()) + rows++; + + StringBuffer buffer = new StringBuffer(); + + for(int row = 0; row < rows; row++) + { + BigInteger rowAddress = start.add(BigInteger.valueOf(row + * columns * bytesPerColumn)); + + if(fRendering.getPaneVisible(Rendering.PANE_ADDRESS)) + { + buffer.append(fRendering.getAddressString(rowAddress)); + buffer.append(PANE_SPACING); + } + + if(fRendering.getPaneVisible(Rendering.PANE_BINARY)) + { + for(int col = 0; col < columns; col++) + { + BigInteger cellAddress = rowAddress.add(BigInteger + .valueOf(col * bytesPerColumn)); + + if(cellAddress.compareTo(end) < 0) + { + try + { + MemoryByte bytes[] = fRendering.getBytes( + cellAddress, bytesPerColumn); + buffer.append(fRendering.getRadixText(bytes, + radix, isLittleEndian)); + } + catch(DebugException de) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_COPY_OPERATION"), de); //$NON-NLS-1$ + return; + } + } + else + { + for(int i = fRendering.getRadixCharacterCount( + radix, bytesPerColumn); i > 0; i--) + buffer.append(' '); + } + + if(col != columns - 1) + buffer.append(' '); + } + } + + if(fRendering.getPaneVisible(Rendering.PANE_BINARY) + && fRendering.getPaneVisible(Rendering.PANE_TEXT)) + { + buffer.append(PANE_SPACING); + } + + if(fRendering.getPaneVisible(Rendering.PANE_TEXT)) + { + for(int col = 0; col < columns; col++) + { + BigInteger cellAddress = rowAddress.add(BigInteger + .valueOf(col * fRendering.getBytesPerColumn())); + + if(cellAddress.compareTo(end) < 0) + { + try + { + MemoryByte bytes[] = fRendering + .getBytes(cellAddress, fRendering + .getBytesPerColumn()); + buffer.append(fRendering.formatText(bytes, + isLittleEndian, fRendering.getTextMode())); + } + catch(DebugException de) + { + fRendering + .logError( + TraditionalRenderingMessages + .getString("TraditionalRendering.FAILURE_COPY_OPERATION"), de); //$NON-NLS-1$ + return; + } + } + else + { + + } + } + } + + buffer.append("\n"); //$NON-NLS-1$ + } + + if(buffer.length() > 0) + { + TextTransfer plainTextTransfer = TextTransfer.getInstance(); + clip.setContents(new Object[] { buffer.toString() }, + new Transfer[] { plainTextTransfer }, fType); + } + } + finally + { + if(clip != null) + { + clip.dispose(); + } + } + } +} \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingMessages.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingMessages.java new file mode 100644 index 00000000000..d54f864851f --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingMessages.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class TraditionalRenderingMessages +{ + private static final String BUNDLE_NAME = "org.eclipse.cdt.debug.ui.memory.traditional.TraditionalRendering_messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private TraditionalRenderingMessages() + { + } + + public static String getString(String key) + { + // TODO Auto-generated method stub + try + { + return RESOURCE_BUNDLE.getString(key); + } + catch(MissingResourceException e) + { + return '!' + key + '!'; + } + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPlugin.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPlugin.java new file mode 100644 index 00000000000..0dbc658fd1a --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPlugin.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import org.eclipse.ui.plugin.AbstractUIPlugin; + +public class TraditionalRenderingPlugin extends AbstractUIPlugin +{ + private static final String PLUGIN_ID = "org.eclipse.cdt.debug.ui.memory.traditional"; //$NON-NLS-1$ + + private static TraditionalRenderingPlugin plugin; + + public TraditionalRenderingPlugin() + { + super(); + plugin = this; + } + + /** + * Returns the shared instance. + */ + public static TraditionalRenderingPlugin getDefault() { + return plugin; + } + + /** + * Returns the unique identifier for this plugin. + */ + public static String getUniqueIdentifier() { + return PLUGIN_ID; + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceAction.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceAction.java new file mode 100644 index 00000000000..5763d2ccdfb --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceAction.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + + +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.preference.IPreferenceNode; +import org.eclipse.jface.preference.IPreferencePage; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.jface.preference.PreferenceManager; +import org.eclipse.jface.preference.PreferenceNode; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.actions.ActionDelegate; + +public class TraditionalRenderingPreferenceAction extends ActionDelegate implements IViewActionDelegate { + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) + */ + public void run(IAction action) { + IPreferencePage page = new TraditionalRenderingPreferencePage(); + showPreferencePage("org.eclipse.cdt.debug.ui.memory.traditional.TraditionalRenderingPreferencePage", page); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart) + */ + public void init(IViewPart view) { + } + + protected void showPreferencePage(String id, IPreferencePage page) { + final IPreferenceNode targetNode = new PreferenceNode(id, page); + + PreferenceManager manager = new PreferenceManager(); + manager.addToRoot(targetNode); + final PreferenceDialog dialog = new PreferenceDialog(DebugUIPlugin.getShell(), manager); + final boolean [] result = new boolean[] { false }; + BusyIndicator.showWhile(DebugUIPlugin.getStandardDisplay(), new Runnable() { + public void run() { + dialog.create(); + dialog.setMessage(targetNode.getLabelText()); + result[0]= (dialog.open() == Window.OK); + } + }); + } + +} + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceConstants.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceConstants.java new file mode 100644 index 00000000000..934e7c29876 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceConstants.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +/** + * Constant definitions for plug-in preferences + */ +public class TraditionalRenderingPreferenceConstants { + + public static final String MEM_COLOR_CHANGED = "memoryColorChanged"; + + public static final String MEM_USE_GLOBAL_BACKGROUND = "memUseGlobalBackground"; + + public static final String MEM_COLOR_BACKGROUND = "memoryColorBackground"; + + public static final String MEM_COLOR_EDIT = "memoryColorEdit"; + + public static final String MEM_COLOR_TEXT = "memoryColorText"; + + public static final String MEM_USE_GLOBAL_SELECTION = "memUseGlobalSelection"; + + public static final String MEM_COLOR_SELECTION = "memoryColorSelection"; + + public static final String MEM_USE_GLOBAL_TEXT = "memUseGlobalText"; + + public static final String MEM_LIGHTEN_DARKEN_ALTERNATE_CELLS = "memoryColorScaleTextAlternate"; + + public static final String MEM_EDIT_BUFFER_SAVE = "memoryEditBufferSave"; + + public static final String MEM_EDIT_BUFFER_SAVE_ON_ENTER_ONLY = "saveOnEnterCancelOnFocusLost"; + + public static final String MEM_EDIT_BUFFER_SAVE_ON_ENTER_OR_FOCUS_LOST = "saveOnEnterOrFocusLost"; + + public static final String MEM_HISTORY_TRAILS_COUNT = "memoryHistoryTrailsCount"; + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceInitializer.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceInitializer.java new file mode 100644 index 00000000000..3e097300be9 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferenceInitializer.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Display; + +/** + * Class used to initialize default preference values. + */ +public class TraditionalRenderingPreferenceInitializer extends AbstractPreferenceInitializer { + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + public void initializeDefaultPreferences() { + IPreferenceStore store = TraditionalRenderingPlugin.getDefault() + .getPreferenceStore(); + + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_TEXT, true); + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_BACKGROUND, true); + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_SELECTION, true); + + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_COLOR_CHANGED, "255,0,0"); + + Color systemSelection = Display.getDefault().getSystemColor(SWT.COLOR_LIST_SELECTION); + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_COLOR_SELECTION, systemSelection.getRed() + + "," + systemSelection.getGreen() + "," + systemSelection.getBlue()); + + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_LIGHTEN_DARKEN_ALTERNATE_CELLS, "5"); + + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_COLOR_EDIT, "0,255,0"); + + Color systemText = Display.getDefault().getSystemColor(SWT.COLOR_LIST_FOREGROUND); + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_COLOR_TEXT, systemText.getRed() + + "," + systemText.getGreen() + "," + systemText.getBlue()); + + Color systemBackground = Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND); + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_COLOR_BACKGROUND, systemBackground.getRed() + + "," + systemBackground.getGreen() + "," + systemBackground.getBlue()); + + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_EDIT_BUFFER_SAVE, + TraditionalRenderingPreferenceConstants.MEM_EDIT_BUFFER_SAVE_ON_ENTER_ONLY); + + store.setDefault(TraditionalRenderingPreferenceConstants.MEM_HISTORY_TRAILS_COUNT, "1"); + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferencePage.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferencePage.java new file mode 100644 index 00000000000..ca15b61c765 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingPreferencePage.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.ColorFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.RadioGroupFieldEditor; +import org.eclipse.jface.preference.ScaleFieldEditor; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.PlatformUI; + +/** + * This class represents a preference page that + * is contributed to the Preferences dialog. By + * subclassing FieldEditorPreferencePage, we + * can use the field support built into JFace that allows + * us to create a page that is small and knows how to + * save, restore and apply itself. + *

+ * This page is used to modify preferences only. They + * are stored in the preference store that belongs to + * the main plug-in class. That way, preferences can + * be accessed directly via the preference store. + */ + +public class TraditionalRenderingPreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public TraditionalRenderingPreferencePage() { + super(GRID); + setPreferenceStore(TraditionalRenderingPlugin.getDefault().getPreferenceStore()); + setDescription("Traditional Memory Rendering"); + } + + + @Override + public void createControl(Composite parent) { + super.createControl(parent); + PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), TraditionalRenderingPlugin.getUniqueIdentifier() + ".TraditionalRenderingPreferencePage_context"); + } + + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + public void createFieldEditors() { + addField(new BooleanFieldEditor(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_TEXT, + "Use Global Te&xt Color", getFieldEditorParent())); + + addField(new ColorFieldEditor(TraditionalRenderingPreferenceConstants.MEM_COLOR_TEXT, + "&Text Color:", getFieldEditorParent())); + + addField(new ScaleFieldEditor(TraditionalRenderingPreferenceConstants.MEM_LIGHTEN_DARKEN_ALTERNATE_CELLS, + "Brighten Alternate Cells", getFieldEditorParent(), 0, 8, 1, 1)); + + addField(new BooleanFieldEditor(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_BACKGROUND, + "Use Global B&ackground Color", getFieldEditorParent())); + + addField(new ColorFieldEditor(TraditionalRenderingPreferenceConstants.MEM_COLOR_BACKGROUND, + "&Background Color:", getFieldEditorParent())); + + addField(new ColorFieldEditor(TraditionalRenderingPreferenceConstants.MEM_COLOR_CHANGED, + "&Changed Color:", getFieldEditorParent())); + + addField(new ColorFieldEditor(TraditionalRenderingPreferenceConstants.MEM_COLOR_EDIT, + "&Edit Color:", getFieldEditorParent())); + + addField(new BooleanFieldEditor(TraditionalRenderingPreferenceConstants.MEM_USE_GLOBAL_SELECTION, + "Use Global Se&lection Color", getFieldEditorParent())); + + addField(new ColorFieldEditor(TraditionalRenderingPreferenceConstants.MEM_COLOR_SELECTION, + "&Selection Color:", getFieldEditorParent())); + + addField(new RadioGroupFieldEditor(TraditionalRenderingPreferenceConstants.MEM_EDIT_BUFFER_SAVE, + "Edit Buffer", 1, new String[][] { { "Save on E&nter, Cancel on Focus Lost", "saveOnEnterCancelOnFocusLost" }, + { "Save on Enter or Focus L&ost", "saveOnEnterOrFocusLost" } }, getFieldEditorParent())); + + addField(new ScaleFieldEditor(TraditionalRenderingPreferenceConstants.MEM_HISTORY_TRAILS_COUNT, + "History &Trail Levels", getFieldEditorParent(), 1, 10, 1, 1)); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + +} \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingTypeDelegate.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingTypeDelegate.java new file mode 100644 index 00000000000..fdba6dbed01 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRenderingTypeDelegate.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.traditional; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.debug.ui.memory.IMemoryRenderingTypeDelegate; + +public class TraditionalRenderingTypeDelegate + implements IMemoryRenderingTypeDelegate +{ + + public IMemoryRendering createRendering(String id) throws CoreException { + return new TraditionalRendering(id); + } + + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering_messages.properties b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering_messages.properties new file mode 100644 index 00000000000..041aa4d356f --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering_messages.properties @@ -0,0 +1,49 @@ +TraditionalRendering.GO_TO_ADDRESS=Go To Address +TraditionalRendering.RESET_TO_BASE_ADDRESS=Reset To Base Address +TraditionalRendering.REFRESH=Refresh +TraditionalRendering.ADDRESS=Address +TraditionalRendering.BINARY=Binary +TraditionalRendering.TEXT=Text +TraditionalRendering.1_BYTE=1 byte +TraditionalRendering.2_BYTES=2 bytes +TraditionalRendering.4_BYTES=4 bytes +TraditionalRendering.8_BYTES=8 bytes +TraditionalRendering.ISO-8859-1=ISO-8859-1 +TraditionalRendering.USASCII=US-ASCII +TraditionalRendering.UTF8=UTF-8 +TraditionalRendering.UTF16=UTF-16 +TraditionalRendering.BIG=Big +TraditionalRendering.LITTLE=Little +TraditionalRendering.HEX=Hex +TraditionalRendering.DECIMAL_SIGNED=Decimal Signed +TraditionalRendering.DECIMAL_UNSIGNED=Decimal Unsigned +TraditionalRendering.OCTAL=Octal +TraditionalRendering.PANES=Panes +TraditionalRendering.ENDIAN=Endian +TraditionalRendering.CELL_SIZE=Cell Size +TraditionalRendering.RADIX=Radix +TraditionalRendering.RENDERING_NAME=Traditional +TraditionalRendering.FAILURE_RETRIEVE_START_ADDRESS=Failure in retrieving start address. +TraditionalRendering.FAILURE_RETRIEVE_BASE_ADDRESS=Failure in retrieving base address. +TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD=Called on non-dispatch thread +TraditionalRendering.FAILURE_READ_MEMORY=Failed reading memory. +TraditionalRendering.FAILURE_WRITE_MEMORY=Error writing memory. +TraditionalRendering.FAILURE_DETERMINE_ADDRESS_SIZE=Failed to determine address size. +TraditionalRendering.FAILURE_POSITION_CURSOR=Failed to position cursor. +TraditionalRendering.FAILURE_START_SELECTION=Failed to start selection. +TraditionalRendering.FAILURE_APPEND_SELECTION=Failed to append selection. +TraditionalRendering.FAILURE_DETERMINE_CELL_LOCATION=Failed to determine cell location. +TraditionalRendering.FAILURE_PAINT=Failed to paint. +TraditionalRendering.FAILURE_COPY_OPERATION=Failed copy operation. +TraditionalRendering.COLUMN_COUNT=Columns +TraditionalRendering.COLUMN_COUNT_AUTO=Auto Size to Fill +TraditionalRendering.COLUMN_COUNT_1=1 +TraditionalRendering.COLUMN_COUNT_2=2 +TraditionalRendering.COLUMN_COUNT_4=4 +TraditionalRendering.COLUMN_COUNT_8=8 +TraditionalRendering.COLUMN_COUNT_16=16 +TraditionalRendering.COLUMN_COUNT_32=32 +TraditionalRendering.COLUMN_COUNT_64=64 +TraditionalRendering.COLUMN_COUNT_128=128 +TraditionalRendering.COLUMN_COUNT_CUSTOM=Custom... +TraditionalRendering.COPY_ADDRESS=Copy Address \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/.classpath b/memory/org.eclipse.cdt.debug.ui.memory.transport/.classpath new file mode 100644 index 00000000000..2fbb7a23e12 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/.project b/memory/org.eclipse.cdt.debug.ui.memory.transport/.project new file mode 100644 index 00000000000..f011d2cff38 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/.project @@ -0,0 +1,28 @@ + + + org.eclipse.cdt.debug.ui.memory.transport + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/.settings/org.eclipse.jdt.core.prefs b/memory/org.eclipse.cdt.debug.ui.memory.transport/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..b51d4342d8d --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +#Fri May 09 21:44:48 PDT 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.transport/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..4486a9eb402 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/META-INF/MANIFEST.MF @@ -0,0 +1,16 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Memory Transport Plug-in +Bundle-SymbolicName: org.eclipse.cdt.debug.ui.memory.transport;singleton:=true +Bundle-Version: 1.1.0.qualifier +Bundle-Localization: plugin +Bundle-Vendor: Eclipse.org +Require-Bundle: org.eclipse.debug.core, + org.eclipse.debug.ui, + org.eclipse.core.runtime, + org.eclipse.swt, + org.eclipse.jface, + org.eclipse.ui +Bundle-RequiredExecutionEnvironment: J2SE-1.4 +Bundle-ActivationPolicy: lazy +Bundle-Activator: org.eclipse.cdt.debug.ui.memory.transport.MemoryTransportPlugin diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/about.html b/memory/org.eclipse.cdt.debug.ui.memory.transport/about.html new file mode 100644 index 00000000000..04492dd7e1b --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/about.html @@ -0,0 +1,24 @@ + + + + +About +

About This Content

+ +

May 14, 2008

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/build.properties b/memory/org.eclipse.cdt.debug.ui.memory.transport/build.properties new file mode 100644 index 00000000000..835e763df2c --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/build.properties @@ -0,0 +1,9 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + schema/,\ + plugin.xml,\ + build.properties,\ + plugin.properties,\ + icons/ diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/icons/export.png b/memory/org.eclipse.cdt.debug.ui.memory.transport/icons/export.png new file mode 100644 index 00000000000..91b2198825c Binary files /dev/null and b/memory/org.eclipse.cdt.debug.ui.memory.transport/icons/export.png differ diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/icons/import.png b/memory/org.eclipse.cdt.debug.ui.memory.transport/icons/import.png new file mode 100644 index 00000000000..fa02317c7fd Binary files /dev/null and b/memory/org.eclipse.cdt.debug.ui.memory.transport/icons/import.png differ diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/plugin.properties b/memory/org.eclipse.cdt.debug.ui.memory.transport/plugin.properties new file mode 100644 index 00000000000..1ce59a6a290 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/plugin.properties @@ -0,0 +1,2 @@ +ExportMemoryAction.label=Export +ImportMemoryAction.label=Import \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/plugin.xml b/memory/org.eclipse.cdt.debug.ui.memory.transport/plugin.xml new file mode 100644 index 00000000000..98cccbccfb7 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/plugin.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/schema/MemoryTransport.exsd b/memory/org.eclipse.cdt.debug.ui.memory.transport/schema/MemoryTransport.exsd new file mode 100644 index 00000000000..6efec619ca9 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/schema/MemoryTransport.exsd @@ -0,0 +1,141 @@ + + + + + + + + + Allows plug-ins to contribute arbitrary memory importers and exporters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0.0 + + + + + + + + + + + + /******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + + + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/BufferedMemoryWriter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/BufferedMemoryWriter.java new file mode 100644 index 00000000000..d767bd86183 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/BufferedMemoryWriter.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.math.BigInteger; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlockExtension; + +public class BufferedMemoryWriter +{ + private IMemoryBlockExtension fBlock; + private byte[] fBuffer; + private int fBufferPosition = 0; + private BigInteger fBufferStart = null; + + public BufferedMemoryWriter(IMemoryBlockExtension block, int bufferLength) + { + fBlock = block; + fBuffer = new byte[bufferLength]; + } + + public void write(BigInteger address, byte[] data) throws DebugException + { + while(data.length > 0) + { + if(fBufferStart == null) + { + fBufferStart = address; + int length = data.length <= fBuffer.length ? data.length : fBuffer.length; + System.arraycopy(data, 0, fBuffer, 0, length); + fBufferPosition = length; + byte[] dataRemainder = new byte[data.length - length]; + System.arraycopy(data, length, dataRemainder, 0, data.length - length); + data = dataRemainder; + address = fBufferStart.add(BigInteger.valueOf(length)); + } + else if(fBufferStart.add(BigInteger.valueOf(fBufferPosition)).compareTo(address) != 0) + { + flush(); + } + else + { + int availableBufferLength = fBuffer.length - fBufferPosition; + int length = data.length <= fBuffer.length - availableBufferLength + ? data.length : fBuffer.length - availableBufferLength; + System.arraycopy(data, 0, fBuffer, fBufferPosition, length); + fBufferPosition += length; + + byte[] dataRemainder = new byte[data.length - length]; + System.arraycopy(data, length, dataRemainder, 0, data.length - length); + data = dataRemainder; + address = fBufferStart.add(BigInteger.valueOf(length)); + } + + if(fBufferPosition == fBuffer.length) + flush(); + } + } + + public void flush() throws DebugException + { + if(fBufferStart != null) + { + byte data[] = new byte[fBufferPosition]; + System.arraycopy(fBuffer, 0, data, 0, fBufferPosition); + fBlock.setValue(fBufferStart, data); + fBufferStart = null; + } + } + +} + + diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/ExportMemoryDialog.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/ExportMemoryDialog.java new file mode 100644 index 00000000000..0301c554a72 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/ExportMemoryDialog.java @@ -0,0 +1,202 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.util.Properties; +import java.util.Vector; + +import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryExporter; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.SelectionDialog; + +public class ExportMemoryDialog extends SelectionDialog +{ + + private Combo fFormatCombo; + + private IMemoryBlock fMemoryBlock; + + private Control fCurrentControl = null; + + private IMemoryExporter fFormatExporters[]; + private String fFormatNames[]; + + private Properties fProperties = new Properties(); + + public ExportMemoryDialog(Shell parent, IMemoryBlock memoryBlock) + { + super(parent); + super.setTitle("Export Memory"); + setShellStyle(getShellStyle() | SWT.RESIZE); + + fMemoryBlock = memoryBlock; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) + */ + protected void createButtonsForButtonBar(Composite parent) { + super.createButtonsForButtonBar(parent); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.SelectionDialog#getResult() + */ + public Object[] getResult() { + + Object[] results = super.getResult(); + + if (results != null) + { + return results; + } + return new Object[0]; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#cancelPressed() + */ + protected void cancelPressed() { + + setResult(null); + + super.cancelPressed(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + protected void okPressed() { + if(fCurrentControl != null) + fCurrentControl.dispose(); + fFormatExporters[fFormatCombo.getSelectionIndex()].exportMemory(); + + super.okPressed(); + } + + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + protected Control createDialogArea(Composite parent) { + + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, MemoryTransportPlugin.getUniqueIdentifier() + ".ExportMemoryDialog_context"); //$NON-NLS-1$ + Composite composite = new Composite(parent, SWT.NONE); + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + + // format + + Label textLabel = new Label(composite, SWT.NONE); + textLabel.setText("Format: "); + + fFormatCombo = new Combo(composite, SWT.BORDER | SWT.READ_ONLY); + + FormData data = new FormData(); + data.top = new FormAttachment(fFormatCombo, 0, SWT.CENTER); + textLabel.setLayoutData(data); + + data = new FormData(); + data.left = new FormAttachment(textLabel); + fFormatCombo.setLayoutData(data); + + Vector exporters = new Vector(); + + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = + registry.getExtensionPoint("org.eclipse.cdt.debug.ui.memory.transport.memoryTransport"); + IConfigurationElement points[] = + extensionPoint.getConfigurationElements(); + + for (int i = 0; i < points.length; i++) + { + IConfigurationElement element = points[i]; + if("exporter".equals(element.getName())) + { + try + { + exporters.addElement((IMemoryExporter) element.createExecutableExtension("class")); + } + catch(Exception e) { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + } + } + + fFormatExporters = new IMemoryExporter[exporters.size()]; + fFormatNames = new String[exporters.size()]; + for(int i = 0; i < fFormatExporters.length; i++) + { + fFormatExporters[i] = (IMemoryExporter) exporters.elementAt(i); + fFormatNames[i] = ((IMemoryExporter) exporters.elementAt(i)).getName(); + } + + final Composite container = new Composite(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fFormatCombo); + data.left = new FormAttachment(0); + container.setLayoutData(data); + + fFormatCombo.setItems(fFormatNames); + + fFormatCombo.addSelectionListener(new SelectionListener(){ + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + public void widgetSelected(SelectionEvent e) { + if(fCurrentControl != null) + fCurrentControl.dispose(); + fCurrentControl = fFormatExporters[fFormatCombo.getSelectionIndex()].createControl(container, + fMemoryBlock, fProperties, ExportMemoryDialog.this); + } + }); + + + fFormatCombo.select(0); + fCurrentControl = fFormatExporters[0].createControl(container, + fMemoryBlock, fProperties, ExportMemoryDialog.this); + + return composite; + } + + public void setValid(boolean isValid) + { + getButton(IDialogConstants.OK_ID).setEnabled(isValid); + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/ImportMemoryDialog.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/ImportMemoryDialog.java new file mode 100644 index 00000000000..98574c8a504 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/ImportMemoryDialog.java @@ -0,0 +1,245 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.math.BigInteger; +import java.util.Properties; +import java.util.Vector; + +import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryImporter; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.internal.ui.views.memory.MemoryView; +import org.eclipse.debug.internal.ui.views.memory.RenderingViewPane; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; +import org.eclipse.debug.ui.memory.IRepositionableMemoryRendering; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.SelectionDialog; +import org.eclipse.ui.progress.UIJob; + +public class ImportMemoryDialog extends SelectionDialog +{ + + private Combo fFormatCombo; + + private IMemoryBlock fMemoryBlock; + + private Control fCurrentControl = null; + + private IMemoryImporter fFormatImporters[]; + private String fFormatNames[]; + + private Properties fProperties = new Properties(); + + private MemoryView fMemoryView; + + public ImportMemoryDialog(Shell parent, IMemoryBlock memoryBlock, MemoryView view) + { + super(parent); + super.setTitle("Download to Memory"); + setShellStyle(getShellStyle() | SWT.RESIZE); + + fMemoryBlock = memoryBlock; + fMemoryView = view; + } + + protected void scrollRenderings(final BigInteger address) + { + UIJob job = new UIJob("repositionRenderings"){ //$NON-NLS-1$ + public IStatus runInUIThread(IProgressMonitor monitor) { + final IMemoryRenderingContainer containers[] = fMemoryView.getMemoryRenderingContainers(); + for(int i = 0; i < containers.length; i++) + { + if(containers[i] instanceof RenderingViewPane) + { + IMemoryRendering rendering = containers[i].getActiveRendering(); + + if(rendering instanceof IRepositionableMemoryRendering) + { + try + { + ((IRepositionableMemoryRendering) rendering).goToAddress(address); + } + catch (DebugException e) + { + // do nothing + } + } + } + } + + return Status.OK_STATUS; + }}; + job.setSystem(true); + job.setThread(Display.getDefault().getThread()); + job.schedule(); + + + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) + */ + protected void createButtonsForButtonBar(Composite parent) { + super.createButtonsForButtonBar(parent); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.SelectionDialog#getResult() + */ + public Object[] getResult() { + + Object[] results = super.getResult(); + + if (results != null) + { + return results; + } + return new Object[0]; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#cancelPressed() + */ + protected void cancelPressed() { + + setResult(null); + + super.cancelPressed(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + protected void okPressed() { + if(fCurrentControl != null) + fCurrentControl.dispose(); + fFormatImporters[fFormatCombo.getSelectionIndex()].importMemory(); + + super.okPressed(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + protected Control createDialogArea(Composite parent) { + + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, MemoryTransportPlugin.getUniqueIdentifier() + ".ImportMemoryDialog_context"); //$NON-NLS-1$ + Composite composite = new Composite(parent, SWT.NONE); + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + + // format + + Label textLabel = new Label(composite, SWT.NONE); + textLabel.setText("Format: "); + + fFormatCombo = new Combo(composite, SWT.BORDER | SWT.READ_ONLY); + + FormData data = new FormData(); + data.top = new FormAttachment(fFormatCombo, 0, SWT.CENTER); + textLabel.setLayoutData(data); + + data = new FormData(); + data.left = new FormAttachment(textLabel); + fFormatCombo.setLayoutData(data); + + Vector importers = new Vector(); + + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = + registry.getExtensionPoint("org.eclipse.cdt.debug.ui.memory.transport.memoryTransport"); + IConfigurationElement points[] = + extensionPoint.getConfigurationElements(); + + for (int i = 0; i < points.length; i++) + { + IConfigurationElement element = points[i]; + if("importer".equals(element.getName())) + { + try + { + importers.addElement((IMemoryImporter) element.createExecutableExtension("class")); + } + catch(Exception e) { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + } + } + + fFormatImporters = new IMemoryImporter[importers.size()]; + fFormatNames = new String[importers.size()]; + for(int i = 0; i < fFormatImporters.length; i++) + { + fFormatImporters[i] = (IMemoryImporter) importers.elementAt(i); + fFormatNames[i] = ((IMemoryImporter) importers.elementAt(i)).getName(); + } + + final Composite container = new Composite(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fFormatCombo); + data.left = new FormAttachment(0); + container.setLayoutData(data); + + fFormatCombo.setItems(fFormatNames); + + fFormatCombo.addSelectionListener(new SelectionListener(){ + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + public void widgetSelected(SelectionEvent e) { + if(fCurrentControl != null) + fCurrentControl.dispose(); + fCurrentControl = fFormatImporters[fFormatCombo.getSelectionIndex()].createControl(container, + fMemoryBlock, fProperties, ImportMemoryDialog.this); + } + }); + + fFormatCombo.select(0); + fCurrentControl = + fFormatImporters[0].createControl(container,fMemoryBlock, fProperties, ImportMemoryDialog.this); + + return composite; + } + + public void setValid(boolean isValid) + { + getButton(IDialogConstants.OK_ID).setEnabled(isValid); + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/MemoryTransportPlugin.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/MemoryTransportPlugin.java new file mode 100644 index 00000000000..4449a062dbf --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/MemoryTransportPlugin.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +public class MemoryTransportPlugin extends AbstractUIPlugin +{ + private static final String PLUGIN_ID = "org.eclipse.cdt.debug.ui.memory.transport"; //$NON-NLS-1$ + + private static MemoryTransportPlugin plugin; + + public MemoryTransportPlugin() + { + super(); + plugin = this; + } + + /** + * Returns the shared instance. + */ + public static MemoryTransportPlugin getDefault() { + return plugin; + } + + /** + * Returns the unique identifier for this plugin. + */ + public static String getUniqueIdentifier() { + return PLUGIN_ID; + } + + /** + * Returns the currently active workbench window shell or null + * if none. + * + * @return the currently active workbench window shell or null + */ + public static Shell getShell() { + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) { + IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); + if (windows.length > 0) { + return windows[0].getShell(); + } + } + else { + return window.getShell(); + } + return null; + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/Messages.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/Messages.java new file mode 100644 index 00000000000..e0d4fdc92a1 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/Messages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class Messages { + private static final String BUNDLE_NAME = "org.eclipse.cdt.debug.ui.memory.transport.messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private Messages() { + } + + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextExporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextExporter.java new file mode 100644 index 00000000000..48d62a568d7 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextExporter.java @@ -0,0 +1,476 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.io.File; +import java.io.FileWriter; +import java.math.BigInteger; +import java.util.Properties; + +import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryExporter; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class PlainTextExporter implements IMemoryExporter { + + File fOutputFile; + BigInteger fStartAddress; + BigInteger fEndAddress; + + private Text fStartText; + private Text fEndText; + private Text fLengthText; + private Text fFileText; + + private IMemoryBlock fMemoryBlock; + + private ExportMemoryDialog fParentDialog; + + private Properties fProperties; + + public Control createControl(final Composite parent, IMemoryBlock memBlock, Properties properties, ExportMemoryDialog parentDialog) + { + fMemoryBlock = memBlock; + fParentDialog = parentDialog; + fProperties = properties; + + Composite composite = new Composite(parent, SWT.NONE) + { + public void dispose() + { + fProperties.setProperty(TRANSFER_FILE, fFileText.getText()); + fProperties.setProperty(TRANSFER_START, fStartText.getText()); + fProperties.setProperty(TRANSFER_END, fEndText.getText()); + + fStartAddress = getStartAddress(); + fEndAddress = getEndAddress(); + fOutputFile = getFile(); + + super.dispose(); + } + }; + + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + + // start address + + Label startLabel = new Label(composite, SWT.NONE); + startLabel.setText("Start address: "); + FormData data = new FormData(); + startLabel.setLayoutData(data); + + fStartText = new Text(composite, SWT.NONE); + data = new FormData(); + data.left = new FormAttachment(startLabel); + data.width = 100; + fStartText.setLayoutData(data); + + // end address + + Label endLabel = new Label(composite, SWT.NONE); + endLabel.setText("End address: "); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(fStartText); + endLabel.setLayoutData(data); + + fEndText = new Text(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(endLabel); + data.width = 100; + fEndText.setLayoutData(data); + + // length + + Label lengthLabel = new Label(composite, SWT.NONE); + lengthLabel.setText("Length: "); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(fEndText); + lengthLabel.setLayoutData(data); + + fLengthText = new Text(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(lengthLabel); + data.width = 100; + fLengthText.setLayoutData(data); + + // file + + Label fileLabel = new Label(composite, SWT.NONE); + fFileText = new Text(composite, SWT.NONE); + Button fileButton = new Button(composite, SWT.PUSH); + + fileLabel.setText("File name: "); + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + fileLabel.setLayoutData(data); + + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + data.left = new FormAttachment(fileLabel); + data.width = 300; + fFileText.setLayoutData(data); + + fileButton.setText("Browse..."); + data = new FormData(); + data.top = new FormAttachment(fLengthText); + data.left = new FormAttachment(fFileText); + fileButton.setLayoutData(data); + + + fFileText.setText(properties.getProperty(TRANSFER_FILE, "")); + try + { + BigInteger startAddress = null; + if(fMemoryBlock instanceof IMemoryBlockExtension) + startAddress = ((IMemoryBlockExtension) fMemoryBlock) + .getBigBaseAddress(); // FIXME use selection/caret address? + else + startAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress()); + + if(properties.getProperty(TRANSFER_START) != null) + fStartText.setText(properties.getProperty(TRANSFER_START)); + else + fStartText.setText("0x" + startAddress.toString(16)); + + if(properties.getProperty(TRANSFER_END) != null) + fEndText.setText(properties.getProperty(TRANSFER_END)); + else + fEndText.setText("0x" + startAddress.toString(16)); + + fLengthText.setText(getEndAddress().subtract(getStartAddress()).toString()); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + + fileButton.addSelectionListener(new SelectionListener() { + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + public void widgetSelected(SelectionEvent e) { + FileDialog dialog = new FileDialog(parent.getShell(), SWT.SAVE); + dialog.setText("Choose memory export file"); + dialog.setFilterExtensions(new String[] { "*.*;*" } ); + dialog.setFilterNames(new String[] { "All Files" } ); + dialog.setFileName(fFileText.getText()); + dialog.open(); + + String filename = dialog.getFileName(); + if(filename != null && filename.length() != 0 ) + { + fFileText.setText(dialog.getFilterPath() + File.separator + filename); + } + + validate(); + } + + }); + + fStartText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + boolean valid = true; + try + { + getStartAddress(); + } + catch(Exception ex) + { + valid = false; + } + + fStartText.setForeground(valid ? Display.getDefault().getSystemColor(SWT.COLOR_BLACK) : + Display.getDefault().getSystemColor(SWT.COLOR_RED)); + + // + + BigInteger endAddress = getEndAddress(); + BigInteger startAddress = getStartAddress(); + + fLengthText.setText(endAddress.subtract(startAddress).toString()); + + validate(); + } + + public void keyPressed(KeyEvent e) {} + }); + + fEndText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + try + { + getEndAddress(); + fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + + BigInteger endAddress = getEndAddress(); + BigInteger startAddress = getStartAddress(); + + String lengthString = endAddress.subtract(startAddress).toString(); + + if(!fLengthText.getText().equals(lengthString)) + fLengthText.setText(lengthString); + } + catch(Exception ex) + { + fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + } + + validate(); + } + + public void keyPressed(KeyEvent e) {} + + }); + + fLengthText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + try + { + BigInteger length = getLength(); + fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + BigInteger startAddress = getStartAddress(); + String endString = "0x" + startAddress.add(length).toString(16); + if(!fEndText.getText().equals(endString)) + fEndText.setText(endString); + } + catch(Exception ex) + { + fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + } + + validate(); + } + + + + public void keyPressed(KeyEvent e) { + + } + }); + + fFileText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + validate(); + } + + public void keyPressed(KeyEvent e) { + + } + }); + + composite.pack(); + + return composite; + } + + public BigInteger getEndAddress() + { + String text = fEndText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger endAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return endAddress; + } + + public BigInteger getStartAddress() + { + String text = fStartText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger startAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return startAddress; + } + + public BigInteger getLength() + { + String text = fLengthText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger lengthAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return lengthAddress; + } + + public File getFile() + { + return new File(fFileText.getText()); + } + + private void validate() + { + boolean isValid = true; + + try + { + getEndAddress(); + + getStartAddress(); + + BigInteger length = getLength(); + + if(length.compareTo(BigInteger.ZERO) <= 0) + isValid = false; + + if(!getFile().getParentFile().exists()) + isValid = false; + } + catch(Exception e) + { + isValid = false; + } + + fParentDialog.setValid(isValid); + + } + + public String getId() + { + return "PlainTextExporter"; + } + + public String getName() + { + return "Plain Text"; + } + + public void exportMemory() { + Job job = new Job("Memory Export to Plain Text File"){ //$NON-NLS-1$ + public IStatus run(IProgressMonitor monitor) { + + try + { + try + { + // FIXME 4 byte default + + BigInteger CELLSIZE = BigInteger.valueOf(4); + + BigInteger COLUMNS = BigInteger.valueOf(5); // FIXME + + BigInteger DATA_PER_LINE = CELLSIZE.multiply(COLUMNS); + + BigInteger transferAddress = fStartAddress; + + FileWriter writer = new FileWriter(fOutputFile); + + BigInteger jobs = fEndAddress.subtract(transferAddress).divide(DATA_PER_LINE); + BigInteger factor = BigInteger.ONE; + if(jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) + { + factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); + jobs = jobs.divide(factor); + } + + monitor.beginTask("Transferring Data", jobs.intValue()); + + BigInteger jobCount = BigInteger.ZERO; + while(transferAddress.compareTo(fEndAddress) < 0 && !monitor.isCanceled()) + { + BigInteger length = DATA_PER_LINE; + if(fEndAddress.subtract(transferAddress).compareTo(length) < 0) + length = fEndAddress.subtract(transferAddress); + + StringBuffer buf = new StringBuffer(); + +// String transferAddressString = transferAddress.toString(16); + + // future option +// for(int i = 0; i < 8 - transferAddressString.length(); i++) +// buf.append("0"); +// buf.append(transferAddressString); +// buf.append(" "); // TODO tab? + + // data + + for(int i = 0; i < length.divide(CELLSIZE).intValue(); i++) + { + if(i != 0) + buf.append(" "); + MemoryByte bytes[] = ((IMemoryBlockExtension) fMemoryBlock).getBytesFromAddress( + transferAddress.add(CELLSIZE.multiply(BigInteger.valueOf(i))), + CELLSIZE.longValue() / ((IMemoryBlockExtension) fMemoryBlock).getAddressableSize()); + for(int byteIndex = 0; byteIndex < bytes.length; byteIndex++) + { + String bString = BigInteger.valueOf(0xFF & bytes[byteIndex].getValue()).toString(16); + if(bString.length() == 1) + buf.append("0"); + buf.append(bString); + } + } + + writer.write(buf.toString().toUpperCase()); + writer.write("\n"); + + transferAddress = transferAddress.add(length); + + jobCount = jobCount.add(BigInteger.ONE); + if(jobCount.compareTo(factor) == 0) + { + jobCount = BigInteger.ZERO; + monitor.worked(1); + } + } + + writer.close(); + monitor.done(); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + return Status.OK_STATUS; + }}; + job.setUser(true); + job.schedule(); + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextImporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextImporter.java new file mode 100644 index 00000000000..2da8b589549 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextImporter.java @@ -0,0 +1,371 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.util.Properties; +import java.util.StringTokenizer; + +import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryImporter; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class PlainTextImporter implements IMemoryImporter { + + File fInputFile; + BigInteger fStartAddress; + boolean fUseCustomAddress; + Boolean fScrollToStart; + + private Text fStartText; + private Text fFileText; + +// private Button fComboRestoreToThisAddress; +// private Button fComboRestoreToFileAddress; + + private Button fScrollToBeginningOnImportComplete; + + private IMemoryBlock fMemoryBlock; + + private ImportMemoryDialog fParentDialog; + + private Properties fProperties; + + private static final int BUFFER_LENGTH = 64 * 1024; + + public Control createControl(final Composite parent, IMemoryBlock memBlock, Properties properties, ImportMemoryDialog parentDialog) + { + fMemoryBlock = memBlock; + fParentDialog = parentDialog; + fProperties = properties; + + fUseCustomAddress = true; + + Composite composite = new Composite(parent, SWT.NONE) + { + public void dispose() + { + fProperties.setProperty(TRANSFER_FILE, fFileText.getText()); + fProperties.setProperty(TRANSFER_START, fStartText.getText()); + fProperties.setProperty(TRANSFER_SCROLL_TO_START, fScrollToStart.toString()); + + fStartAddress = getStartAddress(); + fInputFile = getFile(); + + super.dispose(); + } + }; + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + +// // restore to file address +// +// fComboRestoreToFileAddress = new Button(composite, SWT.RADIO); +// fComboRestoreToFileAddress.setText("Restore to address specified in the file"); +// //comboRestoreToFileAddress.setLayoutData(data); +// +// // restore to this address +// +// fComboRestoreToThisAddress = new Button(composite, SWT.RADIO); +// fComboRestoreToThisAddress.setText("Restore to this address: "); + FormData data = new FormData(); +// data.top = new FormAttachment(fComboRestoreToFileAddress); +// fComboRestoreToThisAddress.setLayoutData(data); + + Label labelStartText = new Label(composite, SWT.NONE); + labelStartText.setText("Restore to address: "); + + fStartText = new Text(composite, SWT.NONE); + data = new FormData(); +// data.top = new FormAttachment(fComboRestoreToFileAddress); + data.left = new FormAttachment(labelStartText); + data.width = 100; + fStartText.setLayoutData(data); + + // file + + Label fileLabel = new Label(composite, SWT.NONE); + fFileText = new Text(composite, SWT.NONE); + Button fileButton = new Button(composite, SWT.PUSH); + + fileLabel.setText("File name: "); + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + fileLabel.setLayoutData(data); + + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + data.left = new FormAttachment(fileLabel); + data.width = 300; + fFileText.setLayoutData(data); + + fileButton.setText("Browse..."); + data = new FormData(); + data.top = new FormAttachment(fStartText); + data.left = new FormAttachment(fFileText); + fileButton.setLayoutData(data); + + fFileText.setText(properties.getProperty(TRANSFER_FILE, "")); + fScrollToStart = new Boolean(properties.getProperty(TRANSFER_SCROLL_TO_START, "true")); + try + { + BigInteger startAddress = null; + if(fMemoryBlock instanceof IMemoryBlockExtension) + startAddress = ((IMemoryBlockExtension) fMemoryBlock) + .getBigBaseAddress(); // FIXME use selection/caret address? + else + startAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress()); + + if(properties.getProperty(TRANSFER_START) != null) + fStartText.setText(properties.getProperty(TRANSFER_START)); + else + fStartText.setText("0x" + startAddress.toString(16)); + + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + + fileButton.addSelectionListener(new SelectionListener() { + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + public void widgetSelected(SelectionEvent e) { + FileDialog dialog = new FileDialog(parent.getShell(), SWT.SAVE); + dialog.setText("Choose memory import file"); + dialog.setFilterExtensions(new String[] { "*.*;*" } ); + dialog.setFilterNames(new String[] { "All Files" } ); + dialog.setFileName(fFileText.getText()); + dialog.open(); + + String filename = dialog.getFileName(); + if(filename != null && filename.length() != 0 ) + { + fFileText.setText(dialog.getFilterPath() + File.separator + filename); + } + + validate(); + } + + }); + + fStartText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + boolean valid = true; + try + { + getStartAddress(); + } + catch(Exception ex) + { + valid = false; + } + + fStartText.setForeground(valid ? Display.getDefault().getSystemColor(SWT.COLOR_BLACK) : + Display.getDefault().getSystemColor(SWT.COLOR_RED)); + + // + + validate(); + } + + }); + fFileText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + validate(); + } + }); + + fScrollToBeginningOnImportComplete = new Button(composite, SWT.CHECK); + fScrollToBeginningOnImportComplete.setText("Scroll to File Start Address"); + data = new FormData(); + data.top = new FormAttachment(fileButton); + fScrollToBeginningOnImportComplete.setLayoutData(data); + + composite.pack(); + parent.pack(); + + Display.getDefault().asyncExec(new Runnable(){ + public void run() + { + validate(); + } + }); + + return composite; + } + + private void validate() + { + boolean isValid = true; + + try + { + getStartAddress(); + if(!getFile().exists()) + isValid = false; + } + catch(Exception e) + { + isValid = false; + } + + fParentDialog.setValid(isValid); + } + + public boolean getScrollToStart() + { + return fScrollToBeginningOnImportComplete.getSelection(); + } + + public BigInteger getStartAddress() + { + String text = fStartText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger startAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return startAddress; + } + + public File getFile() + { + return new File(fFileText.getText()); + } + + public String getId() + { + return "PlainTextImporter"; + } + + public String getName() + { + return "Plain Text"; + } + + public void importMemory() { + Job job = new Job("Memory Import from Plain Text File"){ //$NON-NLS-1$ + + public IStatus run(IProgressMonitor monitor) { + + try + { + try + { + BufferedMemoryWriter memoryWriter = new BufferedMemoryWriter((IMemoryBlockExtension) fMemoryBlock, BUFFER_LENGTH); + + BigInteger scrollToAddress = null; + + BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fInputFile))); + + BigInteger jobs = BigInteger.valueOf(fInputFile.length()); + BigInteger factor = BigInteger.ONE; + if(jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) + { + factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); + jobs = jobs.divide(factor); + } + + monitor.beginTask("Transferring Data", jobs.intValue()); //$NON-NLS-1$ + + BigInteger jobCount = BigInteger.ZERO; + BigInteger recordAddress = fStartAddress; + String line = reader.readLine(); + while(line != null && !monitor.isCanceled()) + { + StringTokenizer st = new StringTokenizer(line, " "); + int bytesRead = 0; + while(st.hasMoreElements()) + { + String valueString = (String) st.nextElement(); + int position = 0; + byte data[] = new byte[valueString.length() / 2]; + for(int i = 0; i < data.length; i++) + { + data[i] = new BigInteger(valueString.substring(position++, position++ + 1), 16).byteValue(); + } + + if(scrollToAddress == null) + scrollToAddress = recordAddress; + + BigInteger writeAddress = + + recordAddress.subtract(((IMemoryBlockExtension)fMemoryBlock).getBigBaseAddress()).add(BigInteger.valueOf(bytesRead)); + + memoryWriter.write(writeAddress, data); + + bytesRead += data.length; + } + + recordAddress = recordAddress.add(BigInteger.valueOf(bytesRead)); + + jobCount = jobCount.add(BigInteger.valueOf(bytesRead)); + while(jobCount.compareTo(factor) >= 0) + { + jobCount = jobCount.subtract(factor); + monitor.worked(1); + } + + line = reader.readLine(); + } + + memoryWriter.flush(); + reader.close(); + monitor.done(); + + if(fProperties.getProperty(TRANSFER_SCROLL_TO_START, "false").equals("true")) + fParentDialog.scrollRenderings(scrollToAddress); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + } + catch(Exception e) {e.printStackTrace();} + return Status.OK_STATUS; + }}; + job.setUser(true); + job.schedule(); + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryExporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryExporter.java new file mode 100644 index 00000000000..ca15bfdd2a8 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryExporter.java @@ -0,0 +1,465 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.io.File; +import java.io.FileOutputStream; +import java.math.BigInteger; +import java.util.Properties; + +import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryExporter; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class RAWBinaryExporter implements IMemoryExporter +{ + File fOutputFile; + BigInteger fStartAddress; + BigInteger fEndAddress; + + private Text fStartText; + private Text fEndText; + private Text fLengthText; + private Text fFileText; + + private IMemoryBlock fMemoryBlock; + + private ExportMemoryDialog fParentDialog; + + private Properties fProperties; + + public Control createControl(final Composite parent, IMemoryBlock memBlock, Properties properties, ExportMemoryDialog parentDialog) + { + fMemoryBlock = memBlock; + fParentDialog = parentDialog; + fProperties = properties; + + Composite composite = new Composite(parent, SWT.NONE) + { + public void dispose() + { + fProperties.setProperty(TRANSFER_FILE, fFileText.getText()); + fProperties.setProperty(TRANSFER_START, fStartText.getText()); + fProperties.setProperty(TRANSFER_END, fEndText.getText()); + + fStartAddress = getStartAddress(); + fEndAddress = getEndAddress(); + fOutputFile = getFile(); + + super.dispose(); + } + }; + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + + // start address + + Label startLabel = new Label(composite, SWT.NONE); + startLabel.setText("Start address: "); + FormData data = new FormData(); + startLabel.setLayoutData(data); + + fStartText = new Text(composite, SWT.NONE); + data = new FormData(); + data.left = new FormAttachment(startLabel); + data.width = 100; + fStartText.setLayoutData(data); + + // end address + + Label endLabel = new Label(composite, SWT.NONE); + endLabel.setText("End address: "); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(fStartText); + endLabel.setLayoutData(data); + + fEndText = new Text(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(endLabel); + data.width = 100; + fEndText.setLayoutData(data); + + // length + + Label lengthLabel = new Label(composite, SWT.NONE); + lengthLabel.setText("Length: "); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(fEndText); + lengthLabel.setLayoutData(data); + + fLengthText = new Text(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(lengthLabel); + data.width = 100; + fLengthText.setLayoutData(data); + + // file + + Label fileLabel = new Label(composite, SWT.NONE); + fFileText = new Text(composite, SWT.NONE); + Button fileButton = new Button(composite, SWT.PUSH); + + fileLabel.setText("File name: "); + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + fileLabel.setLayoutData(data); + + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + data.left = new FormAttachment(fileLabel); + data.width = 300; + fFileText.setLayoutData(data); + + fileButton.setText("Browse..."); + data = new FormData(); + data.top = new FormAttachment(fLengthText); + data.left = new FormAttachment(fFileText); + fileButton.setLayoutData(data); + + fFileText.setText(properties.getProperty(TRANSFER_FILE, "")); + try + { + BigInteger startAddress = null; + if(fMemoryBlock instanceof IMemoryBlockExtension) + startAddress = ((IMemoryBlockExtension) fMemoryBlock).getBigBaseAddress(); + else + startAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress()); + + if(properties.getProperty(TRANSFER_START) != null) + fStartText.setText(properties.getProperty(TRANSFER_START)); + else + fStartText.setText("0x" + startAddress.toString(16)); + + if(properties.getProperty(TRANSFER_END) != null) + fEndText.setText(properties.getProperty(TRANSFER_END)); + else + fEndText.setText("0x" + startAddress.toString(16)); + + fLengthText.setText(getEndAddress().subtract(getStartAddress()).toString()); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + + fileButton.addSelectionListener(new SelectionListener() { + + public void widgetDefaultSelected(SelectionEvent e) { + } + + public void widgetSelected(SelectionEvent e) { + FileDialog dialog = new FileDialog(parent.getShell(), SWT.SAVE); + dialog.setText("Choose memory export file"); + dialog.setFilterExtensions(new String[] { "*.*;*" } ); + dialog.setFilterNames(new String[] { "All Files" } ); + dialog.setFileName(fFileText.getText()); + dialog.open(); + + String filename = dialog.getFileName(); + if(filename != null && filename.length() != 0 ) + { + fFileText.setText(dialog.getFilterPath() + File.separator + filename); + } + + validate(); + } + + }); + + fStartText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + boolean valid = true; + try + { + getStartAddress(); + } + catch(Exception ex) + { + valid = false; + } + + fStartText.setForeground(valid ? Display.getDefault().getSystemColor(SWT.COLOR_BLACK) : + Display.getDefault().getSystemColor(SWT.COLOR_RED)); + + // + + BigInteger endAddress = getEndAddress(); + BigInteger startAddress = getStartAddress(); + + fLengthText.setText(endAddress.subtract(startAddress).toString()); + + validate(); + } + + public void keyPressed(KeyEvent e) {} + }); + + fEndText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + try + { + getEndAddress(); + fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + + BigInteger endAddress = getEndAddress(); + BigInteger startAddress = getStartAddress(); + + String lengthString = endAddress.subtract(startAddress).toString(); + + if(!fLengthText.getText().equals(lengthString)) + fLengthText.setText(lengthString); + } + catch(Exception ex) + { + fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + } + + validate(); + } + + public void keyPressed(KeyEvent e) {} + + }); + + fLengthText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + try + { + BigInteger length = getLength(); + fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + BigInteger startAddress = getStartAddress(); + String endString = "0x" + startAddress.add(length).toString(16); + if(!fEndText.getText().equals(endString)) + fEndText.setText(endString); + } + catch(Exception ex) + { + fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + } + + validate(); + } + + + + public void keyPressed(KeyEvent e) { + + } + }); + + fFileText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + validate(); + } + + public void keyPressed(KeyEvent e) { + + } + }); + + composite.pack(); + parent.pack(); + + /* + * We need to perform a validation. If we do it immediately we will get an exception + * because things are not totally setup. So we schedule an immediate running of the + * validation. For a very brief time the view logically may show a state which does + * not reflect the true state of affairs. But the validate immediately corrects the + * info. In practice the user never sees the invalid state displayed, because of the + * speed of the draw of the dialog. + */ + Display.getDefault().asyncExec(new Runnable(){ + public void run() + { + validate(); + } + }); + + return composite; + } + + public BigInteger getEndAddress() + { + String text = fEndText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger endAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return endAddress; + } + + public BigInteger getStartAddress() + { + String text = fStartText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger startAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return startAddress; + } + + public BigInteger getLength() + { + String text = fLengthText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger lengthAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return lengthAddress; + } + + public File getFile() + { + return new File(fFileText.getText()); + } + + private void validate() + { + boolean isValid = true; + + try + { + getEndAddress(); + + getStartAddress(); + + BigInteger length = getLength(); + + if(length.compareTo(BigInteger.ZERO) <= 0) + isValid = false; + + if(!getFile().getParentFile().exists()) + isValid = false; + } + catch(Exception e) + { + isValid = false; + } + + fParentDialog.setValid(isValid); + } + + + public String getId() + { + return "rawbinary"; + } + + public String getName() + { + return "RAW Binary"; + } + + public void exportMemory() + { + Job job = new Job("Memory Export to RAW Binary File"){ //$NON-NLS-1$ + public IStatus run(IProgressMonitor monitor) { + + try + { + try + { + BigInteger DATA_PER_RECORD = BigInteger.valueOf(1024); + + BigInteger transferAddress = fStartAddress; + + FileOutputStream writer = new FileOutputStream(fOutputFile); + + BigInteger jobs = fEndAddress.subtract(transferAddress).divide(DATA_PER_RECORD); + BigInteger factor = BigInteger.ONE; + if(jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) + { + factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); + jobs = jobs.divide(factor); + } + + monitor.beginTask("Transferring Data", jobs.intValue()); + + BigInteger jobCount = BigInteger.ZERO; + while(transferAddress.compareTo(fEndAddress) < 0 && !monitor.isCanceled()) + { + BigInteger length = DATA_PER_RECORD; + if(fEndAddress.subtract(transferAddress).compareTo(length) < 0) + length = fEndAddress.subtract(transferAddress); + + // data + byte[] byteValues = new byte[length.intValue()]; + + MemoryByte bytes[] = ((IMemoryBlockExtension) fMemoryBlock).getBytesFromAddress(transferAddress, + length.longValue() / ((IMemoryBlockExtension) fMemoryBlock).getAddressableSize()); + for(int byteIndex = 0; byteIndex < bytes.length; byteIndex++) + { + byteValues[byteIndex] = bytes[byteIndex].getValue(); + } + + + writer.write(byteValues); + + transferAddress = transferAddress.add(length); + + jobCount = jobCount.add(BigInteger.ONE); + if(jobCount.compareTo(factor) == 0) + { + jobCount = BigInteger.ZERO; + monitor.worked(1); + } + } + + writer.close(); + monitor.done(); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + return Status.OK_STATUS; + }}; + job.setUser(true); + job.schedule(); + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryImporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryImporter.java new file mode 100644 index 00000000000..d0270ae962e --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryImporter.java @@ -0,0 +1,344 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.io.File; +import java.io.FileInputStream; +import java.math.BigInteger; +import java.util.Properties; + +import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryImporter; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class RAWBinaryImporter implements IMemoryImporter { + + File fInputFile; + BigInteger fStartAddress; + Boolean fScrollToStart; + + private Text fStartText; + private Text fFileText; + + private Button fScrollToBeginningOnImportComplete; + + private IMemoryBlock fMemoryBlock; + + private ImportMemoryDialog fParentDialog; + + private Properties fProperties; + + private static final int BUFFER_LENGTH = 64 * 1024; + + public Control createControl(final Composite parent, IMemoryBlock memBlock, Properties properties, ImportMemoryDialog parentDialog) + { + fMemoryBlock = memBlock; + fParentDialog = parentDialog; + fProperties = properties; + + Composite composite = new Composite(parent, SWT.NONE) + { + public void dispose() + { + fProperties.setProperty(TRANSFER_FILE, fFileText.getText()); + fProperties.setProperty(TRANSFER_START, fStartText.getText()); + fProperties.setProperty(TRANSFER_SCROLL_TO_START, fScrollToStart.toString()); + fStartAddress = getStartAddress(); + fInputFile = getFile(); + + super.dispose(); + } + }; + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + + // restore to this address + + Label labelStartText = new Label(composite, SWT.NONE); + labelStartText.setText("Restore to address: "); + + fStartText = new Text(composite, SWT.NONE); + FormData data = new FormData(); + data.left = new FormAttachment(labelStartText); + data.width = 100; + fStartText.setLayoutData(data); + + // file + + Label fileLabel = new Label(composite, SWT.NONE); + fFileText = new Text(composite, SWT.NONE); + Button fileButton = new Button(composite, SWT.PUSH); + + fileLabel.setText("File name: "); + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + fileLabel.setLayoutData(data); + + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + data.left = new FormAttachment(fileLabel); + data.width = 300; + fFileText.setLayoutData(data); + + fileButton.setText("Browse..."); + data = new FormData(); + data.top = new FormAttachment(fStartText); + data.left = new FormAttachment(fFileText); + fileButton.setLayoutData(data); + + fFileText.setText(properties.getProperty(TRANSFER_FILE, "")); + fScrollToStart = new Boolean(properties.getProperty(TRANSFER_SCROLL_TO_START, "true")); + try + { + BigInteger startAddress = null; + if(fMemoryBlock instanceof IMemoryBlockExtension) + startAddress = ((IMemoryBlockExtension) fMemoryBlock).getBigBaseAddress(); + else + startAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress()); + + if(properties.getProperty(TRANSFER_START) != null) + fStartText.setText(properties.getProperty(TRANSFER_START)); + else + fStartText.setText("0x" + startAddress.toString(16)); + + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + + fileButton.addSelectionListener(new SelectionListener() { + + public void widgetDefaultSelected(SelectionEvent e) { + } + + public void widgetSelected(SelectionEvent e) { + FileDialog dialog = new FileDialog(parent.getShell(), SWT.SAVE); + dialog.setText("Choose memory import file"); + dialog.setFilterExtensions(new String[] { "*.*;*" } ); + dialog.setFilterNames(new String[] { "All Files" } ); + dialog.setFileName(fFileText.getText()); + dialog.open(); + + String filename = dialog.getFileName(); + if(filename != null && filename.length() != 0 ) + { + fFileText.setText(dialog.getFilterPath() + File.separator + filename); + } + + validate(); + } + + }); + + fStartText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + boolean valid = true; + try + { + getStartAddress(); + } + catch(Exception ex) + { + valid = false; + } + + fStartText.setForeground(valid ? Display.getDefault().getSystemColor(SWT.COLOR_BLACK) : + Display.getDefault().getSystemColor(SWT.COLOR_RED)); + + // + + validate(); + } + + }); + fFileText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + validate(); + } + }); + + fScrollToBeginningOnImportComplete = new Button(composite, SWT.CHECK); + fScrollToBeginningOnImportComplete.setText("Scroll to File Start Address"); + data = new FormData(); + data.top = new FormAttachment(fileButton); + fScrollToBeginningOnImportComplete.setLayoutData(data); + + composite.pack(); + parent.pack(); + + Display.getDefault().asyncExec(new Runnable(){ + public void run() + { + validate(); + } + }); + + return composite; + } + + private void validate() + { + boolean isValid = true; + + try + { + getStartAddress(); + if(!getFile().exists()) + isValid = false; + } + catch(Exception e) + { + isValid = false; + } + + fParentDialog.setValid(isValid); + } + + public boolean getScrollToStart() + { + return fScrollToBeginningOnImportComplete.getSelection(); + } + + public BigInteger getStartAddress() + { + String text = fStartText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger startAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return startAddress; + } + + public File getFile() + { + return new File(fFileText.getText()); + } + + public String getId() + { + return "rawbinary"; + } + + public String getName() + { + return "RAW Binary"; + } + + public void importMemory() { + Job job = new Job("Memory Import from RAW Binary File"){ //$NON-NLS-1$ + + public IStatus run(IProgressMonitor monitor) { + + try + { + try + { + BufferedMemoryWriter memoryWriter = new BufferedMemoryWriter((IMemoryBlockExtension) fMemoryBlock, BUFFER_LENGTH); + + BigInteger scrollToAddress = null; + + FileInputStream reader = new FileInputStream(fInputFile); + + BigInteger jobs = BigInteger.valueOf(fInputFile.length()); + BigInteger factor = BigInteger.ONE; + if(jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) + { + factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); + jobs = jobs.divide(factor); + } + + byte[] byteValues = new byte[1024]; + + monitor.beginTask("Transferring Data", jobs.intValue()); //$NON-NLS-1$ + + BigInteger jobCount = BigInteger.ZERO; + int actualByteCount = reader.read(byteValues); + BigInteger recordAddress = fStartAddress; + + while(actualByteCount != -1 && !monitor.isCanceled()) + { + byte data[] = new byte[actualByteCount]; + for(int i = 0; i < data.length; i++) + { + data[i] = byteValues[i]; + } + + if(scrollToAddress == null) + scrollToAddress = recordAddress; + + BigInteger baseAddress = null; + if(fMemoryBlock instanceof IMemoryBlockExtension) + baseAddress = ((IMemoryBlockExtension) fMemoryBlock).getBigBaseAddress(); + else + baseAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress()); + + memoryWriter.write(recordAddress.subtract(baseAddress), data); + + jobCount = jobCount.add(BigInteger.valueOf(actualByteCount)); + while(jobCount.compareTo(factor) >= 0) + { + jobCount = jobCount.subtract(factor); + monitor.worked(1); + } + + recordAddress.add(BigInteger.valueOf(actualByteCount)); + actualByteCount = reader.read(byteValues); + } + + memoryWriter.flush(); + reader.close(); + monitor.done(); + + if(fProperties.getProperty(TRANSFER_SCROLL_TO_START, "false").equals("true")) + fParentDialog.scrollRenderings(scrollToAddress); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + return Status.OK_STATUS; + }}; + job.setUser(true); + job.schedule(); + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordExporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordExporter.java new file mode 100644 index 00000000000..8e6f61b7c9a --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordExporter.java @@ -0,0 +1,508 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.io.File; +import java.io.FileWriter; +import java.math.BigInteger; +import java.util.Properties; + +import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryExporter; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class SRecordExporter implements IMemoryExporter +{ + File fOutputFile; + BigInteger fStartAddress; + BigInteger fEndAddress; + + private Text fStartText; + private Text fEndText; + private Text fLengthText; + private Text fFileText; + + private IMemoryBlock fMemoryBlock; + + private ExportMemoryDialog fParentDialog; + + private Properties fProperties; + + public Control createControl(final Composite parent, IMemoryBlock memBlock, Properties properties, ExportMemoryDialog parentDialog) + { + fMemoryBlock = memBlock; + fParentDialog = parentDialog; + fProperties = properties; + + Composite composite = new Composite(parent, SWT.NONE) + { + public void dispose() + { + fProperties.setProperty(TRANSFER_FILE, fFileText.getText()); + fProperties.setProperty(TRANSFER_START, fStartText.getText()); + fProperties.setProperty(TRANSFER_END, fEndText.getText()); + + fStartAddress = getStartAddress(); + fEndAddress = getEndAddress(); + fOutputFile = getFile(); + + super.dispose(); + } + }; + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + + // start address + + Label startLabel = new Label(composite, SWT.NONE); + startLabel.setText("Start address: "); + FormData data = new FormData(); + startLabel.setLayoutData(data); + + fStartText = new Text(composite, SWT.NONE); + data = new FormData(); + data.left = new FormAttachment(startLabel); + data.width = 100; + fStartText.setLayoutData(data); + + // end address + + Label endLabel = new Label(composite, SWT.NONE); + endLabel.setText("End address: "); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(fStartText); + endLabel.setLayoutData(data); + + fEndText = new Text(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(endLabel); + data.width = 100; + fEndText.setLayoutData(data); + + // length + + Label lengthLabel = new Label(composite, SWT.NONE); + lengthLabel.setText("Length: "); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(fEndText); + lengthLabel.setLayoutData(data); + + fLengthText = new Text(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fStartText, 0, SWT.CENTER); + data.left = new FormAttachment(lengthLabel); + data.width = 100; + fLengthText.setLayoutData(data); + + // file + + Label fileLabel = new Label(composite, SWT.NONE); + fFileText = new Text(composite, SWT.NONE); + Button fileButton = new Button(composite, SWT.PUSH); + + fileLabel.setText("File name: "); + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + fileLabel.setLayoutData(data); + + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + data.left = new FormAttachment(fileLabel); + data.width = 300; + fFileText.setLayoutData(data); + + fileButton.setText("Browse..."); + data = new FormData(); + data.top = new FormAttachment(fLengthText); + data.left = new FormAttachment(fFileText); + fileButton.setLayoutData(data); + + fFileText.setText(properties.getProperty(TRANSFER_FILE, "")); + try + { + BigInteger startAddress = null; + if(fMemoryBlock instanceof IMemoryBlockExtension) + startAddress = ((IMemoryBlockExtension) fMemoryBlock) + .getBigBaseAddress(); // FIXME use selection/caret address? + else + startAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress()); + + if(properties.getProperty(TRANSFER_START) != null) + fStartText.setText(properties.getProperty(TRANSFER_START)); + else + fStartText.setText("0x" + startAddress.toString(16)); + + if(properties.getProperty(TRANSFER_END) != null) + fEndText.setText(properties.getProperty(TRANSFER_END)); + else + fEndText.setText("0x" + startAddress.toString(16)); + + fLengthText.setText(getEndAddress().subtract(getStartAddress()).toString()); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + + fileButton.addSelectionListener(new SelectionListener() { + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + public void widgetSelected(SelectionEvent e) { + FileDialog dialog = new FileDialog(parent.getShell(), SWT.SAVE); + dialog.setText("Choose memory export file"); + dialog.setFilterExtensions(new String[] { "*.*;*" } ); + dialog.setFilterNames(new String[] { "All Files" } ); + dialog.setFileName(fFileText.getText()); + dialog.open(); + + String filename = dialog.getFileName(); + if(filename != null && filename.length() != 0 ) + { + fFileText.setText(dialog.getFilterPath() + File.separator + filename); + } + + validate(); + } + + }); + + fStartText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + boolean valid = true; + try + { + getStartAddress(); + } + catch(Exception ex) + { + valid = false; + } + + fStartText.setForeground(valid ? Display.getDefault().getSystemColor(SWT.COLOR_BLACK) : + Display.getDefault().getSystemColor(SWT.COLOR_RED)); + + // + + BigInteger endAddress = getEndAddress(); + BigInteger startAddress = getStartAddress(); + + fLengthText.setText(endAddress.subtract(startAddress).toString()); + + validate(); + } + + public void keyPressed(KeyEvent e) {} + }); + + fEndText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + try + { + getEndAddress(); + fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + + BigInteger endAddress = getEndAddress(); + BigInteger startAddress = getStartAddress(); + + String lengthString = endAddress.subtract(startAddress).toString(); + + if(!fLengthText.getText().equals(lengthString)) + fLengthText.setText(lengthString); + } + catch(Exception ex) + { + fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + } + + validate(); + } + + public void keyPressed(KeyEvent e) {} + + }); + + fLengthText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + try + { + BigInteger length = getLength(); + fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + BigInteger startAddress = getStartAddress(); + String endString = "0x" + startAddress.add(length).toString(16); + if(!fEndText.getText().equals(endString)) + fEndText.setText(endString); + } + catch(Exception ex) + { + fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + } + + validate(); + } + + + + public void keyPressed(KeyEvent e) { + + } + }); + + fFileText.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + validate(); + } + + public void keyPressed(KeyEvent e) { + + } + }); + + composite.pack(); + parent.pack(); + + /* + * We need to perform a validation. If we do it immediately we will get an exception + * because things are not totally setup. So we schedule an immediate running of the + * validation. For a very brief time the view logically may show a state which does + * not reflect the true state of affairs. But the validate immediately corrects the + * info. In practice the user never sees the invalid state displayed, because of the + * speed of the draw of the dialog. + */ + Display.getDefault().asyncExec(new Runnable(){ + public void run() + { + validate(); + } + }); + + return composite; + } + + public BigInteger getEndAddress() + { + String text = fEndText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger endAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return endAddress; + } + + public BigInteger getStartAddress() + { + String text = fStartText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger startAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return startAddress; + } + + public BigInteger getLength() + { + String text = fLengthText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger lengthAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return lengthAddress; + } + + public File getFile() + { + return new File(fFileText.getText()); + } + + private void validate() + { + boolean isValid = true; + + try + { + getEndAddress(); + + getStartAddress(); + + BigInteger length = getLength(); + + if(length.compareTo(BigInteger.ZERO) <= 0) + isValid = false; + + if(!getFile().getParentFile().exists()) + isValid = false; + } + catch(Exception e) + { + isValid = false; + } + + fParentDialog.setValid(isValid); + } + + + public String getId() + { + return "srecord"; + } + + public String getName() + { + return "SRecord"; + } + + public void exportMemory() + { + Job job = new Job("Memory Export to S-Record File"){ //$NON-NLS-1$ + public IStatus run(IProgressMonitor monitor) { + + try + { + try + { + // FIXME 4 byte default + + BigInteger DATA_PER_RECORD = BigInteger.valueOf(16); + + BigInteger transferAddress = fStartAddress; + + FileWriter writer = new FileWriter(fOutputFile); + + BigInteger jobs = fEndAddress.subtract(transferAddress).divide(DATA_PER_RECORD); + BigInteger factor = BigInteger.ONE; + if(jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) + { + factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); + jobs = jobs.divide(factor); + } + + monitor.beginTask("Transferring Data", jobs.intValue()); + + BigInteger jobCount = BigInteger.ZERO; + while(transferAddress.compareTo(fEndAddress) < 0 && !monitor.isCanceled()) + { + BigInteger length = DATA_PER_RECORD; + if(fEndAddress.subtract(transferAddress).compareTo(length) < 0) + length = fEndAddress.subtract(transferAddress); + + writer.write("S3"); // FIXME 4 byte address + + StringBuffer buf = new StringBuffer(); + + BigInteger sRecordLength = BigInteger.valueOf(4); // address size + sRecordLength = sRecordLength.add(length); + sRecordLength = sRecordLength.add(BigInteger.ONE); // checksum + + String transferAddressString = transferAddress.toString(16); + + String lengthString = sRecordLength.toString(16); + if(lengthString.length() == 1) + buf.append("0"); + buf.append(lengthString); + for(int i = 0; i < 8 - transferAddressString.length(); i++) + buf.append("0"); + buf.append(transferAddressString); + + // data + + MemoryByte bytes[] = ((IMemoryBlockExtension) fMemoryBlock).getBytesFromAddress(transferAddress, + length.longValue() / ((IMemoryBlockExtension) fMemoryBlock).getAddressableSize()); + for(int byteIndex = 0; byteIndex < bytes.length; byteIndex++) + { + String bString = BigInteger.valueOf(0xFF & bytes[byteIndex].getValue()).toString(16); + if(bString.length() == 1) + buf.append("0"); + buf.append(bString); + } + + /* + * The least significant byte of the one's complement of the sum of the values + * represented by the pairs of characters making up the records length, address, + * and the code/data fields. + */ + byte checksum = 0; + + for(int i = 0; i < buf.length(); i+=2) + { + BigInteger value = new BigInteger(buf.substring(i, i+2), 16); + checksum += value.byteValue(); + } + + String bString = BigInteger.valueOf(0xFF - checksum).and(BigInteger.valueOf(0xFF)).toString(16); + if(bString.length() == 1) + buf.append("0"); + buf.append(bString); + + writer.write(buf.toString().toUpperCase()); + writer.write("\n"); + + transferAddress = transferAddress.add(length); + + jobCount = jobCount.add(BigInteger.ONE); + if(jobCount.compareTo(factor) == 0) + { + jobCount = BigInteger.ZERO; + monitor.worked(1); + } + } + + writer.close(); + monitor.done(); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + return Status.OK_STATUS; + }}; + job.setUser(true); + job.schedule(); + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordImporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordImporter.java new file mode 100644 index 00000000000..4a586c48d8d --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordImporter.java @@ -0,0 +1,441 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.util.Properties; + +import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryImporter; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class SRecordImporter implements IMemoryImporter { + + File fInputFile; + BigInteger fStartAddress; + Boolean fScrollToStart; + + private Text fStartText; + private Text fFileText; + + private Button fComboRestoreToThisAddress; + private Button fComboRestoreToFileAddress; + + private Button fScrollToBeginningOnImportComplete; + + private IMemoryBlock fMemoryBlock; + + private ImportMemoryDialog fParentDialog; + + private Properties fProperties; + + private static final int BUFFER_LENGTH = 64 * 1024; + + public Control createControl(final Composite parent, IMemoryBlock memBlock, Properties properties, ImportMemoryDialog parentDialog) + { + fMemoryBlock = memBlock; + fParentDialog = parentDialog; + fProperties = properties; + + Composite composite = new Composite(parent, SWT.NONE) + { + public void dispose() + { + fProperties.setProperty(TRANSFER_FILE, fFileText.getText()); + fProperties.setProperty(TRANSFER_START, fStartText.getText()); + fProperties.setProperty(TRANSFER_SCROLL_TO_START, fScrollToStart.toString()); + fProperties.setProperty(TRANSFER_CUSTOM_START_ADDRESS, "" + fComboRestoreToThisAddress.getSelection()); + + fStartAddress = getStartAddress(); + fInputFile = getFile(); + + super.dispose(); + } + }; + FormLayout formLayout = new FormLayout(); + formLayout.spacing = 5; + formLayout.marginWidth = formLayout.marginHeight = 9; + composite.setLayout(formLayout); + + // restore to file address + + fComboRestoreToFileAddress = new Button(composite, SWT.RADIO); + fComboRestoreToFileAddress.setSelection(true); + fComboRestoreToFileAddress.setText("Restore to address specified in the file"); + fComboRestoreToFileAddress.setSelection(!new Boolean(properties.getProperty(TRANSFER_CUSTOM_START_ADDRESS, "false")).booleanValue()); + //comboRestoreToFileAddress.setLayoutData(data); + + // restore to this address + + fComboRestoreToThisAddress = new Button(composite, SWT.RADIO); + fComboRestoreToThisAddress.setText("Restore to this address: "); + fComboRestoreToThisAddress.setSelection(new Boolean(properties.getProperty(TRANSFER_CUSTOM_START_ADDRESS, "false")).booleanValue()); + FormData data = new FormData(); + data.top = new FormAttachment(fComboRestoreToFileAddress); + fComboRestoreToThisAddress.setLayoutData(data); + + fStartText = new Text(composite, SWT.NONE); + data = new FormData(); + data.top = new FormAttachment(fComboRestoreToFileAddress); + data.left = new FormAttachment(fComboRestoreToThisAddress); + data.width = 100; + fStartText.setLayoutData(data); + + fComboRestoreToFileAddress.addSelectionListener(new SelectionListener() { + + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + validate(); + } + }); + + fComboRestoreToThisAddress.addSelectionListener(new SelectionListener() { + + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + validate(); + } + }); + + // file + + Label fileLabel = new Label(composite, SWT.NONE); + fFileText = new Text(composite, SWT.NONE); + Button fileButton = new Button(composite, SWT.PUSH); + + fileLabel.setText("File name: "); + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + fileLabel.setLayoutData(data); + + data = new FormData(); + data.top = new FormAttachment(fileButton, 0, SWT.CENTER); + data.left = new FormAttachment(fileLabel); + data.width = 300; + fFileText.setLayoutData(data); + + fileButton.setText("Browse..."); + data = new FormData(); + data.top = new FormAttachment(fStartText); + data.left = new FormAttachment(fFileText); + fileButton.setLayoutData(data); + + fFileText.setText(properties.getProperty(TRANSFER_FILE, "")); + fScrollToStart = new Boolean(properties.getProperty(TRANSFER_SCROLL_TO_START, "true")); + try + { + BigInteger startAddress = null; + if(fMemoryBlock instanceof IMemoryBlockExtension) + startAddress = ((IMemoryBlockExtension) fMemoryBlock) + .getBigBaseAddress(); // FIXME use selection/caret address? + else + startAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress()); + + if(properties.getProperty(TRANSFER_START) != null) + fStartText.setText(properties.getProperty(TRANSFER_START)); + else + fStartText.setText("0x" + startAddress.toString(16)); + + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + + fileButton.addSelectionListener(new SelectionListener() { + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + public void widgetSelected(SelectionEvent e) { + FileDialog dialog = new FileDialog(parent.getShell(), SWT.SAVE); + dialog.setText("Choose memory import file"); + dialog.setFilterExtensions(new String[] { "*.*;*" } ); + dialog.setFilterNames(new String[] { "All Files" } ); + dialog.setFileName(fFileText.getText()); + dialog.open(); + + String filename = dialog.getFileName(); + if(filename != null && filename.length() != 0 ) + { + fFileText.setText(dialog.getFilterPath() + File.separator + filename); + } + + validate(); + } + + }); + + fStartText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + boolean valid = true; + try + { + getStartAddress(); + } + catch(Exception ex) + { + valid = false; + } + + fStartText.setForeground(valid ? Display.getDefault().getSystemColor(SWT.COLOR_BLACK) : + Display.getDefault().getSystemColor(SWT.COLOR_RED)); + + // + + validate(); + } + + }); + fFileText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + validate(); + } + }); + + fScrollToBeginningOnImportComplete = new Button(composite, SWT.CHECK); + fScrollToBeginningOnImportComplete.setText("Scroll to File Start Address"); + data = new FormData(); + data.top = new FormAttachment(fileButton); + fScrollToBeginningOnImportComplete.setLayoutData(data); + + composite.pack(); + parent.pack(); + + Display.getDefault().asyncExec(new Runnable(){ + public void run() + { + validate(); + } + }); + + return composite; + } + + private void validate() + { + boolean isValid = true; + + try + { + boolean restoreToAddress = fComboRestoreToThisAddress.getSelection(); + if ( restoreToAddress ) { + getStartAddress(); + } + + boolean restoreToAddressFromFile = fComboRestoreToFileAddress.getSelection(); + if ( restoreToAddressFromFile ) { + if(!getFile().exists()) { + isValid = false; + } + } + } + catch(Exception e) + { + isValid = false; + } + + fParentDialog.setValid(isValid); + } + + public boolean getScrollToStart() + { + return fScrollToBeginningOnImportComplete.getSelection(); + } + + public BigInteger getStartAddress() + { + String text = fStartText.getText(); + boolean hex = text.startsWith("0x"); + BigInteger startAddress = new BigInteger(hex ? text.substring(2) : text, + hex ? 16 : 10); + + return startAddress; + } + + public File getFile() + { + return new File(fFileText.getText()); + } + + public String getId() + { + return "srecord"; + } + + public String getName() + { + return "SRecord"; + } + + public void importMemory() { + Job job = new Job("Memory Import from S-Record File"){ //$NON-NLS-1$ + + public IStatus run(IProgressMonitor monitor) { + + try + { + try + { + BufferedMemoryWriter memoryWriter = new BufferedMemoryWriter((IMemoryBlockExtension) fMemoryBlock, BUFFER_LENGTH); + + // FIXME 4 byte default + + final int CHECKSUM_LENGTH = 1; + + BigInteger scrollToAddress = null; + + BigInteger offset = null; + if(!fProperties.getProperty(TRANSFER_CUSTOM_START_ADDRESS, "false").equals("true")) + offset = BigInteger.ZERO; + + BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fInputFile))); + + BigInteger jobs = BigInteger.valueOf(fInputFile.length()); + BigInteger factor = BigInteger.ONE; + if(jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) + { + factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); + jobs = jobs.divide(factor); + } + + monitor.beginTask("Transferring Data", jobs.intValue()); //$NON-NLS-1$ + + BigInteger jobCount = BigInteger.ZERO; + String line = reader.readLine(); + while(line != null && !monitor.isCanceled()) + { + String recordType = line.substring(0, 2); + int recordCount = Integer.parseInt(line.substring(2, 4), 16); + int bytesRead = 4 + recordCount; + int position = 4; + int addressSize = 0; + + BigInteger recordAddress = null; + + if("S3".equals(recordType)) //$NON-NLS-1$ + addressSize = 4; + else if("S1".equals(recordType)) //$NON-NLS-1$ + addressSize = 2; + else if("S2".equals(recordType)) //$NON-NLS-1$ + addressSize = 3; + + recordAddress = new BigInteger(line.substring(position, position + addressSize * 2), 16); + recordCount -= addressSize; + position += addressSize * 2; + + if(offset == null) + offset = fStartAddress.subtract(recordAddress); + + recordAddress = recordAddress.add(offset); + + byte data[] = new byte[recordCount - CHECKSUM_LENGTH]; + for(int i = 0; i < data.length; i++) + { + data[i] = new BigInteger(line.substring(position++, position++ + 1), 16).byteValue(); + } + + /* + * The least significant byte of the one's complement of the sum of the values + * represented by the pairs of characters making up the records length, address, + * and the code/data fields. + */ + StringBuffer buf = new StringBuffer(line.substring(2)); + byte checksum = 0; + + for(int i = 0; i < buf.length(); i+=2) + { + BigInteger value = new BigInteger(buf.substring(i, i+2), 16); + checksum += value.byteValue(); + } + + /* + * Since we included the checksum in the checksum calculation the checksum + * ( if correct ) will always be 0xFF which is -1 using the signed byte size + * calculation here. + */ + if ( checksum != (byte) -1 ) { + reader.close(); + monitor.done(); + return new Status( IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), "Checksum failure of line = " + line); //$NON-NLS-1$ + } + + if(scrollToAddress == null) + scrollToAddress = recordAddress; + + // FIXME error on incorrect checksum + + memoryWriter.write(recordAddress.subtract(((IMemoryBlockExtension) fMemoryBlock).getBigBaseAddress()), data); + + jobCount = jobCount.add(BigInteger.valueOf(bytesRead)); + while(jobCount.compareTo(factor) >= 0) + { + jobCount = jobCount.subtract(factor); + monitor.worked(1); + } + + line = reader.readLine(); + } + + memoryWriter.flush(); + reader.close(); + monitor.done(); + + if(fProperties.getProperty(TRANSFER_SCROLL_TO_START, "false").equals("true")) + fParentDialog.scrollRenderings(scrollToAddress); + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + } + catch(Exception e) + { + MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), + DebugException.INTERNAL_ERROR, "Failure", e)); + } + return Status.OK_STATUS; + }}; + job.setUser(true); + job.schedule(); + } +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/actions/ExportMemoryAction.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/actions/ExportMemoryAction.java new file mode 100644 index 00000000000..e722e9a906a --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/actions/ExportMemoryAction.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport.actions; + +import org.eclipse.cdt.debug.ui.memory.transport.ExportMemoryDialog; +import org.eclipse.cdt.debug.ui.memory.transport.MemoryTransportPlugin; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.internal.ui.views.memory.MemoryView; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * Action for exporting memory. + */ +public class ExportMemoryAction implements IViewActionDelegate { + + private MemoryView fView; + + public void init(IViewPart view) { + if (view instanceof MemoryView) + fView = (MemoryView) view; + } + + private IMemoryBlock getMemoryBlock(ISelection selection) + { + IMemoryBlock memBlock = null; + + if (selection instanceof IStructuredSelection) { + IStructuredSelection strucSel = (IStructuredSelection) selection; + + // return if current selection is empty + if (strucSel.isEmpty()) + return null; + + Object obj = strucSel.getFirstElement(); + + if (obj == null) + return null; + + if (obj instanceof IMemoryRendering) { + memBlock = ((IMemoryRendering) obj).getMemoryBlock(); + } else if (obj instanceof IMemoryBlock) { + memBlock = (IMemoryBlock) obj; + } + } + return memBlock; + } + + public void run(IAction action) { + + ISelection selection = fView.getSite().getSelectionProvider() + .getSelection(); + IMemoryBlock memBlock = getMemoryBlock(selection); + if(memBlock == null) + return; + ExportMemoryDialog dialog = new ExportMemoryDialog(MemoryTransportPlugin.getShell(), memBlock); + dialog.open(); + + dialog.getResult(); + } + + public void selectionChanged(IAction action, ISelection selection) { + action.setEnabled(getMemoryBlock(selection) != null); + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/actions/ImportMemoryAction.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/actions/ImportMemoryAction.java new file mode 100644 index 00000000000..37f81921ae4 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/actions/ImportMemoryAction.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport.actions; + +import org.eclipse.cdt.debug.ui.memory.transport.ImportMemoryDialog; +import org.eclipse.cdt.debug.ui.memory.transport.MemoryTransportPlugin; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.internal.ui.views.memory.MemoryView; +import org.eclipse.debug.ui.memory.IMemoryRendering; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * Action for downloading memory. + */ +public class ImportMemoryAction implements IViewActionDelegate { + + + private MemoryView fView; + + public void init(IViewPart view) { + if (view instanceof MemoryView) + fView = (MemoryView) view; + +// IDebugContextService debugContextService = DebugUITools.getDebugContextManager().getContextService(view.getSite().getWorkbenchWindow()); +// this. +// debugContextService.getActiveContext(); + } + + private IMemoryBlock getMemoryBlock(ISelection selection) + { + IMemoryBlock memBlock = null; + + if (selection instanceof IStructuredSelection) { + IStructuredSelection strucSel = (IStructuredSelection) selection; + + // return if current selection is empty + if (strucSel.isEmpty()) + return null; + + Object obj = strucSel.getFirstElement(); + + if (obj == null) + return null; + + if (obj instanceof IMemoryRendering) { + memBlock = ((IMemoryRendering) obj).getMemoryBlock(); + } else if (obj instanceof IMemoryBlock) { + memBlock = (IMemoryBlock) obj; + } + } + return memBlock; + } + + public void run(IAction action) { + + ISelection selection = fView.getSite().getSelectionProvider() + .getSelection(); + IMemoryBlock memBlock = getMemoryBlock(selection); + if(memBlock == null) + return; + + ImportMemoryDialog dialog = new ImportMemoryDialog(MemoryTransportPlugin.getShell(), memBlock, fView); + dialog.open(); + + dialog.getResult(); + } + + public void selectionChanged(IAction action, ISelection selection) { + action.setEnabled(getMemoryBlock(selection) != null); + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/messages.properties b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/messages.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/model/IMemoryExporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/model/IMemoryExporter.java new file mode 100644 index 00000000000..d90853b8fce --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/model/IMemoryExporter.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport.model; + +import java.util.Properties; + +import org.eclipse.cdt.debug.ui.memory.transport.ExportMemoryDialog; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +public interface IMemoryExporter +{ + public static final String TRANSFER_FILE = "File"; + public static final String TRANSFER_START = "Start"; + public static final String TRANSFER_END = "End"; + + public Control createControl(Composite parent, IMemoryBlock memBlock, Properties properties, ExportMemoryDialog parentDialog); + + public void exportMemory(); + + public String getId(); + + public String getName(); +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/model/IMemoryImporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/model/IMemoryImporter.java new file mode 100644 index 00000000000..5defe42fc6e --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/model/IMemoryImporter.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2006-2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.ui.memory.transport.model; + +import java.util.Properties; + +import org.eclipse.cdt.debug.ui.memory.transport.ImportMemoryDialog; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +public interface IMemoryImporter +{ + public static final String TRANSFER_FILE = "File"; + public static final String TRANSFER_START = "Start"; + public static final String TRANSFER_END = "End"; + public static final String TRANSFER_CUSTOM_START_ADDRESS = "CustomStartAddress"; + public static final String TRANSFER_SCROLL_TO_START = "ScrollToStart"; + + public Control createControl(Composite parent, IMemoryBlock memBlock, Properties properties, ImportMemoryDialog parentDialog); + + public void importMemory(); + + public String getId(); + + public String getName(); +}