//------------------------------------------------------------------------------
// 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.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$

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

	private static final int STATUS_PREFIX_LENGTH = STATUS_PREFIX.length();
	
	private static final int STATUS_NOP = 0;

	private static final int STATUS_INITIALIZED = 1;

	private static final int STATUS_MODIFIED = 2;

	private static final int STATUS_GET_TEXT = 3;

	private static final int STATUS_KEY_DOWN = 4;

	private static final int STATUS_KEY_UP = 5;

	private static final int STATUS_SELECT_TEXT = 6;

	private static final int STATUS_SELECT_CONTROL = 7;

	private static final int STATUS_SELECT_NONE = 8;

	private static final int STATUS_EXEC_CMD = 9;

	// 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.
	private Menu contextMenu;

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

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

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

	// The DHTML initialization flag.
	private boolean initialized;

	// The initial focus.
	private 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.
	private String initialText;

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

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

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

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

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

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

	// The HTML source formatter.
	private HTMLFormatter htmlFormatter;

	// The SWT event listeners.
	private Map listeners;

	// The modify listeners.
	private List modifyListeners;

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

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

	// The control's find/replace text action
	private FindReplaceAction findReplaceAction;

	/**
	 * 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();
		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 (!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 ediatble
	 */
	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$			
					try {
						// Call JTidy to format the source to XHTML.
						currentText = htmlFormatter.formatHTML(currentText);
					} catch (Exception e) {
						logger.logError(e);
					}
					currentText = tidyText(currentText);
					try {
						// Call JTidy to reformat the source again just in case
						// tidyText() destroys the formatting.
						currentText = htmlFormatter.formatHTML(currentText);
					} catch (Exception e) {
					}
				} 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$
	}

	/**
	 * 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.length() > 0) {
				try {
					// Call JTidy to format the source to XHTML.
					newText = htmlFormatter.formatHTML(newText);
				} catch (Exception e) {
					logger.logError(e);
				}
				newText = tidyText(newText);
				try {
					// Call JTidy to reformat the source again just in case
					// tidyText() destroys the formatting.
					newText = htmlFormatter.formatHTML(newText);
				} catch (Exception e) {
				}
			} else {
				newText = ""; //$NON-NLS-1$
			}

			if (initialized) {
				modified = !newText.equals(currentText);
			}
			initialText = newText;

			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);
	}

	/**
	 * 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(String script) {
		status = 0;
		if (editor != null && script != null && script.length() > 0) {
			try {
				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 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 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 {
						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();
									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();
									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.setOffsetStart(Integer.parseInt(strings[0]));

									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;
						}
					} catch (Exception e) {
					}
				}
			}
		});
	}

	/**
	 * 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();
				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();
				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();
				action.execute(RichText.this);
			}
		});

		final MenuItem pastePlainTextItem = new MenuItem(contextMenu, SWT.PUSH);
		pastePlainTextItem.setText(RichTextResources.pastePlainTextAction_text);
		pastePlainTextItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				PastePlainTextAction action = new PastePlainTextAction();
				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$
			}

			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();
		modifyListeners = new ArrayList();
	}

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

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

		for (Iterator i = listeners.values().iterator(); i.hasNext();) {
			RichTextListener listener = (RichTextListener) 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 i = modifyListeners.iterator(); i.hasNext();) {
			ModifyListener listener = (ModifyListener) 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() {
		if (modified) {
			notifyModifyListeners();
		} else {
			if (!getText().equals(initialText)) {
				modified = true;
				notifyModifyListeners();
			}
		}
		if (debug) {
			printDebugMessage("checkModify", "modified=" + modified); //$NON-NLS-1$ //$NON-NLS-2$	
		}
	}

	/**
	 * 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
	 */
	private 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.
	 */
	private 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.
	 */
	private void printDebugMessage(String method, String msg) {
		printDebugMessage(method, msg, null);
	}

	/**
	 * Displays the given debug message to the console.
	 */
	private 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);
		}
	}

}