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

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

import org.eclipse.core.runtime.ListenerList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.Accessible;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TypedListener;
import org.eclipse.ui.forms.HyperlinkSettings;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.internal.forms.Messages;
import org.eclipse.ui.internal.forms.widgets.ControlSegment;
import org.eclipse.ui.internal.forms.widgets.FormTextModel;
import org.eclipse.ui.internal.forms.widgets.FormUtil;
import org.eclipse.ui.internal.forms.widgets.IFocusSelectable;
import org.eclipse.ui.internal.forms.widgets.IHyperlinkSegment;
import org.eclipse.ui.internal.forms.widgets.ImageSegment;
import org.eclipse.ui.internal.forms.widgets.Locator;
import org.eclipse.ui.internal.forms.widgets.Paragraph;
import org.eclipse.ui.internal.forms.widgets.ParagraphSegment;
import org.eclipse.ui.internal.forms.widgets.SelectionData;
import org.eclipse.ui.internal.forms.widgets.TextSegment;

/**
 * This class is a read-only text control that is capable of rendering wrapped
 * text. Text can be rendered as-is or by parsing the formatting XML tags.
 * Independently, words that start with http:// can be converted into hyperlinks
 * on the fly.
 * <p>
 * When configured to use formatting XML, the control requires the root element
 * <code>form</code> to be used. The following tags can be children of the
 * <code>form</code> element:
 * </p>
 * <ul>
 * <li><b>p </b>- for defining paragraphs. The following attributes are
 * allowed:
 * <ul>
 * <li><b>vspace </b>- if set to 'false', no vertical space will be added
 * (default is 'true')</li>
 * </ul>
 * </li>
 * <li><b>li </b>- for defining list items. The following attributes are
 * allowed:
 * <ul>
 * <li><b>vspace </b>- the same as with the <b>p </b> tag</li>
 * <li><b>style </b>- could be 'bullet' (default), 'text' and 'image'</li>
 * <li><b>value </b>- not used for 'bullet'. For text, it is the value of the
 * text that is rendered as a bullet. For image, it is the href of the image to
 * be rendered as a bullet.</li>
 * <li><b>indent </b>- the number of pixels to indent the text in the list item
 * </li>
 * <li><b>bindent </b>- the number of pixels to indent the bullet itself</li>
 * </ul>
 * </li>
 * </ul>
 * <p>
 * Text in paragraphs and list items will be wrapped according to the width of
 * the control. The following tags can appear as children of either <b>p </b> or
 * <b>li </b> elements:
 * <ul>
 * <li><b>img </b>- to render an image. Element accepts attribute 'href' that
 * is a key to the <code>Image</code> set using 'setImage' method. Vertical
 * position of image relative to surrounding text is optionally controlled by
 * the attribute <b>align</b> that can have values <b>top</b>, <b>middle</b>
 * and <b>bottom</b></li>
 * <li><b>a </b>- to render a hyperlink. Element accepts attribute 'href' that
 * will be provided to the hyperlink listeners via HyperlinkEvent object. The
 * element also accepts 'nowrap' attribute (default is false). When set to
 * 'true', the hyperlink will not be wrapped. Hyperlinks automatically created
 * when 'http://' is encountered in text are not wrapped.</li>
 * <li><b>b </b>- the enclosed text will use bold font.</li>
 * <li><b>br </b>- forced line break (no attributes).</li>
 * <li><b>span </b>- the enclosed text will have the color and font specified
 * in the element attributes. Color is provided using 'color' attribute and is a
 * key to the Color object set by 'setColor' method. Font is provided using
 * 'font' attribute and is a key to the Font object set by 'setFont' method. As with
 * hyperlinks, it is possible to block wrapping by setting 'nowrap' to true
 * (false by default).
 * </li>
 * <li><b>control (new in 3.1)</b> - to place a control that is a child of the
 * text control. Element accepts attribute 'href' that is a key to the Control
 * object set using 'setControl' method. Optionally, attribute 'fill' can be set
 * to <code>true</code> to make the control fill the entire width of the text.
 * Form text is not responsible for creating or disposing controls, it only
 * places them relative to the surrounding text. Similar to <b>img</b>,
 * vertical position of the control can be set using the <b>align</b>
 * attribute. In addition, <b>width</b> and <b>height</b> attributes can
 * be used to force the dimensions of the control. If not used,
 * the preferred control size will be used.
 * </ul>
 * <p>
 * None of the elements can nest. For example, you cannot have <b>b </b> inside
 * a <b>span </b>. This was done to keep everything simple and transparent.
 * Since 3.1, an exception to this rule has been added to support nesting images
 * and text inside the hyperlink tag (<b>a</b>). Image enclosed in the
 * hyperlink tag acts as a hyperlink, can be clicked on and can accept and
 * render selection focus. When both text and image is enclosed, selection and
 * rendering will affect both as a single hyperlink.
 * </p>
 * <p>
 * Since 3.1, it is possible to select text. Text selection can be
 * programmatically accessed and also copied to clipboard. Non-textual objects
 * (images, controls etc.) in the selection range are ignored.
 * <p>
 * Care should be taken when using this control. Form text is not an HTML
 * browser and should not be treated as such. If you need complex formatting
 * capabilities, use Browser widget. If you need editing capabilities and
 * font/color styles of text segments is all you need, use StyleText widget.
 * Finally, if all you need is to wrap text, use SWT Label widget and create it
 * with SWT.WRAP style.
 * 
 * @see FormToolkit
 * @see TableWrapLayout
 * @since 3.0
 */
public class FormText extends Canvas {
	/**
	 * The object ID to be used when registering action to handle URL hyperlinks
	 * (those that should result in opening the web browser). Value is
	 * "urlHandler".
	 */
	public static final String URL_HANDLER_ID = "urlHandler"; //$NON-NLS-1$

	/**
	 * Value of the horizontal margin (default is 0).
	 */
	public int marginWidth = 0;

	/**
	 * Value of tue vertical margin (default is 1).
	 */
	public int marginHeight = 1;

	// private fields
	//TODO We should remove the dependency on Platform
	private static final boolean DEBUG_TEXT = false;//"true".equalsIgnoreCase(Platform.getDebugOption(FormUtil.DEBUG_TEXT));
	private static final boolean DEBUG_TEXTSIZE = false;//"true".equalsIgnoreCase(Platform.getDebugOption(FormUtil.DEBUG_TEXTSIZE));

	private static final boolean DEBUG_FOCUS = false;//"true".equalsIgnoreCase(Platform.getDebugOption(FormUtil.DEBUG_FOCUS));	

	private boolean hasFocus;

	private boolean paragraphsSeparated = true;

	private FormTextModel model;

	private ListenerList listeners;

	private Hashtable resourceTable = new Hashtable();

	private IHyperlinkSegment entered;

	private IHyperlinkSegment armed;

	private boolean mouseFocus = false;

	private boolean controlFocusTransfer = false;

	private boolean inSelection = false;

	private SelectionData selData;

	private static final String INTERNAL_MENU = "__internal_menu__"; //$NON-NLS-1$

	private static final String CONTROL_KEY = "__segment__"; //$NON-NLS-1$

	private class FormTextLayout extends Layout implements ILayoutExtension {
		public FormTextLayout() {
		}

		public int computeMaximumWidth(Composite parent, boolean changed) {
			return computeSize(parent, SWT.DEFAULT, SWT.DEFAULT, changed).x;
		}

		public int computeMinimumWidth(Composite parent, boolean changed) {
			return computeSize(parent, 5, SWT.DEFAULT, true).x;
		}

		/*
		 * @see Layout#computeSize(Composite, int, int, boolean)
		 */
		public Point computeSize(Composite composite, int wHint, int hHint,
				boolean changed) {
			long start = 0;

			if (DEBUG_TEXT)
				start = System.currentTimeMillis();
			int innerWidth = wHint;
			if (innerWidth != SWT.DEFAULT)
				innerWidth -= marginWidth * 2;
			Point textSize = computeTextSize(innerWidth);
			int textWidth = textSize.x + 2 * marginWidth;
			int textHeight = textSize.y + 2 * marginHeight;
			Point result = new Point(textWidth, textHeight);
			if (DEBUG_TEXT) {
				long stop = System.currentTimeMillis();
				System.out.println("FormText computeSize: " + (stop - start) //$NON-NLS-1$
						+ "ms"); //$NON-NLS-1$
			}
			if (DEBUG_TEXTSIZE) {
				System.out.println("FormText ("+model.getAccessibleText()+"), computeSize: wHint="+wHint+", result="+result); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
			return result;
		}

		private Point computeTextSize(int wHint) {
			Paragraph[] paragraphs = model.getParagraphs();
			GC gc = new GC(FormText.this);
			gc.setFont(getFont());
			Locator loc = new Locator();
			int width = wHint != SWT.DEFAULT ? wHint : 0;
			FontMetrics fm = gc.getFontMetrics();
			int lineHeight = fm.getHeight();
			boolean selectableInTheLastRow = false;
			for (int i = 0; i < paragraphs.length; i++) {
				Paragraph p = paragraphs[i];
				if (i > 0 && getParagraphsSeparated()
						&& p.getAddVerticalSpace())
					loc.y += getParagraphSpacing(lineHeight);
				loc.rowHeight = 0;
				loc.indent = p.getIndent();
				loc.x = p.getIndent();
				ParagraphSegment[] segments = p.getSegments();
				if (segments.length > 0) {
					selectableInTheLastRow = false;
					int pwidth = 0;
					for (int j = 0; j < segments.length; j++) {
						ParagraphSegment segment = segments[j];
						segment.advanceLocator(gc, wHint, loc, resourceTable,
								false);
						if (wHint != SWT.DEFAULT) {
							width = Math.max(width, loc.width);
						} else {
							pwidth += loc.width;
						}
						if (segment instanceof IFocusSelectable)
							selectableInTheLastRow = true;
					}
					if (wHint == SWT.DEFAULT)
						width = Math.max(width, pwidth);
					loc.y += loc.rowHeight;
				} else {
					// empty new line
					loc.y += lineHeight;
				}
			}
			gc.dispose();
			if (selectableInTheLastRow)
				loc.y += 1;
			return new Point(width, loc.y);
		}

		protected void layout(Composite composite, boolean flushCache) {
			long start = 0;

			if (DEBUG_TEXT) {
				start = System.currentTimeMillis();
			}
			selData = null;
			Rectangle carea = composite.getClientArea();
			if (DEBUG_TEXTSIZE) {
				System.out.println("FormText layout ("+model.getAccessibleText()+"), carea="+carea); //$NON-NLS-1$ //$NON-NLS-2$
			}			
			GC gc = new GC(composite);
			gc.setFont(getFont());
			ensureBoldFontPresent(getFont());
			gc.setForeground(getForeground());
			gc.setBackground(getBackground());

			Locator loc = new Locator();
			loc.marginWidth = marginWidth;
			loc.marginHeight = marginHeight;
			loc.x = marginWidth;
			loc.y = marginHeight;
			FontMetrics fm = gc.getFontMetrics();
			int lineHeight = fm.getHeight();

			Paragraph[] paragraphs = model.getParagraphs();
			IHyperlinkSegment selectedLink = getSelectedLink();
			for (int i = 0; i < paragraphs.length; i++) {
				Paragraph p = paragraphs[i];
				if (i > 0 && paragraphsSeparated && p.getAddVerticalSpace())
					loc.y += getParagraphSpacing(lineHeight);
				loc.indent = p.getIndent();
				loc.resetCaret();
				loc.rowHeight = 0;
				p.layout(gc, carea.width, loc, lineHeight, resourceTable,
						selectedLink);
			}
			gc.dispose();
			if (DEBUG_TEXT) {
				long stop = System.currentTimeMillis();
				System.out.println("FormText.layout: " + (stop - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
	}

	/**
	 * Contructs a new form text widget in the provided parent and using the
	 * styles.
	 * 
	 * @param parent
	 *            form text parent control
	 * @param style
	 *            the widget style
	 */
	public FormText(Composite parent, int style) {
		super(parent, SWT.NO_BACKGROUND | SWT.WRAP | style);
		setLayout(new FormTextLayout());
		model = new FormTextModel();
		addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				model.dispose();
				disposeResourceTable(true);
			}
		});
		addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				paint(e);
			}
		});
		addListener(SWT.KeyDown, new Listener() {
			public void handleEvent(Event e) {
				if (e.character == '\r') {
					activateSelectedLink();
					return;
				}
			}
		});
		addListener(SWT.Traverse, new Listener() {
			public void handleEvent(Event e) {
				if (DEBUG_FOCUS)
					System.out.println("Traversal: " + e); //$NON-NLS-1$
				switch (e.detail) {
				case SWT.TRAVERSE_PAGE_NEXT:
				case SWT.TRAVERSE_PAGE_PREVIOUS:
				case SWT.TRAVERSE_ARROW_NEXT:
				case SWT.TRAVERSE_ARROW_PREVIOUS:
					e.doit = false;
					return;
				}
				if (!model.hasFocusSegments()) {
					e.doit = true;
					return;
				}
				if (e.detail == SWT.TRAVERSE_TAB_NEXT)
					e.doit = advance(true);
				else if (e.detail == SWT.TRAVERSE_TAB_PREVIOUS)
					e.doit = advance(false);
				else if (e.detail != SWT.TRAVERSE_RETURN)
					e.doit = true;
			}
		});
		addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent e) {
				if (!hasFocus) {
					hasFocus = true;
					if (DEBUG_FOCUS) {
						System.out.println("FormText: focus gained"); //$NON-NLS-1$
					}
					if (!mouseFocus && !controlFocusTransfer) {
						handleFocusChange();
					}
				}
			}

			public void focusLost(FocusEvent e) {
				if (DEBUG_FOCUS) {
					System.out.println("FormText: focus lost"); //$NON-NLS-1$
				}
				if (hasFocus) {
					hasFocus = false;
					if (!controlFocusTransfer)
						handleFocusChange();
				}
			}
		});
		addMouseListener(new MouseListener() {
			public void mouseDoubleClick(MouseEvent e) {
			}

			public void mouseDown(MouseEvent e) {
				// select a link
				handleMouseClick(e, true);
			}

			public void mouseUp(MouseEvent e) {
				// activate a link
				handleMouseClick(e, false);
			}
		});
		addMouseTrackListener(new MouseTrackListener() {
			public void mouseEnter(MouseEvent e) {
				handleMouseMove(e);
			}

			public void mouseExit(MouseEvent e) {
				if (entered != null) {
					exitLink(entered, e.stateMask);
					paintLinkHover(entered, false);
					entered = null;
					setCursor(null);
				}
			}

			public void mouseHover(MouseEvent e) {
				handleMouseHover(e);
			}
		});
		addMouseMoveListener(new MouseMoveListener() {
			public void mouseMove(MouseEvent e) {
				handleMouseMove(e);
			}
		});
		initAccessible();
		ensureBoldFontPresent(getFont());
		createMenu();
		// we will handle traversal of controls, if any
		setTabList(new Control[] {});
	}

	/**
	 * Test for focus.
	 * 
	 * @return <samp>true </samp> if the widget has focus.
	 */
	public boolean getFocus() {
		return hasFocus;
	}

	/**
	 * Test if the widget is currently processing the text it is about to
	 * render.
	 * 
	 * @return <samp>true </samp> if the widget is still loading the text,
	 *         <samp>false </samp> otherwise.
	 * @deprecated not used any more - returns <code>false</code>
	 */
	public boolean isLoading() {
		return false;
	}

	/**
	 * Returns the text that will be shown in the control while the real content
	 * is loading.
	 * 
	 * @return loading text message
	 * @deprecated loading text is not used since 3.1
	 */
	public String getLoadingText() {
		return null;
	}

	/**
	 * Sets the text that will be shown in the control while the real content is
	 * loading. This is significant when content to render is loaded from the
	 * input stream that was created from a remote URL, and the time to load the
	 * entire content is nontrivial.
	 * 
	 * @param loadingText
	 *            loading text message
	 * @deprecated use setText(loadingText, false, false);
	 */
	public void setLoadingText(String loadingText) {
		setText(loadingText, false, false);
	}

	/**
	 * If paragraphs are separated, spacing will be added between them.
	 * Otherwise, new paragraphs will simply start on a new line with no
	 * spacing.
	 * 
	 * @param value
	 *            <samp>true </samp> if paragraphs are separated, </samp> false
	 *            </samp> otherwise.
	 */
	public void setParagraphsSeparated(boolean value) {
		paragraphsSeparated = value;
	}

	/**
	 * Tests if there is some inter-paragraph spacing.
	 * 
	 * @return <samp>true </samp> if paragraphs are separated, <samp>false
	 *         </samp> otherwise.
	 */
	public boolean getParagraphsSeparated() {
		return paragraphsSeparated;
	}

	/**
	 * Registers the image referenced by the provided key.
	 * <p>
	 * For <samp>img </samp> tags, an object of a type <samp>Image </samp> must
	 * be registered using the key equivalent to the value of the <samp>href
	 * </samp> attribute used in the tag.
	 * 
	 * @param key
	 *            unique key that matches the value of the <samp>href </samp>
	 *            attribute.
	 * @param image
	 *            an object of a type <samp>Image </samp>.
	 */
	public void setImage(String key, Image image) {
		resourceTable.put("i." + key, image); //$NON-NLS-1$
	}

	/**
	 * Registers the color referenced by the provided key.
	 * <p>
	 * For <samp>span </samp> tags, an object of a type <samp>Color </samp> must
	 * be registered using the key equivalent to the value of the <samp>color
	 * </samp> attribute.
	 * 
	 * @param key
	 *            unique key that matches the value of the <samp>color </samp>
	 *            attribute.
	 * @param color
	 *            an object of the type <samp>Color </samp> or <samp>null</samp>
	 *            if the key needs to be cleared.
	 */
	public void setColor(String key, Color color) {
		String fullKey = "c." + key; //$NON-NLS-1$
		if (color == null)
			resourceTable.remove(fullKey);
		else
			resourceTable.put(fullKey, color);
	}

	/**
	 * Registers the font referenced by the provided key.
	 * <p>
	 * For <samp>span </samp> tags, an object of a type <samp>Font </samp> must
	 * be registered using the key equivalent to the value of the <samp>font
	 * </samp> attribute.
	 * 
	 * @param key
	 *            unique key that matches the value of the <samp>font </samp>
	 *            attribute.
	 * @param font
	 *            an object of the type <samp>Font </samp> or <samp>null</samp>
	 *            if the key needs to be cleared.
	 */
	public void setFont(String key, Font font) {
		String fullKey = "f." + key; //$NON-NLS-1$
		if (font == null)
			resourceTable.remove(fullKey);
		else
			resourceTable.put(fullKey, font);
		model.clearCache(fullKey);
	}

	/**
	 * Registers the control referenced by the provided key.
	 * <p>
	 * For <samp>control</samp> tags, an object of a type <samp>Control</samp>
	 * must be registered using the key equivalent to the value of the
	 * <samp>control</samp> attribute.
	 * 
	 * @param key
	 *            unique key that matches the value of the <samp>control</samp>
	 *            attribute.
	 * @param control
	 *            an object of the type <samp>Control</samp> or <samp>null</samp>
	 *            if the existing control at the specified key needs to be
	 *            removed.
	 * @since 3.1
	 */
	public void setControl(String key, Control control) {
		String fullKey = "o." + key; //$NON-NLS-1$
		if (control == null)
			resourceTable.remove(fullKey);
		else
			resourceTable.put(fullKey, control);
	}

	/**
	 * Sets the font to use to render the default text (text that does not have
	 * special font property assigned). Bold font will be constructed from this
	 * font.
	 * 
	 * @param font
	 *            the default font to use
	 */
	public void setFont(Font font) {
		super.setFont(font);
		model.clearCache(null);
		Font boldFont = (Font) resourceTable.get(FormTextModel.BOLD_FONT_ID);
		if (boldFont != null) {
			boldFont.dispose();
			resourceTable.remove(FormTextModel.BOLD_FONT_ID);
		}
		ensureBoldFontPresent(getFont());
	}

	/**
	 * Sets the provided text. Text can be rendered as-is, or by parsing the
	 * formatting tags. Optionally, sections of text starting with http:// will
	 * be converted to hyperlinks.
	 * 
	 * @param text
	 *            the text to render
	 * @param parseTags
	 *            if <samp>true </samp>, formatting tags will be parsed.
	 *            Otherwise, text will be rendered as-is.
	 * @param expandURLs
	 *            if <samp>true </samp>, URLs found in the untagged text will be
	 *            converted into hyperlinks.
	 */
	public void setText(String text, boolean parseTags, boolean expandURLs) {
		disposeResourceTable(false);
		entered = null;
		if (parseTags)
			model.parseTaggedText(text, expandURLs);
		else
			model.parseRegularText(text, expandURLs);
		hookControlSegmentFocus();
		layout();
		redraw();
	}

	/**
	 * Sets the contents of the stream. Optionally, URLs in untagged text can be
	 * converted into hyperlinks. The caller is responsible for closing the
	 * stream.
	 * 
	 * @param is
	 *            stream to render
	 * @param expandURLs
	 *            if <samp>true </samp>, URLs found in untagged text will be
	 *            converted into hyperlinks.
	 */
	public void setContents(InputStream is, boolean expandURLs) {
		entered = null;
		disposeResourceTable(false);
		model.parseInputStream(is, expandURLs);
		hookControlSegmentFocus();
		layout();
		redraw();
	}

	private void hookControlSegmentFocus() {
		Paragraph[] paragraphs = model.getParagraphs();
		if (paragraphs == null)
			return;
		Listener listener = new Listener() {
			public void handleEvent(Event e) {
				switch (e.type) {
				case SWT.FocusIn:
					if (!controlFocusTransfer)
						syncControlSegmentFocus((Control) e.widget);
					break;
				case SWT.Traverse:
					if (DEBUG_FOCUS)
						System.out.println("Control traversal: " + e); //$NON-NLS-1$
					switch (e.detail) {
					case SWT.TRAVERSE_PAGE_NEXT:
					case SWT.TRAVERSE_PAGE_PREVIOUS:
					case SWT.TRAVERSE_ARROW_NEXT:
					case SWT.TRAVERSE_ARROW_PREVIOUS:
						e.doit = false;
						return;
					}
					Control c = (Control) e.widget;
					ControlSegment segment = (ControlSegment) c
							.getData(CONTROL_KEY);
					if (e.detail == SWT.TRAVERSE_TAB_NEXT)
						e.doit = advanceControl(c, segment, true);
					else if (e.detail == SWT.TRAVERSE_TAB_PREVIOUS)
						e.doit = advanceControl(c, segment, false);
					if (!e.doit)
						e.detail = SWT.TRAVERSE_NONE;
					break;
				}
			}
		};
		for (int i = 0; i < paragraphs.length; i++) {
			Paragraph p = paragraphs[i];
			ParagraphSegment[] segments = p.getSegments();
			for (int j = 0; j < segments.length; j++) {
				if (segments[j] instanceof ControlSegment) {
					ControlSegment cs = (ControlSegment) segments[j];
					Control c = cs.getControl(resourceTable);
					if (c != null) {
						if (c.getData(CONTROL_KEY) == null) {
							// first time - hook
							c.setData(CONTROL_KEY, cs);
							attachTraverseListener(c, listener);
						}
					}
				}
			}
		}
	}

	private void attachTraverseListener(Control c, Listener listener) {
		if (c instanceof Composite) {
			Composite parent = (Composite) c;
			Control[] children = parent.getChildren();
			for (int i = 0; i < children.length; i++) {
				attachTraverseListener(children[i], listener);
			}
			if (c instanceof Canvas) {
				// If Canvas, the control iteself can accept
				// traverse events and should be monitored
				c.addListener(SWT.Traverse, listener);
				c.addListener(SWT.FocusIn, listener);
			}
		} else {
			c.addListener(SWT.Traverse, listener);
			c.addListener(SWT.FocusIn, listener);
		}
	}

	/**
	 * If we click on the control randomly, our internal book-keeping will be
	 * off. We need to update the model and mark the control segment and
	 * currently selected. Hyperlink that may have had focus must also be
	 * exited.
	 * 
	 * @param control
	 *            the control that got focus
	 */
	private void syncControlSegmentFocus(Control control) {
		ControlSegment cs = null;

		while (control != null) {
			cs = (ControlSegment) control.getData(CONTROL_KEY);
			if (cs != null)
				break;
			control = control.getParent();
		}
		if (cs == null)
			return;
		IFocusSelectable current = model.getSelectedSegment();
		// If the model and the control match, all is well
		if (current == cs)
			return;
		IHyperlinkSegment oldLink = null;
		if (current != null && current instanceof IHyperlinkSegment) {
			oldLink = (IHyperlinkSegment) current;
			exitLink(oldLink, SWT.NULL);
		}
		if (DEBUG_FOCUS)
			System.out.println("Sync control: " + cs + ", oldLink=" + oldLink); //$NON-NLS-1$ //$NON-NLS-2$
		model.select(cs);
		if (oldLink != null)
			paintFocusTransfer(oldLink, null);
		// getAccessible().setFocus(model.getSelectedSegmentIndex());
	}

	private boolean advanceControl(Control c, ControlSegment segment,
			boolean next) {
		Composite parent = c.getParent();
		if (parent == this) {
			// segment-level control
			IFocusSelectable nextSegment = model.getNextFocusSegment(next);
			if (nextSegment != null) {
				controlFocusTransfer = true;
				super.forceFocus();
				controlFocusTransfer = false;
				model.select(segment);
				return advance(next);
			}
			// nowhere to go
			return setFocusToNextSibling(this, next);
		}
		if (setFocusToNextSibling(c, next))
			return true;
		// still here - must go one level up
		segment = (ControlSegment) parent.getData(CONTROL_KEY);
		return advanceControl(parent, segment, next);
	}

	private boolean setFocusToNextSibling(Control c, boolean next) {
		Composite parent = c.getParent();
		Control[] children = parent.getTabList();
		for (int i = 0; i < children.length; i++) {
			Control child = children[i];
			if (child == c) {
				// here
				if (next) {
					for (int j = i + 1; j < children.length; j++) {
						Control nc = children[j];
						if (nc.setFocus())
							return false;
					}
				} else {
					for (int j = i - 1; j >= 0; j--) {
						Control pc = children[j];
						if (pc.setFocus())
							return false;
					}
				}
			}
		}
		return false;
	}

	/**
	 * Controls whether whitespace inside paragraph and list items is
	 * normalized. Note that the new value will not affect the current text in
	 * the control, only subsequent calls to <code>setText</code> or
	 * <code>setContents</code>.
	 * <p>
	 * If normalized:
	 * <ul>
	 * <li>all white space characters will be condensed into at most one when
	 * between words.</li>
	 * <li>new line characters will be ignored and replaced with one white
	 * space character</li>
	 * <li>white space characters after the opening tags and before the closing
	 * tags will be trimmed</li>
	 * 
	 * @param value
	 *            <code>true</code> if whitespace is normalized,
	 *            <code>false</code> otherwise.
	 */
	public void setWhitespaceNormalized(boolean value) {
		model.setWhitespaceNormalized(value);
	}

	/**
	 * Tests whether whitespace inside paragraph and list item is normalized.
	 * 
	 * @see #setWhitespaceNormalized(boolean)
	 * @return <code>true</code> if whitespace is normalized,
	 *         <code>false</code> otherwise.
	 */
	public boolean isWhitespaceNormalized() {
		return model.isWhitespaceNormalized();
	}

	/**
	 * Disposes the internal menu if created and sets the menu provided as a
	 * parameter.
	 * 
	 * @param menu
	 *            the menu to associate with this text control
	 */
	public void setMenu(Menu menu) {
		Menu currentMenu = super.getMenu();
		if (currentMenu != null && INTERNAL_MENU.equals(currentMenu.getData())) {
			// internal menu set
			if (menu != null) {
				currentMenu.dispose();
				super.setMenu(menu);
			}
		} else
			super.setMenu(menu);
	}

	private void createMenu() {
		Menu menu = new Menu(this);
		final MenuItem copyItem = new MenuItem(menu, SWT.PUSH);
		copyItem.setText(Messages.FormText_copy);

		SelectionListener listener = new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				if (e.widget == copyItem) {
					copy();
				}
			}
		};
		copyItem.addSelectionListener(listener);
		menu.addMenuListener(new MenuListener() {
			public void menuShown(MenuEvent e) {
				copyItem.setEnabled(canCopy());
			}

			public void menuHidden(MenuEvent e) {
			}
		});
		menu.setData(INTERNAL_MENU);
		super.setMenu(menu);
	}

	/**
	 * Returns the hyperlink settings that are in effect for this control.
	 * 
	 * @return current hyperlinks settings
	 */
	public HyperlinkSettings getHyperlinkSettings() {
		return model.getHyperlinkSettings();
	}

	/**
	 * Sets the hyperlink settings to be used for this control. Settings will
	 * affect things like hyperlink color, rendering style, cursor etc.
	 * 
	 * @param settings
	 *            hyperlink settings for this control
	 */
	public void setHyperlinkSettings(HyperlinkSettings settings) {
		model.setHyperlinkSettings(settings);
	}

	/**
	 * Adds a listener that will handle hyperlink events.
	 * 
	 * @param listener
	 *            the listener to add
	 */
	public void addHyperlinkListener(IHyperlinkListener listener) {
		if (listeners == null)
			listeners = new ListenerList();
		listeners.add(listener);
	}

	/**
	 * Removes the hyperlink listener.
	 * 
	 * @param listener
	 *            the listener to remove
	 */
	public void removeHyperlinkListener(IHyperlinkListener listener) {
		if (listeners == null)
			return;
		listeners.remove(listener);
	}

	/**
	 * Adds a selection listener. A Selection event is sent by the widget when
	 * the selection has changed.
	 * <p>
	 * <code>widgetDefaultSelected</code> is not called for FormText.
	 * </p>
	 * 
	 * @param listener
	 *            the listener
	 * @exception SWTException
	 *                <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
	 *                disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the receiver</li>
	 *                </ul>
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT when listener is null</li>
	 *                </ul>
	 * @since 3.1
	 */
	public void addSelectionListener(SelectionListener listener) {
		checkWidget();
		if (listener == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		TypedListener typedListener = new TypedListener(listener);
		addListener(SWT.Selection, typedListener);
	}

	/**
	 * Removes the specified selection listener.
	 * <p>
	 * 
	 * @param listener
	 *            the listener
	 * @exception SWTException
	 *                <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
	 *                disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the receiver</li>
	 *                </ul>
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT when listener is null</li>
	 *                </ul>
	 * @since 3.1
	 */
	public void removeSelectionListener(SelectionListener listener) {
		checkWidget();
		if (listener == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		removeListener(SWT.Selection, listener);
	}

	/**
	 * Returns the selected text.
	 * <p>
	 * 
	 * @return selected text, or an empty String if there is no selection.
	 * @exception SWTException
	 *                <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
	 *                disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the receiver</li>
	 *                </ul>
	 * @since 3.1
	 */

	public String getSelectionText() {
		checkWidget();
		if (selData != null)
			return selData.getSelectionText();
		return ""; //$NON-NLS-1$
	}

	/**
	 * Tests if the text is selected and can be copied into the clipboard.
	 * 
	 * @return <code>true</code> if the selected text can be copied into the
	 *         clipboard, <code>false</code> otherwise.
	 * @since 3.1
	 */
	public boolean canCopy() {
		return selData != null && selData.canCopy();
	}

	/**
	 * Copies the selected text into the clipboard. Does nothing if no text is
	 * selected or the text cannot be copied for any other reason.
	 * 
	 * @since 3.1
	 */

	public void copy() {
		if (!canCopy())
			return;
		Clipboard clipboard = new Clipboard(getDisplay());
		Object[] o = new Object[] { getSelectionText() };
		Transfer[] t = new Transfer[] { TextTransfer.getInstance() };
		clipboard.setContents(o, t);
		clipboard.dispose();
	}

	/**
	 * Returns the reference of the hyperlink that currently has keyboard focus,
	 * or <code>null</code> if there are no hyperlinks in the receiver or no
	 * hyperlink has focus at the moment.
	 * 
	 * @return href of the selected hyperlink or <code>null</code> if none
	 *         selected.
	 * @since 3.1
	 */
	public Object getSelectedLinkHref() {
		IHyperlinkSegment link = getSelectedLink();
		return link != null ? link.getHref() : null;
	}

	/**
	 * Returns the text of the hyperlink that currently has keyboard focus, or
	 * <code>null</code> if there are no hyperlinks in the receiver or no
	 * hyperlink has focus at the moment.
	 * 
	 * @return text of the selected hyperlink or <code>null</code> if none
	 *         selected.
	 * @since 3.1
	 */
	public String getSelectedLinkText() {
		IHyperlinkSegment link = getSelectedLink();
		return link != null ? link.getText() : null;
	}

	private IHyperlinkSegment getSelectedLink() {
		IFocusSelectable segment = model.getSelectedSegment();
		if (segment != null && segment instanceof IHyperlinkSegment)
			return (IHyperlinkSegment) segment;
		return null;
	}

	private void initAccessible() {
		Accessible accessible = getAccessible();
		accessible.addAccessibleListener(new AccessibleAdapter() {
			public void getName(AccessibleEvent e) {
				if (e.childID == ACC.CHILDID_SELF)
					e.result = model.getAccessibleText();
				else {
					int linkCount = model.getHyperlinkCount();
					if (e.childID >= 0 && e.childID < linkCount) {
						IHyperlinkSegment link = model.getHyperlink(e.childID);
						e.result = link.getText();
					}
				}
			}

			public void getHelp(AccessibleEvent e) {
				e.result = getToolTipText();
				int linkCount = model.getHyperlinkCount();
				if (e.result == null && e.childID >= 0 && e.childID < linkCount) {
					IHyperlinkSegment link = model.getHyperlink(e.childID);
					e.result = link.getText();
				}
			}
		});
		accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
			public void getChildAtPoint(AccessibleControlEvent e) {
				Point pt = toControl(new Point(e.x, e.y));
				IHyperlinkSegment link = model.findHyperlinkAt(pt.x, pt.y);
				if (link != null)
					e.childID = model.indexOf(link);
				else
					e.childID = ACC.CHILDID_SELF;
			}

			public void getLocation(AccessibleControlEvent e) {
				Rectangle location = null;
				if (e.childID != ACC.CHILDID_SELF
						&& e.childID != ACC.CHILDID_NONE) {
					int index = e.childID;
					IHyperlinkSegment link = model.getHyperlink(index);
					if (link != null) {
						location = link.getBounds();
					}
				}
				if (location == null) {
					location = getBounds();
				}
				Point pt = toDisplay(new Point(location.x, location.y));
				e.x = pt.x;
				e.y = pt.y;
				e.width = location.width;
				e.height = location.height;
			}

			public void getFocus(AccessibleControlEvent e) {
				int childID = ACC.CHILDID_NONE;

				if (isFocusControl()) {
					int selectedIndex = model.getSelectedSegmentIndex();
					if (selectedIndex == -1) {
						childID = ACC.CHILDID_SELF;
					} else {
						childID = selectedIndex;
					}
				}
				e.childID = childID;
			}
			
			public void getDefaultAction (AccessibleControlEvent e) {
				if (model.getHyperlinkCount() > 0) {
				    e.result = SWT.getMessage ("SWT_Press"); //$NON-NLS-1$
				} 
			}

			public void getChildCount(AccessibleControlEvent e) {
				e.detail = model.getHyperlinkCount();
			}

			public void getRole(AccessibleControlEvent e) {
				int role = 0;
				int childID = e.childID;
				int linkCount = model.getHyperlinkCount();
				if (childID == ACC.CHILDID_SELF) { 
					if (linkCount > 0) {
					    role = ACC.ROLE_LINK;
					} else {
						role = ACC.ROLE_TEXT;
					}
				} else if (childID >= 0 && childID < linkCount) {
					role = ACC.ROLE_LINK;
				}
				e.detail = role;
			}

			public void getSelection(AccessibleControlEvent e) {
				int selectedIndex = model.getSelectedSegmentIndex();
				e.childID = (selectedIndex == -1) ? ACC.CHILDID_NONE
						: selectedIndex;
			}

			public void getState(AccessibleControlEvent e) {
				int linkCount = model.getHyperlinkCount();
				int selectedIndex = model.getSelectedSegmentIndex();
				int state = 0;
				int childID = e.childID;
				if (childID == ACC.CHILDID_SELF) {
					state = ACC.STATE_NORMAL;
				} else if (childID >= 0 && childID < linkCount) {
					state = ACC.STATE_SELECTABLE;
					if (isFocusControl()) {
						state |= ACC.STATE_FOCUSABLE;
					}
					if (selectedIndex == childID) {
						state |= ACC.STATE_SELECTED;
						if (isFocusControl()) {
							state |= ACC.STATE_FOCUSED;
						}
					}
				}
				state |= ACC.STATE_READONLY;
				e.detail = state;
			}

			public void getChildren(AccessibleControlEvent e) {
				int linkCount = model.getHyperlinkCount();
				Object[] children = new Object[linkCount];
				for (int i = 0; i < linkCount; i++) {
					children[i] = new Integer(i);
				}
				e.children = children;
			}

			public void getValue(AccessibleControlEvent e) {
				// e.result = model.getAccessibleText();
			}
		});
	}

	private void startSelection(MouseEvent e) {
		inSelection = true;
		selData = new SelectionData(e);
		redraw();
		Form form = FormUtil.getForm(this);
		if (form != null)
			form.setSelectionText(this);
	}

	private void endSelection(MouseEvent e) {
		inSelection = false;
		if (selData != null) {
			if (!selData.isEnclosed())
				selData = null;
			else
				computeSelection();
		}
		notifySelectionChanged();
	}

	private void computeSelection() {
		GC gc = new GC(this);
		Paragraph[] paragraphs = model.getParagraphs();
		IHyperlinkSegment selectedLink = getSelectedLink();
		if (getDisplay().getFocusControl() != this)
			selectedLink = null;
		for (int i = 0; i < paragraphs.length; i++) {
			Paragraph p = paragraphs[i];
			if (i > 0)
				selData.markNewLine();
			p.computeSelection(gc, resourceTable, selectedLink, selData);
		}
		gc.dispose();
	}

	void clearSelection() {
		selData = null;
		if (!isDisposed()) {
			redraw();
			notifySelectionChanged();
		}
	}

	private void notifySelectionChanged() {
		Event event = new Event();
		event.widget = this;
		event.display = this.getDisplay();
		event.type = SWT.Selection;
		notifyListeners(SWT.Selection, event);
		getAccessible().selectionChanged();
	}

	private void handleDrag(MouseEvent e) {
		if (selData != null) {
			ScrolledComposite scomp = FormUtil.getScrolledComposite(this);
			if (scomp != null) {
				FormUtil.ensureVisible(scomp, this, e);
			}
			selData.update(e);
			redraw();
		}
	}

	private void handleMouseClick(MouseEvent e, boolean down) {
		if (DEBUG_FOCUS)
			System.out.println("FormText: mouse click(" + down + ")"); //$NON-NLS-1$ //$NON-NLS-2$
		if (down) {
			// select a hyperlink
			mouseFocus = true;
			IHyperlinkSegment segmentUnder = model.findHyperlinkAt(e.x, e.y);
			if (segmentUnder != null) {
				IHyperlinkSegment oldLink = getSelectedLink();
				if (getDisplay().getFocusControl() != this) {
					setFocus();
				}
				model.selectLink(segmentUnder);
				enterLink(segmentUnder, e.stateMask);
				paintFocusTransfer(oldLink, segmentUnder);
			}
			if (e.button == 1) {
				startSelection(e);
				armed = segmentUnder;
			}
			else {
			}
		} else {
			if (e.button == 1) {
				endSelection(e);
				IHyperlinkSegment segmentUnder = model
						.findHyperlinkAt(e.x, e.y);
				if (segmentUnder != null && armed == segmentUnder && selData == null) {
					activateLink(segmentUnder, e.stateMask);
					armed = null;
				}
			}
			mouseFocus = false;
		}
	}

	private void handleMouseHover(MouseEvent e) {
	}

	private void updateTooltipText(ParagraphSegment segment) {
		String tooltipText = null;
		if (segment != null) {
			tooltipText = segment.getTooltipText();
		}
		String currentTooltipText = getToolTipText();

		if ((currentTooltipText != null && tooltipText == null)
				|| (currentTooltipText == null && tooltipText != null))
			setToolTipText(tooltipText);
	}

	private void handleMouseMove(MouseEvent e) {
		if (inSelection) {
			handleDrag(e);
			return;
		}
		ParagraphSegment segmentUnder = model.findSegmentAt(e.x, e.y);
		updateTooltipText(segmentUnder);
		if (segmentUnder == null) {
			if (entered != null) {
				exitLink(entered, e.stateMask);
				paintLinkHover(entered, false);
				entered = null;
			}
			setCursor(null);
		} else {
			if (segmentUnder instanceof IHyperlinkSegment) {
				IHyperlinkSegment linkUnder = (IHyperlinkSegment) segmentUnder;
				if (entered!=null && linkUnder!=entered) {
					// Special case: links are so close that there are 0 pixels between.
					// Must exit the link before entering the next one.
					exitLink(entered, e.stateMask);
					paintLinkHover(entered, false);
					entered = null;
				}
				if (entered == null) {
					entered = linkUnder;
					enterLink(linkUnder, e.stateMask);
					paintLinkHover(entered, true);
					setCursor(model.getHyperlinkSettings().getHyperlinkCursor());
				}
			} else {
				if (entered != null) {
					exitLink(entered, e.stateMask);
					paintLinkHover(entered, false);
					entered = null;
				}
				if (segmentUnder instanceof TextSegment)
					setCursor(model.getHyperlinkSettings().getTextCursor());
				else
					setCursor(null);
			}
		}
	}

	private boolean advance(boolean next) {
		if (DEBUG_FOCUS)
			System.out.println("Advance: next=" + next); //$NON-NLS-1$
		IFocusSelectable current = model.getSelectedSegment();
		if (current != null && current instanceof IHyperlinkSegment)
			exitLink((IHyperlinkSegment) current, SWT.NULL);
		IFocusSelectable newSegment = null;
		boolean valid = false;
		// get the next segment that can accept focus. Links
		// can always accept focus but controls may not
		while (!valid) {
			if (!model.traverseFocusSelectableObjects(next))
				break;
			newSegment = model.getSelectedSegment();
			if (newSegment == null)
				break;
			valid = setControlFocus(next, newSegment);
		}
		IHyperlinkSegment newLink = newSegment instanceof IHyperlinkSegment ? (IHyperlinkSegment) newSegment
				: null;
		if (valid)
			enterLink(newLink, SWT.NULL);
		IHyperlinkSegment oldLink = current instanceof IHyperlinkSegment ? (IHyperlinkSegment) current
				: null;
		if (oldLink != null || newLink != null)
			paintFocusTransfer(oldLink, newLink);
		if (newLink != null)
			ensureVisible(newLink);
		if (newLink != null)
			getAccessible().setFocus(model.getSelectedSegmentIndex());
		return !valid;
	}

	private boolean setControlFocus(boolean next, IFocusSelectable selectable) {
		controlFocusTransfer = true;
		boolean result = selectable.setFocus(resourceTable, next);
		controlFocusTransfer = false;
		return result;
	}

	private void handleFocusChange() {
		if (DEBUG_FOCUS) {
			System.out.println("Handle focus change: hasFocus=" + hasFocus //$NON-NLS-1$
					+ ", mouseFocus=" + mouseFocus); //$NON-NLS-1$
		}
		if (hasFocus) {
			boolean advance = true;
			if (!mouseFocus) {
				// if (model.restoreSavedLink() == false)
				boolean valid = false;
				IFocusSelectable selectable = null;
				while (!valid) {
					if (!model.traverseFocusSelectableObjects(advance))
						break;
					selectable = model.getSelectedSegment();
					if (selectable == null)
						break;
					valid = setControlFocus(advance, selectable);
				}
				if (selectable != null)
					ensureVisible(selectable);
				if (selectable instanceof IHyperlinkSegment) {
					enterLink((IHyperlinkSegment) selectable, SWT.NULL);
					paintFocusTransfer(null, (IHyperlinkSegment) selectable);
				}
			}
		} else {
			paintFocusTransfer(getSelectedLink(), null);
			model.selectLink(null);
		}
	}

	private void enterLink(IHyperlinkSegment link, int stateMask) {
		if (link == null || listeners == null)
			return;
		int size = listeners.size();
		HyperlinkEvent he = new HyperlinkEvent(this, link.getHref(), link
				.getText(), stateMask);
		Object [] listenerList = listeners.getListeners();
		for (int i = 0; i < size; i++) {
			IHyperlinkListener listener = (IHyperlinkListener) listenerList[i];
			listener.linkEntered(he);
		}
	}

	private void exitLink(IHyperlinkSegment link, int stateMask) {
		if (link == null || listeners == null)
			return;
		int size = listeners.size();
		HyperlinkEvent he = new HyperlinkEvent(this, link.getHref(), link
				.getText(), stateMask);
		Object [] listenerList = listeners.getListeners();
		for (int i = 0; i < size; i++) {
			IHyperlinkListener listener = (IHyperlinkListener) listenerList[i];
			listener.linkExited(he);
		}
	}

	private void paintLinkHover(IHyperlinkSegment link, boolean hover) {
		GC gc = new GC(this);
		HyperlinkSettings settings = getHyperlinkSettings();
		Color newFg = hover ? settings.getActiveForeground() : settings
				.getForeground();
		if (newFg != null)
			gc.setForeground(newFg);
		gc.setBackground(getBackground());
		gc.setFont(getFont());
		boolean selected = (link == getSelectedLink());
		((ParagraphSegment) link).paint(gc, hover, resourceTable, selected,
				selData, null);
		gc.dispose();
	}

	private void activateSelectedLink() {
		IHyperlinkSegment link = getSelectedLink();
		if (link != null)
			activateLink(link, SWT.NULL);
	}

	private void activateLink(IHyperlinkSegment link, int stateMask) {
		setCursor(model.getHyperlinkSettings().getBusyCursor());
		if (listeners != null) {
			int size = listeners.size();
			HyperlinkEvent e = new HyperlinkEvent(this, link.getHref(), link
					.getText(), stateMask);
			Object [] listenerList = listeners.getListeners();
			for (int i = 0; i < size; i++) {
				IHyperlinkListener listener = (IHyperlinkListener) listenerList[i];
				listener.linkActivated(e);
			}
		}
		if (!isDisposed() && model.linkExists(link)) {
			setCursor(model.getHyperlinkSettings().getHyperlinkCursor());
		}
	}

	private void ensureBoldFontPresent(Font regularFont) {
		Font boldFont = (Font) resourceTable.get(FormTextModel.BOLD_FONT_ID);
		if (boldFont != null)
			return;
		boldFont = FormUtil.createBoldFont(getDisplay(), regularFont);
		resourceTable.put(FormTextModel.BOLD_FONT_ID, boldFont);
	}

	private void paint(PaintEvent e) {
		GC gc = e.gc;
		gc.setFont(getFont());
		ensureBoldFontPresent(getFont());
		gc.setForeground(getForeground());
		gc.setBackground(getBackground());
		repaint(gc, e.x, e.y, e.width, e.height);
	}

	private void repaint(GC gc, int x, int y, int width, int height) {
		Image textBuffer = new Image(getDisplay(), width, height);
		Color bg = getBackground();
		Color fg = getForeground();
		if (!getEnabled()) {
			bg = getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
			fg = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
		}
		GC textGC = new GC(textBuffer, gc.getStyle());
		textGC.setForeground(fg);
		textGC.setBackground(bg);
		textGC.setFont(getFont());
		textGC.fillRectangle(0, 0, width, height);
		Rectangle repaintRegion = new Rectangle(x, y, width, height);

		Paragraph[] paragraphs = model.getParagraphs();
		IHyperlinkSegment selectedLink = getSelectedLink();
		if (getDisplay().getFocusControl() != this)
			selectedLink = null;
		for (int i = 0; i < paragraphs.length; i++) {
			Paragraph p = paragraphs[i];
			p
					.paint(textGC, repaintRegion, resourceTable, selectedLink,
							selData);
		}
		textGC.dispose();
		gc.drawImage(textBuffer, x, y);
		textBuffer.dispose();
	}

	private int getParagraphSpacing(int lineHeight) {
		return lineHeight / 2;
	}

	private void paintFocusTransfer(IHyperlinkSegment oldLink,
			IHyperlinkSegment newLink) {
		GC gc = new GC(this);
		Color bg = getBackground();
		Color fg = getForeground();
		gc.setFont(getFont());
		if (oldLink != null) {
			gc.setBackground(bg);
			gc.setForeground(fg);
			oldLink.paintFocus(gc, bg, fg, false, null);
		}
		if (newLink != null) {
			// ensureVisible(newLink);
			gc.setBackground(bg);
			gc.setForeground(fg);
			newLink.paintFocus(gc, bg, fg, true, null);
		}
		gc.dispose();
	}

	private void ensureVisible(IFocusSelectable segment) {
		if (mouseFocus) {
			mouseFocus = false;
			return;
		}
		if (segment == null)
			return;
		Rectangle bounds = segment.getBounds();
		ScrolledComposite scomp = FormUtil.getScrolledComposite(this);
		if (scomp == null)
			return;
		Point origin = FormUtil.getControlLocation(scomp, this);
		origin.x += bounds.x;
		origin.y += bounds.y;
		FormUtil.ensureVisible(scomp, origin, new Point(bounds.width,
				bounds.height));
	}

	/**
	 * Overrides the method by fully trusting the layout manager (computed width
	 * or height may be larger than the provider width or height hints). Callers
	 * should be prepared that the computed width is larger than the provided
	 * wHint.
	 * 
	 * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
	 */
	public Point computeSize(int wHint, int hHint, boolean changed) {
		checkWidget();
		Point size;
		FormTextLayout layout = (FormTextLayout) getLayout();
		if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
			size = layout.computeSize(this, wHint, hHint, changed);
		} else {
			size = new Point(wHint, hHint);
		}
		Rectangle trim = computeTrim(0, 0, size.x, size.y);
		if (DEBUG_TEXTSIZE)
			System.out.println("FormText Computed size: "+trim); //$NON-NLS-1$
		return new Point(trim.width, trim.height);
	}

	private void disposeResourceTable(boolean disposeBoldFont) {
		if (disposeBoldFont) {
			Font boldFont = (Font) resourceTable
					.get(FormTextModel.BOLD_FONT_ID);
			if (boldFont != null) {
				boldFont.dispose();
				resourceTable.remove(FormTextModel.BOLD_FONT_ID);
			}
		}
		ArrayList imagesToRemove = new ArrayList();
		for (Enumeration enm = resourceTable.keys(); enm.hasMoreElements();) {
			String key = (String) enm.nextElement();
			if (key.startsWith(ImageSegment.SEL_IMAGE_PREFIX)) {
				Object obj = resourceTable.get(key);
				if (obj instanceof Image) {
					Image image = (Image) obj;
					if (!image.isDisposed()) {
						image.dispose();
						imagesToRemove.add(key);
					}
				}
			}
		}
		for (int i = 0; i < imagesToRemove.size(); i++) {
			resourceTable.remove(imagesToRemove.get(i));
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.swt.widgets.Control#setEnabled(boolean)
	 */
	public void setEnabled(boolean enabled) {
		super.setEnabled(enabled);
		redraw();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.widgets.Control#setFocus()
	 */
	public boolean setFocus() {
		mouseFocus = true;
		FormUtil.setFocusScrollingEnabled(this, false);
		boolean result = super.setFocus();
		mouseFocus = false;
		FormUtil.setFocusScrollingEnabled(this, true);
		return result;
	}
}
