Bug 387500 PgDn/PgUp jumps uses large address increments for memory

spaces with 64-bit address

- Fix scroll adjustments according to current viewport addresses
- Add CTRL-Home/CTRL-END to go to start/end of memory space
- Add Home/END to go to start/end of the row
- Add eclipse debug tracing support

Change-Id: Ifba9f1e6c67e1cc6ccb8f6f8787a55520d8bf9be
Signed-off-by: Teodor Madan <teodor.madan@freescale.com>
This commit is contained in:
Teodor Madan 2015-06-10 18:04:23 +03:00
parent 6e7a509f9b
commit c5a5040e62
8 changed files with 275 additions and 103 deletions

View file

@ -0,0 +1 @@
org.eclipse.cdt.debug.ui.memory.traditional/debug = false

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.debug.ui.memory.traditional;singleton:=true
Bundle-Version: 1.2.1.qualifier
Bundle-Version: 1.3.0.qualifier
Bundle-Localization: plugin
Require-Bundle: org.eclipse.debug.core,
org.eclipse.debug.ui,

View file

@ -44,6 +44,19 @@
</viewContribution>
</extension>
<extension
point = "org.eclipse.ui.trace.traceComponents">
<component
id="org.eclipse.cdt.debug.ui.memory.traditional.component"
label="Traditional Rendering">
<bundle
consumed="true"
name="org.eclipse.cdt.debug.ui.memory.traditional">
</bundle>
</component>
</extension>
</plugin>

View file

@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<version>1.2.1-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.debug.ui.memory.traditional</artifactId>
<packaging>eclipse-plugin</packaging>
</project>

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2015 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
@ -7,6 +7,7 @@
*
* Contributors:
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
* Teodor Madan (Freescale) - Fix PageDn/PageUp
*******************************************************************************/
package org.eclipse.cdt.debug.ui.memory.traditional;
@ -211,6 +212,22 @@ public abstract class AbstractPane extends Canvas
{
handlePageUpKey();
}
else if(ke.keyCode == SWT.HOME && (ke.stateMask & SWT.CTRL) != 0)
{
fRendering.gotoAddress(fRendering.getMemoryBlockStartAddress());
}
else if(ke.keyCode == SWT.END && (ke.stateMask & SWT.CTRL) != 0)
{
fRendering.gotoAddress(fRendering.getMemoryBlockEndAddress());
}
else if(ke.keyCode == SWT.HOME && (ke.stateMask & SWT.CTRL) == 0)
{
handleHomeKey();
}
else if(ke.keyCode == SWT.END && (ke.stateMask & SWT.CTRL) == 0)
{
handleEndKey();
}
else if(ke.keyCode == SWT.ESC)
{
fRendering.getViewportCache().clearEditBuffer();
@ -311,7 +328,7 @@ public abstract class AbstractPane extends Canvas
this.addFocusListener(createFocusListener());
}
protected MouseListener createMouseListener(){
protected MouseListener createMouseListener(){
return new AbstractPaneMouseListener();
}
@ -422,7 +439,35 @@ public abstract class AbstractPane extends Canvas
updateCaret();
ensureCaretWithinViewport();
}
/**
* @since 1.3
*/
protected void handleEndKey() {
// calculate offset from the end of the row
BigInteger lastCellAddress = fRendering.getViewportEndAddress().subtract(BigInteger.ONE);
int cellOffset = fCaretAddress.subtract(lastCellAddress).intValue();
int row = cellOffset / fRendering.getAddressableCellsPerRow();
setCaretAddress(lastCellAddress.add(BigInteger.valueOf(row * fRendering.getAddressableCellsPerRow())));
updateCaret();
ensureCaretWithinViewport();
}
/**
* @since 1.3
*/
protected void handleHomeKey() {
// calculate offset from the beginning of the row
int cellOffset = fCaretAddress.subtract(fRendering.getViewportStartAddress()).intValue();
int row = cellOffset / fRendering.getAddressableCellsPerRow();
setCaretAddress(fRendering.getViewportStartAddress().add(BigInteger.valueOf(row * fRendering.getAddressableCellsPerRow())));
updateCaret();
ensureCaretWithinViewport();
}
protected void handleMouseDoubleClick(MouseEvent me)
{
try
@ -586,10 +631,16 @@ public abstract class AbstractPane extends Canvas
{
// The caret was moved outside the viewport bounds: Scroll the
// viewport up or down by a row, depending on where the caret is
boolean upArrow = fCaretAddress.compareTo(vpStart) <= 0;
int rows = (upArrow ? -1 : 1 );
if (upArrow) {
rows -= vpStart.subtract(fCaretAddress).intValue()/fRendering.getAddressableCellsPerRow();
} else {
rows += fCaretAddress.subtract(vpEnd).intValue()/fRendering.getAddressableCellsPerRow();
}
ScrollBar vBar = fRendering.getVerticalBar();
vBar.setSelection(vBar.getSelection() + (upArrow ? -1 : 1));
vBar.setSelection(vBar.getSelection() + rows);
vBar.notifyListeners(SWT.Selection, new Event());
// Check to see if we're at the beginning or end of a line, and

View file

@ -9,13 +9,13 @@
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
* Ling Wang (Silicon Laboratories) - Honor start address (Bug 414519)
* Teodor Madan (Freescale) - Fix scrolling for memory spaces with 64-bit address
*******************************************************************************/
package org.eclipse.cdt.debug.ui.memory.traditional;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
@ -131,14 +131,6 @@ public class Rendering extends Composite implements IDebugEventSetListener
public final static int PANE_TEXT = 3;
/**
* 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;
@ -426,32 +418,14 @@ public class Rendering extends Composite implements IDebugEventSetListener
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() - fCurrentScrollSelection;
if (deltaScroll == 0)
break;
BigInteger deltaRows = scrollbar2rows(deltaScroll);
BigInteger newAddress = fViewportAddress.add(BigInteger.valueOf(
getAddressableCellsPerRow()).multiply(deltaRows));
fViewportAddress = newAddress;
}
// Figure out the delta, ignore events with no delta
int deltaScroll = getVerticalBar().getSelection() - fCurrentScrollSelection;
if (deltaScroll == 0)
break;
fViewportAddress = fViewportAddress.add(BigInteger.valueOf(
getAddressableCellsPerRow()).multiply(BigInteger.valueOf(deltaScroll)));
ensureViewportAddressDisplayable();
// Update tooltip
// FIXME conversion from slider to scrollbar
@ -709,7 +683,9 @@ public class Rendering extends Composite implements IDebugEventSetListener
}
// default visibility for performance
ViewportCache fViewportCache = new ViewportCache();
ViewportCache fViewportCache = new ViewportCache();
private BigInteger fScrollStartAddress = BigInteger.ZERO;
private interface Request
{
@ -1461,7 +1437,7 @@ public class Rendering extends Composite implements IDebugEventSetListener
getVerticalBar().setMinimum(1);
// scrollbar maximum range is Integer.MAX_VALUE.
getVerticalBar().setMaximum(getMaxScrollRange().min(BigInteger.valueOf(Integer.MAX_VALUE)).intValue());
getVerticalBar().setMaximum(getMaxScrollLines());
getVerticalBar().setIncrement(1);
getVerticalBar().setPageIncrement(this.getRowCount() -1);
//TW FIXME conversion of slider to scrollbar
@ -1528,7 +1504,8 @@ public class Rendering extends Composite implements IDebugEventSetListener
// reset the caret and selection state (no caret and no selection)
fCaretAddress = null;
fSelection = new Selection();
ensureViewportAddressDisplayable();
redrawPanes();
}
@ -1547,6 +1524,30 @@ public class Rendering extends Composite implements IDebugEventSetListener
return fViewportAddress.add(BigInteger.valueOf(this.getBytesPerRow() * getRowCount() / getAddressableSize()));
}
private BigInteger getScrollStartAddress()
{
return fScrollStartAddress;
}
private void setScrollStartAddress(BigInteger newAddress)
{
fScrollStartAddress = newAddress;
}
private BigInteger getScrollEndAddress()
{
int scrollLines = getMaxScrollLines();
// substract scroll thumb as it is not possible to scroll beyond it
scrollLines -= getVerticalBar().getThumb();
BigInteger newAddress = getScrollStartAddress().add(
BigInteger.valueOf(getAddressableCellsPerRow()).multiply(
BigInteger.valueOf(scrollLines))
);
return newAddress.min(getMemoryBlockEndAddress());
}
public String getAddressString(BigInteger address)
{
StringBuffer addressString = new StringBuffer(address.toString(16)
@ -1647,77 +1648,83 @@ public class Rendering extends Composite implements IDebugEventSetListener
}
/**
* @return Set current scroll selection
* Update current scroll selection to match current viewport range
*/
protected void setCurrentScrollSelection()
{
BigInteger selection = getViewportStartAddress().divide(
BigInteger.valueOf(getAddressableCellsPerRow()));
fCurrentScrollSelection = rows2scrollbar(selection);
BigInteger viewportStartAddress = getViewportStartAddress();
if (TraceOptions.DEBUG) {
TraceOptions.trace(MessageFormat.format(
"Update scroll for viewrange[0x{0} : 0x{1}]:\n",
viewportStartAddress.toString(16), getViewportEndAddress().toString(16)));
TraceOptions.trace(MessageFormat.format(
" current ScrollRange=[0x{0} : 0x{1}]; selection = {2}\n",
getScrollStartAddress().toString(16), getScrollEndAddress().toString(16),
fCurrentScrollSelection));
}
BigInteger addressableRow = BigInteger.valueOf(getAddressableCellsPerRow());
if ((viewportStartAddress.compareTo(getScrollStartAddress()) <= 0)) {
// must reposition scroll area, center position into the center of the new scroll area
// unless it is already at the start of first line.
int scrollLines = getMaxScrollLines()/2;
BigInteger newScrollStart = BigInteger.ZERO.max(viewportStartAddress.subtract(
BigInteger.valueOf(scrollLines).multiply(addressableRow))
);
setScrollStartAddress(newScrollStart);
if (TraceOptions.DEBUG) {
TraceOptions.trace(MessageFormat.format(
" new ScrollRange=[0x{0} : 0x{1}]\n",
getScrollStartAddress().toString(16), getScrollEndAddress().toString(16)));
}
} else if (getViewportEndAddress().compareTo(getScrollEndAddress()) >= 0) {
// must reposition scroll area, center position into the center of the new scroll area
// unless when user gets closer to end of addressable size of memory, when leave
// scroll start address at end of block memory scroll start
BigInteger eomScrollStart = getMemoryBlockEndAddress().add(BigInteger.ONE).
subtract( BigInteger.valueOf(getMaxScrollLines() - getVerticalBar().getThumb()).multiply(addressableRow));
int scrollLines = getMaxScrollLines()/2;
BigInteger newScrollStart = eomScrollStart.min(viewportStartAddress.subtract(
BigInteger.valueOf(scrollLines).multiply(addressableRow))
);
setScrollStartAddress(newScrollStart);
if (TraceOptions.DEBUG) {
TraceOptions.trace(MessageFormat.format(
" new ScrollRange=[0x{0} : 0x{1}]\n",
getScrollStartAddress().toString(16), getScrollEndAddress().toString(16)));
}
}
// calculate selection line from the start of scroll area
fCurrentScrollSelection = viewportStartAddress.subtract(getScrollStartAddress()).divide(
addressableRow).intValue() + 1;
if (TraceOptions.DEBUG) {
TraceOptions.trace(MessageFormat.format(" new selection={0}\n", fCurrentScrollSelection));
}
getVerticalBar().setSelection(fCurrentScrollSelection);
}
/**
* compute the maximum scrolling range.
* @return number of lines that rendering can display
*/
private BigInteger getMaxScrollRange() {
private int getMaxScrollLines() {
BigInteger difference = getMemoryBlockEndAddress().subtract(getMemoryBlockStartAddress()).add(BigInteger.ONE);
BigInteger maxScrollRange = difference.divide(BigInteger.valueOf(getAddressableCellsPerRow()));
if(maxScrollRange.multiply(BigInteger.valueOf(getAddressableCellsPerRow())).compareTo(difference) != 0)
maxScrollRange = maxScrollRange.add(BigInteger.ONE);
maxScrollRange = maxScrollRange.add(BigInteger.ONE); // add a line to hold bytes that do not fill an entire raw
// support targets with an addressable size greater than 1
maxScrollRange = maxScrollRange.divide(BigInteger.valueOf(getAddressableSize()));
return maxScrollRange;
// cap to maximum lines a SWT ScrollBar can hold.
return maxScrollRange.min(BigInteger.valueOf(Integer.MAX_VALUE)).intValue();
}
/**
* The scroll range is limited by SWT. Because it can be less than the
* number of rows (of memory) that we need to display, we need an arithmetic
* mapping.
*
* @return ratio this function returns how many rows a scroll bar unit
* represents. The number will be some fractional value, up to but
* not exceeding the value 1. I.e., when the scroll range exceeds
* the row range, we use a 1:1 mapping.
*/
private final BigDecimal getScrollRatio() {
BigInteger maxRange = getMaxScrollRange();
if (maxRange.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0 ) {
return new BigDecimal(maxRange).divide(BigDecimal.valueOf(Integer.MAX_VALUE), SCROLL_CONVERSION_PRECISION);
} else {
return BigDecimal.ONE;
}
}
/**
* Convert memory row units to scroll bar units. The scroll range is limited
* by SWT. Because it can be less than the number of rows (of memory) that
* we need to display, we need an arithmetic mapping.
* @param rows
* units of memory
* @return scrollbar units
*/
private int rows2scrollbar(BigInteger rows) {
return new BigDecimal(rows).divide(getScrollRatio(), SCROLL_CONVERSION_PRECISION).intValue();
}
/**
* Convert scroll bar units to memory row units. The scroll range is limited
* by SWT. Because it can be less than the number of rows (of memory) that
* we need to display, we need an arithmetic mapping.
*
* @param scrollbarUnits
* scrollbar units
* @return number of rows of memory
*/
private BigInteger scrollbar2rows(int scrollbarUnits) {
return getScrollRatio().multiply(BigDecimal.valueOf(scrollbarUnits), SCROLL_CONVERSION_PRECISION).toBigInteger();
}
/**
* @return start address of the memory block
*/

View file

@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) 2015 Freescale, 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:
* Teodor Madan (Freescale) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.ui.memory.traditional;
import java.util.Hashtable;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.debug.DebugOptionsListener;
import org.eclipse.osgi.service.debug.DebugTrace;
import org.osgi.framework.BundleContext;
/**
* Hooks debug options to the Platform trace functionality.
* In essence, we can open Window -> Preferences -> Tracing
* and turn on debug options for this package. The debug output
* will come out on the console and can be saved directly to
* a file. Classes that need to be debugged can call into
* TraceOptions to get debug flags. If new flags need to be
* created, they will need to have a unique identifier and added to
* the .options file in this plugin
*
*/
class TraceOptions implements DebugOptionsListener {
private static final String DEBUG_FLAG = "org.eclipse.cdt.debug.ui.memory.traditional/debug"; //$NON-NLS-1$
public static boolean DEBUG = false;
/**
* The {@link DebugTrace} object to print to OSGi tracing
*/
private static DebugTrace fgDebugTrace;
private String pluginID;
/**
* Constructor
*/
public TraceOptions(BundleContext context, String pluginID) {
this.pluginID = pluginID;
Hashtable<String, String> props = new Hashtable<String, String>(2);
props.put(org.eclipse.osgi.service.debug.DebugOptions.LISTENER_SYMBOLICNAME, pluginID);
context.registerService(DebugOptionsListener.class.getName(), this, props);
}
@Override
public void optionsChanged(DebugOptions options) {
fgDebugTrace = options.newDebugTrace(pluginID);
DEBUG = options.getBooleanOption(DEBUG_FLAG, false);
}
/**
* Prints the given message to System.out and to the OSGi tracing (if started)
* @param option the option or <code>null</code>
* @param message the message to print or <code>null</code>
* @param throwable the {@link Throwable} or <code>null</code>
*/
public static void trace(String option, String message, Throwable throwable) {
//divide the string into substrings of 100 chars or less for printing
//to console
String systemPrintableMessage = message;
while (systemPrintableMessage.length() > 100) {
String partial = systemPrintableMessage.substring(0, 100);
systemPrintableMessage = systemPrintableMessage.substring(100);
System.out.println(partial + "\\"); //$NON-NLS-1$
}
System.out.print(systemPrintableMessage);
//then pass the original message to be traced into a file
if(fgDebugTrace != null) {
fgDebugTrace.trace(option, message, throwable);
}
}
/**
* Prints the given message to System.out and to the OSGi tracing (if enabled)
*
* @param message the message or <code>null</code>
*/
public static void trace(String message) {
trace(null, message, null);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006-2009 Wind River Systems, Inc. and others.
* Copyright (c) 2006-2015 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
@ -16,6 +16,7 @@ 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 TraditionalRenderingPlugin extends AbstractUIPlugin
{
@ -29,6 +30,12 @@ public class TraditionalRenderingPlugin extends AbstractUIPlugin
plugin = this;
}
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
new TraceOptions(context, PLUGIN_ID);
}
/**
* Returns the shared instance.
*/
@ -68,5 +75,5 @@ public class TraditionalRenderingPlugin extends AbstractUIPlugin
return window.getShell();
}
return null;
}
}
}