/******************************************************************************* * 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.BigInteger; import org.eclipse.debug.core.DebugException; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; public class FPDataPane extends FPAbstractPane { public FPDataPane(Rendering parent) { super(parent); } // Returns the representation of the given memory bytes as a scientific notation string protected String bytesToSciNotation(FPMemoryByte[] bytes) { return fRendering.sciNotationString(bytes, fRendering.getFPDataType(), fRendering.isDisplayLittleEndian()); } // Cell editing: Accumulate text entry characters, replacing or inserting them at the current cursor position @Override protected void editCell(BigInteger cellAddress, int subCellPosition, char character) { try { // Switch to cell edit mode if not we're not currently in the middle of an edit if (!fRendering.isEditingCell()) { // Calculate the memory address from the cell address BigInteger vpStart = fRendering.getViewportStartAddress(); BigInteger colChars = BigInteger.valueOf(fRendering.getCharsPerColumn()); BigInteger dtBytes = BigInteger.valueOf(fRendering.getFPDataType().getByteLength()); BigInteger memoryAddress = vpStart.add(((cellAddress.subtract(vpStart)).divide(colChars)).multiply(dtBytes)); if (!fRendering.insertMode()) { // Overstrike/overwrite mode: Enter cell-edit mode; start with the current cell contents. fRendering.startCellEditing(cellAddress, memoryAddress, bytesToSciNotation(fRendering.getBytes(cellAddress, fRendering.getFPDataType().getByteLength()))); } else { // Insert/Replace mode: Clear the current cell contents; start // with a blank string. Move the caret to the start of the cell. fRendering.startCellEditing(cellAddress, memoryAddress, FPutilities.fillString(fRendering.getCharsPerColumn(), ' ')); subCellPosition = 0; Point cellCoordinates = getCellLocation(cellAddress); positionCaret(cellCoordinates.x, cellCoordinates.y); fCaret.setVisible(true); } } // Validate the current string: Only one decimal point and exponent character ('e' or 'E') is allowed. Number // signs may be present up to two times - once for the number and once for the exponent, and may occur at the // very beginning of a number or immediately after the exponent character. If an entry violates a rule, do not // echo the character (implicitly, through replacement and re-paint) and do not advance the cursor. String cellString = fRendering.getEditBuffer().toString().toLowerCase(); // Check to see if a second decimal point or exponent was entered if ((character == '.' && FPutilities.countMatches(cellString, ".") > 0 && cellString.indexOf('.') != subCellPosition) || //$NON-NLS-1$ (character == 'e' && FPutilities.countMatches(cellString, "e") > 0 && cellString.indexOf('e') != subCellPosition)) //$NON-NLS-1$ return; // Check to see if more than two number signs have been entered if ((character == '+' && FPutilities.countMatches(cellString, "+") > 1) || //$NON-NLS-1$ (character == '-' && FPutilities.countMatches(cellString, "-") > 1)) //$NON-NLS-1$ return; // We've passed the previous checks: Make the character substitution, if possible. // Advance the cursor as long as we're inside the column. Re-paint the view. if (subCellPosition < fRendering.getEditBuffer().length()) fRendering.getEditBuffer().setCharAt(subCellPosition, character); if (subCellPosition < fRendering.getCharsPerColumn()) advanceCursor(); redraw(); } catch (Exception e) { e.printStackTrace(); } } // Returns cell width, in pixels @Override protected int getCellWidth() { return getCellCharacterCount() * getCellCharacterWidth() + (fRendering.getCellPadding() * 2); } @Override protected int getCellCharacterCount() { return fRendering.getCharsPerColumn(); } @Override public Point computeSize(int wHint, int hHint) { return new Point(fRendering.getColumnCount() * getCellWidth() + fRendering.getRenderSpacing(), 100); } private BigInteger getCellAddressAt(int x, int y) throws DebugException { BigInteger address = fRendering.getViewportStartAddress(); int col = x / getCellWidth(); int row = y / getCellHeight(); if (col >= fRendering.getColumnCount()) return null; address = address.add(BigInteger.valueOf(row * fRendering.getColumnCount() * fRendering.getFPDataType().getByteLength())); address = address.add(BigInteger.valueOf(col * fRendering.getFPDataType().getByteLength())); return address; } // Return a Point representing the cell address @Override protected Point getCellLocation(BigInteger cellAddress) { try { BigInteger address = fRendering.getViewportStartAddress(); int cellOffset = cellAddress.subtract(address).intValue(); cellOffset *= fRendering.getAddressableSize(); int row = cellOffset / (fRendering.getColumnCount() * fRendering.getFPDataType().getByteLength()); cellOffset -= row * fRendering.getColumnCount() * fRendering.getFPDataType().getByteLength(); int col = cellOffset / fRendering.getFPDataType().getByteLength(); int x = col * getCellWidth() + fRendering.getCellPadding(); int y = row * getCellHeight() + fRendering.getCellPadding(); return new Point(x, y); } catch (Exception e) { fRendering.logError(FPRenderingMessages.getString("FPRendering.FAILURE_DETERMINE_CELL_LOCATION"), e); //$NON-NLS-1$ return null; } } @Override protected void positionCaret(int x, int y) { try { BigInteger cellAddress = getCellAddressAt(x, y); if (cellAddress != null) { Point cellPosition = getCellLocation(cellAddress); int offset = x - cellPosition.x; int subCellCharacterPosition = offset / getCellCharacterWidth(); if (subCellCharacterPosition == this.getCellCharacterCount()) { cellAddress = cellAddress.add(BigInteger.valueOf(fRendering.getFPDataType().getByteLength())); subCellCharacterPosition = 0; cellPosition = getCellLocation(cellAddress); } fCaret.setLocation(cellPosition.x + subCellCharacterPosition * getCellCharacterWidth(), cellPosition.y); this.fCaretAddress = cellAddress; this.fSubCellCaretPosition = subCellCharacterPosition; setCaretAddress(fCaretAddress); } } catch (Exception e) { fRendering.logError(FPRenderingMessages.getString("FPRendering.FAILURE_POSITION_CURSOR"), e); //$NON-NLS-1$ } } @Override protected BigInteger getViewportAddress(int col, int row) throws DebugException { BigInteger address = fRendering.getViewportStartAddress(); address = address.add(BigInteger.valueOf((row * fRendering.getColumnCount() + col) * fRendering.getFPDataType().getByteLength())); return address; } @Override protected void paint(PaintEvent pe) { super.paint(pe); // Allow subclasses to override this method to do their own painting doPaintData(pe); } // Display text in the cell protected void doPaintData(PaintEvent pe) { GC gc = pe.gc; gc.setFont(fRendering.getFont()); int cellHeight = getCellHeight(); int cellWidth = getCellWidth(); int boundsHeight = this.getBounds().height; int columns = fRendering.getColumnCount(); int cellX = 0; int cellY = 0; String displayString = FPutilities.fillString(fRendering.getCharsPerColumn(), '.'); try { BigInteger vpStart = fRendering.getViewportStartAddress(); BigInteger cellStartAddr = vpStart; BigInteger memoryAddr = vpStart; BigInteger cellEndAddr; for(int row = 0; row < boundsHeight / cellHeight; row++) { for (int column = 0; column < columns; column++) { // Set alternating colors for every other column and display the text // FIXME: There is duplicate code in applyCustomColor() in this class if (isOdd(column)) gc.setForeground(fRendering.getFPRendering().getColorText()); else gc.setForeground(fRendering.getFPRendering().getColorTextAlternate()); // Calculate the cell starting address and X/Y coordinates cellStartAddr = vpStart.add(BigInteger.valueOf((row * fRendering.getColumnCount() + column) * fRendering.getFPDataType().getByteLength())); cellEndAddr = cellStartAddr.add(BigInteger.valueOf(fRendering.getFPDataType().getByteLength()).subtract(BigInteger.ONE)); cellX = (cellWidth * column) + fRendering.getCellPadding(); cellY = (cellHeight * row ) + fRendering.getCellPadding(); // Cell editing: If we're in edit mode, change the cell color and then set the // edit buffer as the string to display. Otherwise, just use the memory contents. if (fRendering.isEditingCell() && cellStartAddr.equals(fRendering.getCellEditAddress())) { gc.setForeground(fRendering.getFPRendering().getColorEdit()); FPMemoryByte[] memoryBytes = fRendering.getBytes(cellStartAddr, fRendering.getFPDataType().getByteLength()); for (FPMemoryByte memoryByte : memoryBytes) memoryByte.setEdited(true); applyCustomColor(gc, memoryBytes, column); displayString = fRendering.getEditBuffer().toString(); } else displayString = bytesToSciNotation(fRendering.getBytes(memoryAddr, fRendering.getFPDataType().getByteLength())); // Cell selection if (fRendering.getSelection().isSelected(cellStartAddr)) { gc.setBackground(fRendering.getFPRendering().getColorSelection()); gc.fillRectangle(cellX, row * cellHeight, cellWidth, cellHeight); gc.setForeground(fRendering.getFPRendering().getColorBackground()); } else { gc.setBackground(fRendering.getFPRendering().getColorBackground()); gc.fillRectangle(cellX, row * cellHeight, cellWidth, cellHeight); // Allow subclasses to override this method to do their own coloring applyCustomColor(gc, fRendering.getBytes(cellStartAddr, fRendering.getFPDataType().getByteLength()), column); } gc.drawText(displayString, cellX, cellY); // Move the caret if appropriate if (fCaretEnabled) { if(cellStartAddr.compareTo(fCaretAddress) <= 0 && cellEndAddr.compareTo(fCaretAddress) >= 0) { int x = cellWidth * column + fRendering.getCellPadding() + fSubCellCaretPosition * this.getCellCharacterWidth(); int y = cellHeight * row + fRendering.getCellPadding(); fCaret.setLocation(x, y); } } // For debugging if (fRendering.isDebug()) gc.drawRectangle(cellX, cellY, cellWidth, cellHeight); // Increment the memory address by the length of the data type memoryAddr = memoryAddr.add(BigInteger.valueOf(fRendering.getFPDataType().getByteLength())); } } } catch(Exception e) { fRendering.logError(FPRenderingMessages.getString("FPRendering.FAILURE_PAINT"), e); //$NON-NLS-1$ e.printStackTrace(); } } // Allow subclasses to override this method to do their own coloring protected void applyCustomColor(GC gc, FPMemoryByte bytes[], int col) { // Check to see if any byte has been changed and whether we're actually in edit mode boolean anyByteEditing = false; for (int n = 0; n < bytes.length && !anyByteEditing; n++) if (bytes[n].isEdited()) anyByteEditing = true; anyByteEditing = anyByteEditing && fRendering.isEditingCell(); // Even/odd column coloring if (isOdd(col)) gc.setForeground(fRendering.getFPRendering().getColorText()); else gc.setForeground(fRendering.getFPRendering().getColorTextAlternate()); // Background gc.setBackground(fRendering.getFPRendering().getColorBackground()); if (anyByteEditing) { gc.setForeground(fRendering.getFPRendering().getColorEdit()); } else { boolean isColored = false; for (int index = 0; index < fRendering.getHistoryDepth() && !isColored; index++) { // TODO consider adding finer granularity? for (int n = 0; n < bytes.length; n++) { if (bytes[n].isChanged(index)) { if (index == 0) gc.setForeground(fRendering.getFPRendering().getColorsChanged()[index]); else gc.setBackground(fRendering.getFPRendering().getColorsChanged()[index]); isColored = true; break; } } } } } // Draw a box around the specified cell public void highCellBox(BigInteger memoryAddress) { // if (fRendering.isDebug()) // gc.drawRectangle(cellX, cellY, cellWidth, cellHeight); } // Clear the box around the specified cell public void clearCellBox(BigInteger memoryAddress) { } }