/*******************************************************************************
 * Copyright (c) 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.debug.ui.memory;

import java.math.BigInteger;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
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.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
import org.eclipse.debug.internal.ui.views.memory.renderings.CopyTableRenderingToClipboardAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.FormatColumnAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.GoToAddressAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.PrintTableRenderingAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.ReformatAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.ResetToBaseAddressAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.SetColumnSizeDefaultAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingCellModifier;
import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingContentInput;
import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingContentProvider;
import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingLabelProvider;
import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingLine;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.IBasicPropertyConstants;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.TableCursor;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.PageBook;

/**
 * This is an abstract implementation to a table rendering.  Clients should
 * subclass from this class if they wish to provide a table rendering.
 * 
 * @since 3.1
 */
public abstract class AbstractTableRendering extends AbstractMemoryRendering implements IPropertyChangeListener{	

	// Property Ids for the selected address in a table rendering
	public static final String PROPERTY_SELECTED_ADDRESS = "selectedAddress"; //$NON-NLS-1$
	// Property Ids for the column size in a table rendering
	public static final String PROPERTY_COL_SIZE = "columnSize"; //$NON-NLS-1$
	// Property Ids for the top row address in a table rendering
	public static final String PROPERTY_TOP_ADDRESS = "topAddress"; //$NON-NLS-1$
	
	private PageBook fPageBook;
	private TableViewer fTableViewer;
	private TextViewer fTextViewer;
	
	private int fBytePerLine;								// number of bytes per line: 16
	private int fColumnSize;								// number of bytes per column:  1,2,4,8
	private int fAddressibleSize;	
	
	private boolean fIsShowingErrorPage;
	
	private TableRenderingContentProvider fContentProvider;
	private BigInteger fSelectedAddress;
	private TableRenderingContentInput fContentInput;
	private TableRenderingCellModifier fCellModifier;
	private boolean fIsCreated;
	private CellEditor[] fEditors;
	private String fLabel;
	private TableCursor fTableCursor;
	private boolean fIsDisposed;
	private TraverseListener fCursorTraverseListener;
	private KeyAdapter fCursorKeyAdapter;
	private BigInteger fTopRowAddress;
	
	private CopyTableRenderingToClipboardAction fCopyToClipboardAction;
	private GoToAddressAction fGoToAddressAction;
	private ResetToBaseAddressAction fResetMemoryBlockAction;
	private PrintTableRenderingAction fPrintViewTabAction;
	private Action[] fFormatColumnActions;
	private ReformatAction fReformatAction;
	private ToggleAddressColumnAction fToggleAddressColumnAction;
	private EventHandleLock fEvtHandleLock = new EventHandleLock();
	private TableEditor fCursorEditor;
	private FocusAdapter fEditorFocusListener;
	private MouseAdapter fCursorMouseListener;
	private KeyAdapter fEditorKeyListener;
	private SelectionAdapter fCursorSelectionListener;
	
	private boolean fIsShowAddressColumn = true;
	private SelectionAdapter fScrollbarSelectionListener;
	
	private class EventHandleLock
	{
		Object fOwner;
		
		public boolean acquireLock(Object client)
		{
			if (fOwner == null)
			{
				fOwner = client;
				return true;
			}
			return false;
		}
		
		public boolean releaseLock(Object client)
		{
			if (fOwner == client)
			{
				fOwner = null;
				return true;
			}
			return false;
		}
		
		public boolean isLocked()
		{
			return (fOwner != null);
		}
	}	
	
	
	private class ToggleAddressColumnAction extends Action {

		public ToggleAddressColumnAction() {
			super();
			PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID
					+ ".ShowAddressColumnAction_context"); //$NON-NLS-1$
			updateActionLabel();
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.action.IAction#run()
		 */
		public void run() {
			fIsShowAddressColumn = !fIsShowAddressColumn;
			resizeColumnsToPreferredSize();
			updateActionLabel();
		}

		/**
		 * 
		 */
		private void updateActionLabel() {
			if (fIsShowAddressColumn) {
				setText(DebugUIMessages.getString("ShowAddressColumnAction.0")); //$NON-NLS-1$
			} else {
				setText(DebugUIMessages.getString("ShowAddressColumnAction.1")); //$NON-NLS-1$
			}
		}
	}
	
	/**
	 * @param renderingId
	 */
	public AbstractTableRendering(String renderingId) {
		super(renderingId);
	}
	
	public void propertyChange(PropertyChangeEvent event) {
		// if memory view table font has changed
		if (event.getProperty().equals(IInternalDebugUIConstants.FONT_NAME))
		{
			if (!fIsDisposed)
			{			
				Font memoryViewFont = JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME);
				setFont(memoryViewFont);		
			}
			return;
		}
		
		Object evtSrc = event.getSource();
		
		// do not handle event if the rendering is displaying an error
		if (isDisplayingError())
			return;
		
		// do not handle property change event if the rendering is not visible
		if (!isVisible())
			return;
		
		if (evtSrc == this)
			return;
		
		if (!(evtSrc instanceof IMemoryRendering))
			return;
		
		IMemoryRendering rendering = (IMemoryRendering)evtSrc;
		IMemoryBlock memoryBlock = rendering.getMemoryBlock();
		
		// do not handle event from renderings displaying other memory blocks
		if (memoryBlock != getMemoryBlock())
			return;
	
		String propertyName = event.getProperty();
		Object value = event.getNewValue();
		
		if (propertyName.equals(AbstractTableRendering.PROPERTY_SELECTED_ADDRESS) && value instanceof BigInteger)
		{
			selectedAddressChanged((BigInteger)value);
		}
		else if (propertyName.equals(AbstractTableRendering.PROPERTY_COL_SIZE) && value instanceof Integer)
		{
			columnSizeChanged(((Integer)value).intValue());
		}
		else if (propertyName.equals(AbstractTableRendering.PROPERTY_TOP_ADDRESS) && value instanceof BigInteger)
		{
			if (needMoreLines())
			{
				reloadTable(getTopVisibleAddress(), false);
			}
			topVisibleAddressChanged((BigInteger)value);
		}
	}

	/**
	 * Handle top visible address change event from synchronizer
	 * @param address
	 */
	private void topVisibleAddressChanged(final BigInteger address)
	{
		// do not handle event if view tab is disabled
		if (!isVisible())
			return;
	
		if (!address.equals(fTopRowAddress))
		{
			fTopRowAddress = address;
			updateSyncTopAddress();
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
			
				handleTopAddressChangedforExtended(address);
			}
			else
			{
				handleTopAddressChangedForSimple(address);
			}
		}
	}

	/**
	 * @param address
	 */
	private void handleTopAddressChangedForSimple(final BigInteger address) {
		// IMemoryBlock support
		int index = findAddressIndex(address);
		Table table = fTableViewer.getTable();
		if (index >= 0)
		{
			setTopIndex(table,  index);
		}
		
		if (isAddressVisible(fSelectedAddress))
			fTableCursor.setVisible(true);
		else
			fTableCursor.setVisible(false);
		
	}

	/**
	 * @param address
	 */
	private void handleTopAddressChangedforExtended(final BigInteger address) {
		
		Object evtLockClient = new Object();
		try 
		{
		if (!fEvtHandleLock.acquireLock(evtLockClient))
			return;
		
		if (!isAddressOutOfRange(address))
		{
			Table table = fTableViewer.getTable();
			int index = findAddressIndex(address);
			if (index >= 3 && table.getItemCount() - (index+getNumberOfVisibleLines()) >= 3)
			{
				// update cursor position
				setTopIndex(table, index);
			}
			else
			{
				int numInBuffer = table.getItemCount();
				if (index < 3)
				{
					if (fContentInput.getPreBuffer() == 0)
						setTopIndex(table, index);
					else
						reloadTable(address, false);
				}
				else if ((numInBuffer-(index+getNumberOfVisibleLines())) < 3)
				{
					reloadTable(address, false);
				}
			}
		}
		else
		{	
			// approaching limit, reload table
			reloadTable(address, false);
		}
		
		if (isAddressVisible(fSelectedAddress))
			fTableCursor.setVisible(true);
		else
			fTableCursor.setVisible(false);
		}
		finally
		{
			fEvtHandleLock.releaseLock(evtLockClient);
		}
	}	
	
	/**
	 * @param value
	 */
	private void selectedAddressChanged(BigInteger value) {
		
		try {
			goToAddress(value);
		} catch (DebugException e) {
			DebugUIPlugin.log(e);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRendering#createControl(org.eclipse.swt.widgets.Composite)
	 */
	public Control createControl(Composite parent) {
		
		fPageBook = new PageBook(parent, SWT.NONE);
		createErrorPage(fPageBook);
		createTableViewer(fPageBook);
		return fPageBook;
	}

	/**
	 * Create the table viewer and other support controls
	 * for this rendering
	 * @param parent
	 */
	private void createTableViewer(Composite parent) {
		
		fTableViewer= new TableViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.HIDE_SELECTION | SWT.BORDER);
		
		TableRenderingLabelProvider labelProvider = new TableRenderingLabelProvider(this);
		fTableViewer.setLabelProvider(labelProvider);
		
		fContentProvider = new TableRenderingContentProvider();
		fTableViewer.setContentProvider(fContentProvider);		
		fContentProvider.setViewer(fTableViewer);
		
		ScrollBar scroll = ((Table)fTableViewer.getControl()).getVerticalBar();
		scroll.setMinimum(-100);
		scroll.setMaximum(200);		

		fTableViewer.getTable().setHeaderVisible(true);
		fTableViewer.getTable().setLinesVisible(true);
		
// FORMAT RENDERING
		// set up addressible size and figure out number of bytes required per line
		fAddressibleSize = -1;
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
			fAddressibleSize = ((IMemoryBlockExtension)getMemoryBlock()).getAddressibleSize();
		if (fAddressibleSize < 1)
			fAddressibleSize = 1;
		int bytePerLine = IInternalDebugUIConstants.ADD_UNIT_PER_LINE * fAddressibleSize;
		
		// get default column size from preference store
		IPreferenceStore prefStore = DebugUIPlugin.getDefault().getPreferenceStore();
		// column size is now stored as number of addressible units
		int columnSize = prefStore.getInt(IDebugPreferenceConstants.PREF_COLUMN_SIZE);
		// actual column size is number of addressible units * size of the addressible unit
		columnSize = columnSize * getAddressibleSize();
		
		// check synchronized col size
		Integer colSize = (Integer)getSynchronizedProperty(AbstractTableRendering.PROPERTY_COL_SIZE);
		
		if (colSize != null)
		{
			int syncColSize = colSize.intValue(); 
			if (syncColSize > 0)
			{
				columnSize = syncColSize;
			}	
		}
		
		// format memory block with specified "bytesPerLine" and "columnSize"	
		boolean ok = format(bytePerLine, columnSize);

		if (!ok)
		{
			DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.getString("AbstractTableRendering.0"), null)); //$NON-NLS-1$
			displayError(e);
			return;
		}
// END FORMAT RENDERING		
		
		// figure out selected address 
		BigInteger selectedAddress = (BigInteger) getSynchronizedProperty(AbstractTableRendering.PROPERTY_SELECTED_ADDRESS);
		if (selectedAddress == null)
		{
			if (getMemoryBlock() instanceof IMemoryBlockExtension) {
				selectedAddress = ((IMemoryBlockExtension) getMemoryBlock())
						.getBigBaseAddress();
	
				if (selectedAddress == null) {
					selectedAddress = new BigInteger("0"); //$NON-NLS-1$
				}
	
			} else {
				long address = getMemoryBlock().getStartAddress();
				selectedAddress = BigInteger.valueOf(address);
			}
		}
		fSelectedAddress = selectedAddress;
		
		// figure out top visible address
		BigInteger topVisibleAddress = (BigInteger) getSynchronizedProperty(AbstractTableRendering.PROPERTY_TOP_ADDRESS);
		if (topVisibleAddress == null)
		{
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				topVisibleAddress = ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
			}
			else
			{
				topVisibleAddress = BigInteger.valueOf(getMemoryBlock().getStartAddress());
			}
		}
		
		fContentInput = new TableRenderingContentInput(this, 20, 20, 20, topVisibleAddress, getNumberOfVisibleLines(), false);
		fTableViewer.setInput(fContentInput);
		
		fCellModifier = new TableRenderingCellModifier(this);
		fTableViewer.setCellModifier(fCellModifier);
		
				
// SET UP FONT		
		// set to a non-proportional font
		fTableViewer.getTable().setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
		
		if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
		{		
			// If not extended memory block, do not create any buffer
			// no scrolling
			fContentInput.setPreBuffer(0);
			fContentInput.setPostBuffer(0);
			fContentInput.setDefaultBufferSize(0);
		}
		
		createCursor(fTableViewer.getTable(), fSelectedAddress);
		
		fTableViewer.getTable().addMouseListener(new MouseAdapter() {
			public void mouseDown(MouseEvent e) {
				handleTableMouseEvent(e);
			}});
		
		// create pop up menu for the rendering
		createActions();
		createPopupMenu(fTableViewer.getControl());
		createPopupMenu(fTableCursor);

		getPopupMenuManager().addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				fillContextMenu(manager);
				manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
			}});

		fIsCreated = true;

		addRenderingToSyncService();
		//synchronize
		synchronize();
		
		fTopRowAddress = getTopVisibleAddress();
		
		// Need to resize column after content is filled in
		// Pack function does not work unless content is not filled in
		// since the table is not able to compute the preferred size.
		resizeColumnsToPreferredSize();
		
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
		{
			if(((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress() == null)
			{
				DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.getString("AbstractTableRendering.1"), null)); //$NON-NLS-1$
				displayError(e);				
			}
		}
		
		// add font change listener and update font when the font has been changed
		JFaceResources.getFontRegistry().addListener(this);
		
		
		fScrollbarSelectionListener = new SelectionAdapter() {

			public void widgetSelected(SelectionEvent event) {
				handleScrollBarSelection();
				
			}};
		scroll.addSelectionListener(fScrollbarSelectionListener);
		
	}
	
	private void createCursor(Table table, BigInteger address)
	{
		fTableCursor = new TableCursor(table, SWT.NONE);
		Display display = fTableCursor.getDisplay();
		
		// set up cursor color
		fTableCursor.setBackground(display.getSystemColor(SWT.COLOR_LIST_SELECTION));
		fTableCursor.setForeground(display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));
		
		fTableCursor.setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
		fTableCursor.setVisible(true);
		fTableCursor.setFocus();
		
		fCursorKeyAdapter = new KeyAdapter() {
			public void keyPressed(KeyEvent e)
			 {
			 	handleCursorKeyPressed(e);
			 }	
		};
		fTableCursor.addKeyListener(fCursorKeyAdapter);
		
		fCursorTraverseListener = new TraverseListener() {
			public void keyTraversed(TraverseEvent e) {
				handleCursorTraverseEvt(e);
			}};
					
		fTableCursor.addTraverseListener(fCursorTraverseListener);
		
		fCursorMouseListener = new MouseAdapter() {
			public void mouseDown(MouseEvent e) {
				handleCursorMouseEvent(e);
			}};
		fTableCursor.addMouseListener(fCursorMouseListener);
		
		// cursor may be disposed before disposed is called
		// remove listeners whenever the cursor is disposed
		fTableCursor.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				if (fTableCursor == null)
					return;
				fTableCursor.removeTraverseListener(fCursorTraverseListener);
				fTableCursor.removeKeyListener(fCursorKeyAdapter);
				fTableCursor.removeMouseListener(fCursorMouseListener);
				fTableCursor.removeSelectionListener(fCursorSelectionListener);
			}});
		
		fCursorSelectionListener = new SelectionAdapter() {
					public void widgetSelected(SelectionEvent e) {
						
						if (!fEvtHandleLock.acquireLock(this))
							return;
	
						handleCursorMoved();
						
						fEvtHandleLock.releaseLock(this);

					}
				};
		fTableCursor.addSelectionListener(fCursorSelectionListener);
		
		
		setCursorAtAddress(address);
		
		fCursorEditor = new TableEditor (fTableViewer.getTable());	
	}
	
	private void handleCursorTraverseEvt(TraverseEvent e){
		
		if (fTableCursor.getRow() == null)
			return;
		
		Table table = (Table)fTableCursor.getParent();
		int row = table.indexOf(fTableCursor.getRow());
		int col = fTableCursor.getColumn();
		if (col == getNumCol() && e.keyCode == SWT.ARROW_RIGHT)
		{
			if (row + 1>= table.getItemCount())
			{
				return;
			}
			
			row = row +1;
			col = 0;
			fTableCursor.setSelection(row, col);
		}
		if (col <= 1 && e.keyCode == SWT.ARROW_LEFT)
		{
			if (row-1 < 0)
			{
				return;
			}
			
			row = row - 1;
			col = getNumCol()+1;
			fTableCursor.setSelection(row, col);
		}			
		
		Object evtLockClient = new Object();
		if (!fEvtHandleLock.acquireLock(evtLockClient))
			return;
		
		handleCursorMoved();
		
		fEvtHandleLock.releaseLock(evtLockClient);

	}
	
	/**
	 * Update selected address.
	 * Load more memory if required.
	 */
	private void handleCursorMoved()
	{	
		if (fIsDisposed)
			return;
		
		BigInteger selectedAddress = getSelectedAddressFromCursor(fTableCursor);
		
		// when the cursor is moved, the selected address is changed
		if (selectedAddress != null && !selectedAddress.equals(fSelectedAddress))
		{
			fSelectedAddress = selectedAddress;
			updateSyncSelectedAddress();
		}
		
		// now check to see if the cursor is approaching buffer limit
		TableItem item = fTableCursor.getRow();
		if (item == null)
			return;
		
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
		{
			int row = fTableViewer.getTable().indexOf(item);
			
			if (row < 3)
			{
				
				// get start address
				int preBuffer = fContentInput.getPreBuffer();
				if (preBuffer > 0)
				{
					refresh();
					setCursorAtAddress(fSelectedAddress);
				}
			}
			else if (row >= fTableViewer.getTable().getItemCount() - 3)
			{
				refresh();
				setCursorAtAddress(fSelectedAddress);
	
			}
		}
		
		// if the cursor has moved, the top index of the table may change
		// just update the synchronization service
		BigInteger address = getTopVisibleAddress();
		if (!address.equals(fTopRowAddress))
		{
			fTopRowAddress = address;
			updateSyncTopAddress();
		}
	}
	
	private void handleCursorKeyPressed(KeyEvent event)
	{
		// allow edit if user hits return
		if (event.character == '\r' && event.getSource() instanceof TableCursor)
		{
			activateCellEditor(null);
			return;
		}		
		
		if (MemoryViewUtil.isValidEditEvent(event.keyCode))
		{	
			// activate edit as soon as user types something at the cursor
			if (event.getSource() instanceof TableCursor)
			{
				String initialValue = String.valueOf(event.character);
				activateCellEditor(initialValue);
				return;
			}
		}
	}
	
	/**
	 * Calculate selected address based on cursor's current position
	 * @param cursor
	 * @return the selected address
	 */
	private BigInteger getSelectedAddressFromCursor(TableCursor cursor)
	{
		TableItem row = cursor.getRow();
		int col = cursor.getColumn();
		
		if (row == null)
			return null;
		
		// get row address
		String temp = ((TableRenderingLine)row.getData()).getAddress();
		BigInteger rowAddress = new BigInteger(temp, 16);
		
		int offset;
		if (col > 0)
		{	
			// 	get address offset
			int addressibleUnit = getAddressibleUnitPerColumn();
			offset = (col-1) * addressibleUnit;
		}
		else
		{
			offset = 0;
		}
		
		return rowAddress.add(BigInteger.valueOf(offset));
	}
	
	
	/**
	 * Sets the cursor at the specified address
	 * @param address
	 * @return true if successful, false otherwise
	 */
	private boolean setCursorAtAddress(BigInteger address)
	{
		// selected address is out of range, simply return false
		if (address.compareTo(fContentProvider.getBufferTopAddress()) < 0)
			return false;
		
		// calculate selected row address
		int addressibleUnit = getAddressibleUnitPerLine();
		int numOfRows = address.subtract(fContentProvider.getBufferTopAddress()).intValue()/addressibleUnit;
		BigInteger rowAddress = fContentProvider.getBufferTopAddress().add(BigInteger.valueOf(numOfRows * addressibleUnit));

		// try to find the row of the selected address
		int row = findAddressIndex(address);
			
		if (row == -1)
		{
			return false;
		}
		
		// calculate offset to the row address
		BigInteger offset = address.subtract(rowAddress);
		
		// locate column
		int colAddressibleUnit = getAddressibleUnitPerColumn();
		int col = ((offset.intValue()/colAddressibleUnit)+1);
		
		if (col == 0)
			col = 1;
		
		fTableCursor.setSelection(row, col);
		
		return true;		
	}
	
	
	/**
	 * Format view tab based on parameters.
	 * @param bytesPerLine - number of bytes per line, possible values: 16 * addressibleSize
	 * @param columnSize - number of bytes per column, possible values: (1 / 2 / 4 / 8 / 16) * addressibleSize
	 * @return true if format is successful, false, otherwise
	 */
	public boolean format(int bytesPerLine, int columnSize)
	{			
		// selected address gets changed as the cursor is moved
		// during the reformat.
		// Back up the address and restore it later.
		BigInteger selectedAddress = fSelectedAddress;
		
		// check parameter, limit number of addressible unit to 16
		if (bytesPerLine/fAddressibleSize != IInternalDebugUIConstants.ADD_UNIT_PER_LINE)
		{
			return false;
		}
		
		// bytes per cell must be divisible to bytesPerLine
		if (bytesPerLine % columnSize != 0)
		{
			return false;
		}
		
		// do not format if the view tab is already in that format
		if(fBytePerLine == bytesPerLine && fColumnSize == columnSize){
			return false;
		}
		
		fBytePerLine = bytesPerLine;
		fColumnSize = columnSize;
		
		Object evtLockClient = new Object();
		if (!fEvtHandleLock.acquireLock(evtLockClient))
			return false;
		
		// if the tab is already created and is being reformated
		if (fIsCreated)
		{	
			if (fTableViewer == null)
				return false;
			
			if (fTableViewer.getTable() == null)
				return false;
			
			// clean up old columns
			TableColumn[] oldColumns = fTableViewer.getTable().getColumns();
			
			for (int i=0; i<oldColumns.length; i++)
			{
				oldColumns[i].dispose();
			}
			
			// clean up old cell editors
			CellEditor[] oldCellEditors = fTableViewer.getCellEditors();
			
			for (int i=0; i<oldCellEditors.length; i++)
			{
				oldCellEditors[i].dispose();
			}
		}
		
		TableColumn column0 = new TableColumn(fTableViewer.getTable(),SWT.LEFT,0);
		column0.setText(DebugUIMessages.getString("AbstractTableRendering.2")); //$NON-NLS-1$
		
		// create new byte columns
		TableColumn [] byteColumns = new TableColumn[bytesPerLine/columnSize];		
		
		String[] columnLabels = new String[0];
		IDebugModelPresentation presentation = DebugUIPlugin.getModelPresentation();
		if (presentation instanceof IMemoryBlockTablePresentation)
			columnLabels = ((IMemoryBlockTablePresentation)presentation).getColumnLabels(getMemoryBlock(), bytesPerLine, getNumCol());
		
		// check that column labels are not null
		if (columnLabels == null)
			columnLabels = new String[0];
		
		for (int i=0;i<byteColumns.length; i++)
		{
			TableColumn column = new TableColumn(fTableViewer.getTable(), SWT.LEFT, i+1);
			
			// if the number of column labels returned is correct
			// use supplied column labels
			if (columnLabels.length == byteColumns.length)
			{
				column.setText(columnLabels[i]);
			}
			else
			{
				// otherwise, use default
				int addressibleUnit = columnSize/fAddressibleSize;
				if (getAddressibleUnitPerColumn() >= 4)
				{
					column.setText(Integer.toHexString(i*addressibleUnit).toUpperCase() + 
						" - " + Integer.toHexString(i*addressibleUnit+addressibleUnit-1).toUpperCase()); //$NON-NLS-1$
				}
				else
				{
					column.setText(Integer.toHexString(i*addressibleUnit).toUpperCase());
				}
			}
		}
		
		//Empty column for cursor navigation
		TableColumn emptyCol = new TableColumn(fTableViewer.getTable(),SWT.LEFT,byteColumns.length+1);
		emptyCol.setText(" "); //$NON-NLS-1$
		emptyCol.setWidth(1);
		emptyCol.setResizable(false);

		// +2 to include properties for address and navigation column
		String[] columnProperties = new String[byteColumns.length+2];
		columnProperties[0] = TableRenderingLine.P_ADDRESS;
		
		int addressibleUnit = columnSize / getAddressibleSize();

		// use column beginning offset to the row address as properties
		for (int i=1; i<columnProperties.length-1; i++)
		{
			// column properties are stored as number of addressible units from the
			// the line address
			columnProperties[i] = Integer.toHexString((i-1)*addressibleUnit);
		}
		
		// Empty column for cursor navigation
		columnProperties[columnProperties.length-1] = " "; //$NON-NLS-1$
		
		fTableViewer.setColumnProperties(columnProperties);		
		
		
		Table table = fTableViewer.getTable();
		fEditors = new CellEditor[table.getColumnCount()];
		for (int i=0; i<fEditors.length; i++)
		{
			fEditors[i] = new TextCellEditor(table);
		}
		
		// create and set cell editors
		fTableViewer.setCellEditors(fEditors);	
		
		if (fIsCreated)
		{
			fTableViewer.refresh();
		}		
		
		
		resizeColumnsToPreferredSize();
		updateSyncColSize();
		
		if (fIsCreated)
		{
			// for Linux GTK, this must happen after table viewer is refreshed
			int i = findAddressIndex(fTopRowAddress);
			
			if (i >= 0)
				setTopIndex(fTableViewer.getTable(), i);
			
			if (isAddressVisible(selectedAddress))
				// after refresh, make sure the cursor is at the correct position
				setCursorAtAddress(selectedAddress);			
		}
		
		fEvtHandleLock.releaseLock(evtLockClient);
		
		return true;
	}
	
	/**
	 * Create the error page for this rendering.
	 * The error page is used to report any error resulted from
	 * getting memory from a memory block.
	 * @param parent
	 */
	private void createErrorPage(Composite parent)
	{
		if (fTextViewer == null)
		{
			fTextViewer = new TextViewer(parent, SWT.WRAP);	
			fTextViewer.setDocument(new Document());
			StyledText styleText = fTextViewer.getTextWidget();
			styleText.setEditable(false);
			styleText.setEnabled(false);
		}
	}
	
	/**
	 * Display content of the table viewer
	 */
	public void displayTable()
	{
		fIsShowingErrorPage = false;
		fPageBook.showPage(fTableViewer.getControl());
	}
	
	/**
	 * Display an error in the view tab.
	 * Make use of the text viewer instead of the table viewer.
	 * @param e
	 */
	public void displayError(DebugException e)
	{
		StyledText styleText = null;
		fIsShowingErrorPage = true;

		styleText = fTextViewer.getTextWidget();
		
		if (styleText != null)
			styleText.setText(DebugUIMessages.getString("AbstractTableRendering.3") + e.getMessage());	 //$NON-NLS-1$
		fPageBook.showPage(fTextViewer.getControl());
		
		// clear content cache if we need to display error
		fContentProvider.clearContentCache();
	}
	
	public boolean isDisplayingError()
	{	
		return fIsShowingErrorPage;
	}
	
	public Control getControl() {
		return fPageBook;
	}
	
	
	
	public int getAddressibleSize() {
		return fAddressibleSize;
	}
	
	private Object getSynchronizedProperty(String propertyId)
	{
		IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
		
		if (syncService == null)
			return null;
		
		return syncService.getProperty(getMemoryBlock(), propertyId);	
	}
	
	/**
	 * This method estimates the number of visible lines in the rendering
	 * table.  
	 * @return estimated number of visible lines in the table
	 */
	private int getNumberOfVisibleLines()
	{
		if(fTableViewer == null)
			return -1;
		
		Table table = fTableViewer.getTable();
		int height = fTableViewer.getTable().getSize().y;
		
		// when table is not yet created, height is zero
		if (height == 0)
		{
			// make use of the table viewer to estimate table size
			height = fTableViewer.getTable().getParent().getSize().y;
		}
		
		// height of border
		int border = fTableViewer.getTable().getHeaderHeight();
		
		// height of scroll bar
		int scroll = fTableViewer.getTable().getHorizontalBar().getSize().y;

		// height of table is table's area minus border and scroll bar height		
		height = height-border-scroll;

		// calculate number of visible lines
		int lineHeight = getMinTableItemHeight(table);
		
		int numberOfLines = height/lineHeight;
		
		if (numberOfLines < 0)
			return 20;
	
		return numberOfLines;		
	}
	
	private static void  setTopIndex(Table table, int index)
	{
		MemoryViewUtil.linuxWorkAround(table);
		table.setTopIndex(index);
	}

	private void addRenderingToSyncService()
	{
		IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
		
		if (syncService == null)
			return;
		
		syncService.addPropertyChangeListener(this, null);
	
		if (!isDisplayingError())
		{
			if (getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationProvider() == null)
				getMemoryRenderingContainer().getMemoryRenderingSite().setSynchronizationProvider(this);
			
			// check if there is already synchronization info available
			Object selectedAddress =getSynchronizedProperty( AbstractTableRendering.PROPERTY_SELECTED_ADDRESS);
			Object size =getSynchronizedProperty( AbstractTableRendering.PROPERTY_COL_SIZE);
			Object topAddress =getSynchronizedProperty( AbstractTableRendering.PROPERTY_TOP_ADDRESS);
			
			// if info is available, some other view tab has already been
			// created
			// do not overwirte info int he synchronizer if that's the case
			if (selectedAddress == null) {
				updateSyncSelectedAddress();
			}

			if (size == null) {
				updateSyncColSize();
			}
			if (topAddress == null) {
				updateSyncTopAddress();
			}
		}
	}
	
	/**
	 * Get properties from synchronizer and synchronize settings
	 */
	private void synchronize()
	{	
		Integer columnSize = (Integer) getSynchronizedProperty(AbstractTableRendering.PROPERTY_COL_SIZE);
		BigInteger selectedAddress = (BigInteger)getSynchronizedProperty(AbstractTableRendering.PROPERTY_SELECTED_ADDRESS);
		BigInteger topAddress = (BigInteger)getSynchronizedProperty(AbstractTableRendering.PROPERTY_TOP_ADDRESS);
		
		if (columnSize != null) {
			int colSize = columnSize.intValue();
			if (colSize > 0 && colSize != fColumnSize) {
				columnSizeChanged(colSize);
			}
		}
		if (topAddress != null) {
			if (!topAddress.equals(getTopVisibleAddress())) {
				if (selectedAddress != null) {
					if (!fSelectedAddress.equals(selectedAddress)) {
						selectedAddressChanged(selectedAddress);
					}
				}
				topVisibleAddressChanged(topAddress);
			}
		}
		if (selectedAddress != null) {
			if (selectedAddress.compareTo(fSelectedAddress) != 0) {
				selectedAddressChanged(selectedAddress);
			}
		}
	}
	
	/**
	 * Resize column to the preferred size
	 */
	public void resizeColumnsToPreferredSize() {
		// pack columns
		Table table = fTableViewer.getTable();
		TableColumn[] columns = table.getColumns();
		
		for (int i=0 ;i<columns.length-1; i++)
		{	
			columns[i].pack();
		}
		
		if (!fIsShowAddressColumn)
		{
			columns[0].setWidth(0);
		}
	}
	
	/**
	 * update selected address in synchronizer if update is true.
	 */
	private void updateSyncSelectedAddress() {
		
		if (!fIsCreated)
			return;
		PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractTableRendering.PROPERTY_SELECTED_ADDRESS, null, fSelectedAddress);
		firePropertyChangedEvent(event);
	}

	/**
	 * update column size in synchronizer
	 */
	private void updateSyncColSize() {
		
		if (!fIsCreated)
			return;
		
		PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractTableRendering.PROPERTY_COL_SIZE, null, new Integer(fColumnSize));
		firePropertyChangedEvent(event);
	}
	
	/**
	 * update top visible address in synchronizer
	 */
	private void updateSyncTopAddress() {
		
		if (!fIsCreated)
			return;

		PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractTableRendering.PROPERTY_TOP_ADDRESS, null, fTopRowAddress);
		firePropertyChangedEvent(event);
	}
	
	/**
	 * Fill context menu of this rendering
	 * @param menu
	 */
	protected void fillContextMenu(IMenuManager menu) {
	
		menu.add(new Separator("topMenu")); //$NON-NLS-1$
		menu.add(fResetMemoryBlockAction);
		menu.add(fGoToAddressAction);
	
		menu.add(new Separator());
		
		if (fFormatColumnActions.length > 0)
		{
			// Format view tab actions
			IMenuManager formatMenu = new MenuManager(DebugUIMessages.getString("AbstractTableRendering.5"),  //$NON-NLS-1$
				"format"); //$NON-NLS-1$
			
			menu.appendToGroup("topMenu", formatMenu); //$NON-NLS-1$
		
			for (int i=0; i<fFormatColumnActions.length; i++)
			{
				formatMenu.add(fFormatColumnActions[i]);	
		
				// add check mark to the action to reflect current format of the view tab
				if (fFormatColumnActions[i] instanceof FormatColumnAction)
				{
					if (((FormatColumnAction)fFormatColumnActions[i]).getColumnSize() == getBytesPerColumn())
					{
						fFormatColumnActions[i].setChecked(true);
					}
					else
					{
						fFormatColumnActions[i].setChecked(false);
					}
				}
			}
		}
		
		menu.add(new Separator());
		menu.add(fReformatAction);
		menu.add(fToggleAddressColumnAction);
		menu.add(new Separator());
		menu.add(fCopyToClipboardAction);
		menu.add(fPrintViewTabAction);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.internal.ui.views.memory.ITableMemoryViewTab#getNumAddressibleUnitPerLine()
	 */
	public int getAddressibleUnitPerLine() {
		return fBytePerLine / fAddressibleSize;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.internal.ui.views.memory.ITableMemoryViewTab#getNumbAddressibleUnitPerColumn()
	 */
	public int getAddressibleUnitPerColumn() {
		return fColumnSize / fAddressibleSize;
	}
	
	/**
	 * @return current column size
	 */
	public int getBytesPerColumn()
	{
		return fColumnSize;
	}

	/**
	 * @return number of bytes per line
	 */
	public int getBytesPerLine()
	{
		return fBytePerLine;
	}
	
	/**
	 * Update labels of this rendering without regetting memory from the
	 * memory block.
	 */
	public void updateLabels()
	{
		// update tab labels
		updateRenderingLabel(true);
		
		if (fTableViewer != null)
		{
			// update column labels
			setColumnHeadings();
			fTableViewer.refresh();
		}
	}
	
	protected void updateRenderingLabel(boolean showAddress)
	{	
		fLabel = ""; //$NON-NLS-1$
		try {			
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				fLabel = ((IMemoryBlockExtension)getMemoryBlock()).getExpression();
				
				if (fLabel.startsWith("&")) //$NON-NLS-1$
					fLabel = "&" + fLabel; //$NON-NLS-1$
				
				if (fLabel == null)
				{
					fLabel = DebugUIMessages.getString("AbstractTableRendering.8"); //$NON-NLS-1$
				}
				
				if (showAddress && ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress() != null)
				{	
					fLabel += " : 0x"; //$NON-NLS-1$
					fLabel += ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress().toString(16);
				}
			}
			else
			{
				long address = getMemoryBlock().getStartAddress();
				fLabel = Long.toHexString(address);
			}
		} catch (DebugException e) {
			fLabel = DebugUIMessages.getString("AbstractTableRendering.9");					 //$NON-NLS-1$
			DebugUIPlugin.log(e.getStatus());
		}
		
		String preName = DebugUITools.getMemoryRenderingManager().getRenderingType(getRenderingId()).getLabel();
		
		if (preName != null)
			fLabel += " <" + preName + ">"; //$NON-NLS-1$ //$NON-NLS-2$
		
		firePropertyChangedEvent(new PropertyChangeEvent(this, IBasicPropertyConstants.P_TEXT, null, fLabel));
	}
	
	private void setColumnHeadings()
	{
		String[] columnLabels = new String[0];

		IDebugModelPresentation presentation = DebugUIPlugin.getModelPresentation();
		if (presentation instanceof IMemoryBlockTablePresentation)
			columnLabels = ((IMemoryBlockTablePresentation)presentation).getColumnLabels(getMemoryBlock(), fBytePerLine, getNumCol());
		
		// check that column labels returned are not null
		if (columnLabels == null)
			columnLabels = new String[0];
		
		int numByteColumns = fBytePerLine/fColumnSize;
		
		TableColumn[] columns = fTableViewer.getTable().getColumns();
		
		int j=0;
		for (int i=1; i<columns.length-1; i++)
		{	
			// if the number of column labels returned is correct
			// use supplied column labels
			if (columnLabels.length == numByteColumns)
			{
				columns[i].setText(columnLabels[j]);
				j++;
			}
			else
			{
				// otherwise, use default
				if (fColumnSize >= 4)
				{
					columns[i].setText(Integer.toHexString(i*fColumnSize).toUpperCase() + 
							" - " + Integer.toHexString(i*fColumnSize+fColumnSize-1).toUpperCase()); //$NON-NLS-1$
				}
				else
				{
					columns[i].setText(Integer.toHexString(i*fColumnSize).toUpperCase());
				}
			}
		}
	}
	
	/**
	 * Refresh the table viewer with the current top visible address.
	 * Update labels in the memory rendering.
	 */
	public void refresh()
	{	
		// refresh at start address of this memory block
		// address may change if expression is evaluated to a different value
		IMemoryBlock mem = getMemoryBlock();
		BigInteger address;
		
		if (mem instanceof IMemoryBlockExtension)
		{
			address = ((IMemoryBlockExtension)mem).getBigBaseAddress();
			
			if (address == null)
			{	
				DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.getString("AbstractTableRendering.10"), null)); //$NON-NLS-1$
				displayError(e);
				return;
			}
			
			updateRenderingLabel(true);
			
			// base address has changed
			if (address.compareTo(fContentProvider.getContentBaseAddress()) != 0)
			{
				// get to new address
				fSelectedAddress = address;
				updateSyncSelectedAddress();
				reloadTable(address, true);
				
				fTopRowAddress = address;
				updateSyncTopAddress();
				
				fContentInput.updateContentBaseAddress();
			}
			else
			{
				// reload at top of table
				address = getTopVisibleAddress();
				reloadTable(address, true);
			}				
		}
		else
		{
			address = BigInteger.valueOf(mem.getStartAddress());
			reloadTable(address, true);
		}
	}
	
	synchronized private void reloadTable(BigInteger topAddress, boolean updateDelta){
		
		if (fTableViewer == null)
			return;
		
		try
		{
			Table table = (Table)fTableViewer.getControl();	
			
			TableRenderingContentInput input = new TableRenderingContentInput(this, fContentInput.getPreBuffer(), fContentInput.getPostBuffer(), fContentInput.getDefaultBufferSize(), topAddress, getNumberOfVisibleLines(), updateDelta);
			fContentInput = input;
			fTableViewer.setInput(fContentInput);
	
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				int topIdx = findAddressIndex(topAddress);
				
				if (topIdx != -1)
				{
					setTopIndex(table, topIdx);
				}
			}
			
			// cursor needs to be refreshed after reload
			if (isAddressVisible(fSelectedAddress))
				setCursorAtAddress(fSelectedAddress);
			
			MemoryViewUtil.linuxWorkAround(fTableViewer.getTable());
		}
		finally
		{
		}
	}
	
	private BigInteger getTopVisibleAddress() {
		
		if (fTableViewer == null)
			return BigInteger.valueOf(0);

		Table table = fTableViewer.getTable();
		int topIndex = getTopVisibleIndex(table);

		if (topIndex < 1) { topIndex = 0; }

		if (table.getItemCount() > topIndex) 
		{
			TableRenderingLine topItem = (TableRenderingLine)table.getItem(topIndex).getData();
			
			String calculatedAddress = null;
			if (topItem == null)
			{
				calculatedAddress = table.getItem(topIndex).getText();
			}
			else
			{
				calculatedAddress = topItem.getAddress();				
			}
			
			BigInteger bigInt = new BigInteger(calculatedAddress, 16);
			return bigInt;
		}
		return BigInteger.valueOf(0);
	}
	
	private int findAddressIndex(BigInteger address)
	{
		TableItem items[] = fTableViewer.getTable().getItems();
	
		for (int i=0; i<items.length; i++){
			
			// Again, when the table resizes, the table may have a null item
			// at then end.  This is to handle that.
			if (items[i] != null)
			{	
				TableRenderingLine line = (TableRenderingLine)items[i].getData();
				BigInteger lineAddress = new BigInteger(line.getAddress(), 16);
				int addressibleUnit = getAddressibleUnitPerLine();
				BigInteger endLineAddress = lineAddress.add(BigInteger.valueOf(addressibleUnit));
				
				if (lineAddress.compareTo(address) <= 0 && endLineAddress.compareTo(address) > 0)
				{	
					return i;
				}
			}
		}
		
		return -1;
	}
	
	private static int getTopVisibleIndex(Table table)
	{
		MemoryViewUtil.linuxWorkAround(table);
		int index = table.getTopIndex();
		
		TableItem item = table.getItem(index);
		
		MemoryViewUtil.linuxWorkAround(table);
		while (item.getBounds(0).y < 0)
		{
			index++;
			item = table.getItem(index);
		}
		
		return index;
	}
	
	public TableViewer getTableViewer()
	{
		return fTableViewer;
	}
	
	public void dispose() {
		try {	
			// prevent rendering from being disposed again
			if (fIsDisposed)
				return;
			
			fIsDisposed = true;
			
			if (fContentProvider != null)
				fContentProvider.dispose();
			
			ScrollBar scroll = ((Table)fTableViewer.getControl()).getVerticalBar();
			if (scroll != null)
				scroll.removeSelectionListener(fScrollbarSelectionListener);
			
			fTableCursor.removeTraverseListener(fCursorTraverseListener);
			fTableCursor.removeKeyListener(fCursorKeyAdapter);
			fTableCursor.removeMouseListener(fCursorMouseListener);
			
			fCursorEditor.dispose();
			
			fTextViewer = null;
			fTableViewer = null;
			fTableCursor = null;
			
			// clean up cell editors
			for (int i=0; i<fEditors.length; i++)
			{
				fEditors[i].dispose();
			}
			
			// remove font change listener when the view tab is disposed
			JFaceResources.getFontRegistry().removeListener(this);
			
			// remove the view tab from the synchronizer
			IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
			if (syncService != null)
				syncService.removePropertyChangeListener(this);
			
			super.dispose();

		} catch (Exception e) {}
	}
	
	private int getNumCol() {
		
		int bytesPerLine = getBytesPerLine();
		int columnSize = getBytesPerColumn();
		
		return bytesPerLine/columnSize;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.IMemoryViewTab#setFont(org.eclipse.swt.graphics.Font)
	 */
	private void setFont(Font font)
	{	
		int oldIdx = getTopVisibleIndex(fTableViewer.getTable());
		
		// BUG in table, if font is changed when table is not starting
		// from the top, causes table gridline to be misaligned.
		setTopIndex(fTableViewer.getTable(),  0);
		
		// set font
		fTableViewer.getTable().setFont(font);
		fTableCursor.setFont(font);
		
		setTopIndex(fTableViewer.getTable(),  oldIdx);
		
		resizeColumnsToPreferredSize();
		
		// update table cursor and force redraw
		setCursorAtAddress(fSelectedAddress);
	}
	
	
	/**
	 * Move cursor to the specified address.
	 * Will load more memory if the address is not currently visible.
	 * @param address
	 * @throws DebugException
	 */
	public void goToAddress(BigInteger address) throws DebugException {
		Object evtLockClient = new Object();
		try
		{	
			if (!fEvtHandleLock.acquireLock(evtLockClient))
				return;

			// if address is within the range, highlight			
			if (!isAddressOutOfRange(address))
			{
				fSelectedAddress = address;
				updateSyncSelectedAddress();
				setCursorAtAddress(fSelectedAddress);
				
				// force the cursor to be shown
				if (!isAddressVisible(fSelectedAddress))
				{	
					int i = findAddressIndex(fSelectedAddress);
					fTableViewer.getTable().showItem(fTableViewer.getTable().getItem(i));
				}
			}
			else
			{
				// if not extended memory block
				// do not allow user to go to an address that's out of range
				if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
				{
					Status stat = new Status(
					 IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(),
					 DebugException.NOT_SUPPORTED, DebugUIMessages.getString("AbstractTableRendering.11"), null  //$NON-NLS-1$
					);
					DebugException e = new DebugException(stat);
					throw e;
				}
				
				fSelectedAddress = address;
				updateSyncSelectedAddress();
				
				//otherwise, reload at the address
				reloadTable(address,false);
				
				// if the table is reloaded, the top address is chagned in this case
				fTopRowAddress = address;
				updateSyncTopAddress();
				
				// set the cursor at the selected address after reload
				setCursorAtAddress(address);
			}
			fTableCursor.setVisible(true);
		}
		catch (DebugException e)
		{
			throw e;
		}
		finally
		{
			fEvtHandleLock.releaseLock(evtLockClient);
		}
	}
	
	/**
	 * Check if address provided is out of buffered range
	 * @param address
	 * @return if address is out of bufferred range
	 */
	private boolean isAddressOutOfRange(BigInteger address)
	{
		return fContentProvider.isAddressOutOfRange(address);
	}
	
	/**
	 * Check if address is visible
	 * @param address
	 * @return if the given address is visible
	 */
	private boolean isAddressVisible(BigInteger address)
	{
		// if view tab is not yet created 
		// cursor should always be visible
		if (!fIsCreated)
			return true;
		
		BigInteger topVisible = getTopVisibleAddress();
		int addressibleUnit = getAddressibleUnitPerLine();
		BigInteger lastVisible = getTopVisibleAddress().add(BigInteger.valueOf((getNumberOfVisibleLines() * addressibleUnit) + addressibleUnit));
		
		if (topVisible.compareTo(address) <= 0 && lastVisible.compareTo(address) > 0)
		{
			return true;
		}
		return false;
	}
	
	/**
	 * Create actions for the view tab
	 */
	protected void createActions() {
		fCopyToClipboardAction = new CopyTableRenderingToClipboardAction(this);
		fGoToAddressAction = new GoToAddressAction(this);
		fResetMemoryBlockAction = new ResetToBaseAddressAction(this);
		fPrintViewTabAction = new PrintTableRenderingAction(this);
		
		fFormatColumnActions = new Action[6];
		fFormatColumnActions[0] =  new FormatColumnAction(1, fAddressibleSize, this);
		fFormatColumnActions[1] =  new FormatColumnAction(2, fAddressibleSize, this);
		fFormatColumnActions[2] =  new FormatColumnAction(4, fAddressibleSize, this);
		fFormatColumnActions[3] =  new FormatColumnAction(8, fAddressibleSize, this);
		fFormatColumnActions[4] =  new FormatColumnAction(16, fAddressibleSize, this);
		fFormatColumnActions[5] =  new SetColumnSizeDefaultAction(this);
		
		fReformatAction = new ReformatAction(this);
		fToggleAddressColumnAction = new ToggleAddressColumnAction();
	}
	
	/**
	 * Handle scrollling and reload table if necessary
	 * @param event
	 */
	private synchronized void handleScrollBarSelection()
	{
		Object evtLockClient = new Object();
		try
		{			
			if (fIsDisposed)
				return;
			
			BigInteger address = getTopVisibleAddress();
	
			if (!fTopRowAddress.equals(address))
			{
				fTopRowAddress = address;
				updateSyncTopAddress();
			}
			
			if (!fEvtHandleLock.acquireLock(evtLockClient))
				return;
			
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				if (!isAddressOutOfRange(address))
				{
					Table table = fTableViewer.getTable();
					int numInBuffer = table.getItemCount();
					int index = findAddressIndex(address);
					if (index < 3)
					{
						if (fContentInput.getPreBuffer() == 0)
							setTopIndex(table, index);
						else
							reloadTable(address, false);
					}
					else if ((numInBuffer-(index+getNumberOfVisibleLines())) < 3)
					{
						reloadTable(address, false);
					}
				}
				else
				{	
					// approaching limit, reload table
					reloadTable(address, false);
				}
				
				if (isAddressVisible(fSelectedAddress))
					fTableCursor.setVisible(true);
				else
					fTableCursor.setVisible(false);
			}
		}
		finally
		{
			fEvtHandleLock.releaseLock(evtLockClient);
		}
	}
	
	
	private boolean needMoreLines()
	{
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
		{		
			Table table = fTableViewer.getTable();
			TableItem firstItem = table.getItem(0);
			TableItem lastItem = table.getItem(table.getItemCount()-1);
			
			if (firstItem == null || lastItem == null)
				return true;
			
			TableRenderingLine first = (TableRenderingLine)firstItem.getData();
			TableRenderingLine last = (TableRenderingLine) lastItem.getData();
			
			if (first == null ||last == null)
			{
				// For some reason, the table does not return the correct number
				// of table items in table.getItemCount(), causing last to be null.
				// This check is to ensure that we don't get a null pointer exception.
				return true;
			}
			
			BigInteger startAddress = new BigInteger(first.getAddress(), 16);
			BigInteger lastAddress = new BigInteger(last.getAddress(), 16);
			int addressibleUnit = getAddressibleUnitPerLine();
			lastAddress = lastAddress.add(BigInteger.valueOf(addressibleUnit));
			
			BigInteger topVisibleAddress = getTopVisibleAddress();
			long numVisibleLines = getNumberOfVisibleLines();
			long numOfBytes = numVisibleLines * addressibleUnit;
			
			BigInteger lastVisibleAddrss = topVisibleAddress.add(BigInteger.valueOf(numOfBytes));
			
			// if there are only 3 lines left at the top, refresh
			BigInteger numTopLine = topVisibleAddress.subtract(startAddress).divide(BigInteger.valueOf(addressibleUnit));
			if (numTopLine.compareTo(BigInteger.valueOf(3)) <= 0 && (startAddress.compareTo(BigInteger.valueOf(0)) != 0))
				return true;
			
			// if there are only 3 lines left at the bottom, refresh
			BigInteger numBottomLine = lastAddress.subtract(lastVisibleAddrss).divide(BigInteger.valueOf(addressibleUnit));
			if (numBottomLine.compareTo(BigInteger.valueOf(3)) <= 0)
			{
				return true;
			}
			
			return false;
		}
		
		return false;
	}

	private void handleTableMouseEvent(MouseEvent e) {
		// figure out new cursor position based on here the mouse is pointing
		TableItem[] tableItems = fTableViewer.getTable().getItems();
		TableItem selectedRow = null;
		int colNum = -1;
		int numCol = fTableViewer.getColumnProperties().length;
		
		for (int j=0; j<tableItems.length; j++)
		{
			TableItem item = tableItems[j];
			for (int i=0; i<numCol; i++)
			{
				Rectangle bound = item.getBounds(i);
				if (bound.contains(e.x, e.y))
				{
					colNum = i;
					selectedRow = item;
					break;
				}
			}
		}
		
		// if column position cannot be determined, return
		if (colNum < 1)
			return;
		
		// handle user mouse click onto table
		// move cursor to new position
		if (selectedRow != null)
		{
			int row = fTableViewer.getTable().indexOf(selectedRow);
			fTableCursor.setVisible(true);
			fTableCursor.setSelection(row, colNum);
			
			// manually call this since we don't get an event when
			// the table cursor changes selection.
			handleCursorMoved();
			
			fTableCursor.setFocus();
		}			
	}
	
	/**
	 * Handle column size changed event from synchronizer
	 * @param newColumnSize
	 */
	private void columnSizeChanged(final int newColumnSize) {
		// ignore event if view tab is disabled
		if (!isVisible())
			return;

		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				format(getBytesPerLine(), newColumnSize);
			}
		});
	}
	
	private void handleCursorMouseEvent(MouseEvent e){
		if (e.button == 1)
		{
			int col = fTableCursor.getColumn();
			if (col > 0 && col <= (getNumCol()))
				activateCellEditor(null);
		}			
	}
	
	/**
	 * Activate celll editor and prefill it with initial value.
	 * If initialValue is null, use cell content as initial value
	 * @param initialValue
	 */
	private void activateCellEditor(String initialValue) {
		
		int col = fTableCursor.getColumn();
		int row = findAddressIndex(fSelectedAddress);
		
		if (row < 0)
			return;
		// do not allow user to edit address column
		if (col == 0 || col > getNumCol())
		{
			return;
		}
		
		ICellModifier cellModifier = null;
		
		if (fTableViewer == null)
		{
			return;
		}
		cellModifier = fTableViewer.getCellModifier();
		
		TableItem tableItem = fTableViewer.getTable().getItem(row);
		
		Object element = tableItem.getData();
		Object property = fTableViewer.getColumnProperties()[col];
		Object value = cellModifier.getValue(element, (String)property);
		
		// The cell modifier canModify function always returns false if the edit action 
		// is not invoked from here.  This is to prevent data to be modified when
		// the table cursor loses focus from a cell.  By default, data will
		// be changed in a table when the cell loses focus.  This is to workaround
		// this default behaviour and only change data when the cell editor
		// is activated.
		((TableRenderingCellModifier)cellModifier).setEditActionInvoked(true);
		boolean canEdit = cellModifier.canModify(element, (String)property);
		((TableRenderingCellModifier)cellModifier).setEditActionInvoked(false);
		
		if (!canEdit)
			return;
		
		// activate based on current cursor position
		TextCellEditor selectedEditor = (TextCellEditor)fTableViewer.getCellEditors()[col];

		
		if (fTableViewer != null && cellModifier != null && selectedEditor != null && tableItem != null)
		{
			// The control that will be the editor must be a child of the Table
			Text text = (Text)selectedEditor.getControl();
			
			String cellValue  = null;
			
			if (initialValue != null)
			{
				cellValue = initialValue;	
			}
			else	
			{
				cellValue = ((String)value);
			}
			
			text.setText(cellValue);
	
			fCursorEditor.horizontalAlignment = SWT.LEFT;
			fCursorEditor.grabHorizontal = true;
	
			// Open the text editor in selected column of the selected row.
			fCursorEditor.setEditor (text, tableItem, col);
	
			// Assign focus to the text control
			selectedEditor.setFocus();
			
			if (initialValue != null)
			{
				text.clearSelection();
			}
			
			text.setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));

			// add listeners for the text control
			addListeners(text);
			
			// move cursor below text control
			fTableCursor.moveBelow(text);
		}
	}
	
	/**
	 * @param text
	 */
	private void addListeners(Text text) {
		fEditorFocusListener = new FocusAdapter() {
			public void focusLost(FocusEvent e)
			{
				handleTableEditorFocusLost(e);
			}
		};
		text.addFocusListener(fEditorFocusListener);
		
		fEditorKeyListener = new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				handleKeyEventInEditor(e);
			}
		};

		text.addKeyListener(fEditorKeyListener);
	}
	
	/**
	 * @param text
	 */
	private void removeListeners(Text text) {
		
		text.removeFocusListener(fEditorFocusListener);
		text.removeKeyListener(fEditorKeyListener);
	}
	
	private void handleTableEditorFocusLost(FocusEvent event)
	{
		final FocusEvent e = event;

		Display.getDefault().syncExec(new Runnable() {

			public void run()
			{
				try
				{
					int row = findAddressIndex(fSelectedAddress);
					int col = fTableCursor.getColumn();
					
					Text text = (Text)e.getSource();
					removeListeners(text);

					// get new value
					String newValue = text.getText();
					
					// modify memory at fRow and fCol
					modifyValue(row, col, newValue);
							
					// show cursor after modification is completed
					setCursorAtAddress(fSelectedAddress);
					fTableCursor.moveAbove(text);
					fTableCursor.setVisible(false);
					fTableCursor.setVisible(true);
				}
				catch (NumberFormatException e1)
				{
					MemoryViewUtil.openError(DebugUIMessages.getString(TableRenderingCellModifier.TITLE), 
						DebugUIMessages.getString(TableRenderingCellModifier.DATA_IS_INVALID), null);
				}		
			}
		});		
	}
	
	/**
	 * @param event
	 */
	private void handleKeyEventInEditor(KeyEvent event) {
		final KeyEvent e = event;
		Display.getDefault().asyncExec(new Runnable()
		{
			public void run()
			{
				Text text = (Text)e.getSource();
				int row = findAddressIndex(fSelectedAddress);
				int col = fTableCursor.getColumn();
				
				try
				{
					switch (e.keyCode)
					{
						case SWT.ARROW_UP :
							
							// move text editor box up one row		
							if (row-1 < 0)
								return;
						
							// modify value for current cell
							modifyValue(row, col, text.getText());
													
							row--;

							//	update cursor location and selection in table	
							fTableCursor.setSelection(row, col);
							handleCursorMoved();
							
							// remove listeners when focus is lost
							removeListeners(text);
							activateCellEditor(null);
							break;
						case SWT.ARROW_DOWN :
							
							// move text editor box down one row
							
							if (row+1 >= fTableViewer.getTable().getItemCount())
								return;
							
							// modify value for current cell
							modifyValue(row, col, text.getText());
						
							row++;
							
							//	update cursor location and selection in table								
							fTableCursor.setSelection(row, col);
							handleCursorMoved();
												
							// remove traverse listener when focus is lost
							removeListeners(text);
							activateCellEditor(null);		
							break;
						case 0:
							
						// if user has entered the max number of characters allowed in a cell, move to next cell
						// Extra changes will be used as initial value for the next cell
							int numCharsPerByte = getNumCharsPerByte();
							if (numCharsPerByte > 0)
							{
								if (text.getText().length() > getBytesPerColumn()*numCharsPerByte)
								{
									String newValue = text.getText();
									text.setText(newValue.substring(0, getBytesPerColumn()*numCharsPerByte));
									
									modifyValue(row, col, text.getText());
									
									// if cursor is at the end of a line, move to next line
									if (col >= getNumCol())
									{
										col = 1;
										row++;
									}
									else
									{
										// move to next column
										row++;
									}
									
									// update cursor position and selected address
									fTableCursor.setSelection(row, col);
									handleCursorMoved();
									
									removeListeners(text);
						
									// activate text editor at next cell
									activateCellEditor(newValue.substring(getBytesPerColumn()*numCharsPerByte));
								}
							}
							break;	
						case SWT.ESC:

							// if user has pressed escape, do not commit the changes
							// that's why "modifyValue" is not called
							fTableCursor.setSelection(row, col);
							handleCursorMoved();
					
							removeListeners(text);
							
							// cursor needs to have focus to remove focus from cell editor
							fTableCursor.setFocus();
							break;	
						default :
							numCharsPerByte = getNumCharsPerByte();
							if (numCharsPerByte > 0)
							{								
								if (text.getText().length()> getBytesPerColumn()* numCharsPerByte)
								{
									String newValue = text.getText();
									text.setText(newValue.substring(0,getBytesPerColumn()* numCharsPerByte));
									modifyValue(row, col, text.getText());
									// if cursor is at the end of a line, move to next line
									if (col >= getNumCol())
									{
										col = 1;
										row++;
									}
									else
									{
										col++;
									}
									
									fTableCursor.setSelection(row, col);
									handleCursorMoved();
									
									removeListeners(text);
									
									activateCellEditor(newValue.substring(getBytesPerColumn()*numCharsPerByte));
								}
							}
						break;
					}
				}
				catch (NumberFormatException e1)
				{
					MemoryViewUtil.openError(DebugUIMessages.getString(TableRenderingCellModifier.TITLE), 
						DebugUIMessages.getString(TableRenderingCellModifier.DATA_IS_INVALID), null);
					
					fTableCursor.setSelection(row, col);
					handleCursorMoved();
			
					removeListeners(text);
				}
			}
		});
	}

	
	/**
	 * Modify value and send new value to debug adapter
	 * @param row
	 * @param col
	 * @param newValue
	 * @throws NumberFormatException
	 */
	private void modifyValue(int row, int col, String newValue) throws NumberFormatException
	{
		if (newValue.length() == 0)
		{	
			// do not do anything if user has not entered anything
			return;
		}
		
		TableItem tableItem = fTableViewer.getTable().getItem(row);

		Object property = fTableViewer.getColumnProperties()[col];
		fTableViewer.getCellModifier().modify(tableItem, (String)property, newValue);
	}
	
	public void becomesHidden() {
		
		if (isVisible() == false)
			return;

		super.becomesHidden();
		
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
		{	
			updateRenderingLabel(false);
		}
			
		// once the view tab is disabled, all deltas information becomes invalid.
		// reset changed information and recompute if data has really changed when
		// user revisits the same tab.	
		fContentProvider.resetDeltas();
		
	}
	public void becomesVisible() {
		
		// do not do anything if already visible
		if (isVisible() == true)
			return;
		
		super.becomesVisible();
		
		IMemoryBlock mem = getMemoryBlock();
		
		BigInteger oldBase = fContentProvider.getContentBaseAddress();

		refresh();
		
		if (mem instanceof IMemoryBlockExtension)
		{
			BigInteger baseAddress = ((IMemoryBlockExtension)mem).getBigBaseAddress();
			
			if (baseAddress == null)
			{
				if (fSelectedAddress != null)
					baseAddress = fSelectedAddress;
				else
					baseAddress = new BigInteger("0"); //$NON-NLS-1$
			}
			
			Object[] connected = ((IMemoryBlockExtension)mem).getConnected();				
			
			// if the base address has changed, update cursor
			// and this is the first time this memory block is enabled
			if (!baseAddress.equals(oldBase) && connected.length == 1)
			{
				fSelectedAddress = baseAddress;
				setCursorAtAddress(fSelectedAddress);
				
				updateSyncTopAddress();
				updateSyncSelectedAddress();
			}
			else
			{
				// otherwise, take synchronized settings
				synchronize();
			}
		}
		else
		{
			synchronize();
		}
		updateRenderingLabel(true);
	}
	
	/**
	 * Reset this memory rendering.
	 * Cursor will be moved to the base address of the memory block.
	 * The table will be positioned back to have the base address
	 * at the top.
	 */
	public void reset()
	{
		BigInteger baseAddress;
	
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
		{
			baseAddress = ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
		}
		else
		{
			baseAddress = BigInteger.valueOf(getMemoryBlock().getStartAddress());
		}
		try {
			goToAddress(baseAddress);
			topVisibleAddressChanged(baseAddress);
		} catch (DebugException e) {
			MemoryViewUtil.openError(DebugUIMessages.getString("AbstractTableRendering.12"), DebugUIMessages.getString("AbstractTableRendering.13"), e); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}
	
	/**
	 * @return the current selected address in the rendering.
	 */
	public BigInteger getSelectedAddress() {
		return fSelectedAddress;
	}

	/**
	 * @return the content at the selected address.
	 */
	public String getSelectedContent() {

		if (isAddressOutOfRange(fSelectedAddress))
			return ""; //$NON-NLS-1$
		
		int col = fTableCursor.getColumn();
		TableItem rowItem = fTableCursor.getRow();
		int row = fTableViewer.getTable().indexOf(rowItem);
		
		// check precondition
		if (col == 0 || col > getBytesPerLine()/getBytesPerColumn())
		{
			return ""; //$NON-NLS-1$
		}
				
		TableItem tableItem = getTableViewer().getTable().getItem(row);
		
		return tableItem.getText(col);	
	}
	
	public void activated() {
		super.activated();
		
		// When the rendering is resized, the rendering does not handle
		// any resize event to figure out if more memory should be loaded.
		// Instead the rendering checks to see if the table has enough memory
		// to display when it becomes activated.  
		// This is to ensure that the refresh does not interfere with the
		// resize event due to limitation to Linux GTK.  The display event loop
		// in linuxWorkAround will cause the resize to fail sometimes.
		BigInteger lastAddress = fTopRowAddress.add(BigInteger.valueOf((getNumberOfVisibleLines()-3) * getBytesPerLine() + getBytesPerLine()));
		
		// force a reload if the last address is out of buffer range
		if (isAddressOutOfRange(lastAddress))
		{
			refresh();
		}
	}
	
	/**
	 * @return number of characters a byte will converted to.  Return
	 * -1 if this value is unknown.
	 */
	public int getNumCharsPerByte()
	{
		return -1;
	}
	
	private int getMinTableItemHeight(Table table){
		
		// Hack to get around Linux GTK problem.
		// On Linux GTK, table items have variable item height as
		// carriage returns are actually shown in a cell.  Some rows will be
		// taller than others.  When calculating number of visible lines, we
		// need to find the smallest table item height.  Otherwise, the rendering
		// underestimates the number of visible lines.  As a result the rendering
		// will not be able to get more memory as needed.
		if (MemoryViewUtil.isLinuxGTK())
		{
			// check each of the items and find the minimum
			TableItem[] items = table.getItems();
			int minHeight = table.getItemHeight();
			for (int i=0; i<items.length; i++)
			{
				minHeight = Math.min(items[i].getBounds(0).height, minHeight);
			}
			
			return minHeight;
				
		}
		return table.getItemHeight();
	}
	
	/**
	 * This is called by the label provider for <code>AbstractTableRendering</code> Implementor can
	 * reuse a memory view tab and presents data in a different format.
	 * 
	 * @param dataType -
	 *            type of data the bytes hold
	 * @param address -
	 *            addres where the bytes belong to
	 * @param data -
	 *            the bytes
	 * @param paddedStr -
	 *            fill each byte that is invalid with this padded string.
	 * @return a string to represent the memory. Do not return null. Return a
	 *         string to pad the cell if the memory cannot be converted
	 *         successfully.
	 */
	abstract public String getString(String dataType, BigInteger address, MemoryByte[] data);
	
	/**
	 * This is called by the cell modifier from an AbstractTableRendering.
	 * Implementor will convert the string value to an array of bytes.  The bytes will
	 * be passed to the debug adapter for memory block modification.
	 * Return null if the byte cannot be formatted properly.
	 * @param dataType - type of data the string represents
	 * @param address - address where the bytes belong to
	 * @param currentValues - current values of the data in bytes format
	 * @param data - the string to be converted to bytes
	 * @return the bytes to be passed to debug adapter for modification.
	 */
	abstract public byte[] getBytes(String dataType, BigInteger address, MemoryByte[] currentValues, String data);

}	

