+ * 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.
+ */
+
+@SuppressWarnings({ "restriction" })
+public class FPRendering extends AbstractMemoryRendering
+ implements IRepositionableMemoryRendering, IResettableMemoryRendering, IMemoryRenderingViewportProvider, IModelChangedListener
+{
+ protected Rendering fRendering;
+ protected Action actionDisplayBigEndian;
+ protected Action actionDisplayLittleEndian;
+ protected Action actionDisplayFloatingPoint;
+
+ private IWorkbenchAdapter fWorkbenchAdapter;
+ private IMemoryBlockConnection fConnection;
+
+ private final static int MAX_MENU_COLUMN_COUNT = 8;
+
+ Action actionFloatingPoint32 = null;
+ Action actionFloatingPoint64 = null;
+
+ Action actionDisplay4Digits = null;
+ Action actionDisplay8Digits = null;
+ Action actionDisplay16Digits = null;
+
+ // Constructor
+
+ public FPRendering(String id)
+ {
+ super(id);
+
+ JFaceResources.getFontRegistry().addListener(new IPropertyChangeListener()
+ {
+ @Override
+ public void propertyChange(PropertyChangeEvent event)
+ {
+ if (event.getProperty().equals(IInternalDebugUIConstants.FONT_NAME))
+ {
+ FPRendering.this.fRendering.handleFontPreferenceChange(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
+ }
+ }
+ });
+
+ this.addPropertyChangeListener(new IPropertyChangeListener()
+ {
+ @Override
+ 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)
+ {
+ FPRendering.this.fRendering.ensureVisible((BigInteger) address);
+ }
+ }
+ });
+
+ FPRenderingPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener()
+ {
+ @Override
+ public void propertyChange(PropertyChangeEvent event)
+ {
+ disposeColors();
+ allocateColors();
+ applyPreferences();
+ }
+ });
+
+ DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener()
+ {
+ @Override
+ public void propertyChange(PropertyChangeEvent event)
+ {
+ if (event.getProperty().equals(IDebugUIConstants.PREF_PADDED_STR))
+ {
+ if (FPRendering.this.fRendering != null)
+ {
+ setRenderingPadding((String) event.getNewValue());
+ FPRendering.this.fRendering.redrawPanes();
+ }
+ }
+ }
+ });
+ }
+
+ static int paddingCounter = 0;
+
+ void setRenderingPadding(String padding)
+ {
+ if (padding == null || padding.length() == 0) padding = " "; //$NON-NLS-1$
+ FPRendering.this.fRendering.setPaddingString(padding);
+ }
+
+ protected void logError(String message, Exception e)
+ {
+ Status status = new Status(IStatus.ERROR, getRenderingId(), DebugException.INTERNAL_ERROR, message, e);
+ FPRenderingPlugin.getDefault().getLog().log(status);
+ }
+
+ BigInteger fBigBaseAddress; // Memory base address
+ private BigInteger fStartAddress; // Starting address
+ private BigInteger fEndAddress; // Ending address
+ private int fAddressableSize; // Memory block size
+ private int fAddressSize; // Size of address
+
+ /*
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener#modelChanged(org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta, org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy)
+ */
+ @Override
+ public void modelChanged(IModelDelta delta, IModelProxy proxy)
+ {
+ /*
+ * The event model in the traditional renderer is written to expect a suspend first
+ * which will cause it to save its current data set away in an archive. Then when
+ * the state change comes through it will compare and refresh showing a difference.
+ */
+ int flags = delta.getFlags();
+ if ( ( flags & IModelDelta.STATE ) != 0 ) {
+ fRendering.handleSuspend(false);
+ }
+
+ fRendering.handleChange();
+ }
+
+ /*
+ * We use the model proxy which is supplied by the TCF implementation to provide the knowledge of memory
+ * change notifications. The older backends ( the reference model, Wind River Systems Inc. ) are written
+ * to generate the Debug Model events. TCF follows the "ModelDelta/IModelProxy" implementation that the
+ * platform renderers use. So this implementation acts as a shim. If the older Debug Events come in then
+ * fine. If the newer model deltas come in fine also.
+ */
+ IModelProxy fModel;
+
+ @Override
+ public void dispose()
+ {
+ /*
+ * We use the UI dispatch thread to protect the proxy information. Even though I believe the
+ * dispose routine is always called in the UI dispatch thread. I am going to make sure.
+ */
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if ( fModel != null ) {
+ fModel.removeModelChangedListener(FPRendering.this);
+ fModel.dispose();
+ }
+ }});
+
+ if(this.fRendering != null)
+ this.fRendering.dispose();
+ disposeColors();
+ super.dispose();
+ }
+
+ @Override
+ public void init(final IMemoryRenderingContainer container, final IMemoryBlock block)
+ {
+ super.init(container, block);
+
+ /*
+ * Working with the model proxy must be done on the UI dispatch thread.
+ */
+ final IModelProxyFactory factory = (IModelProxyFactory) DebugPlugin.getAdapter(block, IModelProxyFactory.class );
+ if ( factory != null ) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+
+ /*
+ * The asynchronous model assumes we have an asynchronous viewer that has an IPresentationContext
+ * to represent it. The Platform memory subsystem provides a way to create one without a viewewr.
+ */
+ IMemoryRenderingSite site = container.getMemoryRenderingSite();
+ MemoryViewPresentationContext context = new MemoryViewPresentationContext(site, container, FPRendering.this);
+
+ /*
+ * Get a new proxy and perform the initialization sequence so we are known the
+ * the model provider.
+ */
+ fModel = factory.createModelProxy(block, context);
+ fModel.installed(null);
+ fModel.addModelChangedListener(FPRendering.this);
+
+ }});
+ }
+
+ try
+ {
+ fBigBaseAddress = ((IMemoryBlockExtension) block).getBigBaseAddress();
+ }
+ catch (DebugException de)
+ {
+ logError(FPRenderingMessages.getString("FPRendering.FAILURE_RETRIEVE_BASE_ADDRESS"), de); //$NON-NLS-1$
+ }
+
+ try
+ {
+ fAddressableSize = ((IMemoryBlockExtension) block).getAddressableSize();
+ }
+ catch (DebugException de)
+ {
+ fAddressableSize = 1;
+ }
+
+ try
+ {
+ fStartAddress = ((IMemoryBlockExtension) block).getMemoryBlockStartAddress();
+ }
+ catch (DebugException de)
+ {
+ fStartAddress = null;
+ logError(FPRenderingMessages.getString("FPRendering.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.ONE);
+ 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;
+ }
+
+ @Override
+ public Control createControl(Composite parent)
+ {
+ allocateColors();
+
+ this.fRendering = new Rendering(parent, this);
+
+ applyPreferences();
+
+ createMenus();
+
+ if (actionFloatingPoint32.isChecked())
+ actionDisplay16Digits.setEnabled(false);
+ else
+ actionDisplay16Digits.setEnabled(true);
+
+ return this.fRendering;
+ }
+
+ /*
+ * We are duplicating the reference to the GoToAddress command because it is private in the platform.
+ * This is not going to change at this point so just live with it.
+ */
+ private static final String ID_GO_TO_ADDRESS_COMMAND = "org.eclipse.debug.ui.command.gotoaddress"; //$NON-NLS-1$
+ private AbstractHandler fGoToAddressHandler;
+
+ @Override
+ 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()
+ {
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException
+ {
+ return null;
+ }
+ };
+ }
+ gotoCommand.setHandler(fGoToAddressHandler);
+ }
+ }
+
+ @Override
+ 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$
+ @SuppressWarnings("synthetic-access")
+ @Override
+ public IStatus runInUIThread(IProgressMonitor monitor)
+ {
+
+ // Update tab labels
+ String fLabel = getLabel();
+ firePropertyChangedEvent(new PropertyChangeEvent(FPRendering.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 = FPRenderingPlugin.getDefault().getPreferenceStore();
+
+ colorBackground = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_BACKGROUND));
+ colorChanged = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_CHANGED));
+ colorEdit = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_EDIT));
+ colorSelection = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_SELECTION));
+ colorText = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_TEXT));
+
+ // alternate cell color
+ Color textColor = getColorText();
+ int red = textColor.getRed();
+ int green = textColor.getGreen();
+ int blue = textColor.getBlue();
+
+ float scale = store.getInt(FPRenderingPreferenceConstants.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 != null && !fRendering.isDisposed())
+ {
+ IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore();
+ fRendering.setHistoryDepth(store.getInt(FPRenderingPreferenceConstants.MEM_HISTORY_TRAILS_COUNT));
+ fRendering.setBackground(getColorBackground());
+
+ FPAbstractPane panes[] = fRendering.getRenderingPanes();
+ for (int index = 0; index < panes.length; index++)
+ panes[index].setBackground(getColorBackground());
+
+ setRenderingPadding(FPRenderingPlugin.getDefault().getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR));
+
+ fRendering.redrawPanes();
+ }
+ }
+
+ public Color getColorBackground()
+ {
+ IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore();
+
+ if (store.getBoolean(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_BACKGROUND))
+ return Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+
+ return colorBackground;
+ }
+
+ public Color getColorChanged()
+ {
+ return colorChanged;
+ }
+
+ private void disposeChangedColors()
+ {
+ if (colorsChanged != null)
+ for (int index = 0; index < colorsChanged.length; index++)
+ colorsChanged[index].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 index = 1; index < fRendering.getHistoryDepth(); index++)
+ {
+ colorsChanged[index] = new Color(colorChanged.getDevice(), colorChanged.getRed() + ((shades - index) * red), colorChanged.getGreen()
+ + ((shades - index) * green), colorChanged.getBlue() + ((shades - index) * blue));
+ }
+ }
+
+ return colorsChanged;
+ }
+
+ public Color getColorEdit()
+ {
+ return colorEdit;
+ }
+
+ public Color getColorSelection()
+ {
+ IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore();
+
+ if (store.getBoolean(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_SELECTION))
+ return Display.getDefault().getSystemColor(SWT.COLOR_LIST_SELECTION);
+
+ return colorSelection;
+ }
+
+ public Color getColorText()
+ {
+ IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore();
+
+ if (store.getBoolean(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_TEXT))
+ return Display.getDefault().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+
+ return colorText;
+ }
+
+ public Color getColorTextAlternate()
+ {
+ return colorTextAlternate;
+ }
+
+ // Menu creation
+
+ public void createMenus()
+ {
+ // Add the menu to each of the rendering panes
+
+ Control[] renderingControls = this.fRendering.getRenderingPanes();
+
+ for (int index = 0; index < renderingControls.length; index++)
+ super.createPopupMenu(renderingControls[index]);
+
+ super.createPopupMenu(this.fRendering);
+
+ // Copy
+
+ final Action copyAction = new CopyAction(this.fRendering);
+
+ // Copy address
+
+ final Action copyAddressAction = new Action(FPRenderingMessages.getString("FPRendering.COPY_ADDRESS")) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ Display.getDefault().asyncExec(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ FPRendering.this.fRendering.copyAddressToClipboard();
+ }
+ });
+ }
+ };
+
+ // Reset to base address
+
+ final Action gotoBaseAddressAction = new Action(FPRenderingMessages.getString("FPRendering.RESET_TO_BASE_ADDRESS")) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ Display.getDefault().asyncExec(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ FPRendering.this.fRendering.gotoAddress(FPRendering.this.fRendering.fBaseAddress);
+ }
+ });
+ }
+ };
+
+ // Refresh
+
+ final Action refreshAction = new Action(FPRenderingMessages.getString("FPRendering.REFRESH")) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ Display.getDefault().asyncExec(new Runnable()
+ {
+ @Override
+ 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]); //$NON-NLS-1$
+ if (m != null)
+ m.invoke(fRendering.getMemoryBlock(), new Object[0]);
+ }
+ catch (Exception e)
+ {
+ }
+
+ FPRendering.this.fRendering.refresh();
+ }
+ });
+ }
+ };
+
+ // Little Endian
+
+ actionDisplayLittleEndian = new Action(FPRenderingMessages.getString("FPRendering.ENDIAN_LITTLE"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ fRendering.setDisplayLittleEndian(true);
+ setRMCvalue(IFPRConstants.ENDIAN_KEY, Endian.LITTLE.getValue());
+ }
+ };
+
+ // Big Endian
+
+ actionDisplayBigEndian = new Action(FPRenderingMessages.getString("FPRendering.ENDIAN_BIG"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ fRendering.setDisplayLittleEndian(false);
+ setRMCvalue(IFPRConstants.ENDIAN_KEY, Endian.BIG.getValue());
+ }
+ };
+
+ // Endian settings
+
+ int endian = getRMCvalue(IFPRConstants.ENDIAN_KEY);
+
+ endian = endian != -1 ? endian : (fRendering.isDisplayLittleEndian() ? Endian.LITTLE.getValue() : Endian.BIG.getValue());
+ boolean le = (endian == Endian.LITTLE.getValue());
+
+ fRendering.setDisplayLittleEndian(le);
+ actionDisplayLittleEndian.setChecked(le);
+ actionDisplayBigEndian.setChecked(!le);
+
+ // Float
+
+ boolean dtFloat = getRMCvalue(IFPRConstants.DATATYPE_KEY) == FPDataType.FLOAT.getValue();
+ this.fRendering.setFPDataType(dtFloat ? FPDataType.FLOAT : FPDataType.DOUBLE);
+
+ actionFloatingPoint32 = new Action(FPRenderingMessages.getString("FPRendering.FLOATING_POINT_32"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ fRendering.setDisplayedPrecision(getRMCvalue(IFPRConstants.FLOAT_DISP_KEY));
+ fRendering.setFPDataType(FPDataType.FLOAT);
+ setRMCvalue(IFPRConstants.DATATYPE_KEY, FPDataType.FLOAT.getValue());
+ setSelections();
+ }
+ };
+
+ // Double
+
+ actionFloatingPoint64 = new Action(FPRenderingMessages.getString("FPRendering.FLOATING_POINT_64"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ fRendering.setDisplayedPrecision(getRMCvalue(IFPRConstants.DOUBLE_DISP_KEY));
+ fRendering.setFPDataType(FPDataType.DOUBLE);
+ setRMCvalue(IFPRConstants.DATATYPE_KEY, FPDataType.DOUBLE.getValue());
+ setSelections();
+ }
+ };
+
+ // Displayed precision: 4 digits
+
+ int savedPrecision = getDisplayedPrecision();
+
+ actionDisplay4Digits = new Action(FPRenderingMessages.getString("FPRendering.DISPLAYED_PRECISION_4"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ FPRendering.this.fRendering.setDisplayedPrecision(4);
+ setDisplayedPrecision(4);
+ }
+ };
+
+ if (savedPrecision == 4)
+ {
+ FPRendering.this.fRendering.setDisplayedPrecision(4);
+ actionDisplay4Digits.setChecked(savedPrecision == 4);
+ }
+
+ // Displayed precision: 8 digits
+
+ actionDisplay8Digits = new Action(FPRenderingMessages.getString("FPRendering.DISPLAYED_PRECISION_8"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ FPRendering.this.fRendering.setDisplayedPrecision(8);
+ setDisplayedPrecision(8);
+ }
+ };
+
+ if (savedPrecision == 8)
+ {
+ FPRendering.this.fRendering.setDisplayedPrecision(8);
+ actionDisplay8Digits.setChecked(savedPrecision == 8);
+ }
+
+ // Displayed precision: 16 digits (doubles only)
+
+ actionDisplay16Digits = new Action(FPRenderingMessages.getString("FPRendering.DISPLAYED_PRECISION_16"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ FPRendering.this.fRendering.setDisplayedPrecision(16);
+ setDisplayedPrecision(16);
+ }
+ };
+
+ if (savedPrecision == 16)
+ {
+ FPRendering.this.fRendering.setDisplayedPrecision(16);
+ actionDisplay16Digits.setChecked(savedPrecision == 16);
+ }
+
+ // Set RMC selections based on datatype and displayed precision settings in effect
+
+ setSelections();
+
+ // Columns
+
+ int savedColumnCount = getRMCvalue(IFPRConstants.COLUMN_COUNT_KEY);
+
+ final Action displayColumnCountAuto = new Action(FPRenderingMessages.getString("FPRendering.COLUMN_COUNT_AUTO"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ FPRendering.this.fRendering.setColumnsSetting(Rendering.COLUMNS_AUTO_SIZE_TO_FIT);
+ setRMCvalue(IFPRConstants.COLUMN_COUNT_KEY, Rendering.COLUMNS_AUTO_SIZE_TO_FIT);
+ }
+ };
+
+ boolean autoMode = savedColumnCount == Rendering.COLUMNS_AUTO_SIZE_TO_FIT;
+ displayColumnCountAuto.setChecked(autoMode);
+
+ final Action[] displayColumnCounts = new Action[MAX_MENU_COLUMN_COUNT];
+
+ for (int index = 0, j = 1; index < MAX_MENU_COLUMN_COUNT; index++, j *= 2)
+ {
+ final int finali = j;
+ displayColumnCounts[index] = new Action(FPRenderingMessages.getString("FPRendering.COLUMN_COUNT_" + finali), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ FPRendering.this.fRendering.setColumnsSetting(finali);
+ setRMCvalue(IFPRConstants.COLUMN_COUNT_KEY, finali);
+ }
+ };
+ displayColumnCounts[index].setChecked(fRendering.getColumnsSetting() == finali);
+ }
+
+ // Set/clear column count selections as appropriate
+
+ int countValue = getRMCvalue(IFPRConstants.COLUMN_COUNT_KEY);
+
+ for (int index = 0; index < MAX_MENU_COLUMN_COUNT; index++)
+ displayColumnCounts[index].setChecked(countValue != Rendering.COLUMNS_AUTO_SIZE_TO_FIT && (countValue == (1 << index)));
+
+ fRendering.setColumnsSetting(getRMCvalue(IFPRConstants.COLUMN_COUNT_KEY));
+
+ final Action displayColumnCountCustomValue = new Action("", IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ }
+ };
+
+ final Action displayColumnCountCustom = new Action(FPRenderingMessages.getString("FPRendering.COLUMN_COUNT_CUSTOM"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ InputDialog inputDialog = new InputDialog
+ (
+ fRendering.getShell(), "Set Column Count", "Please enter column count", "", new IInputValidator() //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ {
+ @Override
+ public String isValid(String input)
+ {
+ try
+ {
+ int index = Integer.parseInt(input);
+
+ if (index <= 0)
+ return "Please enter a positive integer"; //$NON-NLS-1$
+
+ if (index > 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 = FPRendering.this.fRendering.getColumnsSetting();
+
+ if (currentColumnSetting == Rendering.COLUMNS_AUTO_SIZE_TO_FIT)
+ displayColumnCountAuto.setChecked(true);
+ else
+ {
+ boolean currentCountIsCustom = true;
+
+ for (int index = 0, j = 1; index < MAX_MENU_COLUMN_COUNT && currentCountIsCustom; index++, j *= 2)
+ {
+ currentCountIsCustom = (j != fRendering.getColumnsSetting());
+ if (j == fRendering.getColumnsSetting())
+ displayColumnCounts[index].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 index = 0, j = 1; index < MAX_MENU_COLUMN_COUNT; index++, j *= 2)
+ {
+ if (newColumnCount == j)
+ {
+ customIsOneOfStandardListChoices = true;
+ FPRendering.this.fRendering.setColumnsSetting(newColumnCount);
+ setRMCvalue(IFPRConstants.COLUMN_COUNT_KEY, newColumnCount);
+ this.setChecked(false);
+ displayColumnCountCustomValue.setChecked(false);
+ displayColumnCounts[index].setChecked(true);
+ break;
+ }
+ }
+
+ if (!customIsOneOfStandardListChoices)
+ {
+ FPRendering.this.fRendering.setColumnsSetting(newColumnCount);
+ setRMCvalue(IFPRConstants.COLUMN_COUNT_KEY, newColumnCount);
+ this.setChecked(false);
+
+ displayColumnCountCustomValue.setChecked(true);
+ displayColumnCountCustomValue.setText(Integer.valueOf(fRendering.getColumnsSetting()).toString());
+ }
+ }
+ };
+
+ // Check for a custom value: If we're not in "Auto Fill" mode, check for standard column sizes.
+ // If none of the standard sizes were entered, then it's a custom value; set it and display it.
+
+ boolean customColumnCountSet = true;
+ countValue = getRMCvalue(IFPRConstants.COLUMN_COUNT_KEY);
+
+ if (countValue != Rendering.COLUMNS_AUTO_SIZE_TO_FIT)
+ {
+ for (int index = 0; index < MAX_MENU_COLUMN_COUNT; index++)
+ {
+ // If the column count is one of the standard values, set flag to false and exit the loop
+
+ if (countValue == (1 << index))
+ {
+ customColumnCountSet = false;
+ break;
+ }
+ }
+
+ if (customColumnCountSet)
+ {
+ FPRendering.this.fRendering.setColumnsSetting(countValue);
+ displayColumnCountCustomValue.setChecked(true);
+ displayColumnCountCustomValue.setText(Integer.valueOf(fRendering.getColumnsSetting()).toString());
+ }
+ }
+
+ // Add the right-mouse-click (RMC) context menu items
+
+ getPopupMenuManager().addMenuListener(new IMenuListener()
+ {
+ @Override
+ public void menuAboutToShow(IMenuManager manager)
+ {
+ manager.add(new Separator());
+
+ MenuManager sub = new MenuManager(FPRenderingMessages.getString("FPRendering.PANES")); //$NON-NLS-1$
+
+ sub = new MenuManager(FPRenderingMessages.getString("FPRendering.ENDIAN")); //$NON-NLS-1$
+ sub.add(actionDisplayBigEndian);
+ sub.add(actionDisplayLittleEndian);
+ manager.add(sub);
+
+ sub = new MenuManager(FPRenderingMessages.getString("FPRendering.NUMBER_TYPE")); //$NON-NLS-1$
+ sub.add(actionFloatingPoint32);
+ sub.add(actionFloatingPoint64);
+ manager.add(sub);
+
+ sub = new MenuManager(FPRenderingMessages.getString("FPRendering.PRECISION")); //$NON-NLS-1$
+ sub.add(actionDisplay4Digits);
+ sub.add(actionDisplay8Digits);
+ sub.add(actionDisplay16Digits);
+ manager.add(sub);
+
+// TODO: Add separator for FP group here: manager.add(new Separator());
+
+ sub = new MenuManager(FPRenderingMessages.getString("FPRendering.COLUMN_COUNT")); //$NON-NLS-1$
+ sub.add(displayColumnCountAuto);
+
+ for (int index = 0; index < displayColumnCounts.length; index++)
+ sub.add(displayColumnCounts[index]);
+
+ boolean currentCountIsCustom = fRendering.getColumnsSetting() != 0;
+
+ for (int index = 0, j = 1; index < MAX_MENU_COLUMN_COUNT && currentCountIsCustom; index++, j *= 2)
+ currentCountIsCustom = (j != fRendering.getColumnsSetting());
+
+ if (currentCountIsCustom)
+ sub.add(displayColumnCountCustomValue);
+
+ sub.add(displayColumnCountCustom);
+ manager.add(sub);
+
+ // Update modes
+
+ int updateMode = getRMCvalue(IFPRConstants.UPDATEMODE_KEY);
+
+ final Action updateAlwaysAction = new Action(FPRenderingMessages.getString("FPRendering.UPDATE_ALWAYS"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ fRendering.setUpdateMode(Rendering.UPDATE_ALWAYS);
+ setRMCvalue(IFPRConstants.UPDATEMODE_KEY, Rendering.UPDATE_ALWAYS);
+ }
+ };
+ updateAlwaysAction.setChecked(updateMode == Rendering.UPDATE_ALWAYS);
+
+ final Action updateOnBreakpointAction = new Action(FPRenderingMessages.getString("FPRendering.UPDATE_ON_BREAKPOINT"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ fRendering.setUpdateMode(Rendering.UPDATE_ON_BREAKPOINT);
+ setRMCvalue(IFPRConstants.UPDATEMODE_KEY, Rendering.UPDATE_ON_BREAKPOINT);
+ }
+ };
+ updateOnBreakpointAction.setChecked(updateMode == Rendering.UPDATE_ON_BREAKPOINT);
+
+ final Action updateManualAction = new Action(FPRenderingMessages.getString("FPRendering.UPDATE_MANUAL"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$
+ {
+ @Override
+ public void run()
+ {
+ fRendering.setUpdateMode(Rendering.UPDATE_MANUAL);
+ setRMCvalue(IFPRConstants.UPDATEMODE_KEY, Rendering.UPDATE_MANUAL);
+ }
+ };
+ updateManualAction.setChecked(updateMode == Rendering.UPDATE_MANUAL);
+
+ // Add menu
+
+ sub = new MenuManager(FPRenderingMessages.getString("FPRendering.UPDATEMODE")); //$NON-NLS-1$
+ sub.add(updateAlwaysAction);
+ sub.add(updateOnBreakpointAction);
+ sub.add(updateManualAction);
+ manager.add(sub);
+ manager.add(new Separator());
+
+ BigInteger start = fRendering.getSelection().getStart();
+ BigInteger end = fRendering.getSelection().getEnd();
+ copyAction.setEnabled(start != null && end != null);
+
+ manager.add(copyAction);
+ manager.add(copyAddressAction);
+
+ manager.add(gotoBaseAddressAction);
+ manager.add(refreshAction);
+ manager.add(new Separator());
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+ });
+ }
+
+ // Set/clear selections as appropriate
+
+ public void setSelections()
+ {
+ if (actionDisplay4Digits == null || actionDisplay8Digits == null || actionDisplay16Digits == null) return;
+
+ // Enable/disable and set/clear menu RMC elements based on currently selected datatype
+
+ boolean dtFloat = FPRendering.this.fRendering.getFPDataType() == FPDataType.FLOAT;
+
+ actionDisplay16Digits.setEnabled(!dtFloat);
+ actionFloatingPoint32.setChecked(dtFloat);
+ actionFloatingPoint64.setChecked(!dtFloat);
+
+ // Set/clear RMC elements based on displayed precision
+
+ int displayedPrecision = getRMCvalue(dtFloat ? IFPRConstants.FLOAT_DISP_KEY : IFPRConstants.DOUBLE_DISP_KEY);
+
+ actionDisplay4Digits.setChecked (displayedPrecision == 4);
+ actionDisplay8Digits.setChecked (displayedPrecision == 8);
+ actionDisplay16Digits.setChecked(displayedPrecision == 16);
+ }
+
+
+ @Override
+ public Control getControl()
+ {
+ return this.fRendering;
+ }
+
+ // Selection is terminology for caret position
+
+ @Override
+ public BigInteger getSelectedAddress()
+ {
+ FPIMemorySelection selection = fRendering.getSelection();
+ if (selection == null || selection.getStart() == null)
+ return fRendering.getCaretAddress();
+
+ return selection.getStartLow();
+ }
+
+ @Override
+ public MemoryByte[] getSelectedAsBytes()
+ {
+ try
+ {
+ // default to the caret address and the cell count size
+ BigInteger startAddr = fRendering.getCaretAddress();
+ int byteCount = fRendering.getCharsPerColumn();
+
+ // Now see if there's a selection
+ FPIMemorySelection 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)
+ {
+ return new MemoryByte[0];
+ }
+ }
+
+ @Override
+ public void goToAddress(final BigInteger address) throws DebugException
+ {
+ Display.getDefault().asyncExec(new Runnable()
+ {
+ @Override
+ 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.
+ actionDisplayBigEndian.setChecked(!littleEndian);
+ actionDisplayLittleEndian.setChecked(littleEndian);
+
+ // When target endian changes, force display endian to track. User can then change display endian if desired.
+ fRendering.setDisplayLittleEndian(littleEndian);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
+ */
+ @Override
+ public Object getAdapter(Class adapter)
+ {
+ if (adapter == IWorkbenchAdapter.class)
+ {
+ if (this.fWorkbenchAdapter == null)
+ {
+ this.fWorkbenchAdapter = new IWorkbenchAdapter()
+ {
+ @Override
+ public Object[] getChildren(Object o)
+ {
+ return new Object[0];
+ }
+
+ @Override
+ public ImageDescriptor getImageDescriptor(Object object)
+ {
+ return null;
+ }
+
+ @Override
+ public String getLabel(Object o)
+ {
+ return FPRenderingMessages.getString("FPRendering.RENDERING_NAME"); //$NON-NLS-1$
+ }
+
+ @Override
+ public Object getParent(Object o)
+ {
+ return null;
+ }
+ };
+ }
+ return this.fWorkbenchAdapter;
+ }
+
+ if (adapter == IMemoryBlockConnection.class)
+ {
+ if (fConnection == null)
+ {
+ fConnection = new IMemoryBlockConnection()
+ {
+ @Override
+ public void update()
+ {
+ // update UI asynchronously
+ Display display = FPRenderingPlugin.getDefault().getWorkbench().getDisplay();
+ display.asyncExec(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ if (fBigBaseAddress != FPRendering.this.fRendering.getMemoryBlock().getBigBaseAddress())
+ {
+ fBigBaseAddress = FPRendering.this.fRendering.getMemoryBlock().getBigBaseAddress();
+ FPRendering.this.fRendering.gotoAddress(fBigBaseAddress);
+ }
+ FPRendering.this.fRendering.refresh();
+ }
+ catch (DebugException e)
+ {
+ }
+ }
+ });
+ }
+ };
+ }
+
+ return fConnection;
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+ @Override
+ public void resetRendering() throws DebugException
+ {
+ fRendering.gotoAddress(fRendering.fBaseAddress);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.debug.internal.core.model.provisional.
+ * IMemoryRenderingViewportProvider#getViewportAddress()
+ */
+ @Override
+ public BigInteger getViewportAddress()
+ {
+ return fRendering.getViewportStartAddress();
+ }
+
+ // Persistence methods
+
+ void setDisplayedPrecision(int precision)
+ {
+ // Save the appropriate displayed precision value, based on data type, in the store
+
+ if (FPRendering.this.fRendering.getFPDataType() == FPDataType.FLOAT)
+ setRMCvalue(IFPRConstants.FLOAT_DISP_KEY, precision);
+ else
+ setRMCvalue(IFPRConstants.DOUBLE_DISP_KEY, precision);
+ }
+
+ private int getDisplayedPrecision()
+ {
+ // Retrieve the persisted data value from the store
+
+ IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore();
+
+ FPDataType dataType = FPRendering.this.fRendering.getFPDataType();
+
+ if (store != null)
+ return store.getInt(dataType == FPDataType.FLOAT ? IFPRConstants.FLOAT_DISP_KEY : IFPRConstants.DOUBLE_DISP_KEY);
+
+ // If there's nothing persisted, return the default precision for data type
+
+ return dataType == FPDataType.FLOAT ? FPDataType.FLOAT.getDisplayedPrecision() : FPDataType.DOUBLE.getDisplayedPrecision();
+ }
+
+ void setRMCvalue(String key, int value)
+ {
+ // Save the specified key and int value
+
+ IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore();
+ if (store != null) store.setValue(key, value);
+ }
+
+ int getRMCvalue(String key)
+ {
+ // Return the value for the specified key
+
+ IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore();
+ return (store != null) ? store.getInt(key) : 0;
+ }
+}
+
+// Copy class
+
+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);
+ }
+
+ @SuppressWarnings("restriction") // using platform's labels and images; acceptable build risk
+ 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));
+ }
+
+ @Override
+ public void run()
+ {
+ Clipboard clip = null;
+ final String PANE_SPACING = " "; //$NON-NLS-1$
+
+ try
+ {
+ clip = new Clipboard(fRendering.getDisplay());
+
+ BigInteger start = fRendering.getSelection().getStart();
+ BigInteger end = fRendering.getSelection().getEnd();
+
+ if (end == null) return; // End will be null when there is nothing selected
+
+ if (start.compareTo(end) > 0)
+ {
+ // Swap start and end
+
+ BigInteger bigI = end;
+ end = start;
+ start = bigI;
+ }
+
+ final FPDataType numberType = fRendering.getFPDataType();
+ final int bytesPerColumn = numberType.getByteLength();
+ final boolean isLittleEndian = fRendering.isTargetLittleEndian();
+ final int columns = fRendering.getColumnCount();
+ BigInteger lengthToRead = end.subtract(start);
+
+ int rows = lengthToRead.divide(BigInteger.valueOf(columns * (fRendering.getFPDataType().getByteLength()))).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_DATA))
+ {
+ for(int col = 0; col < columns; col++)
+ {
+ BigInteger cellAddress = rowAddress.add(BigInteger.valueOf(col * bytesPerColumn));
+
+ if (cellAddress.compareTo(end) < 0)
+ {
+ try
+ {
+ FPMemoryByte bytes[] = fRendering.getBytes(cellAddress, bytesPerColumn);
+ buffer.append(fRendering.sciNotationString(bytes, numberType, isLittleEndian));
+ }
+ catch(DebugException de)
+ {
+ fRendering
+ .logError(
+ FPRenderingMessages
+ .getString("FPRendering.FAILURE_COPY_OPERATION"), de); //$NON-NLS-1$
+ return;
+ }
+ }
+ else
+ {
+ for(int i = fRendering.getCharsPerColumn(); i > 0; i--)
+ buffer.append(' ');
+ }
+
+ if (col != columns - 1)
+ buffer.append(' ');
+ }
+ }
+
+ if (fRendering.getPaneVisible(Rendering.PANE_DATA))
+ buffer.append(PANE_SPACING);
+
+ 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();
+ }
+ }
+ }
+}
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingMessages.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingMessages.java
new file mode 100644
index 00000000000..88ab53aa05b
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingMessages.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010, 2012 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
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class FPRenderingMessages
+{
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.debug.ui.memory.floatingpoint.messages"; //$NON-NLS-1$
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+
+ private FPRenderingMessages()
+ {
+ }
+
+ 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.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPlugin.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPlugin.java
new file mode 100644
index 00000000000..54f6842d8bf
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPlugin.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010, 2012 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
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+public class FPRenderingPlugin extends AbstractUIPlugin
+{
+ public static final String PLUGIN_ID = "org.eclipse.cdt.debug.ui.memory.floatingpoint"; //$NON-NLS-1$
+
+ private static FPRenderingPlugin plugin;
+
+ public FPRenderingPlugin()
+ {
+ super();
+ }
+
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+
+ /**
+ * Returns the shared instance.
+ */
+ public static FPRenderingPlugin getDefault()
+ {
+ return plugin;
+ }
+
+ /**
+ * Returns the unique identifier for this plugin.
+ */
+ public static String getUniqueIdentifier()
+ {
+ return PLUGIN_ID;
+ }
+
+ /**
+ * Returns the workbench's display.
+ */
+ public static Display getStandardDisplay()
+ {
+ return PlatformUI.getWorkbench().getDisplay();
+ }
+
+ /**
+ * 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.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceAction.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceAction.java
new file mode 100644
index 00000000000..ac158b1e6d9
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceAction.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010, 2012 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
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+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 FPRenderingPreferenceAction extends ActionDelegate implements IViewActionDelegate
+{
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ @Override
+ public void run(IAction action)
+ {
+ IPreferencePage page = new FPRenderingPreferencePage();
+ showPreferencePage("org.eclipse.cdt.debug.ui.memory.floatingpoint.FPRenderingPreferencePage", page); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart)
+ */
+ @Override
+ 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(FPRenderingPlugin.getShell(), manager);
+ final boolean[] result = new boolean[] { false };
+ BusyIndicator.showWhile(FPRenderingPlugin.getStandardDisplay(), new Runnable()
+ {
+ @Override
+ 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.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceConstants.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceConstants.java
new file mode 100644
index 00000000000..1fc4a93670f
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceConstants.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010, 2012 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
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+/**
+ * Constant definitions for plug-in preferences
+ */
+public class FPRenderingPreferenceConstants
+{
+ public static final String MEM_COLOR_CHANGED = "memoryColorChanged"; //$NON-NLS-1$
+ public static final String MEM_USE_GLOBAL_BACKGROUND = "memUseGlobalBackground"; //$NON-NLS-1$
+ public static final String MEM_COLOR_BACKGROUND = "memoryColorBackground"; //$NON-NLS-1$
+ public static final String MEM_COLOR_EDIT = "memoryColorEdit"; //$NON-NLS-1$
+ public static final String MEM_COLOR_TEXT = "memoryColorText"; //$NON-NLS-1$
+ public static final String MEM_USE_GLOBAL_SELECTION = "memUseGlobalSelection"; //$NON-NLS-1$
+ public static final String MEM_COLOR_SELECTION = "memoryColorSelection"; //$NON-NLS-1$
+ public static final String MEM_USE_GLOBAL_TEXT = "memUseGlobalText"; //$NON-NLS-1$
+ public static final String MEM_LIGHTEN_DARKEN_ALTERNATE_CELLS = "memoryColorScaleTextAlternate"; //$NON-NLS-1$
+ public static final String MEM_EDIT_BUFFER_SAVE = "memoryEditBufferSave"; //$NON-NLS-1$
+ public static final String MEM_EDIT_BUFFER_SAVE_ON_ENTER_ONLY = "saveOnEnterCancelOnFocusLost"; //$NON-NLS-1$
+ public static final String MEM_EDIT_BUFFER_SAVE_ON_ENTER_OR_FOCUS_LOST = "saveOnEnterOrFocusLost"; //$NON-NLS-1$
+ public static final String MEM_HISTORY_TRAILS_COUNT = "memoryHistoryTrailsCount"; //$NON-NLS-1$
+}
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceInitializer.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceInitializer.java
new file mode 100644
index 00000000000..7cbcbed5e3f
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferenceInitializer.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010, 2012 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
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+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 FPRenderingPreferenceInitializer extends AbstractPreferenceInitializer
+{
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#
+ * initializeDefaultPreferences()
+ */
+ @Override
+ public void initializeDefaultPreferences()
+ {
+ IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore();
+
+ store.setDefault(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_TEXT, true);
+ store.setDefault(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_BACKGROUND, true);
+ store.setDefault(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_SELECTION, true);
+
+ store.setDefault(FPRenderingPreferenceConstants.MEM_COLOR_CHANGED, "255,0,0"); //$NON-NLS-1$
+
+ Color systemSelection = Display.getDefault().getSystemColor(SWT.COLOR_LIST_SELECTION);
+ store.setDefault(FPRenderingPreferenceConstants.MEM_COLOR_SELECTION, systemSelection.getRed() + "," + systemSelection.getGreen() + "," //$NON-NLS-1$ //$NON-NLS-2$
+ + systemSelection.getBlue());
+
+ store.setDefault(FPRenderingPreferenceConstants.MEM_LIGHTEN_DARKEN_ALTERNATE_CELLS, "5"); //$NON-NLS-1$
+
+ store.setDefault(FPRenderingPreferenceConstants.MEM_COLOR_EDIT, "0,255,0"); //$NON-NLS-1$
+
+ Color systemText = Display.getDefault().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+ store.setDefault(FPRenderingPreferenceConstants.MEM_COLOR_TEXT, systemText.getRed() + "," + systemText.getGreen() + "," + systemText.getBlue()); //$NON-NLS-1$ //$NON-NLS-2$
+
+ Color systemBackground = Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+ store.setDefault(FPRenderingPreferenceConstants.MEM_COLOR_BACKGROUND, systemBackground.getRed() + "," + systemBackground.getGreen() + "," //$NON-NLS-1$ //$NON-NLS-2$
+ + systemBackground.getBlue());
+
+ store.setDefault(FPRenderingPreferenceConstants.MEM_EDIT_BUFFER_SAVE, FPRenderingPreferenceConstants.MEM_EDIT_BUFFER_SAVE_ON_ENTER_ONLY);
+
+ store.setDefault(FPRenderingPreferenceConstants.MEM_HISTORY_TRAILS_COUNT, "1"); //$NON-NLS-1$
+ }
+}
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferencePage.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferencePage.java
new file mode 100644
index 00000000000..716596f25a4
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingPreferencePage.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010, 2012 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
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+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 FPRenderingPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage
+{
+ public FPRenderingPreferencePage()
+ {
+ super(GRID);
+ setPreferenceStore(FPRenderingPlugin.getDefault().getPreferenceStore());
+ setDescription("Floating Point Memory Rendering"); //$NON-NLS-1$
+ }
+
+ @Override
+ public void createControl(Composite parent)
+ {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), FPRenderingPlugin.getUniqueIdentifier() + ".FPRenderingPreferencePage_context"); //$NON-NLS-1$
+ }
+
+ /**
+ * 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.
+ */
+ @Override
+ public void createFieldEditors()
+ {
+ addField(new BooleanFieldEditor(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_TEXT, "Use Global Te&xt Color", getFieldEditorParent())); //$NON-NLS-1$
+ addField(new ColorFieldEditor(FPRenderingPreferenceConstants.MEM_COLOR_TEXT, "&Text Color:", getFieldEditorParent())); //$NON-NLS-1$
+ addField(new ScaleFieldEditor(FPRenderingPreferenceConstants.MEM_LIGHTEN_DARKEN_ALTERNATE_CELLS, "Brighten Alternate Cells", getFieldEditorParent(), 0, 8, 1, 1)); //$NON-NLS-1$
+ addField(new BooleanFieldEditor(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_BACKGROUND, "Use Global B&ackground Color", getFieldEditorParent())); //$NON-NLS-1$
+ addField(new ColorFieldEditor(FPRenderingPreferenceConstants.MEM_COLOR_BACKGROUND, "&Background Color:", getFieldEditorParent())); //$NON-NLS-1$
+ addField(new ColorFieldEditor(FPRenderingPreferenceConstants.MEM_COLOR_CHANGED, "&Changed Color:", getFieldEditorParent())); //$NON-NLS-1$
+ addField(new ColorFieldEditor(FPRenderingPreferenceConstants.MEM_COLOR_EDIT, "&Edit Color:", getFieldEditorParent())); //$NON-NLS-1$
+ addField(new BooleanFieldEditor(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_SELECTION, "Use Global Se&lection Color", getFieldEditorParent())); //$NON-NLS-1$
+ addField(new ColorFieldEditor(FPRenderingPreferenceConstants.MEM_COLOR_SELECTION, "&Selection Color:", getFieldEditorParent())); //$NON-NLS-1$
+ addField(new RadioGroupFieldEditor(FPRenderingPreferenceConstants.MEM_EDIT_BUFFER_SAVE, "Edit Buffer", 1, new String[][] //$NON-NLS-1$
+ { { "Save on E&nter, Cancel on Focus Lost", "saveOnEnterCancelOnFocusLost" }, //$NON-NLS-1$ //$NON-NLS-2$
+ { "Save on Enter or Focus L&ost", "saveOnEnterOrFocusLost" } }, getFieldEditorParent())); //$NON-NLS-1$ //$NON-NLS-2$
+ addField(new ScaleFieldEditor(FPRenderingPreferenceConstants.MEM_HISTORY_TRAILS_COUNT, "History &Trail Levels", getFieldEditorParent(), 1, 10, 1, 1)); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ @Override
+ public void init(IWorkbench workbench)
+ {
+ }
+
+}
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingTypeDelegate.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingTypeDelegate.java
new file mode 100644
index 00000000000..8a71b83a252
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPRenderingTypeDelegate.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010, 2012 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
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.ui.memory.IMemoryRendering;
+import org.eclipse.debug.ui.memory.IMemoryRenderingTypeDelegate;
+
+public class FPRenderingTypeDelegate implements IMemoryRenderingTypeDelegate
+{
+ @Override
+ public IMemoryRendering createRendering(String id) throws CoreException
+ {
+ return new FPRendering(id);
+ }
+}
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPutilities.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPutilities.java
new file mode 100644
index 00000000000..c59bd5d5e4b
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/FPutilities.java
@@ -0,0 +1,492 @@
+/*******************************************************************************
+ * Copyright (c) 2012 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:
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.progress.UIJob;
+
+public class FPutilities
+{
+ private static final int BYTE_MASK = 0xFF;
+
+ // ANSI C "Smallest" and "largest" negative and positive float and double values
+
+ public static final float floatNegMax = -3.40282347E+38f; // Largest negative float value; farthest from zero
+ public static final float floatNegMin = -1.17549435E-38f; // Smallest negative float value; closest to zero
+ public static final float floatPosMax = 1.17549435E+38f; // Largest positive float value; farthest from zero
+ public static final float floatPosMin = 3.40282347E-38f; // Smallest positive float value; closest to zero
+
+ public static final double doubleNegMax = -1.7976931348623157E+308; // Largest positive double value
+ public static final double doubleNegMin = -2.2250738585072014E-308; // Smallest positive double value
+ public static final double doublePosMax = 1.7976931348623157E+308; // Largest positive double value
+ public static final double doublePosMin = 2.2250738585072014E-308; // Smallest positive double value
+
+ public enum FPDataType
+ {
+ // Value (for persisteance), Bitsize of type, Number of internal precision decimal digits, Default displayed precision
+
+ FLOAT ( 10, 32, 7, 8), // C/C++ single-precision "float"
+ DOUBLE ( 20, 64, 15, 8), // C/C++ double-precision "double"
+ FLOAT_80 ( 30, 80, 19, 16), // Extended precision
+ FLOAT_96 ( 40, 96, 0, 0), // TODO: unknown internal decimal digit precision; C/C++ extended-precision "long double"
+
+ // Future work
+
+ FLOAT_128 (50, 128, 33, 16), // TODO: known values, but not currently implmented
+ FLOAT_256 (60, 256, 0, 0), // TODO: unknown internal decimal digit precision
+ FLOAT_512 (70, 512, 0, 0); // TODO: unknown internal decimal digit precision
+
+ // Member variables
+
+ private int value;
+ private int bitsize;
+ private int decimalPrecision;
+ private int displayedPrecision;
+
+ // Constructor
+
+ private FPDataType(int value, int bitSize, int precisionDigits, int defaultDisplayPrecision)
+ {
+ this.value = value;
+ this.bitsize = bitSize;
+ this.decimalPrecision = precisionDigits;
+ this.displayedPrecision = defaultDisplayPrecision;
+ }
+
+ // Getters
+
+ public int getValue() { return value; }
+ public int getBitsize() { return bitsize; }
+ public int getDecimalPrecision() { return decimalPrecision; }
+ public int getDisplayedPrecision() { return displayedPrecision; }
+ public int getInternalPrecision() { return decimalPrecision; }
+
+ public int getByteLength()
+ {
+ return bitsize/Byte.SIZE;
+ }
+ }
+
+ // Byte ordering
+
+ public enum Endian
+ {
+ // Value
+
+ LITTLE (10),
+ BIG (20);
+
+ // Member variables
+
+ private int value;
+
+ // Constructor
+
+ private Endian(int value)
+ {
+ this.value = value;
+ }
+
+ // Getters
+
+ public int getValue() { return value; }
+ }
+
+ // Justification (latent support)
+
+ public enum Justification
+ {
+ LEFT,
+ RIGHT,
+ CENTER;
+ }
+
+ // Convert raw float bits to a byte array
+
+ public static byte[] rawFloatBitsToByteArray(int floatBits)
+ {
+ int byteCount = Integer.SIZE/Byte.SIZE;
+ byte[] result = new byte[byteCount];
+
+ for (int index = 0; index < byteCount; index++)
+ {
+ int offset = (result.length - 1 - index) * 8;
+ result[index] = (byte) ((floatBits >>> offset) & BYTE_MASK);
+ }
+
+ return result;
+ }
+
+ // Convert raw double bits to a byte array
+
+ public static byte[] rawDoubleBitsToByteArray(long doubleBits)
+ {
+ int byteCount = Long.SIZE/Byte.SIZE;
+ byte[] result = new byte[byteCount];
+
+ for (int index = 0; index < byteCount; index++)
+ {
+ int offset = (result.length - 1 - index) * 8;
+ result[index] = (byte) ((doubleBits >>> offset) & BYTE_MASK);
+ }
+
+ return result;
+ }
+
+ // Return a byte array that is in reverse order of the passed-in array parameter
+
+ public static byte[] reverseByteOrder(byte[] byteArray)
+ {
+ if (byteArray.length == 0) return new byte[0];
+
+ byte tempByte = 0;
+ byte[] reversedByteArray = new byte[byteArray.length];
+
+ // Copy the array that is passed in to the array that will be returned
+
+ System.arraycopy(byteArray, 0, reversedByteArray, 0, byteArray.length);
+
+ // Reverse the bytes
+
+ for(int start = 0, end = reversedByteArray.length - 1; start < end; ++start, --end)
+ {
+ tempByte = reversedByteArray[start];
+ reversedByteArray[start] = reversedByteArray[end];
+ reversedByteArray[end] = tempByte;
+ }
+
+ return reversedByteArray;
+ }
+
+ // Convert a representation of a float or double in a byte array to a scientific notation string (Should we use BigDecimal here???)
+
+ public static String byteArrayToSciNotation(FPDataType dt, boolean isLittleEndian, FPMemoryByte[] memByteArray, int maxDisplayDigits) throws ArithmeticException
+ {
+ int displayedDigits = 8;
+
+ // If the byte array is not a 32-bit float or 64-bit double, throw an exception.
+
+ if (memByteArray.length != (FPDataType.FLOAT.getByteLength()) &&
+ memByteArray.length != (FPDataType.DOUBLE.getByteLength()))
+ throw new ArithmeticException("Conversion of the floating point number cannot be performed; invalid data type or byte array length."); //$NON-NLS-1$
+
+ // Create and initialize a DecimalFormat object for scientific notation. Specify a space
+ // for the preceding plus-sign, which lines up the first significant digit, decimal point
+ // and exponent character. Define the symbol strings for "Not a Number" and "Infinity."
+
+ DecimalFormat df = new DecimalFormat("0.0E0"); //$NON-NLS-1$
+ df.setPositivePrefix(" "); //$NON-NLS-1$
+
+ DecimalFormatSymbols dfSymbols = new DecimalFormatSymbols();
+ dfSymbols.setNaN(" "+ FPRenderingMessages.getString("FPRendering.NAN")); //$NON-NLS-1$ //$NON-NLS-2$
+ dfSymbols.setInfinity(FPRenderingMessages.getString("FPRendering.INFINITY")); //$NON-NLS-1$
+ df.setDecimalFormatSymbols(dfSymbols);
+
+ // Set the integer and fraction digits for normalized scientific notation.
+
+ df.setMinimumIntegerDigits(1);
+ df.setMaximumIntegerDigits(1);
+
+ if (dt == FPDataType.FLOAT)
+ displayedDigits = Math.min(maxDisplayDigits, FPDataType.FLOAT.getInternalPrecision());
+
+ if (dt == FPDataType.DOUBLE)
+ displayedDigits = Math.min(maxDisplayDigits, FPDataType.DOUBLE.getInternalPrecision());
+
+ df.setMinimumFractionDigits(displayedDigits - 1);
+ df.setMaximumFractionDigits(displayedDigits - 1);
+
+ // Convert the byte array to a scientific notation floating point number string (only floats and doubles currently supported)
+
+ ByteOrder byteOrder = isLittleEndian ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
+
+ return df.format(dt == FPDataType.FLOAT ?
+ ByteBuffer.wrap(memoryBytesToByteArray(memByteArray)).order(byteOrder).getFloat() :
+ ByteBuffer.wrap(memoryBytesToByteArray(memByteArray)).order(byteOrder).getDouble());
+ }
+
+ // Convert a floating point string to a byte array (*** only 'floats' and 'doubles' currently supported ***)
+
+ public static byte[] floatingStringToByteArray(FPDataType dt, String valueString, int dataTypeBitCount) throws NumberFormatException
+ {
+ // Remove whitespace and check for non-zero length
+ valueString = valueString.trim().replaceAll(" ", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
+ if (valueString.length() != 0)
+ {
+ // Float handling
+
+ if (dt == FPDataType.FLOAT || FPDataType.FLOAT.getBitsize() == dataTypeBitCount)
+ {
+ // Convert the string to a float. Check the range. Convert to byte array.
+
+ float floatValue = new Float(valueString).floatValue();
+ floatValue = floatLimitCheck(floatValue);
+ return rawFloatBitsToByteArray(Float.floatToRawIntBits(floatValue));
+ }
+
+ // Double handling
+
+ if (dt == FPDataType.DOUBLE || FPDataType.DOUBLE.getBitsize() == dataTypeBitCount)
+ {
+ // Convert the string to a double. Check the range. Convert to byte array.
+
+ double doubleValue = new Double(valueString).doubleValue();
+ doubleValue = doubleLimitCheck(doubleValue);
+ return rawDoubleBitsToByteArray(Double.doubleToRawLongBits(doubleValue));
+ }
+ }
+
+ return new byte[0];
+ }
+
+ // Convert from an FPMemoryByte array to a byte array
+
+ public static byte[] memoryBytesToByteArray(FPMemoryByte[] memoryByteArray)
+ {
+ byte[] byteArray = new byte[memoryByteArray.length];
+
+ for (int index = 0; index < memoryByteArray.length; index++)
+ byteArray[index] = memoryByteArray[index].getValue();
+
+ return byteArray;
+ }
+
+ // Convert from a byte array to a MemoryByte array
+
+ public static FPMemoryByte[] byteArrayToMemoryBytes(Endian endian, byte[] byteArray)
+ {
+ FPMemoryByte[] memoryBytes = new FPMemoryByte[byteArray.length];
+
+ for (int index = 0; index < byteArray.length; index++)
+ {
+ memoryBytes[index] = new FPMemoryByte();
+ memoryBytes[index].setBigEndian(endian == Endian.BIG);
+ memoryBytes[index].setValue(byteArray[index]);
+ }
+
+ return memoryBytes;
+ }
+
+ // Check the character for being valid for number entry, both standard and scientific notation
+
+ public static boolean validEditCharacter(char character)
+ {
+ return (character >= '0' && character <= '9') ||
+ character == '+' || character == '-' ||
+ character == 'e' || character == 'E' ||
+ character == '.' || character == ' ';
+ }
+
+ // Validate floating point number string
+
+ public static boolean isValidFormat(String string)
+ {
+ // Rules:
+ // - A minimum of one digit preceding the optional exponent character is required.
+ // - Allowable characters: 0-9, a decimal point, '+' and '-' number
+ // signs, exponent characters 'e' and 'E', and spaces.
+ //
+ // Strings may also have:
+ // - One [optional] decimal point
+ // - A maximum of two [optional] number signs (one before the number and one after the exponent character)
+ // - Only one [optional] exponent character is allowed
+
+ boolean digit = false;
+ char[] charArray = string.toCharArray();
+
+ // Phase I check:
+
+ String scientificNotationPattern = "^[-+]??(\\d++[.]\\d*?|[.]?\\d+?|\\d+(?=[eE]))([eE][-+]??\\d++)?$"; //$NON-NLS-1$
+
+ if (!Pattern.matches(scientificNotationPattern, string))
+ return false;
+
+ // Phase II check
+
+ for (int index = 0; index < string.length(); index++)
+ {
+ // Check for a digit
+
+ if (charArray[index] >= '0' && charArray[index] <= '9')
+ digit = true;
+
+ // Make sure it's a valid/allowable character
+
+ if (!validEditCharacter(charArray[index]))
+ return false;
+
+ // Only one decimal point and exponent character is allowed
+
+ if (FPutilities.countMatches(string.toLowerCase(), ".") > 1 || FPutilities.countMatches(string.toLowerCase(), "e") > 1) //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+
+ // Number signs are only allowed in the first position and following the exponent character.
+
+ if (((charArray[index] == '+' || charArray[index] == '-') && index != 0) &&
+ (charArray[index-1] != 'e' && charArray[index-1] != 'E'))
+ return false;
+
+ // Decimal points are not allowed after the exponent character
+
+ int eIndex = string.toLowerCase().indexOf('e');
+
+ if (charArray[index] == '.' && eIndex != -1 && eIndex < index)
+ return false;
+ }
+
+ return digit;
+ }
+
+ // Return a string of the specified length filled with the specified character
+
+ public static String fillString(int length, char character)
+ {
+ if (length < 1) return ""; //$NON-NLS-1$
+ char[] charArray = new char[length];
+ Arrays.fill(charArray, character);
+ return new String(charArray);
+ }
+
+ // Count the 'subString' matches in 'string'
+
+ public static int countMatches(String string, String subString)
+ {
+ if (string.length() == 0 || subString.length() == 0) return 0;
+
+ int count = 0;
+ int index = 0;
+
+ while ((index = string.indexOf(subString, index)) != -1)
+ {
+ count++;
+ index += subString.length();
+ }
+
+ return count;
+ }
+
+ // Print out a stack trace; useful for UI operations where stopping at a breakpoint causes button press context to be lost
+
+ public static void stackTrace(int depth)
+ {
+ int offset = 3; // Ignore frames contributed to the stack based on call to this method
+ if (depth == 0) depth = 4; // Default depth if zero supplied
+
+ // Get the stack frames for the current thread; start at the offset
+
+ StackTraceElement[] seArray = Thread.currentThread().getStackTrace();
+
+ if (seArray.length > offset)
+ {
+ System.out.println("Displaying " + depth + " of " + seArray.length + " stack trace elements"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ for (int index = offset; index < Math.min(depth + offset, seArray.length + offset); index++)
+ System.out.println(" " + seArray[index].getClassName() + "." + seArray[index].getMethodName() + ": line " + seArray[index].getLineNumber()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ else
+ System.out.println("No stack frames to display"); //$NON-NLS-1$
+ }
+
+ // Pop up a message inside the UI thread
+
+ public static void popupMessage(final String title, final String errorText, final Status status)
+ {
+ UIJob job = new UIJob("Floating Point Renderer") //$NON-NLS-1$
+ {
+ // Notify the user of some condition via a pop-up box.
+
+ @Override
+ public IStatus runInUIThread(IProgressMonitor monitor)
+ {
+ ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), title, errorText, status);
+ return Status.OK_STATUS;
+ }
+ };
+
+ job.setSystem(true);
+ job.schedule();
+ }
+
+ // Check float range. Returns -Infinity, the original value or +Infinity
+
+ public static float floatLimitCheck(float floatValue)
+ {
+ if (floatValue != 0.0f && floatValue != Float.NEGATIVE_INFINITY && floatValue != Float.POSITIVE_INFINITY)
+ {
+ if (floatValue < 0)
+ {
+ if (Float.compare(floatValue, floatNegMax) < 0 || Float.compare(floatValue, floatNegMin) > 0)
+ return Float.NEGATIVE_INFINITY;
+ }
+ else
+ {
+ if (Float.compare(floatValue, floatPosMin) < 0 || Float.compare(floatValue, floatPosMax) > 0)
+ return Float.POSITIVE_INFINITY;
+ }
+ }
+
+ return floatValue;
+ }
+
+ // Check double range. Returns a value of RangeCheck
+
+ public static double doubleLimitCheck(double doubleValue)
+ {
+ if (doubleValue != 0.0 && doubleValue != Double.NEGATIVE_INFINITY && doubleValue != Double.POSITIVE_INFINITY)
+ {
+ if (doubleValue < 0)
+ {
+ if (Double.compare(doubleValue, doubleNegMax) < 0 || Double.compare(doubleValue, doubleNegMin) > 0)
+ return Double.NEGATIVE_INFINITY;
+ }
+ else
+ {
+ if (Double.compare(doubleValue, doublePosMin) < 0 || Double.compare(doubleValue, doublePosMax) > 0)
+ return Double.POSITIVE_INFINITY;
+ }
+ }
+
+ return doubleValue;
+ }
+
+ // Convert a BigInteger to a hex String and return only the ending number of specified digits.
+
+ public static String bi2HexStr(BigInteger bi, int lastDigits)
+ {
+ final int PAD_LENGTH = 12;
+ String base16 = bi.toString(16);
+ base16 = fillString(PAD_LENGTH - base16.length(), '0') + base16;
+ return "0x" + base16.substring(PAD_LENGTH - lastDigits).toUpperCase(); //$NON-NLS-1$
+ }
+
+ // Convert a BigInteger to a decimal String and return only the ending number of
+ // specified digits. For example: bi2HexStr(239248506, 5) = "48506"
+
+ public static String bi2DecStr(BigInteger bi, int lastDigits)
+ {
+ final int PAD_LENGTH = 12;
+ String base10 = bi.toString();
+ base10 = fillString(PAD_LENGTH - base10.length(), '0') + base10;
+ return base10.substring(PAD_LENGTH - lastDigits);
+ }
+}
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/IFPRConstants.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/IFPRConstants.java
new file mode 100644
index 00000000000..2d65cfead84
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/IFPRConstants.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2012 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:
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+public interface IFPRConstants
+{
+ public final String ENDIAN_KEY = FPRenderingPlugin.PLUGIN_ID + ".endian"; // Endianness key //$NON-NLS-1$
+ public final String DATATYPE_KEY = FPRenderingPlugin.PLUGIN_ID + ".dataType"; // Currently-selected data type //$NON-NLS-1$
+ public final String FLOAT_DISP_KEY = FPRenderingPlugin.PLUGIN_ID + ".floatDispPrec"; // 32-bit floating point data type displayed precision //$NON-NLS-1$
+ public final String DOUBLE_DISP_KEY = FPRenderingPlugin.PLUGIN_ID + ".doubleDispPrec"; // 64-bit floating point data type displayed precision //$NON-NLS-1$
+ public final String COLUMN_COUNT_KEY = FPRenderingPlugin.PLUGIN_ID + ".columns"; // Number of columns to display //$NON-NLS-1$
+ public final String UPDATEMODE_KEY = FPRenderingPlugin.PLUGIN_ID + ".updateMode"; // Renderer update mode //$NON-NLS-1$
+}
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/Rendering.java b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/Rendering.java
new file mode 100644
index 00000000000..bf6ba9cdecd
--- /dev/null
+++ b/memory/org.eclipse.cdt.debug.ui.memory.floatingpoint/src/org/eclipse/cdt/debug/ui/memory/floatingpoint/Rendering.java
@@ -0,0 +1,2297 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010, 2012 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
+ * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.ui.memory.floatingpoint;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+
+import org.eclipse.cdt.debug.ui.memory.floatingpoint.FPutilities.FPDataType;
+import org.eclipse.core.runtime.IProgressMonitor;
+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.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.resource.JFaceResources;
+import org.eclipse.osgi.util.NLS;
+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;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.progress.UIJob;
+
+
+@SuppressWarnings("restriction")
+public class Rendering extends Composite implements IDebugEventSetListener
+{
+ // The IMemoryRendering parent
+
+ private FPRendering fParent;
+
+ // Controls
+
+ protected FPAddressPane fAddressPane;
+ protected FPDataPane fDataPane;
+ private GoToAddressComposite fAddressBar;
+ protected Control fAddressBarControl;
+ private Selection fSelection = new Selection();
+
+ // Internal management
+
+ BigInteger fViewportAddress = null; // Default visibility for performance
+ BigInteger fMemoryBlockStartAddress = null; // Starting address
+ BigInteger fMemoryBlockEndAddress = null; // Ending address
+ protected BigInteger fBaseAddress = null; // Base address
+ protected int fColumnCount = 0; // Auto calculate can be disabled by user, making this user settable
+ protected int fBytesPerRow = 0; // Number of bytes per row are displayed
+ int fScrollSelection = 0; // Scroll selection
+ private BigInteger fCaretAddress = null; // Caret/cursor position
+ private boolean fCellEditState = false; // Cell editing mode: 'true' = currently editing a cell; 'false' = not editing a cell
+ private BigInteger cellEditAddress = null; // The address of the cell currently being edited
+ private BigInteger memoryAddress = null; // The memory address associated with the cell that currently being edited
+ private StringBuffer fEditBuffer = null; // Character buffer used during editing
+ static boolean initialDisplayModeSet = false; // Initial display mode been set to the same endianness as the target
+
+ // Constants used to identify the panes
+
+ public final static int PANE_ADDRESS = 1;
+ public final static int PANE_DATA = 2;
+
+ // Decimal precision used when converting between scroll units and number of memory
+ // rows. Calculations do not need to be exact; two decimal places is good enough.
+
+ static private final MathContext SCROLL_CONVERSION_PRECISION = new MathContext(2);
+
+ // 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;
+
+ // Update modes
+
+ public final static int UPDATE_ALWAYS = 1;
+ public final static int UPDATE_ON_BREAKPOINT = 2;
+ public final static int UPDATE_MANUAL = 3;
+ public int fUpdateMode = UPDATE_ALWAYS;
+
+ // Constants for cell-width calculations
+
+ private static final int DECIMAL_POINT_SIZE = 1;
+ private static final int SIGN_SIZE = 1;
+ private static final int EXPONENT_CHARACTER_SIZE = 1;
+ private static final int EXPONENT_VALUE_SIZE = 3;
+
+ // User settings
+
+ private FPDataType fFPDataType = FPDataType.FLOAT; // Default to float data type
+ private int fDisplayedPrecision = 8; // The default number of digits of displayed precision
+ private int fCharsPerColumn = charsPerColumn(); // Figure out the initial cell-width size
+ private int fColumnsSetting = COLUMNS_AUTO_SIZE_TO_FIT; // Default column setting
+ private boolean fIsTargetLittleEndian = true; // Default target endian setting
+ private boolean fIsDisplayLittleEndian = true; // Default display endian setting
+ private boolean fEditInserMode = false; // Insert mode: true = replace existing number, false = overstrike
+
+ // Constructors
+
+ public Rendering(Composite parent, FPRendering 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();
+
+ // The viewport address 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.fDataPane = createDataPane();
+
+ fAddressBar = new GoToAddressComposite();
+ fAddressBarControl = fAddressBar.createControl(parent);
+ Button button = fAddressBar.getButton(IDialogConstants.OK_ID);
+
+ if (button != null)
+ {
+ button.addSelectionListener(new SelectionAdapter()
+ {
+
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ doGoToAddress();
+ }
+ });
+
+ button = fAddressBar.getButton(IDialogConstants.CANCEL_ID);
+ if (button != null)
+ {
+ button.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ setVisibleAddressBar(false);
+ }
+ });
+ }
+ }
+
+ fAddressBar.getExpressionWidget().addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e)
+ {
+ doGoToAddress();
+ }
+ });
+
+ fAddressBar.getExpressionWidget().addKeyListener(new KeyAdapter()
+ {
+ @Override
+ public void keyPressed(KeyEvent e)
+ {
+ if (e.keyCode == SWT.ESC)
+ setVisibleAddressBar(false);
+ super.keyPressed(e);
+ }
+ });
+
+ this.fAddressBarControl.setVisible(false);
+
+ getHorizontalBar().addSelectionListener(createHorizontalBarSelectionListener());
+ getVerticalBar().addSelectionListener(createVerticalBarSelectinListener());
+
+ this.addPaintListener(new PaintListener()
+ {
+ @Override
+ public void paintControl(PaintEvent pe)
+ {
+ pe.gc.setBackground(Rendering.this.getFPRendering().getColorBackground());
+ pe.gc.fillRectangle(0, 0, Rendering.this.getBounds().width, Rendering.this.getBounds().height);
+ }
+ });
+
+ setLayout();
+
+ this.addControlListener(new ControlListener()
+ {
+ @Override
+ public void controlMoved(ControlEvent ce)
+ {
+ }
+
+ @Override
+ public void controlResized(ControlEvent ce)
+ {
+ packColumns();
+ }
+ });
+
+ DebugPlugin.getDefault().addDebugEventListener(this);
+ }
+
+ // Determine how many characters are allowed in the column
+
+ private int charsPerColumn()
+ {
+ return fDisplayedPrecision + DECIMAL_POINT_SIZE + SIGN_SIZE + EXPONENT_CHARACTER_SIZE + EXPONENT_VALUE_SIZE + fCellPadding;
+ }
+
+ // Establish the visible layout of the view
+
+ protected void setLayout()
+ {
+ this.setLayout(new Layout()
+ {
+ @Override
+ 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 (fDataPane.isPaneVisible())
+ {
+ fDataPane.setBounds(x, y, fDataPane.computeSize(0, 0).x, Rendering.this.getBounds().height - y);
+ x = fDataPane.getBounds().x + fDataPane.getBounds().width;
+ }
+
+ ScrollBar horizontal = Rendering.this.getHorizontalBar();
+
+ horizontal.setVisible(true);
+ horizontal.setMinimum(0);
+ horizontal.setMaximum(fDataPane.getBounds().x + fDataPane.getBounds().width + xOffset);
+ @SuppressWarnings("unused")
+ int temp = horizontal.getMaximum();
+ horizontal.setThumb(getClientArea().width);
+ horizontal.setPageIncrement(40); // TODO ?
+ horizontal.setIncrement(20); // TODO ?
+ }
+
+ @Override
+ protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache)
+ {
+ return new Point(100, 100); // dummy data
+ }
+ });
+ }
+
+ // Handles for the caret/cursor movement keys
+
+ 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 SelectionListener createHorizontalBarSelectionListener()
+ {
+ return new SelectionListener()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent se)
+ {
+ Rendering.this.layout();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent se)
+ {
+ // Do nothing
+ }
+ };
+ }
+
+ protected SelectionListener createVerticalBarSelectinListener()
+ {
+ return new SelectionListener()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent se)
+ {
+ 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, ignore events with no delta
+ int deltaScroll = getVerticalBar().getSelection() - fScrollSelection;
+ if (deltaScroll == 0) break;
+ BigInteger deltaRows = scrollbar2rows(deltaScroll);
+ BigInteger newAddress = fViewportAddress.add(BigInteger.valueOf(getAddressableCellsPerRow()).multiply(deltaRows));
+ fViewportAddress = newAddress;
+ }
+
+ ensureViewportAddressDisplayable();
+
+ // Update tooltip; FIXME conversion from slider to scrollbar
+ // getVerticalBar().setToolTipText(Rendering.this.getAddressString(fViewportAddress));
+
+ // Update the addresses in the Address pane.
+
+ if (fAddressPane.isPaneVisible())
+ fAddressPane.redraw();
+
+ redrawPanes();
+
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent se)
+ {
+ // do nothing
+ }
+ };
+ }
+
+ protected FPAddressPane createAddressPane()
+ {
+ return new FPAddressPane(this);
+ }
+
+ protected FPDataPane createDataPane()
+ {
+ return new FPDataPane(this);
+ }
+
+ public FPRendering getFPRendering() // TODO rename
+ {
+ return fParent;
+ }
+
+ protected void setCaretAddress(BigInteger address)
+ {
+ fCaretAddress = address;
+ }
+
+ protected BigInteger getCaretAddress()
+ {
+ // Return the caret address if it has been set. Otherwise return the viewport address.
+ // When the rendering is first created, the caret is unset until the user clicks somewhere
+ // in the rendering. It also reset (unset) when the user gives us a new viewport address
+
+ return (fCaretAddress != null) ? fCaretAddress : fViewportAddress;
+ }
+
+ void doGoToAddress()
+ {
+ try
+ {
+ BigInteger address = fAddressBar.getGoToAddress(this.getMemoryBlockStartAddress(), this.getCaretAddress());
+ getFPRendering().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));
+ }
+
+ setScrollSelection();
+ }
+
+ public FPIMemorySelection 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);
+ FPRenderingPlugin.getDefault().getLog().log(status);
+ }
+
+ public void handleFontPreferenceChange(Font font)
+ {
+ setFont(font);
+
+ Control controls[] = this.getRenderingPanes();
+ for (int index = 0; index < controls.length; index++)
+ controls[index].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;
+
+ @Override
+ public void handleDebugEvents(DebugEvent[] events)
+ {
+ if (this.isDisposed()) return;
+
+ boolean isChangeOnly = false;
+ boolean isSuspend = false;
+ boolean isBreakpointHit = false;
+
+ for (int index = 0; index < events.length; index++)
+ {
+ if (events[0].getSource() instanceof IDebugElement)
+ {
+ final int kind = events[index].getKind();
+ final int detail = events[index].getDetail();
+ final IDebugElement source = (IDebugElement) events[index].getSource();
+
+ /*
+ * We have to make sure we are comparing memory blocks here. It pretty much is now the
+ * case that the IDebugTarget is always null. Almost no one in the Embedded Space is
+ * using anything but CDT/DSF or CDT/TCF at this point. The older CDI stuff will still
+ * be using the old Debug Model API. But this will generate the same memory block and
+ * a legitimate IDebugTarget which will match properly.
+ */
+ if( source.equals( getMemoryBlock() ) && source.getDebugTarget() == getMemoryBlock().getDebugTarget() )
+ {
+ if ((detail & DebugEvent.BREAKPOINT) != 0) isBreakpointHit = true;
+
+ if (kind == DebugEvent.SUSPEND)
+ {
+ handleSuspendEvent(detail);
+ isSuspend = true;
+ }
+ else if (kind == DebugEvent.CHANGE)
+ {
+ handleChangeEvent();
+ isChangeOnly = true;
+ }
+ }
+ }
+ }
+
+ if (isSuspend)
+ handleSuspend(isBreakpointHit);
+ else if (isChangeOnly)
+ handleChange();
+ }
+
+ protected void handleSuspend(boolean isBreakpointHit)
+ {
+ if (getUpdateMode() == UPDATE_ALWAYS || (getUpdateMode() == UPDATE_ON_BREAKPOINT && isBreakpointHit))
+ {
+ Display.getDefault().asyncExec(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ archiveDeltas();
+ refresh();
+ }
+ });
+ }
+ }
+
+ protected void handleChange()
+ {
+ if (getUpdateMode() == UPDATE_ALWAYS)
+ {
+ Display.getDefault().asyncExec(new Runnable()
+ {
+ @Override
+ 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 FPIViewportCache getViewportCache()
+ {
+ return fViewportCache;
+ }
+
+ public FPMemoryByte[] 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 FPIViewportCache
+ {
+ 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;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() + startAddress.hashCode() + endAddress.hashCode();
+ }
+
+ }
+
+ class MemoryUnit implements Cloneable
+ {
+ BigInteger start;
+
+ BigInteger end;
+
+ FPMemoryByte[] bytes;
+
+ @Override
+ public MemoryUnit clone()
+ {
+ MemoryUnit b = new MemoryUnit();
+
+ b.start = this.start;
+ b.end = this.end;
+ b.bytes = new FPMemoryByte[this.bytes.length];
+ for (int index = 0; index < this.bytes.length; index++)
+ b.bytes[index] = new FPMemoryByte(this.bytes[index].getValue());
+
+ return b;
+ }
+
+ public boolean isValid()
+ {
+ return this.start != null && this.end != null && this.bytes != null;
+ }
+ }
+
+ @SuppressWarnings("hiding")
+ private HashMap