/*******************************************************************************
 * Copyright (c) 2006, 2016 Wind River Systems, Inc. and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     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.BigInteger;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.cdt.debug.core.model.IMemoryBlockAddressInfoRetrieval.IMemoryBlockAddressInfoItem;
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.action.Action;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.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;

@SuppressWarnings("restriction")
public class Rendering extends Composite implements IDebugEventSetListener {
	// the IMemoryRendering parent
	private TraditionalRendering fParent;

	// controls

	protected AddressPane fAddressPane;

	protected DataPane fBinaryPane;

	protected TextPane fTextPane;

	private GoToAddressComposite fAddressBar;

	protected Control fAddressBarControl;

	private Selection fSelection = new Selection();

	// storage

	BigInteger fViewportAddress = null; // default visibility for performance

	BigInteger fMemoryBlockStartAddress = null;
	BigInteger fMemoryBlockEndAddress = null;

	protected BigInteger fBaseAddress = null; // remember the base address

	protected int fColumnCount = 0; // auto calculate can be disabled by user,
	// making this user settable

	protected int fBytesPerRow = 0; // current number of bytes per row are displayed

	private int fCurrentScrollSelection = 0; // current scroll selection;

	private BigInteger fCaretAddress;

	// user settings

	private int fTextMode = 1; // ASCII default, TODO make preference?

	private int fBytesPerColumn = 4; // 4 byte cell width default

	private int fRadix = RADIX_HEX;

	private int fColumnsSetting = COLUMNS_AUTO_SIZE_TO_FIT;

	private boolean fIsTargetLittleEndian = false;

	private boolean fIsDisplayLittleEndian = false;

	// constants used to identify radix
	public final static int RADIX_HEX = 1;

	public final static int RADIX_DECIMAL_SIGNED = 2;

	public final static int RADIX_DECIMAL_UNSIGNED = 3;

	public final static int RADIX_OCTAL = 4;

	public final static int RADIX_BINARY = 5;

	// constants used to identify panes
	public final static int PANE_ADDRESS = 1;

	public final static int PANE_BINARY = 2;

	public final static int PANE_TEXT = 3;

	// constants used to identify text, maybe java should be queried for all available sets
	public final static int TEXT_ISO_8859_1 = 1;
	public final static int TEXT_USASCII = 2;
	public final static int TEXT_UTF8 = 3;
	protected final static int TEXT_UTF16 = 4;

	// internal constants
	public final static int COLUMNS_AUTO_SIZE_TO_FIT = 0;

	// view internal settings
	private int fCellPadding = 2;

	private int fPaneSpacing = 16;

	private String fPaddingString = "?"; //$NON-NLS-1$

	// flag whether the memory cache is dirty
	private boolean fCacheDirty = false;

	// 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;

	/**
	 * Maintains the subset of items visible in the current view address range.
	 * This information is refreshed when the associated Panes are about to be redrawn
	 * Note: Only the start address of each entry is included i.e. one entry per information item
	 * @since 1.4
	 */
	protected final Map<BigInteger, List<IMemoryBlockAddressInfoItem>> fMapStartAddrToInfoItems = Collections
			.synchronizedMap(new HashMap<BigInteger, List<IMemoryBlockAddressInfoItem>>());

	/**
	 * Maps any address within a memory information range to a corresponding list of information items
	 * sharing that address.
	 * This is useful to e.g. produce a tooltip while hovering over any memory location of a memory information range
	 *
	 * @since 1.5
	 */
	protected final Map<BigInteger, List<IMemoryBlockAddressInfoItem>> fMapAddrToInfoItems = Collections
			.synchronizedMap(new HashMap<BigInteger, List<IMemoryBlockAddressInfoItem>>());

	public Rendering(Composite parent, TraditionalRendering renderingParent) {
		super(parent, SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.H_SCROLL | SWT.V_SCROLL);

		this.setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME)); // TODO internal?

		this.fParent = renderingParent;

		// initialize the viewport start
		if (fParent.getMemoryBlock() != null) {
			// This is base address from user.
			// Honor it if the block has no limits or the base is within the block limits.
			// Fix Bug 414519.
			BigInteger base = fParent.getBigBaseAddress();

			fViewportAddress = fParent.getMemoryBlockStartAddress();

			// this will be null if memory may be retrieved at any address less than
			// this memory block's base.  if so use the base address.
			if (fViewportAddress == null)
				fViewportAddress = base;
			else {
				BigInteger blockEndAddr = fParent.getMemoryBlockEndAddress();
				if (base.compareTo(fViewportAddress) > 0) {
					if (blockEndAddr == null || base.compareTo(blockEndAddr) < 0)
						fViewportAddress = base;
				}
			}

			fBaseAddress = fViewportAddress;
		}

		// instantiate the panes, TODO default visibility from state or
		// plugin.xml?
		this.fAddressPane = createAddressPane();
		this.fBinaryPane = createDataPane();
		this.fTextPane = createTextPane();

		fAddressBar = new GoToAddressComposite();
		fAddressBarControl = fAddressBar.createControl(parent);
		Button button = fAddressBar.getButton(IDialogConstants.OK_ID);
		if (button != null) {
			button.addSelectionListener(new SelectionAdapter() {

				@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(pe -> {
			pe.gc.setBackground(Rendering.this.getTraditionalRendering().getColorBackground());
			pe.gc.fillRectangle(0, 0, Rendering.this.getBounds().width, Rendering.this.getBounds().height);
		});

		setLayout();

		this.addControlListener(new ControlListener() {
			@Override
			public void controlMoved(ControlEvent ce) {
			}

			@Override
			public void controlResized(ControlEvent ce) {
				packColumns();
			}
		});

		DebugPlugin.getDefault().addDebugEventListener(this);
	}

	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 (fBinaryPane.isPaneVisible()) {
					fBinaryPane.setBounds(x, y, fBinaryPane.computeSize(0, 0).x, Rendering.this.getBounds().height - y);
					x = fBinaryPane.getBounds().x + fBinaryPane.getBounds().width;
				}

				if (fTextPane.isPaneVisible()) {
					fTextPane.setBounds(x, y,
							Math.max(fTextPane.computeSize(0, 0).x, Rendering.this.getClientArea().width - x - xOffset),
							Rendering.this.getBounds().height - y);
				}

				if (getClientArea().width >= fTextPane.getBounds().x + fTextPane.getBounds().width + xOffset) {
					Rendering.this.getHorizontalBar().setVisible(false);
				} else {
					ScrollBar horizontal = Rendering.this.getHorizontalBar();

					horizontal.setVisible(true);
					horizontal.setMinimum(0);
					horizontal.setMaximum(fTextPane.getBounds().x + fTextPane.getBounds().width + xOffset);
					horizontal.setThumb(getClientArea().width);
					horizontal.setPageIncrement(40); // TODO ?
					horizontal.setIncrement(20); // TODO ?
				}
			}

			@Override
			protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
				return new Point(100, 100); // dummy data
			}
		});
	}

	protected void handleDownArrow() {
		fViewportAddress = fViewportAddress.add(BigInteger.valueOf(getAddressableCellsPerRow()));
		ensureViewportAddressDisplayable();
		redrawPanes();
	}

	protected void handleUpArrow() {
		fViewportAddress = fViewportAddress.subtract(BigInteger.valueOf(getAddressableCellsPerRow()));
		ensureViewportAddressDisplayable();
		redrawPanes();
	}

	protected void handlePageDown() {
		fViewportAddress = fViewportAddress
				.add(BigInteger.valueOf(getAddressableCellsPerRow() * (Rendering.this.getRowCount() - 1)));
		ensureViewportAddressDisplayable();
		redrawPanes();
	}

	protected void handlePageUp() {
		fViewportAddress = fViewportAddress
				.subtract(BigInteger.valueOf(getAddressableCellsPerRow() * (Rendering.this.getRowCount() - 1)));
		ensureViewportAddressDisplayable();
		redrawPanes();
	}

	protected 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:
					// 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
					// getVerticalBar().setToolTipText(Rendering.this.getAddressString(fViewportAddress));

					// Update the addresses on the Address pane.
					if (fAddressPane.isPaneVisible()) {
						fAddressPane.redraw();
					}
					redrawPanes();
					break;
				}

			}

			@Override
			public void widgetDefaultSelected(SelectionEvent se) {
				// do nothing
			}
		};
	}

	protected AddressPane createAddressPane() {
		return new AddressPane(this);
	}

	protected DataPane createDataPane() {
		return new DataPane(this);
	}

	protected TextPane createTextPane() {
		return new TextPane(this);
	}

	public TraditionalRendering getTraditionalRendering() // TODO rename
	{
		return fParent;
	}

	protected void setCaretAddress(BigInteger address) {
		fCaretAddress = address;
	}

	protected BigInteger getCaretAddress() {
		// Return 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;
	}

	private void doGoToAddress() {
		try {
			BigInteger address = fAddressBar.getGoToAddress(this.getMemoryBlockStartAddress(), this.getCaretAddress());
			getTraditionalRendering().gotoAddress(address);
			setVisibleAddressBar(false);
		} catch (NumberFormatException e1) {
			// FIXME log?
		}
	}

	// Ensure that all addresses displayed are within the addressable range
	protected void ensureViewportAddressDisplayable() {
		if (fViewportAddress.compareTo(Rendering.this.getMemoryBlockStartAddress()) < 0) {
			fViewportAddress = Rendering.this.getMemoryBlockStartAddress();
		} else if (getViewportEndAddress().compareTo(getMemoryBlockEndAddress().add(BigInteger.ONE)) > 0) {
			fViewportAddress = getMemoryBlockEndAddress()
					.subtract(BigInteger.valueOf(getAddressableCellsPerRow() * getRowCount() - 1));
		}

		setCurrentScrollSelection();
	}

	public IMemorySelection getSelection() {
		return fSelection;
	}

	protected int getHistoryDepth() {
		return fViewportCache.getHistoryDepth();
	}

	protected void setHistoryDepth(int depth) {
		fViewportCache.setHistoryDepth(depth);
	}

	public void logError(String message, Exception e) {
		Status status = new Status(IStatus.ERROR, fParent.getRenderingId(), DebugException.INTERNAL_ERROR, message, e);

		TraditionalRenderingPlugin.getDefault().getLog().log(status);
	}

	public void handleFontPreferenceChange(Font font) {
		setFont(font);

		Control controls[] = this.getRenderingPanes();
		for (int i = 0; i < controls.length; i++)
			controls[i].setFont(font);

		packColumns();
		layout(true);
	}

	public void setPaddingString(String padding) {
		fPaddingString = padding;

		refresh();
	}

	public char getPaddingCharacter() {
		return fPaddingString.charAt(0); // use only the first character
	}

	static int suspendCount = 0;

	@Override
	public void handleDebugEvents(DebugEvent[] events) {
		if (this.isDisposed())
			return;

		boolean isChangeOnly = false;
		boolean isSuspend = false;
		boolean isBreakpointHit = false;

		for (int i = 0; i < events.length; i++) {
			if (events[0].getSource() instanceof IDebugElement) {
				final int kind = events[i].getKind();
				final int detail = events[i].getDetail();
				final IDebugElement source = (IDebugElement) events[i].getSource();

				if (source.getDebugTarget() == getMemoryBlock().getDebugTarget()) {
					/* For CDT/DSF or CDT/TCF the IDebugTarget interface is not longer used,
					 * and returns null.  In such a case, we should check that we are dealing
					 * with the correct memory block instead.
					 */
					if (source.getDebugTarget() != null || source.equals(getMemoryBlock())) {
						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(() -> {
				archiveDeltas();
				refresh();
			});
		}
	}

	protected void handleChange() {
		if (getUpdateMode() == UPDATE_ALWAYS) {
			Display.getDefault().asyncExec(() -> {
				archiveDeltas();
				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 block.getAdapter(IMemoryBlockExtension.class);

		return null;
	}

	public BigInteger getBigBaseAddress() {
		return fParent.getBigBaseAddress();
	}

	public int getAddressableSize() {
		return fParent.getAddressableSize();
	}

	protected IViewportCache getViewportCache() {
		return fViewportCache;
	}

	public TraditionalMemoryByte[] getBytes(BigInteger address, int bytes) throws DebugException {
		return getViewportCache().getBytes(address, bytes);
	}

	// default visibility for performance
	ViewportCache fViewportCache = new ViewportCache();

	private BigInteger fScrollStartAddress = BigInteger.ZERO;

	private interface Request {
	}

	class ViewportCache extends Thread implements IViewportCache {
		class ArchiveDeltas implements Request {

		}

		class AddressPair implements Request {
			BigInteger startAddress;

			BigInteger endAddress;

			public AddressPair(BigInteger start, BigInteger end) {
				startAddress = start;
				endAddress = end;
			}

			@Override
			public boolean equals(Object obj) {
				if (obj == null)
					return false;
				if (obj instanceof AddressPair) {
					return ((AddressPair) obj).startAddress.equals(startAddress)
							&& ((AddressPair) obj).endAddress.equals(endAddress);
				}

				return false;
			}

		}

		class MemoryUnit {
			BigInteger start;

			BigInteger end;

			TraditionalMemoryByte[] bytes;

			@Override
			public MemoryUnit clone() {
				MemoryUnit b = new MemoryUnit();

				b.start = this.start;
				b.end = this.end;
				b.bytes = new TraditionalMemoryByte[this.bytes.length];
				for (int i = 0; i < this.bytes.length; i++)
					b.bytes[i] = new TraditionalMemoryByte(this.bytes[i].getValue());

				return b;
			}

			public boolean isValid() {
				return this.start != null && this.end != null && this.bytes != null;
			}
		}

		private HashMap<BigInteger, TraditionalMemoryByte[]> fEditBuffer = new HashMap<>();

		private boolean fDisposed = false;

		private Object fLastQueued = null;

		private Vector<Object> fQueue = new Vector<>();

		protected MemoryUnit fCache = null;

		protected MemoryUnit fHistoryCache[] = new MemoryUnit[0];

		protected int fHistoryDepth = 0;

		public ViewportCache() {
			start();
		}

		@Override
		public void dispose() {
			fDisposed = true;
			synchronized (fQueue) {
				fQueue.notify();
			}
		}

		public int getHistoryDepth() {
			return fHistoryDepth;
		}

		public void setHistoryDepth(int depth) {
			fHistoryDepth = depth;
			fHistoryCache = new MemoryUnit[fHistoryDepth];
		}

		@Override
		public void refresh() {
			assert Thread.currentThread().equals(Display.getDefault().getThread()) : TraditionalRenderingMessages
					.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$

			if (fCache != null) {
				queueRequest(fViewportAddress, getViewportEndAddress());
			}
		}

		@Override
		public void archiveDeltas() {
			assert Thread.currentThread().equals(Display.getDefault().getThread()) : TraditionalRenderingMessages
					.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$

			if (fCache != null) {
				queueRequestArchiveDeltas();
			}
		}

		private void queueRequest(BigInteger startAddress, BigInteger endAddress) {
			AddressPair pair = new AddressPair(startAddress, endAddress);
			queue(pair);
		}

		private void queueRequestArchiveDeltas() {
			ArchiveDeltas archive = new ArchiveDeltas();
			queue(archive);
		}

		private void queue(Object element) {
			synchronized (fQueue) {
				if (!(fQueue.size() > 0 && element.equals(fLastQueued))) {
					fQueue.addElement(element);
					fLastQueued = element;
				}
				fQueue.notify();
			}
		}

		@Override
		public void run() {
			while (!fDisposed) {
				AddressPair pair = null;
				boolean archiveDeltas = false;
				synchronized (fQueue) {
					if (fQueue.size() > 0) {
						Request request = (Request) fQueue.elementAt(0);
						Class<?> type = request.getClass();

						while (fQueue.size() > 0 && type.isInstance(fQueue.elementAt(0))) {
							request = (Request) fQueue.elementAt(0);
							fQueue.removeElementAt(0);
						}

						if (request instanceof ArchiveDeltas)
							archiveDeltas = true;
						else if (request instanceof AddressPair)
							pair = (AddressPair) request;
					}
				}
				if (archiveDeltas) {
					for (int i = fViewportCache.getHistoryDepth() - 1; i > 0; i--)
						fHistoryCache[i] = fHistoryCache[i - 1];

					fHistoryCache[0] = fCache.clone();
				} else if (pair != null) {
					populateCache(pair.startAddress, pair.endAddress);
				} else {
					synchronized (fQueue) {
						try {
							if (fQueue.isEmpty()) {
								fQueue.wait();
							}
						} catch (Exception e) {
							// do nothing
						}
					}
				}
			}
		}

		// cache memory necessary to paint viewport
		// TODO: user setting to buffer +/- x lines
		// TODO: reuse existing cache? probably only a minor performance gain
		private void populateCache(final BigInteger startAddress, final BigInteger endAddress) {
			try {
				IMemoryBlockExtension memoryBlock = getMemoryBlock();

				final BigInteger addressableSize = BigInteger.valueOf(getAddressableSize());
				BigInteger lengthInBytes = endAddress.subtract(startAddress).multiply(addressableSize);

				long units = lengthInBytes.divide(addressableSize)
						.add(lengthInBytes.mod(addressableSize).compareTo(BigInteger.ZERO) > 0 ? BigInteger.ONE
								: BigInteger.ZERO)
						.longValue();

				// CDT (and maybe other backends) will call setValue() on these MemoryBlock objects.
				// We don't want this to happen, because it interferes with this rendering's own
				// change history. Ideally, we should strictly use the back end change notification
				// and history, but it is only guaranteed to work for bytes within the address range
				// of the MemoryBlock.
				MemoryByte readBytes[] = memoryBlock.getBytesFromAddress(startAddress, units);

				TraditionalMemoryByte cachedBytes[] = new TraditionalMemoryByte[readBytes.length];
				for (int i = 0; i < readBytes.length; i++)
					cachedBytes[i] = new TraditionalMemoryByte(readBytes[i].getValue(), readBytes[i].getFlags());

				// derive the target endian from the read MemoryBytes.
				if (cachedBytes.length > 0) {
					if (cachedBytes[0].isEndianessKnown()) {
						setTargetLittleEndian(!cachedBytes[0].isBigEndian());
					}
				}

				// reorder bytes within unit to be a sequential byte stream if the endian is already little
				if (isTargetLittleEndian()) {
					// there isn't an order when the unit size is one, so skip for performance
					if (addressableSize.compareTo(BigInteger.ONE) != 0) {
						int unitSize = addressableSize.intValue();
						TraditionalMemoryByte cachedBytesAsByteSequence[] = new TraditionalMemoryByte[cachedBytes.length];
						for (int unit = 0; unit < units; unit++) {
							for (int unitbyte = 0; unitbyte < unitSize; unitbyte++) {
								cachedBytesAsByteSequence[unit * unitSize + unitbyte] = cachedBytes[unit * unitSize
										+ unitSize - unitbyte];
							}
						}
						cachedBytes = cachedBytesAsByteSequence;
					}
				}

				final TraditionalMemoryByte[] cachedBytesFinal = cachedBytes;

				fCache = new MemoryUnit();
				fCache.start = startAddress;
				fCache.end = endAddress;
				fCache.bytes = cachedBytesFinal;

				Display.getDefault().asyncExec(() -> {
					// generate deltas
					for (int historyIndex = 0; historyIndex < getHistoryDepth(); historyIndex++) {
						if (fHistoryCache[historyIndex] != null && fHistoryCache[historyIndex].isValid()) {
							BigInteger maxStart = startAddress.max(fHistoryCache[historyIndex].start);
							BigInteger minEnd = endAddress.min(fHistoryCache[historyIndex].end)
									.subtract(BigInteger.valueOf(1));

							BigInteger overlapLength = minEnd.subtract(maxStart).multiply(addressableSize);
							if (overlapLength.compareTo(BigInteger.valueOf(0)) > 0) {
								// there is overlap

								int offsetIntoOld = (maxStart.subtract(fHistoryCache[historyIndex].start)
										.multiply(addressableSize)).intValue();
								int offsetIntoNew = maxStart.subtract(startAddress).multiply(addressableSize)
										.intValue();

								for (int i = overlapLength.intValue(); i >= 0; i--) {
									cachedBytesFinal[offsetIntoNew + i].setChanged(historyIndex,
											cachedBytesFinal[offsetIntoNew + i]
													.getValue() != fHistoryCache[historyIndex].bytes[offsetIntoOld + i]
															.getValue());
								}
							}
						}
					}

					// If the history does not exist, populate the history with the just populated cache. This solves the
					// use case of 1) connect to target; 2) edit memory before the first suspend debug event; 3) paint
					// differences in changed color.
					if (fHistoryCache[0] == null)
						fHistoryCache[0] = fCache.clone();

					Rendering.this.redrawPanes();
				});

			} catch (Exception e) {
				// User can scroll to any memory, whether it's valid on the
				// target or not. Doesn't make much sense to fill up the Eclipse
				// error log with such "failures".
				//                logError(
				//                    TraditionalRenderingMessages
				//                        .getString("TraditionalRendering.FAILURE_READ_MEMORY"), e); //$NON-NLS-1$
			}
		}

		// bytes will be fetched from cache
		@Override
		public TraditionalMemoryByte[] getBytes(BigInteger address, int bytesRequested) throws DebugException {
			assert Thread.currentThread().equals(Display.getDefault().getThread()) : TraditionalRenderingMessages
					.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$

			//calculate the number of units needed for the number of requested bytes
			int rem = (bytesRequested % getAddressableSize()) > 0 ? 1 : 0;
			int units = bytesRequested / getAddressableSize() + rem;

			if (containsEditedCell(address)) // cell size cannot be switched during an edit
				return getEditedMemory(address);

			boolean contains = false;
			if (fCache != null && fCache.start != null) {
				// see if all of the data requested is in the cache
				BigInteger dataEnd = address.add(BigInteger.valueOf(units));

				if (fCache.start.compareTo(address) <= 0 && fCache.end.compareTo(dataEnd) >= 0
						&& fCache.bytes.length > 0)
					contains = true;
			}

			if (contains) {
				int offset = address.subtract(fCache.start).multiply(BigInteger.valueOf(getAddressableSize()))
						.intValue();
				TraditionalMemoryByte bytes[] = new TraditionalMemoryByte[bytesRequested];
				for (int i = 0; i < bytes.length; i++) {
					bytes[i] = fCache.bytes[offset + i];
				}

				return bytes;
			}

			TraditionalMemoryByte bytes[] = new TraditionalMemoryByte[bytesRequested];
			for (int i = 0; i < bytes.length; i++) {
				bytes[i] = new TraditionalMemoryByte();
				bytes[i].setReadable(false);
			}

			fViewportCache.queueRequest(fViewportAddress, getViewportEndAddress());

			return bytes;
		}

		@Override
		public boolean containsEditedCell(BigInteger address) {
			assert Thread.currentThread().equals(Display.getDefault().getThread()) : TraditionalRenderingMessages
					.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$

			return fEditBuffer.containsKey(address);
		}

		private TraditionalMemoryByte[] getEditedMemory(BigInteger address) {
			assert Thread.currentThread().equals(Display.getDefault().getThread()) : TraditionalRenderingMessages
					.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$

			return fEditBuffer.get(address);
		}

		@Override
		public void clearEditBuffer() {
			assert Thread.currentThread().equals(Display.getDefault().getThread()) : TraditionalRenderingMessages
					.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$

			fEditBuffer.clear();
			Rendering.this.redrawPanes();
		}

		@Override
		public void writeEditBuffer() {
			assert Thread.currentThread().equals(Display.getDefault().getThread()) : TraditionalRenderingMessages
					.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$

			Set<BigInteger> keySet = fEditBuffer.keySet();
			Iterator<BigInteger> iterator = keySet.iterator();

			while (iterator.hasNext()) {
				BigInteger address = iterator.next();
				TraditionalMemoryByte[] bytes = fEditBuffer.get(address);

				byte byteValue[] = new byte[bytes.length];
				for (int i = 0; i < bytes.length; i++)
					byteValue[i] = bytes[i].getValue();

				try {
					IMemoryBlockExtension block = getMemoryBlock();
					BigInteger offset = address.subtract(block.getBigBaseAddress());
					block.setValue(offset, byteValue);
				} catch (Exception e) {
					MemoryViewUtil.openError(
							TraditionalRenderingMessages.getString("TraditionalRendering.FAILURE_WRITE_MEMORY"), "", e); //$NON-NLS-1$ //$NON-NLS-2$

					logError(TraditionalRenderingMessages.getString("TraditionalRendering.FAILURE_WRITE_MEMORY"), e); //$NON-NLS-1$
				}
			}

			clearEditBuffer();
		}

		@Override
		public void setEditedValue(BigInteger address, TraditionalMemoryByte[] bytes) {
			assert Thread.currentThread().equals(Display.getDefault().getThread()) : TraditionalRenderingMessages
					.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$

			fEditBuffer.put(address, bytes);
			Rendering.this.redrawPanes();
		}
	}

	public void setVisibleAddressBar(boolean visible) {
		fAddressBarControl.setVisible(visible);
		if (visible) {
			String selectedStr = "0x" + getCaretAddress().toString(16); //$NON-NLS-1$
			Text text = fAddressBar.getExpressionWidget();
			text.setText(selectedStr);
			text.setSelection(0, text.getCharCount());
			fAddressBar.getExpressionWidget().setFocus();
		}

		layout(true);
		layoutPanes();
	}

	public void setDirty(boolean needRefresh) {
		fCacheDirty = needRefresh;
	}

	public boolean isDirty() {
		return fCacheDirty;
	}

	@Override
	public void dispose() {
		DebugPlugin.getDefault().removeDebugEventListener(this);
		if (fViewportCache != null) {
			fViewportCache.dispose();
			fViewportCache = null;
		}

		fMapStartAddrToInfoItems.clear();
		fMapAddrToInfoItems.clear();
		super.dispose();
	}

	class Selection implements IMemorySelection {
		private BigInteger fStartHigh;
		private BigInteger fStartLow;

		private BigInteger fEndHigh;
		private BigInteger fEndLow;

		@Override
		public void clear() {
			fEndHigh = fEndLow = fStartHigh = fStartLow = null;
			redrawPanes();
		}

		@Override
		public boolean hasSelection() {
			return fStartHigh != null && fStartLow != null && fEndHigh != null && fEndLow != null;
		}

		@Override
		public boolean isSelected(BigInteger address) {
			// do we have valid start and end addresses
			if (getEnd() == null || getStart() == null)
				return false;

			// if end is greater than start
			if (getEnd().compareTo(getStart()) >= 0) {
				if (address.compareTo(getStart()) >= 0 && address.compareTo(getEnd()) < 0)
					return true;
			}
			// if start is greater than end
			else if (getStart().compareTo(getEnd()) >= 0) {
				if (address.compareTo(getEnd()) >= 0 && address.compareTo(getStart()) < 0)
					return true;
			}

			return false;
		}

		@Override
		public void setStart(BigInteger high, BigInteger low) {
			if (high == null && low == null) {
				if (fStartHigh != null && fStartLow != null) {
					fStartHigh = null;
					fStartLow = null;
					redrawPanes();
				}

				return;
			}

			boolean changed = false;

			if (fStartHigh == null || !fStartHigh.equals(high)) {
				fStartHigh = high;
				changed = true;
			}

			if (fStartLow == null || !low.equals(fStartLow)) {
				fStartLow = low;
				changed = true;
			}

			if (changed)
				redrawPanes();
		}

		@Override
		public void setEnd(BigInteger high, BigInteger low) {
			if (high == null && low == null) {
				if (fEndHigh != null && fEndLow != null) {
					fEndHigh = null;
					fEndLow = null;
					redrawPanes();
				}

				return;
			}

			boolean changed = false;

			if (fEndHigh == null || !fEndHigh.equals(high)) {
				fEndHigh = high;
				changed = true;
			}

			if (fEndLow == null || !low.equals(fEndLow)) {
				fEndLow = low;
				changed = true;
			}

			if (changed)
				redrawPanes();
		}

		@Override
		public BigInteger getHigh() {
			if (!hasSelection())
				return null;

			return getStart().max(getEnd());
		}

		@Override
		public BigInteger getLow() {
			if (!hasSelection())
				return null;

			return getStart().min(getEnd());
		}

		@Override
		public BigInteger getStart() {
			// if there is no start, return null
			if (fStartHigh == null)
				return null;

			// if there is no end, return the high address of the start
			if (fEndHigh == null)
				return fStartHigh;

			// if Start High/Low equal End High/Low, return a low start and high end
			if (fStartHigh.equals(fEndHigh) && fStartLow.equals(fEndLow))
				return fStartLow;

			BigInteger differenceEndToStartHigh = fEndHigh.subtract(fStartHigh).abs();
			BigInteger differenceEndToStartLow = fEndHigh.subtract(fStartLow).abs();

			// return the start high or start low based on which creates a larger selection
			if (differenceEndToStartHigh.compareTo(differenceEndToStartLow) > 0)
				return fStartHigh;
			else
				return fStartLow;
		}

		@Override
		public BigInteger getStartLow() {
			return fStartLow;
		}

		@Override
		public BigInteger getEnd() {
			// if there is no end, return null
			if (fEndHigh == null)
				return null;

			// if Start High/Low equal End High/Low, return a low start and high end
			if (fStartHigh.equals(fEndHigh) && fStartLow.equals(fEndLow))
				return fStartHigh;

			BigInteger differenceStartToEndHigh = fStartHigh.subtract(fEndHigh).abs();
			BigInteger differenceStartToEndLow = fStartHigh.subtract(fEndLow).abs();

			// return the start high or start low based on which creates a larger selection
			if (differenceStartToEndHigh.compareTo(differenceStartToEndLow) >= 0)
				return fEndHigh;
			else
				return fEndLow;
		}
	}

	public void setPaneVisible(int pane, boolean visible) {
		switch (pane) {
		case PANE_ADDRESS:
			fAddressPane.setPaneVisible(visible);
			break;
		case PANE_BINARY:
			fBinaryPane.setPaneVisible(visible);
			break;
		case PANE_TEXT:
			fTextPane.setPaneVisible(visible);
			break;
		}

		fireSettingsChanged();
		layoutPanes();
	}

	public boolean getPaneVisible(int pane) {
		switch (pane) {
		case PANE_ADDRESS:
			return fAddressPane.isPaneVisible();
		case PANE_BINARY:
			return fBinaryPane.isPaneVisible();
		case PANE_TEXT:
			return fTextPane.isPaneVisible();
		default:
			return false;
		}
	}

	protected void packColumns() {
		int availableWidth = Rendering.this.getSize().x;

		if (fAddressPane.isPaneVisible()) {
			availableWidth -= fAddressPane.computeSize(0, 0).x;
			availableWidth -= Rendering.this.getRenderSpacing() * 2;
		}

		int combinedWidth = 0;

		if (fBinaryPane.isPaneVisible())
			combinedWidth += fBinaryPane.getCellWidth();

		if (fTextPane.isPaneVisible())
			combinedWidth += fTextPane.getCellWidth();

		if (getColumnsSetting() == Rendering.COLUMNS_AUTO_SIZE_TO_FIT) {
			if (combinedWidth == 0)
				fColumnCount = 0;
			else {
				fColumnCount = availableWidth / combinedWidth;
				if (fColumnCount == 0)
					fColumnCount = 1; // paint one column even if only part can show in view
			}
		} else {
			fColumnCount = getColumnsSetting();
		}

		try {
			// Update the number of bytes per row;
			// the max and min scroll range and the current thumb nail position.
			fBytesPerRow = getBytesPerColumn() * getColumnCount();

			getVerticalBar().setMinimum(1);
			// scrollbar maximum range is Integer.MAX_VALUE.
			getVerticalBar().setMaximum(getMaxScrollLines());
			getVerticalBar().setIncrement(1);
			getVerticalBar().setPageIncrement(this.getRowCount() - 1);
			//TW FIXME conversion of slider to scrollbar
			// fScrollBar.setToolTipText(Rendering.this.getAddressString(fViewportAddress));
			setCurrentScrollSelection();
		} catch (Exception e) {
			// FIXME precautionary
		}

		Rendering.this.redraw();
		Rendering.this.redrawPanes();
	}

	public AbstractPane[] getRenderingPanes() {
		return new AbstractPane[] { fAddressPane, fBinaryPane, fTextPane };
	}

	public int getCellPadding() {
		return fCellPadding;
	}

	protected int getRenderSpacing() {
		return fPaneSpacing;
	}

	public void refresh() {
		if (!this.isDisposed()) {
			if (this.isVisible() && getViewportCache() != null) {
				getViewportCache().refresh();
			} else {
				setDirty(true);
				fParent.updateRenderingLabels();
			}
		}
	}

	protected void archiveDeltas() {
		this.getViewportCache().archiveDeltas();
	}

	public void gotoAddress(BigInteger address) {
		// Ensure that the GoTo address is within the addressable range
		if ((address.compareTo(this.getMemoryBlockStartAddress()) < 0)
				|| (address.compareTo(this.getMemoryBlockEndAddress()) > 0)) {
			return;
		}

		fViewportAddress = address;

		// reset the caret and selection state (no caret and no selection)
		fCaretAddress = null;
		fSelection = new Selection();

		ensureViewportAddressDisplayable();
		redrawPanes();
	}

	public void setViewportStartAddress(BigInteger newAddress) {
		fViewportAddress = newAddress;
	}

	public BigInteger getViewportStartAddress() {
		return fViewportAddress;
	}

	public BigInteger getViewportEndAddress() {
		return fViewportAddress.add(BigInteger.valueOf(this.getBytesPerRow() * getRowCount() / getAddressableSize()));
	}

	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) {
		StringBuilder addressString = new StringBuilder(address.toString(16).toUpperCase());
		for (int chars = getAddressBytes() * 2 - addressString.length(); chars > 0; chars--) {
			addressString.insert(0, '0');
		}
		addressString.insert(0, "0x"); //$NON-NLS-1$

		return addressString.toString();
	}

	protected int getAddressBytes() {
		return fParent.getAddressSize();
	}

	public Control getAddressBarControl() {
		return fAddressBarControl;
	}

	public int getColumnCount() {
		return fColumnCount;
	}

	public int getColumnsSetting() {
		return fColumnsSetting;
	}

	protected void setBytesPerRow(int count) {
		fBytesPerRow = count;
	}

	protected void setColumnCount(int count) {
		fColumnCount = count;
	}

	public void setColumnsSetting(int columns) {
		if (fColumnsSetting != columns) {
			fColumnsSetting = columns;
			fireSettingsChanged();
			layoutPanes();
		}
	}

	protected void ensureVisible(BigInteger address) {
		BigInteger viewportStart = this.getViewportStartAddress();
		BigInteger viewportEnd = this.getViewportEndAddress();

		boolean isAddressBeforeViewportStart = address.compareTo(viewportStart) < 0;
		boolean isAddressAfterViewportEnd = address.compareTo(viewportEnd) > 0;

		if (isAddressBeforeViewportStart || isAddressAfterViewportEnd)
			gotoAddress(address);
	}

	protected int getRowCount() {
		int rowCount = 0;
		Control panes[] = getRenderingPanes();
		for (int i = 0; i < panes.length; i++) {
			if (panes[i] instanceof AbstractPane)
				rowCount = Math.max(rowCount, ((AbstractPane) panes[i]).getRowCount());
		}

		// Add an extra row of information as we can present part of the information on
		// the remaining space of the canvas
		int extra = 1;
		return rowCount + extra;
	}

	public int getBytesPerColumn() {
		return fBytesPerColumn;
	}

	protected int getBytesPerRow() {
		return fBytesPerRow;
	}

	protected int getAddressableCellsPerRow() {
		return getBytesPerRow() / getAddressableSize();
	}

	public int getAddressesPerColumn() {
		return this.getBytesPerColumn() / getAddressableSize();
	}

	/**
	 *  Update current scroll selection to match current viewport range
	 */
	protected void setCurrentScrollSelection() {
		BigInteger viewportStartAddress = getViewportStartAddress();
		if (TraceOptions.DEBUG) {
			TraceOptions.trace(MessageFormat.format("Update scroll for viewrange[0x{0} : 0x{1}]:\n", //$NON-NLS-1$
					viewportStartAddress.toString(16), getViewportEndAddress().toString(16)));
			TraceOptions.trace(MessageFormat.format("  current ScrollRange=[0x{0} : 0x{1}]; selection = {2}\n", //$NON-NLS-1$
					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", //$NON-NLS-1$
						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", //$NON-NLS-1$
						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)); //$NON-NLS-1$
		}
		getVerticalBar().setSelection(fCurrentScrollSelection);
	}

	/**
	 * compute the maximum scrolling range.
	 * @return number of lines that rendering can display
	 */
	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); // 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()));

		// cap to maximum lines a SWT ScrollBar can hold.
		return maxScrollRange.min(BigInteger.valueOf(Integer.MAX_VALUE)).intValue();
	}

	/**
	 * @return start address of the memory block
	 */
	protected BigInteger getMemoryBlockStartAddress() {
		if (fMemoryBlockStartAddress == null)
			fMemoryBlockStartAddress = fParent.getMemoryBlockStartAddress();
		if (fMemoryBlockStartAddress == null)
			fMemoryBlockStartAddress = BigInteger.ZERO;

		return fMemoryBlockStartAddress;
	}

	/**
	 * @return end address of the memory block
	 */
	protected BigInteger getMemoryBlockEndAddress() {
		if (fMemoryBlockEndAddress == null)
			fMemoryBlockEndAddress = fParent.getMemoryBlockEndAddress();

		return fMemoryBlockEndAddress;
	}

	public int getRadix() {
		return fRadix;
	}

	protected int getNumericRadix(int radix) {
		switch (radix) {
		case RADIX_BINARY:
			return 2;
		case RADIX_OCTAL:
			return 8;
		case RADIX_DECIMAL_SIGNED:
		case RADIX_DECIMAL_UNSIGNED:
			return 10;
		case RADIX_HEX:
			return 16;
		}

		return -1;
	}

	public void setRadix(int mode) {
		if (fRadix == mode)
			return;

		fRadix = mode;
		fireSettingsChanged();
		layoutPanes();
	}

	public void setTextMode(int mode) {
		fTextMode = mode;

		fireSettingsChanged();
		layoutPanes();
	}

	public int getTextMode() {
		return fTextMode;
	}

	public int getUpdateMode() {
		return fUpdateMode;
	}

	public void setUpdateMode(int fUpdateMode) {
		this.fUpdateMode = fUpdateMode;
	}

	protected String getCharacterSet(int mode) {
		switch (mode) {
		case Rendering.TEXT_UTF8:
			return "UTF8"; //$NON-NLS-1$
		case Rendering.TEXT_UTF16:
			return "UTF16"; //$NON-NLS-1$
		case Rendering.TEXT_USASCII:
			return "US-ASCII"; //$NON-NLS-1$
		case Rendering.TEXT_ISO_8859_1:
		default:
			return "ISO-8859-1"; //$NON-NLS-1$
		}
	}

	public int getBytesPerCharacter() {
		if (fTextMode == Rendering.TEXT_UTF16)
			return 2;

		return 1;
	}

	public boolean isTargetLittleEndian() {
		return fIsTargetLittleEndian;
	}

	public void setTargetLittleEndian(boolean littleEndian) {
		if (fIsTargetLittleEndian == littleEndian)
			return;

		fParent.setTargetMemoryLittleEndian(littleEndian);
		fIsTargetLittleEndian = littleEndian;
		Display.getDefault().asyncExec(() -> {
			fireSettingsChanged();
			layoutPanes();
		});
	}

	public boolean isDisplayLittleEndian() {
		return fIsDisplayLittleEndian;
	}

	public void setDisplayLittleEndian(boolean littleEndian) {
		if (fIsDisplayLittleEndian == littleEndian)
			return;

		fIsDisplayLittleEndian = littleEndian;

		fireSettingsChanged();
		Display.getDefault().asyncExec(() -> {
			if (isShowCrossReferenceInfo()) {
				resolveAddressInfoForCurrentSelection();
			}
			layoutPanes();
		});
	}

	public void setBytesPerColumn(int byteCount) {
		if (fBytesPerColumn != byteCount) {
			fBytesPerColumn = byteCount;
			fireSettingsChanged();
			layoutPanes();
		}
	}

	protected void redrawPane(int paneId) {
		if (!isDisposed() && this.isVisible()) {
			AbstractPane pane = null;
			if (paneId == Rendering.PANE_ADDRESS) {
				pane = fAddressPane;
			} else if (paneId == Rendering.PANE_BINARY) {
				pane = fBinaryPane;
			}
			if (paneId == Rendering.PANE_TEXT) {
				pane = fTextPane;
			}
			if (pane != null && pane.isPaneVisible()) {
				pane.redraw();
				pane.setRowCount();
				if (pane.isFocusControl())
					pane.updateCaret();
			}

		}

		fParent.updateRenderingLabels();
	}

	protected void redrawPanes() {
		if (!isDisposed() && this.isVisible()) {
			if (fAddressPane.isPaneVisible()) {
				fAddressPane.redraw();
				fAddressPane.setRowCount();
				if (fAddressPane.isFocusControl())
					fAddressPane.updateCaret();
			}

			if (fBinaryPane.isPaneVisible()) {
				fBinaryPane.redraw();
				fBinaryPane.setRowCount();
				if (fBinaryPane.isFocusControl())
					fBinaryPane.updateCaret();
			}

			if (fTextPane.isPaneVisible()) {
				fTextPane.redraw();
				fTextPane.setRowCount();
				if (fTextPane.isFocusControl())
					fTextPane.updateCaret();
			}
		}

		fParent.updateRenderingLabels();
	}

	private void layoutPanes() {
		packColumns();
		layout(true);

		redraw();
		redrawPanes();
	}

	private void fireSettingsChanged() {
		fAddressPane.settingsChanged();
		fBinaryPane.settingsChanged();
		fTextPane.settingsChanged();
	}

	protected void copyAddressToClipboard() {
		Clipboard clip = null;
		try {
			clip = new Clipboard(getDisplay());

			String addressString = "0x" + getCaretAddress().toString(16); //$NON-NLS-1$

			TextTransfer plainTextTransfer = TextTransfer.getInstance();
			clip.setContents(new Object[] { addressString }, new Transfer[] { plainTextTransfer });
		} finally {
			if (clip != null) {
				clip.dispose();
			}
		}
	}

	static final char[] hexdigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	public String getRadixText(MemoryByte bytes[], int radix, boolean isLittleEndian) {
		boolean readableByte = false;
		boolean allBytesReadable = true;
		for (int i = 0; i < bytes.length; i++) {
			if (!bytes[i].isReadable()) {
				allBytesReadable = false;
			} else {
				readableByte = true;
			}
		}

		// convert byte to character if all bytes are readable or
		// it is a mixed of readable&non-readable bytes and format is Hex or Binary. Bugzilla 342239
		if (allBytesReadable || readableByte && (radix == Rendering.RADIX_HEX || radix == Rendering.RADIX_BINARY)) {
			// bytes from the cache are stored as a sequential byte sequence regardless of target endian.
			// the endian attribute tells us the recommended endian for display. the user may change this
			// from the default. if the endian is little, we must swap the byte order.
			boolean needsSwap = false;
			if (isDisplayLittleEndian())
				needsSwap = true;

			switch (radix) {
			case Rendering.RADIX_HEX:
			case Rendering.RADIX_OCTAL:
			case Rendering.RADIX_BINARY: {
				long value = 0;
				if (needsSwap) {
					for (int i = 0; i < bytes.length; i++) {
						value = value << 8;
						value = value | (bytes[bytes.length - 1 - i].getValue() & 0xFF);
					}
				} else {
					for (int i = 0; i < bytes.length; i++) {
						value = value << 8;
						value = value | (bytes[i].getValue() & 0xFF);
					}
				}

				char buf[] = new char[getRadixCharacterCount(radix, bytes.length)];

				switch (radix) {
				case Rendering.RADIX_BINARY: {
					for (int i = buf.length - 1; i >= 0; i--) {
						int byteIndex = needsSwap ? bytes.length - 1 - i / 8 : i / 8;
						if (bytes[byteIndex].isReadable()) {
							buf[i] = hexdigits[(int) (value & 1)];
						} else {
							buf[i] = getPaddingCharacter();
						}
						value = value >>> 1;
					}
					break;
				}
				case Rendering.RADIX_OCTAL: {
					for (int i = buf.length - 1; i >= 0; i--) {
						buf[i] = hexdigits[(int) (value & 7)];
						value = value >>> 3;
					}
					break;
				}
				case Rendering.RADIX_HEX: {
					for (int i = buf.length - 1; i >= 0; i--) {
						int byteIndex = needsSwap ? bytes.length - 1 - i / 2 : i / 2;
						if (bytes[byteIndex].isReadable()) {
							buf[i] = hexdigits[(int) (value & 15)];
						} else {
							buf[i] = getPaddingCharacter();
						}
						value = value >>> 4;
					}
					break;
				}
				}

				return new String(buf);
			}
			case Rendering.RADIX_DECIMAL_UNSIGNED:
			case Rendering.RADIX_DECIMAL_SIGNED: {
				boolean isSignedType = radix == Rendering.RADIX_DECIMAL_SIGNED ? true : false;

				int textWidth = getRadixCharacterCount(radix, bytes.length);

				char buf[] = new char[textWidth];

				byte[] value = new byte[bytes.length + 1];

				if (needsSwap) {
					for (int i = 0; i < bytes.length; i++) {
						value[bytes.length - i] = bytes[i].getValue();
					}
				} else {
					for (int i = 0; i < bytes.length; i++) {
						value[i + 1] = bytes[i].getValue();
					}
				}

				BigInteger bigValue;
				boolean isNegative = false;
				if (isSignedType && (value[1] & 0x80) != 0) {
					value[0] = -1;
					isNegative = true;
					bigValue = new BigInteger(value).abs();
				} else {
					value[0] = 0;
					bigValue = new BigInteger(value);
				}

				for (int i = 0; i < textWidth; i++) {
					BigInteger divideRemainder[] = bigValue.divideAndRemainder(BigInteger.valueOf(10));
					int remainder = divideRemainder[1].intValue();
					buf[textWidth - 1 - i] = hexdigits[remainder % 10];
					bigValue = divideRemainder[0];
				}

				if (isSignedType) {
					buf[0] = isNegative ? '-' : ' ';
				}

				return new String(buf);
			}
			}
		}

		StringBuilder errorText = new StringBuilder();
		for (int i = getRadixCharacterCount(radix, bytes.length); i > 0; i--)
			errorText.append(getPaddingCharacter());

		return errorText.toString();
	}

	public int getRadixCharacterCount(int radix, int bytes) {
		switch (radix) {
		case Rendering.RADIX_HEX:
			return bytes * 2;
		case Rendering.RADIX_BINARY:
			return bytes * 8;
		case Rendering.RADIX_OCTAL: {
			switch (bytes) {
			case 1:
				return 3;
			case 2:
				return 6;
			case 4:
				return 11;
			case 8:
				return 22;
			}
		}
		case Rendering.RADIX_DECIMAL_UNSIGNED: {
			switch (bytes) {
			case 1:
				return 3;
			case 2:
				return 5;
			case 4:
				return 10;
			case 8:
				return 20;
			}
		}
		case Rendering.RADIX_DECIMAL_SIGNED: {
			switch (bytes) {
			case 1:
				return 4;
			case 2:
				return 6;
			case 4:
				return 11;
			case 8:
				return 21;
			}
		}
		}

		return 0;
	}

	protected static boolean isValidEditCharacter(char character) {
		return (character >= '0' && character <= '9') || (character >= 'a' && character <= 'z')
				|| (character >= 'A' && character <= 'Z') || character == '-' || character == ' ';
	}

	public String formatText(MemoryByte[] memoryBytes, boolean isLittleEndian, int textMode) {
		// check memory byte for unreadable bytes
		boolean readable = true;
		for (int i = 0; i < memoryBytes.length; i++)
			if (!memoryBytes[i].isReadable())
				readable = false;

		// if any bytes are not readable, return ?'s
		if (!readable) {
			StringBuilder errorText = new StringBuilder();
			for (int i = memoryBytes.length; i > 0; i--)
				errorText.append(getPaddingCharacter());
			return errorText.toString();
		}

		// TODO
		// does endian mean anything for text? ah, unicode?

		// create byte array from MemoryByte array
		byte bytes[] = new byte[memoryBytes.length];
		for (int i = 0; i < bytes.length; i++) {
			bytes[i] = memoryBytes[i].getValue();
		}

		// replace invalid characters with '.'
		// maybe there is a way to query the character set for
		// valid characters?

		// replace invalid US-ASCII with '.'
		if (textMode == Rendering.TEXT_USASCII) {
			for (int i = 0; i < bytes.length; i++) {
				int byteValue = bytes[i];
				if (byteValue < 0)
					byteValue += 256;

				if (byteValue < 0x20 || byteValue > 0x7e)
					bytes[i] = '.';
			}
		}

		// replace invalid ISO-8859-1 with '.'
		if (textMode == Rendering.TEXT_ISO_8859_1) {
			for (int i = 0; i < bytes.length; i++) {
				int byteValue = bytes[i];
				if (byteValue < 0)
					byteValue += 256;

				if (byteValue < 0x20 || (byteValue >= 0x7f && byteValue < 0x9f))
					bytes[i] = '.';
			}
		}

		try {
			// convert bytes to string using desired character set
			StringBuilder buf = new StringBuilder(new String(bytes, this.getCharacterSet(textMode)));

			// pad string to (byte count - string length) with spaces
			for (int i = 0; i < memoryBytes.length - buf.length(); i++)
				buf.append(' ');
			return buf.toString();
		} catch (Exception e) {
			// return ?s the length of byte count
			StringBuilder buf = new StringBuilder();
			for (int i = 0; i < memoryBytes.length - buf.length(); i++)
				buf.append(getPaddingCharacter());
			return buf.toString();
		}
	}

	public AbstractPane incrPane(AbstractPane currentPane, int offset) {
		final List<AbstractPane> panes = Arrays.asList(getRenderingPanes());
		return panes.get((panes.indexOf(currentPane) + offset) % panes.size());
	}

	/**
	 * Indicates if additional address information is available to display in the current visible range
	 */
	boolean hasVisibleRangeInfo() {
		return false;
	}

	/**
	 * @return True if the given address has additional information to display e.g. variables, registers, etc.
	 */
	boolean hasAddressInfo(BigInteger address) {
		return false;
	}

	/**
	 * @return The items that would be visible in the current viewable area if the rows were to use a single
	 *         height
	 */
	Map<BigInteger, List<IMemoryBlockAddressInfoItem>> getVisibleValueToAddressInfoItems() {
		return fMapStartAddrToInfoItems;
	}

	/**
	 * @since 1.5
	 */
	protected boolean isShowCrossReferenceInfo() {
		// Check settings in preference store
		IPreferenceStore store = TraditionalRenderingPlugin.getDefault().getPreferenceStore();
		boolean prefShowInfo = store.getBoolean(TraditionalRenderingPreferenceConstants.MEM_CROSS_REFERENCE_INFO);

		// Cross Reference information can not be properly highlighted for a Little Endian display
		// see Bug 509577 - [Traditional Rendering] Local variable enclosing markings may be wrong in Little Endian presentation
		return (!isDisplayLittleEndian() && prefShowInfo);
	}

	/**
	 * Provides a string with the information relevant to a given address, the separator helps to format it
	 * e.g. Separated items by comma, new line, etc.
	 *
	 * @param addTypeHeaders
	 *            Indicates if the string shall include a data type name before each list of items of the same
	 *            type e.g. Variables, Registers, etc.
	 */
	String buildAddressInfoString(BigInteger address, String separator, boolean addTypeHeaders) {
		return ""; //$NON-NLS-1$
	}

	/**
	 * Returns Dynamic context menu actions to this render, No actions by default
	 * @since 1.4
	 */
	Action[] getDynamicActions() {
		return new Action[0];
	}

	/**
	 * Trigger the resolution of additional address information - No action by default
	 */
	void resolveAddressInfoForCurrentSelection() {
	}

}
