blob: 0cdaa4b38411286fde4ff1d59e943aebbdd7981a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2005 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.internal.ui.views.memory.renderings;
import java.math.BigInteger;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockExtension;
import org.eclipse.debug.core.model.MemoryByte;
import org.eclipse.debug.internal.ui.DebugUIMessages;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.memory.AbstractTableRendering;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.swt.widgets.TableItem;
/**
* @since 3.1
*/
public class TableRenderingCellModifier implements ICellModifier {
private boolean editActionInvoked = false;
private AbstractTableRendering fRendering;
public TableRenderingCellModifier(AbstractTableRendering rendering) {
fRendering = rendering;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object,
* java.lang.String)
*/
public boolean canModify(Object element, String property) {
boolean canModify = true;
try {
if (!(element instanceof TableRenderingLine))
return false;
if (!editActionInvoked)
return false;
if (fRendering == null)
return false;
if (fRendering.getMemoryBlock().supportsValueModification() == false) {
return false;
}
TableRenderingLine line = (TableRenderingLine) element;
if (TableRenderingLine.P_ADDRESS.equals(property)) {
return false;
}
// property is stored as number of addressable unit away from the
// line address
// to calculate offset to the memory line array, offset =
// numberofAddressableUnit * addressableSize
int addressableSize = getAddressableSize();
int offset = Integer.valueOf(property, 16).intValue() * addressableSize;
int end = offset + fRendering.getBytesPerColumn();
for (int i = offset; i < end; i++) {
MemoryByte oneByte = line.getByte(i);
if (!oneByte.isWritable()) {
canModify = false;
}
}
return canModify;
} catch (NumberFormatException e) {
canModify = false;
return canModify;
}
}
/**
* @return
*/
private int getAddressableSize() {
int addressableSize = fRendering.getAddressableSize();
if (addressableSize < 1)
addressableSize = 1;
return addressableSize;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object,
* java.lang.String)
*/
public Object getValue(Object element, String property) {
// give back the value of the column
if (!(element instanceof TableRenderingLine))
return null;
TableRenderingLine line = (TableRenderingLine) element;
try {
if (TableRenderingLine.P_ADDRESS.equals(property))
return line.getAddress();
int offset = Integer.valueOf(property, 16).intValue() * getAddressableSize();
int end = offset + fRendering.getBytesPerColumn();
// Ask for label provider
MemoryByte[] memory = line.getBytes(offset, end);
if (line.isAvailable(offset, end)) {
// ask the renderer for a string representation of the bytes
offset = Integer.valueOf(property, 16).intValue();
BigInteger address = new BigInteger(((TableRenderingLine) element).getAddress(), 16);
address = address.add(BigInteger.valueOf(offset));
return fRendering.getString(fRendering.getRenderingId(), address, memory);
}
// if the range is not available, just return padded string
return getPaddedString(offset, end);
} catch (NumberFormatException e) {
return "00"; //$NON-NLS-1$
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object,
* java.lang.String, java.lang.Object)
*/
public void modify(Object element, String property, Object value) {
TableRenderingLine line = null;
if (!(element instanceof TableRenderingLine)) {
line = (TableRenderingLine) ((TableItem) element).getData();
} else {
line = (TableRenderingLine) element;
}
// validate data
if (!(value instanceof String))
return;
try {
// calculate offset to update
IMemoryBlock memoryBlk = fRendering.getMemoryBlock();
int lineOffset = Integer.valueOf(property, 16).intValue();
// this offset is number of addressable unit from the line address
BigInteger offset = getOffset(memoryBlk, line.getAddress(), lineOffset);
byte[] bytes = null;
String oldValue = (String) getValue(line, property);
if (!oldValue.equals(value)) {
// property is number of addressable unit from line address
// to calculate proper offset in the memoryViewLine's array
// offset = numberOfAddressableUnit * addressableSize
int offsetToLine = Integer.valueOf(property, 16).intValue() * getAddressableSize();
int end = offsetToLine + fRendering.getBytesPerColumn();
MemoryByte[] oldArray = line.getBytes(offsetToLine, end);
BigInteger address = new BigInteger(line.getAddress(), 16);
address = address.add(BigInteger.valueOf(offsetToLine));
bytes = fRendering.getBytes(fRendering.getRenderingId(), address, oldArray, (String) value);
if (bytes == null)
return;
if (bytes.length == 0)
return;
if (bytes.length <= oldArray.length) {
boolean changed = false;
// check that the bytes returned has actually changed
for (int i = 0; i < bytes.length; i++) {
if (bytes[i] != oldArray[i].getValue()) {
changed = true;
break;
}
}
if (!changed)
return;
}
} else {
// return if value has not changed
return;
}
if (memoryBlk instanceof IMemoryBlockExtension)
((IMemoryBlockExtension) memoryBlk).setValue(offset, bytes);
else
memoryBlk.setValue(offset.longValue(), bytes);
} catch (DebugException e) {
MemoryViewUtil.openError(DebugUIMessages.MemoryViewCellModifier_failure_title, DebugUIMessages.MemoryViewCellModifier_failed, e);
} catch (NumberFormatException e) {
MemoryViewUtil.openError(DebugUIMessages.MemoryViewCellModifier_failure_title, DebugUIMessages.MemoryViewCellModifier_failed + "\n" + DebugUIMessages.MemoryViewCellModifier_data_is_invalid, null); //$NON-NLS-1$
}
}
private BigInteger getOffset(IMemoryBlock memory, String lineAddress, int lineOffset) throws DebugException {
BigInteger lineAddr = new BigInteger(lineAddress, 16);
BigInteger memoryAddr;
if (memory instanceof IMemoryBlockExtension) {
memoryAddr = ((IMemoryBlockExtension) memory).getBigBaseAddress();
} else {
memoryAddr = BigInteger.valueOf(memory.getStartAddress());
}
if (memoryAddr == null)
memoryAddr = new BigInteger("0"); //$NON-NLS-1$
return lineAddr.subtract(memoryAddr).add(BigInteger.valueOf(lineOffset));
}
/**
* @param editActionInvoked
* The editActionInvoked to set.
*/
public void setEditActionInvoked(boolean editActionInvoked) {
this.editActionInvoked = editActionInvoked;
}
/**
* @param start
* @param end
* @return padded string
*/
public String getPaddedString(int start, int end) {
StringBuffer buf = new StringBuffer();
String paddedStr = DebugUIPlugin.getDefault().getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR);
for (int i = start; i < end; i++) {
buf.append(paddedStr);
}
return buf.toString();
}
}