//------------------------------------------------------------------------------
// Copyright (c) 2005, 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.richtext;

import java.io.File;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Platform;
import org.eclipse.epf.common.html.HTMLFormatter;
import org.eclipse.epf.common.serviceability.Logger;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.XMLUtil;
import org.eclipse.epf.common.xml.XSLTProcessor;
import org.eclipse.epf.richtext.actions.CopyAction;
import org.eclipse.epf.richtext.actions.CutAction;
import org.eclipse.epf.richtext.actions.FindReplaceAction;
import org.eclipse.epf.richtext.actions.PasteAction;
import org.eclipse.epf.richtext.actions.PastePlainTextAction;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationAdapter;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.StatusTextEvent;
import org.eclipse.swt.browser.StatusTextListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.PlatformUI;

/**
 * The default rich text control implementation.
 * <p>
 * The default rich text editor uses XHTML as the underlying markup language for
 * the rich text content. It is implemented using a SWT <code>Browser</code>
 * control and DHTML (HTML, CSS and JavaScript).
 * 
 * @author Kelvin Low
 * @author Jeff Hardy
 * @since 1.0
 */
public class RichText implements IRichText {

	// Encoded single quote. All single quotes need to be specially encoded to
	// avoid JavaScript error when calling Browse.executeCommand().
	private static final String ENCODED_SINGLE_QUOTE = "%sq%"; //$NON-NLS-1$

	private static final String ENCODED_NEWLINE = "%EOL%"; //$NON-NLS-1$

	protected static final String STATUS_PREFIX = "$$$"; //$NON-NLS-1$

	protected static final int STATUS_PREFIX_LENGTH = STATUS_PREFIX.length();

	protected static final int STATUS_NOP = 0;

	protected static final int STATUS_INITIALIZED = 1;

	protected static final int STATUS_MODIFIED = 2;

	protected static final int STATUS_GET_TEXT = 3;

	protected static final int STATUS_KEY_DOWN = 4;

	protected static final int STATUS_KEY_UP = 5;

	protected static final int STATUS_SELECT_TEXT = 6;

	protected static final int STATUS_SELECT_CONTROL = 7;

	protected static final int STATUS_SELECT_NONE = 8;

	protected static final int STATUS_EXEC_CMD = 9;

	protected static final int STATUS_REFORMAT_LINKS = 10;

	// The default base path used for resolving links (<href>, <img>, etc.)
	private static final String DEFAULT_BASE_PATH = System
			.getProperty("user.home") //$NON-NLS-1$
			+ System.getProperty("file.separator") + "rte"; //$NON-NLS-1$ //$NON-NLS-2$

	// If true, log debugging info.
	protected boolean debug;

	// The plug-in logger.
	protected Logger logger;

	// The underlying SWT Browser used for loading the JavaScript/DHTML editor.
	protected Browser editor;

	// The underlying OleControlSite for the SWT Browser (Win32 only).
	protected Control editorControl;

	// The base URL of the rich text control whose content was last
	// copied to the clipboard.
	protected static URL copyURL;

	// The context menu associated with this control.
	protected Menu contextMenu;

	// The folder that contains the supporting CSS and JavaScript files
	protected String rteFolder;

	// The URL that points to the supporting CSS and JavaScript files.
	protected String rteURL;

	// The base path used for resolving links (<href>, <img>, etc.)
	protected String basePath;

	// The DHTML initialization flag.
	protected boolean initialized;

	// The initial focus.
	protected boolean initializedWithFocus;

	// The control's initial text. This is used to cache the HTML source passed
	// in via setText()while the DHTML initialization is happening.
	protected String initialText;

	// The control's current text.
	protected String currentText = ""; //$NON-NLS-1$

	// The control's editable flag.
	protected boolean editable = true;

	// The control's modification flag.
	protected boolean modified;

	// The control's text and object selection flag.
	protected boolean hasSelection;

	// The control's text selection
	protected RichTextSelection richTextSelection = new RichTextSelection();

	// JavaScript command execution status code.
	protected int status = 0;

	// The HTML source formatter.
	protected HTMLFormatter htmlFormatter;

	// The SWT event listeners.
	protected Map<Listener, RichTextListener> listeners;

	// The modify listeners.
	protected List<ModifyListener> modifyListeners;

	// The control's edit flag.
	protected boolean notifyingModifyListeners = false;

	// The controls's focus flag.
	protected boolean hasFocus = false;

	// The controls's processing JavaScript event flag.
	protected boolean processingJSEvent = false;

	// The controls's processing MODIFIED JavaScript event flag.
	protected boolean checkingModifyEvent = false;

	// The control's find/replace text action
	protected FindReplaceAction findReplaceAction;
	
	// The control's IE flag
	protected boolean isIE = false;

	/**
	 * Creates a new instance.
	 * 
	 * @param parent
	 *            the parent composite
	 * @param style
	 *            the style for this control
	 * @param basePath
	 *            the path used for resolving links
	 */
	public RichText(Composite parent, int style, String basePath) {
		debug = RichTextPlugin.getDefault().isDebugging();
		logger = RichTextPlugin.getDefault().getLogger();
		findReplaceAction = new FindReplaceAction(this);
		rteFolder = RichTextPlugin.getDefault().getInstallPath() + "rte/"; //$NON-NLS-1$		
		rteURL = XMLUtil.escape("file://" + rteFolder); //$NON-NLS-1$
		setBasePath(basePath);

		try {
			editor = new Browser(parent, SWT.NONE);
			if (debug) {
				printDebugMessage("RichText", "basePath=" + basePath); //$NON-NLS-1$ //$NON-NLS-2$
			}
			editor.setLayoutData(new GridData(GridData.FILL_BOTH));
			editor.setData(PROPERTY_NAME, this);
			init(parent, style);
		} catch (Exception e) {
			editor = null;
			String msg = "Failed to create RichText with basePath=" + basePath; //$NON-NLS-1$
			logger.logError(msg, e);
			if (debug) {
				System.out.println(msg);
				e.printStackTrace();
			}
		}
	}

	/**
	 * Creates a new instance.
	 * 
	 * @param parent
	 *            the parent composite
	 * @param style
	 *            the style for this control
	 */
	public RichText(Composite parent, int style) {
		this(parent, style, null);
	}

	/**
	 * Sets the base path for resolving links.
	 */
	protected void setBasePath(String path) {
		if (path != null && path.length() > 0) {
			if (path.startsWith(FileUtil.UNC_PATH_PREFIX)) {
				basePath = FileUtil.UNC_PATH_PREFIX
						+ FileUtil.appendSeparator(path.substring(
								FileUtil.UNC_PATH_PREFIX_LENGTH).replace('\\',
								'/'), "/"); //$NON-NLS-1$
			} else {
				basePath = FileUtil.appendSeparator(path).replace('\\', '/');
			}
		} else {
			basePath = FileUtil.appendSeparator(DEFAULT_BASE_PATH).replace(
					'\\', '/');
		}
	}

	/**
	 * Initializes this control.
	 * 
	 * @param parent
	 *            the parent composite
	 * @param style
	 *            the style for this control
	 * @throws Exception
	 *             when an error has occurred while initialzing this control
	 */
	protected void init(Composite parent, int style) throws Exception {
		try {
			addStatusTextListener();
			if (debug) {
				printDebugMessage("init", "added status text listener"); //$NON-NLS-1$ //$NON-NLS-2$
			}

			String editorHTML = generateEditorHTML();
			if (debug) {
				printDebugMessage("init", "generated editor HTML"); //$NON-NLS-1$ //$NON-NLS-2$
			}

			editor.setText(editorHTML);
			if (debug) {
				printDebugMessage("init", "loaded editor HTML"); //$NON-NLS-1$ //$NON-NLS-2$
			}

			contextMenu = new Menu(parent.getShell(), SWT.POP_UP);
			editor.setMenu(contextMenu);
			fillContextMenu(contextMenu);
			if (debug) {
				printDebugMessage("init", "added context menu"); //$NON-NLS-1$ //$NON-NLS-2$
			}

			addListeners();
			if (debug) {
				printDebugMessage("init", "added listeners"); //$NON-NLS-1$ //$NON-NLS-2$
			}

			htmlFormatter = new HTMLFormatter();
			if (debug) {
				printDebugMessage("init", "instantiated HTMLFormatter"); //$NON-NLS-1$ //$NON-NLS-2$
			}
		} catch (Exception e) {
			editor = null;
			dispose();
			throw e;
		}
	}

	/**
	 * Returns this rich text control.
	 * 
	 * @return this rich text control
	 */
	public Control getControl() {
		return editor;
	}

	/**
	 * Sets the layout data.
	 * 
	 * @param layoutData
	 *            the layout data to set
	 */
	public void setLayoutData(Object layoutData) {
		if (editor != null) {
			editor.setLayoutData(layoutData);
		}
	}

	/**
	 * Returns the layout data.
	 * 
	 * @return this control's layout data
	 */
	public Object getLayoutData() {
		if (editor != null) {
			return editor.getLayoutData();
		}
		return null;
	}

	/**
	 * Sets focus to this control.
	 */
	public void setFocus() {
		if (debug) {
			printDebugMessage("setFocus, editable=" + editable); //$NON-NLS-1$
		}
		if (editor != null) {
			if (initialized) {
				if (!editor.isFocusControl()) {
					if (!Platform.getOS().equals("win32")) { //$NON-NLS-1$
						// Workaround for Mozilla and Firefox rich text editor focus
						// issue.
						editor.setFocus();
					}
					executeCommand(RichTextCommand.SET_FOCUS);
				}
				hasFocus = true;
			} else {
				initializedWithFocus = true;
			}
		}
	}

	/**
	 * Tells the control it does not have focus.
	 */
	public void setBlur() {
		if (debug) {
			printDebugMessage("setBlur, editable=" + editable); //$NON-NLS-1$
		}
		if (editor != null) {
			if (initialized) {
				hasFocus = false;
			} else {
				initializedWithFocus = false;
			}
		}
	}

	/**
	 * Checks whether this control has focus.
	 * 
	 * @return <code>true</code> if this control has the user-interface focus
	 */
	public boolean hasFocus() {
		if (editor != null) {
			return hasFocus;
		}
		return false;
	}

	/**
	 * Returns the base path used for resolving text and image links.
	 * 
	 * @return the base path used for resolving links in this control
	 */
	public String getBasePath() {
		return basePath;
	}

	/**
	 * Returns the base URL of the rich text control whose content was last
	 * copied to the clipboard.
	 * 
	 * @return the base URL of a rich text control
	 */
	public URL getCopyURL() {
		return copyURL;
	}

	/**
	 * Sets the base URL of the rich text control whose content was last copied
	 * to the clipboard.
	 */
	public void setCopyURL() {
		try {
			copyURL = new File(basePath).toURL();
		} catch (Exception e) {
			copyURL = null;
		}
	}

	/**
	 * Returns the editable state.
	 * 
	 * @return <code>true</code> if the content is editable
	 */
	public boolean getEditable() {
		return editable;
	}

	/**
	 * Sets the editable state.
	 * 
	 * @param editable
	 *            the editable state
	 */
	public void setEditable(boolean editable) {
		this.editable = editable;
		if (initialized) {
			executeCommand(RichTextCommand.SET_EDITABLE, "" + editable); //$NON-NLS-1$
		}
	}

	/**
	 * Checks whether the content has been modified.
	 * 
	 * @return <code>true</code> if the content has been modified
	 */
	public boolean getModified() {
		return modified;
	}

	/**
	 * Sets the modified state.
	 * 
	 * @param modified
	 *            the modified state
	 */
	public void setModified(boolean modified) {
		this.modified = modified;
	}

	/**
	 * Returns the rich text content.
	 * 
	 * @return the rich text content formatted in a markup language
	 */
	public String getText() {
		if (editor != null && initialized) {
			try {
				executeCommand(RichTextCommand.GET_TEXT);
				if (currentText != null && currentText.length() > 0) {
					currentText = currentText.replaceAll(
							"<P>&nbsp;</P>", "<br/>"); //$NON-NLS-1$ //$NON-NLS-2$			
					currentText = tidyText(currentText);
					currentText = formatHTML(currentText);
				} else {
					currentText = ""; //$NON-NLS-1$
				}
				if (debug) {
					printDebugMessage("getText", "text=", currentText); //$NON-NLS-1$ //$NON-NLS-2$
				}
				return currentText;
			} catch (Exception e) {
				logger.logError(e);
			}
		}
		return ""; //$NON-NLS-1$
	}

	protected String formatHTML(String text) {
		String formattedText;
		try {
			// Call JTidy to format the source to XHTML.
			formattedText = htmlFormatter.formatHTML(text);
			if (htmlFormatter.getLastErrorStr() != null) {
				logger.logError(htmlFormatter.getLastErrorStr());
			}
			return formattedText;
		} catch (UnsupportedEncodingException e) {
			logger.logError(e);
		}
		return text;
	}

	/**
	 * Sets the rich text content.
	 * 
	 * @param text
	 *            the rich text content formatted in a markup language
	 */
	public void setText(String text) {
		if (editor != null) {
			if (debug) {
				printDebugMessage("setText", "text=", text); //$NON-NLS-1$ //$NON-NLS-2$
			}

			String newText = text;
			if (newText != null) {
				newText = tidyText(newText);
				// Call JTidy to format the source to XHTML.
				newText = formatHTML(newText);
			} else {
				newText = ""; //$NON-NLS-1$
			}

			if (initialized) {
				modified = !newText.equals(currentText);
			}
			initialText = newText;
			if (initialText.equals("") && !isIE) { //$NON-NLS-1$
				initialText = "<br />"; //$NON-NLS-1$
			}

			if (debug) {
				printDebugMessage(
						"setText", "modified=" + modified + ", newText=", newText); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}

			if (initialized) {
				try {
					executeCommand(RichTextCommand.SET_TEXT, newText);
					executeCommand(RichTextCommand.SET_EDITABLE, "" + editable); //$NON-NLS-1$				
				} catch (Exception e) {
					logger.logError(e);
				}
			}

			currentText = newText;
		}
	}

	/**
	 * Restores the rich text content back to the initial value.
	 */
	public void restoreText() {
		setText(initialText);
		modified = false;
	}

	/**
	 * Returns the currently selected text.
	 * 
	 * @return the selected text or <code>""</code> if there is no
	 *         hasSelection
	 */
	public String getSelectedText() {
		// executeCommand(RichTextCommand.GET_SELECTED_TEXT);
		return richTextSelection.getText();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.richtext.IRichText#getSelected()
	 */
	public RichTextSelection getSelected() {
		return richTextSelection;
	}

	/**
	 * Returns an application specific property value.
	 * 
	 * @param key
	 *            the name of the property
	 * @return the value of the property or <code>null</code> if it has not
	 *         been set
	 */
	public Object getData(String key) {
		if (editor != null) {
			editor.getData(key);
		}
		return null;
	}

	/**
	 * Sets an application specific property name and value.
	 * 
	 * @param key
	 *            the name of the property
	 * @param value
	 *            the property value
	 */
	public void setData(String key, Object value) {
		if (editor != null) {
			editor.setData(key, value);
		}
	}

	/**
	 * Executes the given JavaScript.
	 * 
	 * @param script
	 *            the JavaScript to execute
	 * @return a status code returned by the executed script
	 */
	protected int execute(final String script) {
		status = 0;
		if (editor != null && script != null && script.length() > 0) {
			try {
				if (!isIE && processingJSEvent) {
					Display.getCurrent().asyncExec(new Runnable() {
						public void run() {
							if (!isDisposed()) {
								editor.execute(script);
							}
						}
					});
				} else {
					editor.execute(script);
				}
				if (debug) {
					printDebugMessage("execute", script); //$NON-NLS-1$				
				}
			} catch (Exception e) {
				String msg = "Failed to execute " + script; //$NON-NLS-1$
				logger.logError(msg, e);
				if (debug) {
					printDebugMessage("execute", msg); //$NON-NLS-1$
					e.printStackTrace();
				}
			}
		}
		return status;
	}

	/**
	 * Executes the given rich text command. The supported command strings are
	 * defined in <code>RichTextCommand<code>.
	 * 
	 * @param	command		a rich text command string.
	 * @return	a status code returned by the executed command
	 */
	public int executeCommand(String command) {
		status = 0;
		if (command != null && command.equals(RichTextCommand.CLEAR_CONTENT)) {
			String oldInitialText = initialText;
			setText(""); //$NON-NLS-1$
			initialText = oldInitialText;
			status = 1;
			modified = true;
			notifyModifyListeners();
		} else {
			status = execute(command + "();"); //$NON-NLS-1$
		}
		return status;
	}

	/**
	 * Executes the given rich text command with a single parameter. The
	 * supported command strings are defined in <code>RichTextCommand<code>.
	 * 
	 * @param	command		a rich text command string
	 * @param	param		a parameter for the command or <code>null</code>
	 * @return	a status code returned by the executed command
	 */
	public int executeCommand(String command, String param) {
		if (param == null) {
			return executeCommand(command);
		}
		return execute(command + "('" + formatText(param) + "');"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Executes the given rich text command with an array of parameters. The
	 * supported command strings are defined in <code>RichTextCommand<code>.
	 * 
	 * @param	command		a rich text command string
	 * @param	params		an array of parameters for the command or <code>null</code>
	 * @return	a status code returned by the executed command
	 */
	public int executeCommand(String command, String[] params) {
		if (params == null || params.length == 0) {
			return executeCommand(command);
		}
		StringBuffer sb = new StringBuffer();
		int paramsLength = params.length;
		for (int i = 0; i < paramsLength; i++) {
			sb.append('\'').append(formatText(params[i])).append('\'');
			if (i < paramsLength - 1) {
				sb.append(',');
			}
		}
		String param = sb.toString();
		return execute(command + "(" + param + ");"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Disposes the operating system resources allocated by the control.
	 */
	public void dispose() {
		if (contextMenu != null && !contextMenu.isDisposed()) {
			contextMenu.dispose();
			contextMenu = null;
		}
		if (listeners != null) {
			listeners.clear();
			listeners = null;
		}
		if (modifyListeners != null) {
			modifyListeners.clear();
			modifyListeners = null;
		}
		if (htmlFormatter != null) {
			htmlFormatter = null;
		}
		if (this.findReplaceAction != null) {
			this.findReplaceAction.dispose();
			this.findReplaceAction = null;
		}
	}

	/**
	 * Checks whether this control has been disposed.
	 * 
	 * @return <code>true</code> if this control is disposed successfully
	 */
	public boolean isDisposed() {
		return editor.isDisposed();
	}

	/**
	 * Returns the modify listeners attached to this control.
	 * 
	 * @return an iterator for retrieving the modify listeners
	 */
	public Iterator<ModifyListener> getModifyListeners() {
		return modifyListeners.iterator();
	}

	/**
	 * Adds a listener to the collection of listeners who will be notified when
	 * keys are pressed and released within this control.
	 * 
	 * @param listener
	 *            the listener which should be notified
	 */
	public void addKeyListener(KeyListener listener) {
		if (editor != null) {
			editor.addKeyListener(listener);
		}
	}

	/**
	 * Removes a listener from the collection of listeners who will be notified
	 * when keys are pressed and released within this control.
	 * 
	 * @param listener
	 *            the listener which should no longer be notified
	 */
	public void removeKeyListener(KeyListener listener) {
		if (editor != null) {
			editor.removeKeyListener(listener);
		}
	}

	/**
	 * Adds a listener to the collection of listeners who will be notified when
	 * the content of this control is modified.
	 * 
	 * @param listener
	 *            the listener which should be notified
	 */
	public void addModifyListener(ModifyListener listener) {
		if (editor != null && listener != null
				&& !modifyListeners.contains(listener)) {
			modifyListeners.add(listener);
		}
	}

	/**
	 * Removes a listener from the collection of listeners who will be notified
	 * when the content of this control is modified.
	 * 
	 * @param listener
	 *            the listener which should no longer be notified
	 */
	public void removeModifyListener(ModifyListener listener) {
		if (editor != null && listener != null
				&& modifyListeners.contains(listener)) {
			modifyListeners.remove(listener);
		}
	}

	/**
	 * Adds the listener to the collection of listeners who will be notifed when
	 * this control is disposed.
	 * 
	 * @param listener
	 *            the listener which should be notified
	 */
	public void addDisposeListener(DisposeListener listener) {
		if (editor != null) {
			editor.addDisposeListener(listener);
		}
	}

	/**
	 * Removes a listener from the collection of listeners who will be notified
	 * when this control is disposed.
	 * 
	 * @param listener
	 *            the listener which should no longer be notified
	 */
	public void removeDisposeListener(DisposeListener listener) {
		if (editor != null) {
			editor.removeDisposeListener(listener);
		}
	}

	/**
	 * Adds a listener to the collection of listeners who will be notified when
	 * help events are generated for this control.
	 * 
	 * @param listener
	 *            the listener which should be notified
	 */
	public void addHelpListener(HelpListener listener) {
		if (editor != null) {
			editor.addHelpListener(listener);
		}
	}

	/**
	 * Removes a listener from the collection of listeners who will be notified
	 * when help events are generated for this control.
	 * 
	 * @param listener
	 *            the listener which should no longer be notified
	 */
	public void removeHelpListener(HelpListener listener) {
		if (editor != null) {
			editor.removeHelpListener(listener);
		}
	}

	/**
	 * Adds the listener to the collection of listeners who will be notifed when
	 * an event of the given type occurs within this control.
	 * 
	 * @param eventType
	 *            the type of event to listen for
	 * @param listener
	 *            the listener which should be notified when the event occurs
	 */
	public void addListener(int eventType, Listener listener) {
		if (editor != null && !listeners.containsKey(listener)) {
			if (eventType != SWT.SELECTED) {
				if (editorControl == null
						|| (eventType != SWT.Activate
								&& eventType != SWT.Deactivate
								&& eventType != SWT.FocusIn && eventType != SWT.FocusOut)) {
					editor.addListener(eventType, listener);
				}
			}
			listeners.put(listener, new RichTextListener(eventType, listener));
		}
	}

	/**
	 * Removes the listener from the collection of listeners who will be notifed
	 * when an event of the given type occurs within this control.
	 * 
	 * @param eventType
	 *            the type of event to listen for
	 * @param listener
	 *            the listener which should no longer be notified when the event
	 *            occurs
	 */
	public void removeListener(int eventType, Listener listener) {
		if (editor != null && listeners.containsKey(listener)) {
			if (editorControl == null
					|| (eventType != SWT.Activate
							&& eventType != SWT.Deactivate
							&& eventType != SWT.FocusIn && eventType != SWT.FocusOut)) {
				editor.removeListener(eventType, listener);
			}
			listeners.remove(listener);
		}
	}

	/**
	 * Returns the event listeners attached to this control.
	 * 
	 * @return an iterator for retrieving the event listeners attached to this
	 *         control
	 */
	public Iterator<RichTextListener> getListeners() {
		return listeners.values().iterator();
	}

	/**
	 * Adds the listener to monitor events and status sent by the underlying
	 * DHTML editor.
	 */
	protected void addStatusTextListener() {
		editor.addStatusTextListener(new StatusTextListener() {
			public void changed(StatusTextEvent event) {
				String eventText = event.text;
				int eventTextLength = eventText.length();
				if (eventText.startsWith(STATUS_PREFIX)
						&& eventTextLength > STATUS_PREFIX_LENGTH) {
					try {
						processingJSEvent = true;
						int endStatusIndex = STATUS_PREFIX_LENGTH + 1;
						if (eventText.length() > STATUS_PREFIX_LENGTH + 1
								&& Character.isDigit(eventText
										.charAt(endStatusIndex))) {
							endStatusIndex++;
						}
						int statusType = Integer.parseInt(eventText.substring(
								STATUS_PREFIX_LENGTH, endStatusIndex));
						switch (statusType) {
						case STATUS_NOP:
							break;
						case STATUS_INITIALIZED:
							if (!initialized) {
								initialized = true;
								if (debug) {
									printDebugMessage(
											"statusTextListener", "STATUS_INITIALIZED"); //$NON-NLS-1$ //$NON-NLS-2$
								}
								if (!Platform.getOS().equals("win32")) { //$NON-NLS-1$
									// Workaround Mozilla'a IFRAME
									// height issue.
									executeCommand(RichTextCommand.SET_HEIGHT,
											"" + editor.getBounds().height); //$NON-NLS-1$
								}
								executeCommand(RichTextCommand.SET_TEXT,
										currentText);
								if (initializedWithFocus) {
									setFocus();
								}
								if (!editable) {
									executeCommand(
											RichTextCommand.SET_EDITABLE,
											"" + editable); //$NON-NLS-1$
								}
							}
							break;
						case STATUS_MODIFIED:
							if (debug) {
								printDebugMessage(
										"statusTextListener", "STATUS_MODIFIED"); //$NON-NLS-1$ //$NON-NLS-2$
							}
							checkModify();
							break;
						case STATUS_GET_TEXT:
							if (eventTextLength >= STATUS_PREFIX_LENGTH + 2) {
								currentText = eventText
										.substring(STATUS_PREFIX_LENGTH + 2);
							} else {
								currentText = ""; //$NON-NLS-1$
							}
							if (debug) {
								printDebugMessage(
										"statusTextListener", //$NON-NLS-1$
										"STATUS_GET_TEXT, currentText=", currentText); //$NON-NLS-1$
							}
							break;
						case STATUS_KEY_DOWN:
							if (eventTextLength >= STATUS_PREFIX_LENGTH + 2) {
								String cmd = eventText
										.substring(STATUS_PREFIX_LENGTH + 2);
								if (debug) {
									printDebugMessage("statusTextListener", //$NON-NLS-1$
											"STATUS_KEY_DOWN, cmd=" + cmd); //$NON-NLS-1$
								}
								if (cmd.equals(RichTextCommand.COPY)) {
									setCopyURL();
								} else if (cmd.equals(RichTextCommand.CUT)) {
									setCopyURL();
									CutAction action = new CutAction(
											RichText.this);
									action.execute(RichText.this);
								} else if (cmd
										.equals(RichTextCommand.FIND_TEXT)) {
									getFindReplaceAction().execute(
											RichText.this);
								} else if (cmd.equals(RichTextCommand.PASTE)) {
									PasteAction action = new PasteAction(
											RichText.this);
									action.execute(RichText.this);
								} else if (cmd.equals(RichTextCommand.SAVE)) {
									PlatformUI.getWorkbench()
											.getActiveWorkbenchWindow()
											.getActivePage().getActiveEditor()
											.doSave(null);
								} else if (cmd.equals(RichTextCommand.SAVE_ALL)) {
									PlatformUI.getWorkbench()
											.getActiveWorkbenchWindow()
											.getActivePage().saveAllEditors(
													false);
								}
							}
							break;
						case STATUS_KEY_UP:
							if (debug) {
								printDebugMessage("statusTextListener", //$NON-NLS-1$
										"STATUS_KEY_UP, modified=" + modified); //$NON-NLS-1$
							}
							checkModify();
							break;
						case STATUS_SELECT_TEXT:
							if (eventTextLength >= STATUS_PREFIX_LENGTH + 2) {
								String[] strings = eventText.substring(
										STATUS_PREFIX_LENGTH + 2).split(
										"\\$", 5); //$NON-NLS-1$
								try {
									richTextSelection.setFontName(strings[0]);
									richTextSelection.setFontSize(strings[1]);
									richTextSelection.setBlockStyle(strings[2]);
									richTextSelection.setFlags(Integer
											.parseInt(strings[3]));
									richTextSelection.setText(strings[4]);
								} catch (NumberFormatException e) {
									logger.logError(e);
								}
								if (debug) {
									printDebugMessage(
											"selectionStatusListener", //$NON-NLS-1$
											"current selection is=" + richTextSelection); //$NON-NLS-1$
								}

								hasSelection = true;
								if (hasFocus())
									notifyListeners(SWT.SELECTED, new Event());
							} else {
								richTextSelection.setText(""); //$NON-NLS-1$
								hasSelection = false;
							}
							if (debug) {
								printDebugMessage(
										"statusTextListener", //$NON-NLS-1$
										"STATUS_SELECT_TEXT, selectedText=", richTextSelection.getText()); //$NON-NLS-1$
							}
							break;
						case STATUS_SELECT_CONTROL:
							if (debug) {
								printDebugMessage("statusTextListener", //$NON-NLS-1$
										"STATUS_SELECT_CONTROL, control selected"); //$NON-NLS-1$
							}
							hasSelection = true;
							break;
						case STATUS_SELECT_NONE:
							if (debug) {
								printDebugMessage("statusTextListener", //$NON-NLS-1$
										"STATUS_SELECT_NONE, no selection"); //$NON-NLS-1$
							}
							hasSelection = false;
							break;
						case STATUS_EXEC_CMD:
							if (eventTextLength >= STATUS_PREFIX_LENGTH + 3) {
								try {
									status = Integer.parseInt(eventText
											.substring(
													STATUS_PREFIX_LENGTH + 2,
													STATUS_PREFIX_LENGTH + 3));
								} catch (Exception e) {
									status = -1;
								}
							}
							if (debug && status != 1) {
								printDebugMessage("statusTextListener", //$NON-NLS-1$
										"STATUS_EXEC_CMD, status=" + status); //$NON-NLS-1$
							}
							break;
						case STATUS_REFORMAT_LINKS:
							if (debug) {
								printDebugMessage(
										"statusTextListener", "STATUS_REFORMAT_LINKS"); //$NON-NLS-1$ //$NON-NLS-2$
							}
							if (Platform.getOS().equals("win32")) { //$NON-NLS-1$ 
								// Workaround the drag and drop issue with DBCS
								// characters.
								if (modified) {
									setText(getText());
									modified = true;
								}
							}
							checkModify();
							break;
						}
					} catch (Exception e) {
					} finally {
						processingJSEvent = false;
					}
				}
			}
		});
	}

	/**
	 * Generates the HTML source for the editor.
	 * 
	 * @return the HTML source for the editor
	 */
	protected String generateEditorHTML() throws Exception {
		String escapedBasePath = basePath;
		if (escapedBasePath.startsWith(FileUtil.UNC_PATH_PREFIX))
			escapedBasePath = escapedBasePath.replaceFirst(
					"^\\\\\\\\", "\\\\\\\\\\\\\\\\"); //$NON-NLS-1$ //$NON-NLS-2$
		escapedBasePath = XMLUtil
				.escape("file://" + escapedBasePath.replaceAll("'", "\\\\'")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		String escapedRteUTL = rteURL.replaceAll("&apos;", "%27"); //$NON-NLS-1$ //$NON-NLS-2$

		StringBuffer rteXML = new StringBuffer();
		rteXML.append("<rte id=\"").append("rte") //$NON-NLS-1$ //$NON-NLS-2$
				.append("\" css=\"").append(escapedRteUTL + "rte.css") //$NON-NLS-1$ //$NON-NLS-2$
				.append("\" js=\"").append(escapedRteUTL + "rte.js") //$NON-NLS-1$ //$NON-NLS-2$
				.append("\" baseURL=\"").append(escapedBasePath) //$NON-NLS-1$
				.append("\"/>"); //$NON-NLS-1$
		StringWriter result = new StringWriter();
		XSLTProcessor.transform(
				rteFolder + "rte.xsl", rteXML.toString(), result); //$NON-NLS-1$
		return result.toString();
	}

	/**
	 * Fills the context menu with menu items.
	 * 
	 * @param contextMenu
	 *            a context menu containing rich text actions
	 */
	protected void fillContextMenu(Menu contextMenu) {
		final MenuItem cutItem = new MenuItem(contextMenu, SWT.PUSH);
		cutItem.setText(RichTextResources.cutAction_text);
		cutItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				CutAction action = new CutAction(RichText.this);
				action.execute(RichText.this);
			}
		});
		final MenuItem copyItem = new MenuItem(contextMenu, SWT.PUSH);
		copyItem.setText(RichTextResources.copyAction_text);
		copyItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				CopyAction action = new CopyAction(RichText.this);
				action.execute(RichText.this);
			}
		});
		final MenuItem pasteItem = new MenuItem(contextMenu, SWT.PUSH);
		pasteItem.setText(RichTextResources.pasteAction_text);
		pasteItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				PasteAction action = new PasteAction(RichText.this);
				action.execute(RichText.this);
			}
		});

		final MenuItem pastePlainTextItem = new MenuItem(contextMenu, SWT.PUSH);
		pastePlainTextItem.setText(RichTextResources.pastePlainTextAction_text);
		pastePlainTextItem.setImage(RichTextImages.IMG_PASTE_PLAIN_TEXT);
		pastePlainTextItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				PastePlainTextAction action = new PastePlainTextAction(
						RichText.this);
				action.execute(RichText.this);
			}
		});

		contextMenu.addMenuListener(new MenuListener() {
			public void menuHidden(MenuEvent e) {
			}

			public void menuShown(MenuEvent e) {
				getSelectedText();
				cutItem.setEnabled(editable && hasSelection);
				copyItem.setEnabled(hasSelection);
				pasteItem.setEnabled(editable);
				pastePlainTextItem.setEnabled(editable);
			}
		});
	}

	/**
	 * Adds listeners to manage the activation and focus events.
	 */
	protected void addListeners() {
		editorControl = getControlSite(editor);
		if (editorControl != null) {
			if (debug) {
				printDebugMessage(
						"init", "editorControl=" + editorControl.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
			}
			
			// only IE (win32) has the editorControl != null
			isIE = true;
			
			editorControl.addListener(SWT.Activate, new Listener() {
				public void handleEvent(Event event) {
					if (debug) {
						printDebugMessage("activateListener"); //$NON-NLS-1$
					}
					setFocus();
					notifyListeners(SWT.Activate, event);
				}
			});

			editorControl.addListener(SWT.Deactivate, new Listener() {
				public void handleEvent(Event event) {
					if (debug) {
						printDebugMessage("deactivateListener"); //$NON-NLS-1$
					}
					setBlur();
					notifyListeners(SWT.Deactivate, event);
				}
			});

			editorControl.addListener(SWT.FocusIn, new Listener() {
				public void handleEvent(Event event) {
					if (debug) {
						printDebugMessage("focusInListener"); //$NON-NLS-1$
					}
					executeCommand("updateSelection"); //$NON-NLS-1$					
					notifyListeners(SWT.FocusIn, event);
				}
			});

			editorControl.addListener(SWT.KeyUp, new Listener() {
				public void handleEvent(Event event) {
					int keyCode = event.keyCode;
					int stateMask = event.stateMask;
					if (debug) {
						printDebugMessage(
								"keyUpListener", "keyCode=" + keyCode //$NON-NLS-1$ //$NON-NLS-2$
										+ ", stateMask=" + stateMask + ", editable=" + editable); //$NON-NLS-1$ //$NON-NLS-2$
					}
					if ((stateMask & SWT.CTRL) > 0
							|| (stateMask & SWT.ALT) > 0
							|| ((stateMask & SWT.SHIFT) > 0 && keyCode == stateMask)) {
						return;
					}
					if (editable) {
						switch (event.keyCode) {
						case SWT.ARROW_DOWN:
						case SWT.ARROW_LEFT:
						case SWT.ARROW_RIGHT:
						case SWT.ARROW_UP:
						case SWT.END:
						case SWT.HOME:
						case SWT.PAGE_DOWN:
						case SWT.PAGE_UP:
						case SWT.TAB:
							return;
						default:
							checkModify();
							break;
						}
					}
				}
			});

			editor.addLocationListener(new LocationAdapter() {
				public void changing(LocationEvent event) {
					// Deactivate the links in the content page in readonly
					// mode.
					event.doit = editable;
				}
			});
		} else {
			editor.addListener(SWT.Activate, new Listener() {
				public void handleEvent(Event event) {
					if (debug) {
						printDebugMessage("activateListener"); //$NON-NLS-1$
					}
					setFocus();
				}
			});

			editor.addKeyListener(new KeyListener() {
				public void keyPressed(KeyEvent e) {
					if (e.keyCode == SWT.TAB) {
						if ((e.stateMask & SWT.SHIFT) != 0) {
							editor.traverse(SWT.TRAVERSE_TAB_PREVIOUS);
						} else {
							editor.traverse(SWT.TRAVERSE_TAB_NEXT);
						}
						return;
					}
					if (!editable) {
						e.doit = false;
					}
				}

				public void keyReleased(KeyEvent e) {
					if ((e.stateMask & SWT.CTRL) > 0
							|| (e.stateMask & SWT.ALT) > 0)
						return;
					if (editable) {
						switch (e.keyCode) {
						case SWT.ARROW_DOWN:
						case SWT.ARROW_LEFT:
						case SWT.ARROW_RIGHT:
						case SWT.ARROW_UP:
						case SWT.END:
						case SWT.HOME:
						case SWT.PAGE_DOWN:
						case SWT.PAGE_UP:
						case SWT.SHIFT:
						case SWT.TAB:
							break;
						default:
							checkModify();
							break;
						}
					}
				}
			});
		}

		editor.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				if (debug) {
					printDebugMessage("disposeListener"); //$NON-NLS-1$						
				}
				dispose();
			}
		});

		listeners = new Hashtable<Listener, RichTextListener>();
		modifyListeners = new ArrayList<ModifyListener>();
	}

	/**
	 * Notifies the rich text event listeners.
	 * 
	 * @param eventType
	 *            the event type
	 * @param event
	 *            the SWT event
	 */
	protected void notifyListeners(int eventType, Event event) {
		if (notifyingModifyListeners) {
			return;
		}

		if (listeners != null) {
			event.display = Display.getCurrent();
			event.widget = editor;

			for (Iterator<RichTextListener> i = listeners.values().iterator(); i
					.hasNext();) {
				RichTextListener listener = i.next();
				if (listener.getEventType() == eventType) {
					if (debug) {
						printDebugMessage(
								"notifyListeners", "notifying listener, " + listener + ", eventType=" + eventType); //$NON-NLS-1$ //$NON-NLS-2$	//$NON-NLS-3$	
					}
					listener.getListener().handleEvent(event);
					if (debug) {
						printDebugMessage(
								"notifyListeners", "notified listener, " + listener + ", eventType=" + eventType); //$NON-NLS-1$ //$NON-NLS-2$	//$NON-NLS-3$	
					}
				}
			}
		}
	}

	/**
	 * Notifies the modify listeners that the rich text editor content has
	 * changed.
	 */
	public void notifyModifyListeners() {
		notifyingModifyListeners = true;

		Event event = new Event();
		event.display = Display.getCurrent();
		event.widget = editor;

		for (Iterator<ModifyListener> i = modifyListeners.iterator(); i
				.hasNext();) {
			ModifyListener listener = i.next();
			if (debug) {
				printDebugMessage(
						"notifyModifyListeners", "notifying listener, " + listener); //$NON-NLS-1$ //$NON-NLS-2$	
			}
			listener.modifyText(new ModifyEvent(event));
			if (debug) {
				printDebugMessage(
						"notifyModifyListeners", "notified listener, " + listener); //$NON-NLS-1$ //$NON-NLS-2$	
			}
		}

		notifyingModifyListeners = false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.richtext.IRichText#checkModify()
	 */
	public void checkModify() {
		try {
			if (!checkingModifyEvent) {
				checkingModifyEvent = true;
				if (modified) {
					notifyModifyListeners();
				} else {
					if (!isIE && processingJSEvent) {
						Display.getCurrent().asyncExec(new Runnable() {
							public void run() {
								if (!getText().equals(initialText)) {
									modified = true;
									notifyModifyListeners();
								}
							}
						});
					} else {
						if (!getText().equals(initialText)) {
							modified = true;
							notifyModifyListeners();
						}
					}
				}
				if (debug) {
					printDebugMessage("checkModify", "modified=" + modified); //$NON-NLS-1$ //$NON-NLS-2$	
				}
			}
		} finally {
			checkingModifyEvent = false;
		}
	}

	/**
	 * This provides an opportunity for a sub class to tidy up the rich text.
	 * 
	 * @param text
	 *            rich text encoded in HTML format
	 */
	protected String tidyText(String text) {
		return text;
	}

	/**
	 * Formats the text for consumption by the JavaScript/DHTML editor.
	 * 
	 * @param text
	 *            rich text encoded in HTML format
	 */
	protected String formatText(String text) {
		if (text == null || text.length() == 0) {
			return text;
		}
		StringBuffer result = new StringBuffer();
		int textSize = text.length();
		for (int i = 0; i < textSize; i++) {
			char ch = text.charAt(i);
			switch (ch) {
			case '\r':
				break;
			case '\t':
				result.append(' ');
				break;
			case '\n':
				result.append(ENCODED_NEWLINE);
				break;
			case '\'':
				result.append(ENCODED_SINGLE_QUOTE);
				break;
			case '\\':
				result.append("\\\\"); //$NON-NLS-1$
				break;
			default:
				result.append(ch);
			}
		}
		return result.toString();
	}

	/**
	 * Returns the child <code>OleControlSite</code> contained within the
	 * given <code>Composite</code>.
	 * 
	 * @param composite
	 *            a <code>Composite</code> object, presumably a
	 *            <code>Browser</code>
	 * @return an <code>OleControlSite</code> object
	 */
	protected Control getControlSite(Composite composite) {
		if (Platform.getOS().equals("win32")) { //$NON-NLS-1$
			Control[] controls = composite.getChildren();
			for (int i = 0; i < controls.length; i++) {
				String controlClass = controls[i].getClass().getName();
				if (controlClass.equals("org.eclipse.swt.browser.WebSite")) { //$NON-NLS-1$
					return controls[i];
				} else if (controls[i] instanceof Composite) {
					return getControlSite((Composite) controls[i]);
				}
			}
		}
		return null;
	}

	/**
	 * Displays the given debug message to the console.
	 */
	protected void printDebugMessage(String method, String msg, String text) {
		StringBuffer strBuf = new StringBuffer();
		strBuf.append("RichText[").append(editor.handle).append(']') //$NON-NLS-1$
				.append('.').append(method);
		if (msg != null && msg.length() > 0) {
			strBuf.append(": ").append(msg); //$NON-NLS-1$
		}
		if (text != null && text.length() > 0) {
			strBuf.append('\n').append(text);
		}
		System.out.println(strBuf);
	}

	/**
	 * Displays the given debug message to the console.
	 */
	protected void printDebugMessage(String method, String msg) {
		printDebugMessage(method, msg, null);
	}

	/**
	 * Displays the given debug message to the console.
	 */
	protected void printDebugMessage(String method) {
		printDebugMessage(method, null);
	}

	public FindReplaceAction getFindReplaceAction() {
		return findReplaceAction;
	}

	public void setFindReplaceAction(FindReplaceAction findReplaceAction) {
		if (findReplaceAction != null) {
			if (this.findReplaceAction != null
					&& this.findReplaceAction != findReplaceAction) {
				this.findReplaceAction.dispose();
			}
			this.findReplaceAction = findReplaceAction;
			this.findReplaceAction.setRichText(this);
		}
	}

	public void setInitialText(String text) {
		setText(text);
		initialText = text == null ? "" : text; //$NON-NLS-1$
		modified = false;
	}

}