/*******************************************************************************
 * Copyright (c) 2000, 2012 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.swt.widgets;


import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.win32.*;

/**
 * Instances of this class are selectable user interface
 * objects that allow the user to enter and modify text.
 * Text controls can be either single or multi-line.
 * When a text control is created with a border, the
 * operating system includes a platform specific inset
 * around the contents of the control.  When created
 * without a border, an effort is made to remove the
 * inset such that the preferred size of the control
 * is the same size as the contents.
 * <p>
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>CENTER, ICON_CANCEL, ICON_SEARCH, LEFT, MULTI, PASSWORD, SEARCH, SINGLE, RIGHT, READ_ONLY, WRAP</dd>
 * <dt><b>Events:</b></dt>
 * <dd>DefaultSelection, Modify, Verify, OrientationChange</dd>
 * </dl>
 * <p>
 * Note: Only one of the styles MULTI and SINGLE may be specified,
 * and only one of the styles LEFT, CENTER, and RIGHT may be specified.
 * </p>
 * <p>
 * Note: The styles ICON_CANCEL and ICON_SEARCH are hints used in combination with SEARCH.
 * When the platform supports the hint, the text control shows these icons.  When an icon
 * is selected, a default selection event is sent with the detail field set to one of
 * ICON_CANCEL or ICON_SEARCH.  Normally, application code does not need to check the
 * detail.  In the case of ICON_CANCEL, the text is cleared before the default selection
 * event is sent causing the application to search for an empty string.
 * </p>
 * <p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#text">Text snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * @noextend This class is not intended to be subclassed by clients.
 */
public class Text extends Scrollable {
	int tabs, oldStart, oldEnd;
	boolean doubleClick, ignoreModify, ignoreVerify, ignoreCharacter, allowPasswordChar;
	String message;
	int[] segments;
	int clearSegmentsCount = 0;

	static final char LTR_MARK = '\u200e';
	static final char RTL_MARK = '\u200f';

	/**
	* The maximum number of characters that can be entered
	* into a text widget.
	* <p>
	* Note that this value is platform dependent, based upon
	* the native widget implementation.
	* </p>
	*/
	public static final int LIMIT;
	
	/**
	* The delimiter used by multi-line text widgets.  When text
	* is queried and from the widget, it will be delimited using
	* this delimiter.
	*/
	public static final String DELIMITER;
	
	/*
	* This code is intentionally commented.
	*/
//	static final char PASSWORD;
	
	/*
	* These values can be different on different platforms.
	* Therefore they are not initialized in the declaration
	* to stop the compiler from inlining.
	*/
	static {
		LIMIT = OS.IsWinNT ? 0x7FFFFFFF : 0x7FFF;
		DELIMITER = "\r\n";
	}
	
	static final long /*int*/ EditProc;
	static final TCHAR EditClass = new TCHAR (0, "EDIT", true);
	static {
		WNDCLASS lpWndClass = new WNDCLASS ();
		OS.GetClassInfo (0, EditClass, lpWndClass);
		EditProc = lpWndClass.lpfnWndProc;
		/*
		* This code is intentionally commented.
		*/
//		long /*int*/ hwndText = OS.CreateWindowEx (0,
//			EditClass,
//			null,
//			OS.WS_OVERLAPPED | OS.ES_PASSWORD,
//			0, 0, 0, 0,
//			0,
//			0,
//			OS.GetModuleHandle (null),
//			null);
//		char echo = (char) OS.SendMessage (hwndText, OS.EM_GETPASSWORDCHAR, 0, 0);
//		OS.DestroyWindow (hwndText);
//		PASSWORD = echo != 0 ? echo : '*';
	}

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together 
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a composite control which will be the parent of the new instance (cannot be null)
 * @param style the style of control to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#SINGLE
 * @see SWT#MULTI
 * @see SWT#READ_ONLY
 * @see SWT#WRAP
 * @see SWT#LEFT
 * @see SWT#RIGHT
 * @see SWT#CENTER
 * @see SWT#PASSWORD
 * @see SWT#SEARCH
 * @see SWT#ICON_SEARCH
 * @see SWT#ICON_CANCEL
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Text (Composite parent, int style) {
	super (parent, checkStyle (style));
}

long /*int*/ callWindowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /*int*/ lParam) {
	if (handle == 0) return 0;
	boolean redraw = false;
	switch (msg) {
		case OS.WM_ERASEBKGND: {
			if (findImageControl () != null) return 0;
			break;
		}
		case OS.WM_HSCROLL:
		case OS.WM_VSCROLL: {
			redraw = findImageControl () != null && getDrawing () && OS.IsWindowVisible (handle);
			if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
			break;
		}
		case OS.WM_PAINT: {
			boolean doubleBuffer = findImageControl () != null;
			boolean drawMessage = false;
			if ((style & SWT.SINGLE) != 0 && message.length () > 0) {
				if ((!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) || (style & SWT.READ_ONLY) != 0) {
					drawMessage = hwnd != OS.GetFocus () && OS.GetWindowTextLength (handle) == 0;
				}
			}
			if (doubleBuffer || drawMessage) {
				long /*int*/ paintDC = 0;
				PAINTSTRUCT ps = new PAINTSTRUCT ();
				paintDC = OS.BeginPaint (handle, ps);
				int width = ps.right - ps.left;
				int height = ps.bottom - ps.top;
				if (width != 0 && height != 0) {
					long /*int*/ hDC = paintDC, hBitmap = 0, hOldBitmap = 0;
					POINT lpPoint1 = null, lpPoint2 = null;
					if (doubleBuffer) {
						hDC = OS.CreateCompatibleDC (paintDC);
						lpPoint1 = new POINT ();
						lpPoint2 = new POINT ();
						OS.SetWindowOrgEx (hDC, ps.left, ps.top, lpPoint1);
						OS.SetBrushOrgEx (hDC, ps.left, ps.top, lpPoint2);
						hBitmap = OS.CreateCompatibleBitmap (paintDC, width, height);
						hOldBitmap = OS.SelectObject (hDC, hBitmap);
						RECT rect = new RECT ();
						OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
						drawBackground (hDC, rect);
					}
					
					OS.CallWindowProc (EditProc, hwnd, OS.WM_PAINT, hDC, lParam);
					/*
					* Bug in XP. Windows does not draw the cue message on XP when
					* East Asian language pack is installed. The fix is to draw
					* the cue messages ourselves.
					* Note:  This bug is fixed on Vista.
					*/
					if (drawMessage) {
						RECT rect = new RECT();
						OS.GetClientRect(handle, rect);
						long /*int*/ margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
						rect.left += OS.LOWORD (margins);
						rect.right -= OS.HIWORD (margins);
						if ((style & SWT.BORDER) != 0) {
							rect.left++;
							rect.top++;
							rect.right--;
							rect.bottom--;
						}
						TCHAR buffer = new TCHAR (getCodePage (), message, false);
						int uFormat = OS.DT_EDITCONTROL;
						boolean rtl = (style & SWT.RIGHT_TO_LEFT) != 0;
						if (rtl) uFormat |= OS.DT_RTLREADING; 
						int alignment = style & (SWT.LEFT | SWT.CENTER | SWT.RIGHT);
						switch (alignment) {
							case SWT.LEFT: uFormat |= (rtl ? OS.DT_RIGHT : OS.DT_LEFT); break;
							case SWT.CENTER: uFormat |= OS.DT_CENTER;
							case SWT.RIGHT: uFormat |= (rtl ? OS.DT_LEFT : OS.DT_RIGHT); break;
						}
						long /*int*/ hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
						long /*int*/ hOldFont = OS.SelectObject (hDC, hFont);
						OS.SetTextColor (hDC, OS.GetSysColor (OS.COLOR_GRAYTEXT));
						OS.SetBkMode (hDC, OS.TRANSPARENT);
						OS.DrawText (hDC, buffer, buffer.length (), rect, uFormat);
						OS.SelectObject (hDC, hOldFont);
					}
					
					if (doubleBuffer) {
						OS.SetWindowOrgEx (hDC, lpPoint1.x, lpPoint1.y, null);
						OS.SetBrushOrgEx (hDC, lpPoint2.x, lpPoint2.y, null);
						OS.BitBlt (paintDC, ps.left, ps.top, width, height, hDC, 0, 0, OS.SRCCOPY);
						OS.SelectObject (hDC, hOldBitmap);
						OS.DeleteObject (hBitmap);
						OS.DeleteObject (hDC);
					}
				}
				OS.EndPaint (handle, ps);
				return 0;
			}
			break;
		}
	}
	long /*int*/ code = OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
	switch (msg) {
		case OS.WM_HSCROLL:
		case OS.WM_VSCROLL: {
			if (redraw) {
				OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
				OS.InvalidateRect (handle, null, true);
			}
			break;
		}
	}
	return code;
}

void createHandle () {
	super.createHandle ();
	OS.SendMessage (handle, OS.EM_LIMITTEXT, 0, 0);
	if ((style & SWT.READ_ONLY) != 0) {
		if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
			state |= THEME_BACKGROUND;
		}
	}
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the receiver's text is modified, by sending
 * it one of the messages defined in the <code>ModifyListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @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>
 *
 * @see ModifyListener
 * @see #removeModifyListener
 */
public void addModifyListener (ModifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Modify, typedListener);
}

/**
 * Adds a segment listener.
 * <p>
 * A <code>SegmentEvent</code> is sent whenever text content is being modified or
 * a segment listener is added or removed. You can 
 * customize the appearance of text by indicating certain characters to be inserted
 * at certain text offsets. This may be used for bidi purposes, e.g. when
 * adjacent segments of right-to-left text should not be reordered relative to
 * each other. 
 * E.g., multiple Java string literals in a right-to-left language
 * should generally remain in logical order to each other, that is, the
 * way they are stored.
 * </p>
 * <p>
 * <b>Warning</b>: This API is currently only implemented on Windows and GTK.
 * <code>SegmentEvent</code>s won't be sent on Cocoa.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @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>
 *
 * @see SegmentEvent
 * @see SegmentListener
 * @see #removeSegmentListener
 * 
 * @since 3.8
 */
public void addSegmentListener (SegmentListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	addListener (SWT.Segments, new TypedListener (listener));
	clearSegments (true);
	applySegments ();
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the control is selected by the user, by sending
 * it one of the messages defined in the <code>SelectionListener</code>
 * interface.
 * <p>
 * <code>widgetSelected</code> is not called for texts.
 * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text,
 * or when ENTER is pressed in a search text. If the receiver has the <code>SWT.SEARCH | SWT.ICON_CANCEL</code> style
 * and the user cancels the search, the event object detail field contains the value <code>SWT.ICON_CANCEL</code>.
 * Likewise, if the receiver has the <code>SWT.ICON_SEARCH</code> style and the icon search is selected, the 
 * event object detail field contains the value <code>SWT.ICON_SEARCH</code>.
 * </p>
 *
 * @param listener the listener which should be notified when the control is selected by the user
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @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>
 *
 * @see SelectionListener
 * @see #removeSelectionListener
 * @see SelectionEvent
 */
public void addSelectionListener (SelectionListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Selection,typedListener);
	addListener (SWT.DefaultSelection,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the receiver's text is verified, by sending
 * it one of the messages defined in the <code>VerifyListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @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>
 *
 * @see VerifyListener
 * @see #removeVerifyListener
 */
public void addVerifyListener (VerifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Verify, typedListener);
}

/**
 * Appends a string.
 * <p>
 * The new text is appended to the text at
 * the end of the widget.
 * </p>
 *
 * @param string the string to be appended
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>
 * @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>
 */
public void append (String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	string = Display.withCrLf (string);
	int length = OS.GetWindowTextLength (handle);
	if (hooks (SWT.Verify) || filters (SWT.Verify)) {
		string = verifyText (string, length, length, null);
		if (string == null) return;
	}
	OS.SendMessage (handle, OS.EM_SETSEL, length, length);
	clearSegments (true);
	TCHAR buffer = new TCHAR (getCodePage (), string, true);
	/*
	* Feature in Windows.  When an edit control with ES_MULTILINE
	* style that does not have the WS_VSCROLL style is full (i.e.
	* there is no space at the end to draw any more characters),
	* EM_REPLACESEL sends a WM_CHAR with a backspace character
	* to remove any further text that is added.  This is an
	* implementation detail of the edit control that is unexpected
	* and can cause endless recursion when EM_REPLACESEL is sent
	* from a WM_CHAR handler.  The fix is to ignore calling the
	* handler from WM_CHAR.
	*/
	ignoreCharacter = true;
	OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
	ignoreCharacter = false;
	OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
	applySegments ();
}

void applySegments () {
	if (--clearSegmentsCount != 0) return;
	if (!hooks (SWT.Segments) && !filters (SWT.Segments)) return;
	int length = OS.GetWindowTextLength (handle);
	int cp = getCodePage ();
	TCHAR buffer = new TCHAR (cp, length + 1);
	if (length > 0) OS.GetWindowText (handle, buffer, length + 1);
	String string = buffer.toString (0, length);
	/* Get segments text */
	Event event = new Event ();
	event.text = string;
	event.segments = segments;
	sendEvent (SWT.Segments, event);
	segments = event.segments;
	if (segments == null) return;
	int nSegments = segments.length;
	if (nSegments == 0) return;
	length = string == null ? 0 : string.length ();

	for (int i = 1; i < nSegments; i++) {
		if (event.segments [i] < event.segments [i - 1] || event.segments [i] > length) {
			error (SWT.ERROR_INVALID_ARGUMENT);
		}
	}
	char [] segmentsChars = event.segmentsChars;
	char [] segmentsCharsCrLf = segmentsChars == null ? null : Display.withCrLf(segmentsChars);
	if (segmentsChars != segmentsCharsCrLf) {
		int [] segmentsCrLf = new int [nSegments + Math.min (nSegments, segmentsCharsCrLf.length - segmentsChars.length)];
		for (int i = 0, c = 0; i < segmentsChars.length && i < nSegments; i++) {
			if (segmentsChars [i] == '\n' && segmentsCharsCrLf [i + c] == '\r') {
				segmentsCrLf [i + c++] = segments [i];
			}
			segmentsCrLf [i + c] = segments [i];
		}
		segments = segmentsCrLf;
		nSegments = segments.length;
		segmentsChars = segmentsCharsCrLf;
	}

	int/*64*/ limit = (int/*64*/)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
	OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit + Math.min (nSegments, LIMIT - limit), 0);
	length += nSegments;
	char [] newChars = new char [length + 1];
	int charCount = 0, segmentCount = 0;
	char defaultSeparator = getOrientation () == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
	while (charCount < length) {
		if (segmentCount < nSegments && charCount - segmentCount == segments [segmentCount]) {
			char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars [segmentCount] : defaultSeparator;
			newChars [charCount++] = separator;
			segmentCount++;
		} else if (string != null) {
			newChars [charCount] = string.charAt (charCount++ - segmentCount);
		}
	}
	while (segmentCount < nSegments) {
		segments [segmentCount] = charCount - segmentCount;
		char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars [segmentCount] : defaultSeparator;
		newChars [charCount++] = separator;
		segmentCount++;
	}
	/* Get the current selection */
	int [] start = new int [1], end = new int [1];
	OS.SendMessage (handle, OS.EM_GETSEL, start, end);
	if (!OS.IsUnicode && OS.IsDBLocale) {
		start [0] = mbcsToWcsPos (start [0]);
		end [0] = mbcsToWcsPos (end [0]);
	}
	boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify, oldIgnoreVerify = ignoreVerify;
	ignoreCharacter = ignoreModify = ignoreVerify = true;
	/*
	 * SetWindowText empties the undo buffer and disables undo menu item.
	 * Sending OS.EM_REPLACESEL message instead.
	 */
	newChars [length] = 0;
	buffer = new TCHAR (cp, newChars, false);
	OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
	long /*int*/ undo = OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0);
	OS.SendMessage (handle, OS.EM_REPLACESEL, undo, buffer);
	/* Restore selection */
	start [0] = translateOffset (start [0]);
	end [0] = translateOffset (end [0]);
	if (!OS.IsUnicode && OS.IsDBLocale) {
		start [0] = wcsToMbcsPos (start [0]);
		end [0] = wcsToMbcsPos (end [0]);
	}
	OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
	ignoreCharacter = oldIgnoreCharacter;
	ignoreModify = oldIgnoreModify;
	ignoreVerify = oldIgnoreVerify;
}

static int checkStyle (int style) {
	if ((style & SWT.SEARCH) != 0) {
		style |= SWT.SINGLE | SWT.BORDER;
		style &= ~SWT.PASSWORD;
		/* 
		* NOTE: ICON_CANCEL has the same value as H_SCROLL and
		* ICON_SEARCH has the same value as V_SCROLL so they are
		* cleared because SWT.SINGLE is set. 
		*/
	}
	if ((style & SWT.SINGLE) != 0 && (style & SWT.MULTI) != 0) {
		style &= ~SWT.MULTI;
	}
	style = checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
	if ((style & SWT.SINGLE) != 0) style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP);
	if ((style & SWT.WRAP) != 0) {
		style |= SWT.MULTI;
		style &= ~SWT.H_SCROLL;
	}
	if ((style & SWT.MULTI) != 0) style &= ~SWT.PASSWORD;
	if ((style & (SWT.SINGLE | SWT.MULTI)) != 0) return style;
	if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0) return style | SWT.MULTI;
	return style | SWT.SINGLE;
}

void clearSegments (boolean applyText) {
	if (clearSegmentsCount++ != 0) return;
	if (segments == null) return;
	int nSegments = segments.length;
	if (nSegments == 0) return;
	int/*64*/ limit = (int/*64*/)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
	if (limit < LIMIT) {
		OS.SendMessage (handle, OS.EM_SETLIMITTEXT, Math.max (1, limit - nSegments), 0);
	}
	if (!applyText) {
		segments = null;
		return;
	}
	boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify, oldIgnoreVerify = ignoreVerify;
	ignoreCharacter = ignoreModify = ignoreVerify = true;
	int length = OS.GetWindowTextLength (handle);
	int cp = getCodePage ();
	TCHAR buffer = new TCHAR (cp, length + 1);
	if (length > 0) OS.GetWindowText (handle, buffer, length + 1);
	buffer = deprocessText (buffer, 0, -1, true);
	/* Get the current selection */
	int [] start = new int [1], end = new int [1];
	OS.SendMessage (handle, OS.EM_GETSEL, start, end);
	if (!OS.IsUnicode && OS.IsDBLocale) {
		start [0] = mbcsToWcsPos (start[0]);
		end [0]= mbcsToWcsPos (end [0]);
	}
	start [0] = untranslateOffset (start [0]);
	end [0] = untranslateOffset (end[0]);
	segments = null;
	/*
	 * SetWindowText empties the undo buffer and disables undo in the context
	 * menu. Sending OS.EM_REPLACESEL message instead.
	 */
	OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
	long /*int*/ undo = OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0);
	OS.SendMessage (handle, OS.EM_REPLACESEL, undo, buffer);
	/* Restore selection */
	if (!OS.IsUnicode && OS.IsDBLocale) {
		start [0] = wcsToMbcsPos (start [0]);
		end [0] = wcsToMbcsPos (end [0]);
	}
	OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
	ignoreCharacter = oldIgnoreCharacter;
	ignoreModify = oldIgnoreModify;
	ignoreVerify = oldIgnoreVerify;
}

/**
 * Clears the 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>
 */
public void clearSelection () {
	checkWidget ();
	if (OS.IsWinCE) {
		/*
		* Bug in WinCE.  Calling EM_SETSEL with -1 and 0 is equivalent
		* to calling EM_SETSEL with 0 and -1.  It causes the entire
		* text to be selected instead of clearing the selection.  The
		* fix is to set the start of the selection to the  end of the
		* current selection.
		*/ 
		int [] end = new int [1];
		OS.SendMessage (handle, OS.EM_GETSEL, (int []) null, end);
		OS.SendMessage (handle, OS.EM_SETSEL, end [0], end [0]);
	} else {
		OS.SendMessage (handle, OS.EM_SETSEL, -1, 0);
	}
}

public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget ();
	int height = 0, width = 0;
	if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
		long /*int*/ newFont, oldFont = 0;
		long /*int*/ hDC = OS.GetDC (handle);
		newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
		if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
		TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
		OS.GetTextMetrics (hDC, tm);
		int count = (style & SWT.SINGLE) != 0 ? 1 : (int)/*64*/OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
		height = count * tm.tmHeight;
		RECT rect = new RECT ();
		int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
		boolean wrap = (style & SWT.MULTI) != 0 && (style & SWT.WRAP) != 0;
		if (wrap && wHint != SWT.DEFAULT) {
			flags |= OS.DT_WORDBREAK;
			rect.right = wHint;
		}
		int length = OS.GetWindowTextLength (handle);
		if (length != 0) {
			TCHAR buffer = new TCHAR (getCodePage (), length + 1);
			OS.GetWindowText (handle, buffer, length + 1);
			OS.DrawText (hDC, buffer, length, rect, flags);
			width = rect.right - rect.left;
		}
		if (wrap && hHint == SWT.DEFAULT) {
			int newHeight = rect.bottom - rect.top;
			if (newHeight != 0) height = newHeight;
		}
		if ((style & SWT.SINGLE) != 0 && message.length () > 0) {
			OS.SetRect (rect, 0, 0, 0, 0);
			TCHAR buffer = new TCHAR (getCodePage (), message, false);
			OS.DrawText (hDC, buffer, buffer.length (), rect, flags);
			width = Math.max (width, rect.right - rect.left);
		}
		if (newFont != 0) OS.SelectObject (hDC, oldFont);
		OS.ReleaseDC (handle, hDC);
	}
	if (width == 0) width = DEFAULT_WIDTH;
	if (height == 0) height = DEFAULT_HEIGHT;
	if (wHint != SWT.DEFAULT) width = wHint;
	if (hHint != SWT.DEFAULT) height = hHint;
	Rectangle trim = computeTrim (0, 0, width, height);
	return new Point (trim.width, trim.height);
}

public Rectangle computeTrim (int x, int y, int width, int height) {
	checkWidget ();
	Rectangle rect = super.computeTrim (x, y, width, height);
	/*
	* The preferred height of a single-line text widget
	* has been hand-crafted to be the same height as
	* the single-line text widget in an editable combo
	* box.
	*/
	long /*int*/ margins = OS.SendMessage(handle, OS.EM_GETMARGINS, 0, 0);
	rect.x -= OS.LOWORD (margins);
	rect.width += OS.LOWORD (margins) + OS.HIWORD (margins);
	if ((style & SWT.H_SCROLL) != 0) rect.width++;
	if ((style & SWT.BORDER) != 0) {
		rect.x -= 1;
		rect.y -= 1;
		rect.width += 2;
		rect.height += 2;
	}
	return rect;
}

/**
 * Copies the selected text.
 * <p>
 * The current selection is copied to the clipboard.
 * </p>
 *
 * @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>
 */
public void copy () {
	checkWidget ();
	OS.SendMessage (handle, OS.WM_COPY, 0, 0);
}

void createWidget () {
	super.createWidget ();
	message = "";
	doubleClick = true;
	setTabStops (tabs = 8);
	fixAlignment ();
}

/**
 * Cuts the selected text.
 * <p>
 * The current selection is first copied to the
 * clipboard and then deleted from the widget.
 * </p>
 *
 * @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>
 */
public void cut () {
	checkWidget ();
	if ((style & SWT.READ_ONLY) != 0) return;
	OS.SendMessage (handle, OS.WM_CUT, 0, 0);
}

int defaultBackground () {
	int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
	return OS.GetSysColor ((bits & OS.ES_READONLY) != 0 ? OS.COLOR_3DFACE : OS.COLOR_WINDOW);
}

TCHAR deprocessText (TCHAR text, int start, int end, boolean terminate) {
	if (text == null) return null;
	int length = text.length ();
	char [] chars;
	if (start < 0) start = 0;
	if (OS.IsUnicode) {
		chars = text.chars;
		if (text.chars [length - 1] == 0) length--;
	} else {
		chars = new char [length];
		length = OS.MultiByteToWideChar (getCodePage (), OS.MB_PRECOMPOSED, text.bytes, length, chars, length);
	}
	if (end == -1) end = length;
	if (segments != null && end > segments [0]) {
		int nSegments = segments.length;
		if (nSegments > 0 && start <= segments [nSegments - 1]) {
			int nLeadSegments = 0;
			while (start - nLeadSegments > segments [nLeadSegments]) nLeadSegments++;
			int segmentCount = nLeadSegments;
			for (int i = start; i < end; i++) {
				if (segmentCount < nSegments && i - segmentCount == segments [segmentCount]) {
					++segmentCount;
				} else {
					chars [i - segmentCount + nLeadSegments] = chars [i];
				}
			}
			length = end - start - segmentCount + nLeadSegments;
		}
	}
	if (start != 0 || end != length) {
		char [] newChars = new char [length];
		System.arraycopy(chars, start, newChars, 0, length);
		return new TCHAR (getCodePage (), newChars, terminate);
	}
	return text;
}

boolean dragDetect (long /*int*/ hwnd, int x, int y, boolean filter, boolean [] detect, boolean [] consume) {
	if (filter) {
		int [] start = new int [1], end = new int [1];
		OS.SendMessage (handle, OS.EM_GETSEL, start, end);
		if (start [0] != end [0]) {
			long /*int*/ lParam = OS.MAKELPARAM (x, y);
			int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam));
			if (start [0] <= position && position < end [0]) {
				if (super.dragDetect (hwnd, x, y, filter, detect, consume)) {
					if (consume != null) consume [0] = true;
					return true;
				}
			}
		}
		return false;
	}
	return super.dragDetect (hwnd, x, y, filter, detect, consume);
}

void fixAlignment () {
	/*
	* Feature in Windows.  When the edit control is not
	* mirrored, it uses WS_EX_RIGHT, WS_EX_RTLREADING and
	* WS_EX_LEFTSCROLLBAR to give the control a right to
	* left appearance.  This causes the control to be lead
	* aligned no matter what alignment was specified by
	* the programmer.  For example, setting ES_RIGHT and
	* WS_EX_LAYOUTRTL should cause the contents of the
	* control to be left (trail) aligned in a mirrored world.
	* When the orientation is changed by the user or
	* specified by the programmer, WS_EX_RIGHT conflicts
	* with the mirrored alignment.  The fix is to clear
	* or set WS_EX_RIGHT to achieve the correct alignment
	* according to the orientation and mirroring.
	*/
	if ((style & SWT.MIRRORED) != 0) return;
	int bits1 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
	int bits2 = OS.GetWindowLong (handle, OS.GWL_STYLE);
	if ((style & SWT.LEFT_TO_RIGHT) != 0) {
		/*
		* Bug in Windows 98. When the edit control is created
		* with the style ES_RIGHT it automatically sets the 
		* WS_EX_LEFTSCROLLBAR bit.  The fix is to clear the
		* bit when the orientation of the control is left
		* to right.
		*/
		bits1 &= ~OS.WS_EX_LEFTSCROLLBAR;
		if ((style & SWT.RIGHT) != 0) {
			bits1 |= OS.WS_EX_RIGHT;
			bits2 |= OS.ES_RIGHT;
		}
		if ((style & SWT.LEFT) != 0) {
			bits1 &= ~OS.WS_EX_RIGHT;
			bits2 &= ~OS.ES_RIGHT;
		}
	} else {
		if ((style & SWT.RIGHT) != 0) {
			bits1 &= ~OS.WS_EX_RIGHT;
			bits2 &= ~OS.ES_RIGHT;
		}
		if ((style & SWT.LEFT) != 0) {
			bits1 |= OS.WS_EX_RIGHT;
			bits2 |= OS.ES_RIGHT;
		}
	}
	if ((style & SWT.CENTER) != 0) {
		bits2 |= OS.ES_CENTER;
	}	
	OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits1);
	OS.SetWindowLong (handle, OS.GWL_STYLE, bits2);
}

public int getBorderWidth () {
	checkWidget ();
	/*
	* Feature in Windows 2000 and XP.  Despite the fact that WS_BORDER
	* is set when the edit control is created, the style bit is cleared.
	* The fix is to avoid the check for WS_BORDER and use the SWT widget
	* style bits instead.
	*/
//	if ((style & SWT.BORDER) != 0 && (style & SWT.FLAT) != 0) {
//		return OS.GetSystemMetrics (OS.SM_CXBORDER);
//	}
	return super.getBorderWidth ();
}

/**
 * Returns the line number of the caret.
 * <p>
 * The line number of the caret is returned.
 * </p>
 *
 * @return the line number
 *
 * @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>
 */
public int getCaretLineNumber () {
	checkWidget ();
	return (int)/*64*/OS.SendMessage (handle, OS.EM_LINEFROMCHAR, -1, 0);
}

/**
 * Returns a point describing the location of the caret relative
 * to the receiver.
 *
 * @return a point, the location of the caret
 *
 * @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>
 */
public Point getCaretLocation () {
	checkWidget ();
	/*
	* Bug in Windows.  For some reason, Windows is unable
	* to return the pixel coordinates of the last character
	* in the widget.  The fix is to temporarily insert a
	* space, query the coordinates and delete the space.
	* The selection is always an i-beam in this case because
	* this is the only time the start of the selection can
	* be equal to the last character position in the widget.
	* If EM_POSFROMCHAR fails for any other reason, return
	* pixel coordinates (0,0). 
	*/
	int position = translateOffset (getCaretPosition ());
	long /*int*/ caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
	if (caretPos == -1) {
		caretPos = 0;
		if (position >= OS.GetWindowTextLength (handle)) {
			int cp = getCodePage ();
			int [] start = new int [1], end = new int [1];
			OS.SendMessage (handle, OS.EM_GETSEL, start, end);
			OS.SendMessage (handle, OS.EM_SETSEL, position, position);
			/*
			* Feature in Windows.  When an edit control with ES_MULTILINE
			* style that does not have the WS_VSCROLL style is full (i.e.
			* there is no space at the end to draw any more characters),
			* EM_REPLACESEL sends a WM_CHAR with a backspace character
			* to remove any further text that is added.  This is an
			* implementation detail of the edit control that is unexpected
			* and can cause endless recursion when EM_REPLACESEL is sent
			* from a WM_CHAR handler.  The fix is to ignore calling the
			* handler from WM_CHAR.
			*/
			ignoreCharacter = ignoreModify = true;
			OS.SendMessage (handle, OS.EM_REPLACESEL, 0, new TCHAR (cp, " ", true));
			caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
			OS.SendMessage (handle, OS.EM_SETSEL, position, position + 1);
			OS.SendMessage (handle, OS.EM_REPLACESEL, 0, new TCHAR (cp, "", true));
			ignoreCharacter = ignoreModify = false;
			OS.SendMessage (handle, OS.EM_SETSEL, start [0], start [0]);
			OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
		}
	}
	return new Point (OS.GET_X_LPARAM (caretPos), OS.GET_Y_LPARAM (caretPos));
}

/**
 * Returns the character position of the caret.
 * <p>
 * Indexing is zero based.
 * </p>
 *
 * @return the position of the caret
 *
 * @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>
 */
public int getCaretPosition () {
	checkWidget ();
	int [] start = new int [1], end = new int [1];
	OS.SendMessage (handle, OS.EM_GETSEL, start, end);
	/*
	* In Windows, there is no API to get the position of the caret
	* when the selection is not an i-beam.  The best that can be done
	* is to query the pixel position of the current caret and compare
	* it to the pixel position of the start and end of the selection.
	* 
	* NOTE:  This does not work when the i-beam belongs to another
	* control.  In this case, guess that the i-beam is at the start
	* of the selection.
	*/
	int caret = start [0];
	if (start [0] != end [0]) {
		int startLine = (int)/*64*/OS.SendMessage (handle, OS.EM_LINEFROMCHAR, start [0], 0);
		int endLine = (int)/*64*/OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end [0], 0);
		if (startLine == endLine) {
			if (!OS.IsWinCE) {
				int idThread = OS.GetWindowThreadProcessId (handle, null);
				GUITHREADINFO lpgui = new GUITHREADINFO ();
				lpgui.cbSize = GUITHREADINFO.sizeof;
				if (OS.GetGUIThreadInfo (idThread, lpgui)) {
					if (lpgui.hwndCaret == handle || lpgui.hwndCaret == 0) {
						POINT ptCurrentPos = new POINT ();
						if (OS.GetCaretPos (ptCurrentPos)) {
							long /*int*/ endPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, end [0], 0);
							if (endPos == -1) {
								long /*int*/ startPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, start [0], 0);
								int startX = OS.GET_X_LPARAM (startPos);
								if (ptCurrentPos.x > startX) caret = end [0];
							} else {
								int endX = OS.GET_X_LPARAM (endPos);
								if (ptCurrentPos.x >= endX) caret = end [0];
							}
						}
					}
				}
			}
		} else {
			int caretPos = (int)/*64*/OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
			int caretLine = (int)/*64*/OS.SendMessage (handle, OS.EM_LINEFROMCHAR, caretPos, 0);
			if (caretLine == endLine) caret = end [0];
		}
	}
	if (!OS.IsUnicode && OS.IsDBLocale) caret = mbcsToWcsPos (caret);
	return untranslateOffset (caret);
}

/**
 * Returns the number of characters.
 *
 * @return number of characters in the widget
 *
 * @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>
 */
public int getCharCount () {
	checkWidget ();
	int length = OS.GetWindowTextLength (handle);
	if (!OS.IsUnicode && OS.IsDBLocale) length = mbcsToWcsPos (length);
	return untranslateOffset (length);
}

/**
 * Returns the double click enabled flag.
 * <p>
 * The double click flag enables or disables the
 * default action of the text widget when the user
 * double clicks.
 * </p>
 * 
 * @return whether or not double click is enabled
 *
 * @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>
 */
public boolean getDoubleClickEnabled () {
	checkWidget ();
	return doubleClick;
}

/**
 * Returns the echo character.
 * <p>
 * The echo character is the character that is
 * displayed when the user enters text or the
 * text is changed by the programmer.
 * </p>
 * 
 * @return the echo character
 *
 * @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>
 * 
 * @see #setEchoChar
 */
public char getEchoChar () {
	checkWidget ();
	char echo = (char) OS.SendMessage (handle, OS.EM_GETPASSWORDCHAR, 0, 0);
	if (echo != 0 && (echo = Display.mbcsToWcs (echo, getCodePage ())) == 0) echo = '*';
	return echo;
}

/**
 * Returns the editable state.
 *
 * @return whether or not the receiver is editable
 * 
 * @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>
 */
public boolean getEditable () {
	checkWidget ();
	int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
	return (bits & OS.ES_READONLY) == 0;
}

/**
 * Returns the number of lines.
 *
 * @return the number of lines in the widget
 *
 * @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>
 */
public int getLineCount () {
	checkWidget ();
	return (int)/*64*/OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
}

/**
 * Returns the line delimiter.
 *
 * @return a string that is the line delimiter
 *
 * @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>
 * 
 * @see #DELIMITER
 */
public String getLineDelimiter () {
	checkWidget ();
	return DELIMITER;
}

/**
 * Returns the height of a line.
 *
 * @return the height of a row of text
 *
 * @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>
 */
public int getLineHeight () {
	checkWidget ();
	long /*int*/ newFont, oldFont = 0;
	long /*int*/ hDC = OS.GetDC (handle);
	newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
	if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
	TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
	OS.GetTextMetrics (hDC, tm);
	if (newFont != 0) OS.SelectObject (hDC, oldFont);
	OS.ReleaseDC (handle, hDC);
	return tm.tmHeight;
}

/**
 * Returns the orientation of the receiver, which will be one of the
 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 *
 * @return the orientation style
 * 
 * @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 2.1.2
 */
public int getOrientation () {
	return super.getOrientation ();
}

/**
 * Returns the widget message.  The message text is displayed
 * as a hint for the user, indicating the purpose of the field.
 * <p>
 * Typically this is used in conjunction with <code>SWT.SEARCH</code>.
 * </p>
 * 
 * @return the widget message
 *
 * @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.3
 */
public String getMessage () {
	checkWidget ();
	return message;
}

/**
 * Returns the character position at the given point in the receiver
 * or -1 if no such position exists. The point is in the coordinate
 * system of the receiver.
 * <p>
 * Indexing is zero based.
 * </p>
 *
 * @return the position of the caret
 *
 * @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.3
 */
//TODO - Javadoc
/*public*/ int getPosition (Point point) {
	checkWidget();
	if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
	long /*int*/ lParam = OS.MAKELPARAM (point.x, point.y);
	int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam));
	if (!OS.IsUnicode && OS.IsDBLocale) position = mbcsToWcsPos (position);
	return untranslateOffset (position);
}

/**
 * Returns a <code>Point</code> whose x coordinate is the
 * character position representing the start of the selected
 * text, and whose y coordinate is the character position
 * representing the end of the selection. An "empty" selection
 * is indicated by the x and y coordinates having the same value.
 * <p>
 * Indexing is zero based.  The range of a selection is from
 * 0..N where N is the number of characters in the widget.
 * </p>
 *
 * @return a point representing the selection start and end
 *
 * @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>
 */
public Point getSelection () {
	checkWidget ();
	int [] start = new int [1], end = new int [1];
	OS.SendMessage (handle, OS.EM_GETSEL, start, end);
	if (!OS.IsUnicode && OS.IsDBLocale) {
		start [0] = mbcsToWcsPos (start [0]);
		end [0] = mbcsToWcsPos (end [0]);
	}
	return new Point (untranslateOffset (start [0]), untranslateOffset (end [0]));
}

/**
 * Returns the number of selected characters.
 *
 * @return the number of selected characters.
 *
 * @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>
 */
public int getSelectionCount () {
	checkWidget ();
	Point selection = getSelection ();
	return selection.y - selection.x;
}

/**
 * Gets the selected text, or an empty string if there is no current selection.
 *
 * @return the selected text
 * 
 * @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>
 */
public String getSelectionText () {
	checkWidget ();
	int length = OS.GetWindowTextLength (handle);
	if (length == 0) return "";
	int [] start = new int [1], end = new int [1];
	OS.SendMessage (handle, OS.EM_GETSEL, start, end);
	if (start [0] == end [0]) return "";
	TCHAR buffer = new TCHAR (getCodePage (), length + 1);
	OS.GetWindowText (handle, buffer, length + 1);
	if (segments != null) {
		buffer = deprocessText (buffer, start [0], end [0], false);
		return buffer.toString ();
	}
	return buffer.toString (start [0], end [0] - start [0]);
}

/**
 * Returns the number of tabs.
 * <p>
 * Tab stop spacing is specified in terms of the
 * space (' ') character.  The width of a single
 * tab stop is the pixel width of the spaces.
 * </p>
 *
 * @return the number of tab characters
 *
 * @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>
 */
public int getTabs () {
	checkWidget ();
	return tabs;
}

int getTabWidth (int tabs) {
	long /*int*/ oldFont = 0;
	RECT rect = new RECT ();
	long /*int*/ hDC = OS.GetDC (handle);
	long /*int*/ newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
	if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
	int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
	TCHAR SPACE = new TCHAR (getCodePage (), " ", false);
	OS.DrawText (hDC, SPACE, SPACE.length (), rect, flags);
	if (newFont != 0) OS.SelectObject (hDC, oldFont);
	OS.ReleaseDC (handle, hDC);
	return (rect.right - rect.left) * tabs;
}

/**
 * Returns the widget text.
 * <p>
 * The text for a text widget is the characters in the widget, or
 * an empty string if this has never been set.
 * </p>
 *
 * @return the widget text
 *
 * @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>
 */
public String getText () {
	checkWidget ();
	int length = OS.GetWindowTextLength (handle);
	if (length == 0) return "";
	TCHAR buffer = new TCHAR (getCodePage (), length + 1);
	OS.GetWindowText (handle, buffer, length + 1);
	if (segments != null) {
		buffer = deprocessText (buffer, 0, -1, false);
		return buffer.toString ();
	}
	return buffer.toString (0, length);
}

/**
 * Returns the widget's text as a character array.
 * <p>
 * The text for a text widget is the characters in the widget, or
 * a zero-length array if this has never been set.
 * </p>
 *
 * @return a character array that contains the widget's text
 *
 * @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>
 *
 * @see #setTextChars(char[])
 *
 * @since 3.7
 */
public char[] getTextChars () {
	checkWidget ();
	int length = OS.GetWindowTextLength (handle);
	if (length == 0) return new char[0];
	TCHAR buffer = new TCHAR (getCodePage (), length + 1);
	OS.GetWindowText (handle, buffer, length + 1);
	if (segments != null) buffer = deprocessText (buffer, 0, -1, false);
	char [] chars = new char [length];
	System.arraycopy (buffer.chars, 0, chars, 0, length);
	for (int i = 0; i < buffer.chars.length; i++) buffer.chars [i] = '\0';
	return chars;
}

/**
 * Returns a range of text.  Returns an empty string if the
 * start of the range is greater than the end.
 * <p>
 * Indexing is zero based.  The range of
 * a selection is from 0..N-1 where N is
 * the number of characters in the widget.
 * </p>
 *
 * @param start the start of the range
 * @param end the end of the range
 * @return the range of text
 *
 * @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>
 */
public String getText (int start, int end) {
	checkWidget ();
	if (!(start <= end && 0 <= end)) return "";
	int length = OS.GetWindowTextLength (handle);
	if (!OS.IsUnicode && OS.IsDBLocale) length = mbcsToWcsPos (length);
	end = Math.min (end, untranslateOffset (length) - 1);
	if (start > end) return "";
	start = Math.max (0, start);
	/*
	* NOTE: The current implementation uses substring ()
	* which can reference a potentially large character
	* array.
	*/
	return getText ().substring (start, end + 1);
}

/**
 * Returns the maximum number of characters that the receiver is capable of holding. 
 * <p>
 * If this has not been changed by <code>setTextLimit()</code>,
 * it will be the constant <code>Text.LIMIT</code>.
 * </p>
 * 
 * @return the text limit
 * 
 * @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>
 * 
 * @see #LIMIT
 */
public int getTextLimit () {
	checkWidget ();
	int/*64*/ limit = (int)/*64*/OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
	if (segments != null && limit < LIMIT) limit = Math.max (1, limit - segments.length);
	return limit;
}

/**
 * Returns the zero-relative index of the line which is currently
 * at the top of the receiver.
 * <p>
 * This index can change when lines are scrolled or new lines are added or removed.
 * </p>
 *
 * @return the index of the top line
 *
 * @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>
 */
public int getTopIndex () {
	checkWidget ();
	if ((style & SWT.SINGLE) != 0) return 0;
	return (int)/*64*/OS.SendMessage (handle, OS.EM_GETFIRSTVISIBLELINE, 0, 0);
}

/**
 * Returns the top pixel.
 * <p>
 * The top pixel is the pixel position of the line
 * that is currently at the top of the widget.  On
 * some platforms, a text widget can be scrolled by
 * pixels instead of lines so that a partial line
 * is displayed at the top of the widget.
 * </p><p>
 * The top pixel changes when the widget is scrolled.
 * The top pixel does not include the widget trimming.
 * </p>
 *
 * @return the pixel position of the top line
 *
 * @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>
 */
public int getTopPixel () {
	checkWidget ();
	/*
	* Note, EM_GETSCROLLPOS is implemented in Rich Edit 3.0
	* and greater.  The plain text widget and previous versions
	* of Rich Edit return zero.
	*/
	int [] buffer = new int [2];
	long /*int*/ code = OS.SendMessage (handle, OS.EM_GETSCROLLPOS, 0, buffer);
	if (code == 1) return buffer [1];
	return getTopIndex () * getLineHeight ();
}

/**
 * Inserts a string.
 * <p>
 * The old selection is replaced with the new text.
 * </p>
 *
 * @param string the string
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is <code>null</code></li>
 * </ul>
 * @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>
 */
public void insert (String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	string = Display.withCrLf (string);
	if (hooks (SWT.Verify) || filters (SWT.Verify)) {
		int [] start = new int [1], end = new int [1];
		OS.SendMessage (handle, OS.EM_GETSEL, start, end);
		string = verifyText (string, start [0], end [0], null);
		if (string == null) return;
	}
	clearSegments (true);
	TCHAR buffer = new TCHAR (getCodePage (), string, true);
	/*
	* Feature in Windows.  When an edit control with ES_MULTILINE
	* style that does not have the WS_VSCROLL style is full (i.e.
	* there is no space at the end to draw any more characters),
	* EM_REPLACESEL sends a WM_CHAR with a backspace character
	* to remove any further text that is added.  This is an
	* implementation detail of the edit control that is unexpected
	* and can cause endless recursion when EM_REPLACESEL is sent
	* from a WM_CHAR handler.  The fix is to ignore calling the
	* handler from WM_CHAR.
	*/
	ignoreCharacter = true;
	OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
	ignoreCharacter = false;
	applySegments ();
}

int mbcsToWcsPos (int mbcsPos) {
	if (mbcsPos <= 0) return 0;
	if (OS.IsUnicode) return mbcsPos;
	int cp = getCodePage ();
	int wcsTotal = 0, mbcsTotal = 0;
	byte [] buffer = new byte [128];
	String delimiter = getLineDelimiter();
	int delimiterSize = delimiter.length ();
	int count = (int)/*64*/OS.SendMessageA (handle, OS.EM_GETLINECOUNT, 0, 0);
	for (int line=0; line<count; line++) {
		int wcsSize = 0;
		int linePos = (int)/*64*/OS.SendMessageA (handle, OS.EM_LINEINDEX, line, 0);
		int mbcsSize = (int)/*64*/OS.SendMessageA (handle, OS.EM_LINELENGTH, linePos, 0);
		if (mbcsSize != 0) {
			if (mbcsSize + delimiterSize > buffer.length) {
				buffer = new byte [mbcsSize + delimiterSize];
			}
			//ENDIAN
			buffer [0] = (byte) (mbcsSize & 0xFF);
			buffer [1] = (byte) (mbcsSize >> 8);
			mbcsSize = (int)/*64*/OS.SendMessageA (handle, OS.EM_GETLINE, line, buffer);
			wcsSize = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer, mbcsSize, null, 0);
		}
		if (line - 1 != count) {
			for (int i=0; i<delimiterSize; i++) {
				buffer [mbcsSize++] = (byte) delimiter.charAt (i);
			}
			wcsSize += delimiterSize;
		}
		if ((mbcsTotal + mbcsSize) >= mbcsPos) {
			int bufferSize = mbcsPos - mbcsTotal;
			wcsSize = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer, bufferSize, null, 0);
			return wcsTotal + wcsSize;
		}
		wcsTotal += wcsSize;
		mbcsTotal += mbcsSize;
	}
	return wcsTotal;
}

/**
 * Pastes text from clipboard.
 * <p>
 * The selected text is deleted from the widget
 * and new text inserted from the clipboard.
 * </p>
 *
 * @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>
 */
public void paste () {
	checkWidget ();
	if ((style & SWT.READ_ONLY) != 0) return;
	OS.SendMessage (handle, OS.WM_PASTE, 0, 0);
}

void releaseWidget () {
	super.releaseWidget ();
	message = null;
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the receiver's text is modified.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @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>
 *
 * @see ModifyListener
 * @see #addModifyListener
 */
public void removeModifyListener (ModifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Modify, listener);	
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the receiver's text is modified.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @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>
 *
 * @see SegmentEvent
 * @see SegmentListener
 * @see #addSegmentListener
 * 
 * @since 3.8
 */
public void removeSegmentListener (SegmentListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	eventTable.unhook (SWT.Segments, listener);
	clearSegments (true);
	applySegments ();
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the control is selected by the user.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @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>
 *
 * @see SelectionListener
 * @see #addSelectionListener
 */
public void removeSelectionListener (SelectionListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Selection, listener);
	eventTable.unhook (SWT.DefaultSelection,listener);	
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the control is verified.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @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>
 *
 * @see VerifyListener
 * @see #addVerifyListener
 */
public void removeVerifyListener (VerifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Verify, listener);	
}

/**
 * Selects all the text in the receiver.
 *
 * @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>
 */
public void selectAll () {
	checkWidget ();
	OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
}

boolean sendKeyEvent (int type, int msg, long /*int*/ wParam, long /*int*/ lParam, Event event) {
	if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
		return false;
	}
	if ((style & SWT.READ_ONLY) != 0) return true;
	if (ignoreVerify) return true;
	if (type != SWT.KeyDown) return true;
	if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
		return true;
	}
	if (event.character == 0) return true;
	if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
	char key = event.character;
	int stateMask = event.stateMask;
	
	/*
	* Disable all magic keys that could modify the text
	* and don't send events when Alt, Shift or Ctrl is
	* pressed.
	*/
	switch (msg) {
		case OS.WM_CHAR:
			if (key != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
			// FALL THROUGH
		case OS.WM_KEYDOWN:
			if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
			break;
	}

	/*
	* Feature in Windows.  If the left button is down in
	* the text widget, it refuses the character.  The fix
	* is to detect this case and avoid sending a verify
	* event.
	*/
	if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
		if (handle == OS.GetCapture()) return true;
	}

	/* Verify the character */
	String oldText = "";
	int [] start = new int [1], end = new int [1];
	OS.SendMessage (handle, OS.EM_GETSEL, start, end);
	switch (key) {
		case 0x08:	/* Bs */
			if (start [0] == end [0]) {
				if (start [0] == 0) return true;
				int lineStart = (int)/*64*/OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
				if (start [0] == lineStart) {
					start [0] = start [0] - DELIMITER.length ();
				} else {
					start [0] = start [0] - 1;
					if (!OS.IsUnicode && OS.IsDBLocale) {
						int [] newStart = new int [1], newEnd = new int [1];
						OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
						OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
						if (start [0] != newStart [0]) start [0] = start [0] - 1;
					}
				}
				start [0] = Math.max (start [0], 0);
			}
			break;
		case 0x7F:	/* Del */
			if (start [0] == end [0]) {
				int length = OS.GetWindowTextLength (handle);
				if (start [0] == length) return true;
				int line = (int)/*64*/OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end [0], 0);
				int lineStart = (int)/*64*/OS.SendMessage (handle, OS.EM_LINEINDEX, line + 1, 0);
				if (end [0] == lineStart - DELIMITER.length ()) {
					end [0] = end [0] + DELIMITER.length ();
				} else {
					end [0] = end [0] + 1;
					if (!OS.IsUnicode && OS.IsDBLocale) {
						int [] newStart = new int [1], newEnd = new int [1];
						OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
						OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
						if (end [0] != newEnd [0]) end [0] = end [0] + 1;
					}
				}
				end [0] = Math.min (end [0], length);
			}
			break;
		case '\r':	/* Return */
			if ((style & SWT.SINGLE) != 0) return true;
			oldText = DELIMITER;
			break;
		default:	/* Tab and other characters */
			if (key != '\t' && key < 0x20) return true;
			oldText = new String (new char [] {key});
			break;
	}
	String newText = verifyText (oldText, start [0], end [0], event);
	if (newText == null) return false;
	if (newText == oldText) return true;
	newText = Display.withCrLf (newText);
	TCHAR buffer = new TCHAR (getCodePage (), newText, true);
	OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
	/*
	* Feature in Windows.  When an edit control with ES_MULTILINE
	* style that does not have the WS_VSCROLL style is full (i.e.
	* there is no space at the end to draw any more characters),
	* EM_REPLACESEL sends a WM_CHAR with a backspace character
	* to remove any further text that is added.  This is an
	* implementation detail of the edit control that is unexpected
	* and can cause endless recursion when EM_REPLACESEL is sent
	* from a WM_CHAR handler.  The fix is to ignore calling the
	* handler from WM_CHAR.
	*/
	ignoreCharacter = true;
	OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
	ignoreCharacter = false;
	return false;
}

void setBounds (int x, int y, int width, int height, int flags) {
	/*
	* Feature in Windows.  When the caret is moved,
	* the text widget scrolls to show the new location.
	* This means that the text widget may be scrolled
	* to the right in order to show the caret when the
	* widget is not large enough to show both the caret
	* location and all the text.  Unfortunately, when
	* the text widget is resized such that all the text
	* and the caret could be visible, Windows does not
	* scroll the widget back.  The fix is to resize the
	* text widget, set the selection to the start of the
	* text and then restore the selection.  This will
	* cause the text widget compute the correct scroll
	* position.
	*/
	if ((flags & OS.SWP_NOSIZE) == 0 && width != 0) {
		RECT rect = new RECT ();
		OS.GetWindowRect (handle, rect);
		long /*int*/ margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
		int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins);
		if (rect.right - rect.left <= marginWidth) {
			int [] start = new int [1], end = new int [1];
			OS.SendMessage (handle, OS.EM_GETSEL, start, end);
			if (start [0] != 0 || end [0] != 0) {
				SetWindowPos (handle, 0, x, y, width, height, flags);
				OS.SendMessage (handle, OS.EM_SETSEL, 0, 0);
				OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
				return;
			}
		}
	}
	super.setBounds (x, y, width, height, flags);
	
	/*
	* Bug in Windows. If the client area height is smaller than 
	* the font height, then the multi-line text widget does not
	* update the formatting rectangle when resized. The fix is to
	* detect this case and explicitly set the formatting rectangle.
	*/
	if ((flags & OS.SWP_NOSIZE) == 0) {
		int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
		if ((bits & OS.ES_MULTILINE) != 0) {
			long /*int*/ newFont, oldFont = 0;
			long /*int*/ hDC = OS.GetDC (handle);
			newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
			if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
			TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
			OS.GetTextMetrics (hDC, tm);
			if (newFont != 0) OS.SelectObject (hDC, oldFont);
			OS.ReleaseDC (handle, hDC);
			RECT rect = new RECT();
			OS.GetClientRect (handle, rect);
			if ((rect.bottom - rect.top) < tm.tmHeight) {
				long /*int*/ margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
				rect.left += OS.LOWORD (margins);
				rect.right -= OS.HIWORD (margins);
				rect.top = 0;
				rect.bottom = tm.tmHeight;
				OS.SendMessage (handle, OS.EM_SETRECT, 0, rect);
			}
		}
	}
}

void setDefaultFont () {
	super.setDefaultFont ();
	setMargins ();
}

/**
 * Sets the double click enabled flag.
 * <p>
 * The double click flag enables or disables the
 * default action of the text widget when the user
 * double clicks.
 * </p><p>
 * Note: This operation is a hint and is not supported on
 * platforms that do not have this concept.
 * </p>
 * 
 * @param doubleClick the new double click flag
 *
 * @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>
 */
public void setDoubleClickEnabled (boolean doubleClick) {
	checkWidget ();
	this.doubleClick = doubleClick;
}

/**
 * Sets the echo character.
 * <p>
 * The echo character is the character that is
 * displayed when the user enters text or the
 * text is changed by the programmer. Setting
 * the echo character to '\0' clears the echo
 * character and redraws the original text.
 * If for any reason the echo character is invalid,
 * or if the platform does not allow modification
 * of the echo character, the default echo character
 * for the platform is used.
 * </p>
 *
 * @param echo the new echo character
 *
 * @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>
 */
public void setEchoChar (char echo) {
	checkWidget ();
	if ((style & SWT.MULTI) != 0) return;
	if (echo != 0) {
		if ((echo = (char) Display.wcsToMbcs (echo, getCodePage ())) == 0) echo = '*';
	}
	allowPasswordChar = true;
	OS.SendMessage (handle, OS.EM_SETPASSWORDCHAR, echo, 0);
	allowPasswordChar = false;
	/*
	* Bug in Windows.  When the password character is changed,
	* Windows does not redraw to show the new password character.
	* The fix is to force a redraw when the character is set.
	*/
	OS.InvalidateRect (handle, null, true);
}

/**
 * Sets the editable state.
 *
 * @param editable the new editable state
 *
 * @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>
 */
public void setEditable (boolean editable) {
	checkWidget ();
	style &= ~SWT.READ_ONLY;
	if (!editable) style |= SWT.READ_ONLY; 
	OS.SendMessage (handle, OS.EM_SETREADONLY, editable ? 0 : 1, 0);
}

public void setFont (Font font) {
	checkWidget ();
	super.setFont (font);
	setTabStops (tabs);
	setMargins ();
}

void setMargins () {
	/*
	* Bug in Windows.  When EM_SETCUEBANNER is used to set the
	* banner text, the control does not take into account the
	* margins, causing the first character to be clipped.  The
	* fix is to set the margins to zero.
	*/
	if ((style & SWT.SEARCH) != 0) {
		if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
			OS.SendMessage (handle, OS.EM_SETMARGINS, OS.EC_LEFTMARGIN | OS.EC_RIGHTMARGIN, 0);
		}
	}
}

/**
 * Sets the widget message. The message text is displayed
 * as a hint for the user, indicating the purpose of the field.
 * <p>
 * Typically this is used in conjunction with <code>SWT.SEARCH</code>.
 * </p>
 * 
 * @param message the new message
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the message is null</li>
 * </ul>
 * @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.3
 */
public void setMessage (String message) {
	checkWidget ();
	if (message == null) error (SWT.ERROR_NULL_ARGUMENT);
	this.message = message;
	if (!OS.IsWinCE) {
		if (OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
			int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
			if ((bits & OS.ES_MULTILINE) == 0) {
				int length = message.length ();
				char [] chars = new char [length + 1];
				message.getChars(0, length, chars, 0);
				OS.SendMessage (handle, OS.EM_SETCUEBANNER, 0, chars);
			}
		} else {
			OS.InvalidateRect (handle, null, true);
		}
	}
}

/**
 * Sets the orientation of the receiver, which must be one
 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 * <p>
 * Note: This operation is a hint and is not supported on
 * platforms that do not have this concept.
 * </p>
 *
 * @param orientation new orientation style
 * 
 * @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 2.1.2
 */
public void setOrientation (int orientation) {
	super.setOrientation (orientation);
}

/**
 * Sets the selection.
 * <p>
 * Indexing is zero based.  The range of
 * a selection is from 0..N where N is
 * the number of characters in the widget.
 * </p><p>
 * Text selections are specified in terms of
 * caret positions.  In a text widget that
 * contains N characters, there are N+1 caret
 * positions, ranging from 0..N.  This differs
 * from other functions that address character
 * position such as getText () that use the
 * regular array indexing rules.
 * </p>
 *
 * @param start new caret position
 *
 * @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>
 */
public void setSelection (int start) {
	checkWidget ();
	start = translateOffset (start);
	if (!OS.IsUnicode && OS.IsDBLocale) start = wcsToMbcsPos (start);
	OS.SendMessage (handle, OS.EM_SETSEL, start, start);
	OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
}

/**
 * Sets the selection to the range specified
 * by the given start and end indices.
 * <p>
 * Indexing is zero based.  The range of
 * a selection is from 0..N where N is
 * the number of characters in the widget.
 * </p><p>
 * Text selections are specified in terms of
 * caret positions.  In a text widget that
 * contains N characters, there are N+1 caret
 * positions, ranging from 0..N.  This differs
 * from other functions that address character
 * position such as getText () that use the
 * usual array indexing rules.
 * </p>
 *
 * @param start the start of the range
 * @param end the end of the range
 *
 * @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>
 */
public void setSelection (int start, int end) {
	checkWidget ();
	start = translateOffset (start);
	end = translateOffset (end);
	if (!OS.IsUnicode && OS.IsDBLocale) {
		start = wcsToMbcsPos (start);
		end = wcsToMbcsPos (end);
	}
	OS.SendMessage (handle, OS.EM_SETSEL, start, end);
	OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
}

public void setRedraw (boolean redraw) {
	checkWidget ();
	super.setRedraw (redraw);
	/*
	* Feature in Windows.  When WM_SETREDRAW is used to turn
	* redraw off, the edit control is not scrolled to show the
	* i-beam.  The fix is to detect that the i-beam has moved
	* while redraw is turned off and force it to be visible
	* when redraw is restored.
	*/
	if (!getDrawing ()) return;
	int [] start = new int [1], end = new int [1];
	OS.SendMessage (handle, OS.EM_GETSEL, start, end);
	if (!redraw) {
		oldStart = start [0];  oldEnd = end [0];
	} else {
		if (oldStart == start [0] && oldEnd == end [0]) return;
		OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
	}
}

/**
 * Sets the selection to the range specified
 * by the given point, where the x coordinate
 * represents the start index and the y coordinate
 * represents the end index.
 * <p>
 * Indexing is zero based.  The range of
 * a selection is from 0..N where N is
 * the number of characters in the widget.
 * </p><p>
 * Text selections are specified in terms of
 * caret positions.  In a text widget that
 * contains N characters, there are N+1 caret
 * positions, ranging from 0..N.  This differs
 * from other functions that address character
 * position such as getText () that use the
 * usual array indexing rules.
 * </p>
 *
 * @param selection the point
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
 * </ul>
 * @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>
 */
public void setSelection (Point selection) {
	checkWidget ();
	if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
	setSelection (selection.x, selection.y);
}

/**
 * Sets the number of tabs.
 * <p>
 * Tab stop spacing is specified in terms of the
 * space (' ') character.  The width of a single
 * tab stop is the pixel width of the spaces.
 * </p>
 *
 * @param tabs the number of tabs
 *
 * </ul>
 * @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>
 */
public void setTabs (int tabs) {
	checkWidget ();
	if (tabs < 0) return;
	setTabStops (this.tabs = tabs);
}

void setTabStops (int tabs) {
	/*
	* Feature in Windows.  Windows expects the tab spacing in
	* dialog units so we must convert from space widths.  Due
	* to round off error, the tab spacing may not be the exact
	* number of space widths, depending on the font.
	*/
	int width = (getTabWidth (tabs) * 4) / OS.LOWORD (OS.GetDialogBaseUnits ());
	OS.SendMessage (handle, OS.EM_SETTABSTOPS, 1, new int [] {width});
}

/**
 * Sets the contents of the receiver to the given string. If the receiver has style
 * SINGLE and the argument contains multiple lines of text, the result of this
 * operation is undefined and may vary from platform to platform.
 *
 * @param string the new text
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>
 * @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>
 */
public void setText (String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	string = Display.withCrLf (string);
	if (hooks (SWT.Verify) || filters (SWT.Verify)) {
		int length = OS.GetWindowTextLength (handle);
		string = verifyText (string, 0, length, null);
		if (string == null) return;
	}
	clearSegments (false);
	int limit = (int)/*64*/OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
	if (string.length () > limit) string = string.substring (0, limit);
	TCHAR buffer = new TCHAR (getCodePage (), string, true);
	OS.SetWindowText (handle, buffer);
	applySegments ();
	/*
	* Bug in Windows.  When the widget is multi line
	* text widget, it does not send a WM_COMMAND with
	* control code EN_CHANGE from SetWindowText () to
	* notify the application that the text has changed.
	* The fix is to send the event.
	*/
	int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
	if ((bits & OS.ES_MULTILINE) != 0) {
		sendEvent (SWT.Modify);
		// widget could be disposed at this point
	}
}

/**
 * Sets the contents of the receiver to the characters in the array. If the receiver
 * has style <code>SWT.SINGLE</code> and the argument contains multiple lines of text
 * then the result of this operation is undefined and may vary between platforms.
 *
 * @param text a character array that contains the new text
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the array is null</li>
 * </ul>
 * @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>
 *
 * @see #getTextChars()
 *
 * @since 3.7
 */
public void setTextChars (char[] text) {
	checkWidget ();
	if (text == null) error (SWT.ERROR_NULL_ARGUMENT);
	text = Display.withCrLf (text);
	if (hooks (SWT.Verify) || filters (SWT.Verify)) {
		int length = OS.GetWindowTextLength (handle);
		String string = verifyText (new String (text), 0, length, null);
		if (string == null) return;
		text = new char [string.length()];
		string.getChars (0, text.length, text, 0);
	}
	clearSegments (false);
	int limit = (int)/*64*/OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
	if (text.length > limit) {
		char [] temp = new char [limit];
		for (int i = 0; i < limit; i++) temp [i] = text [i];
		text = temp;
	}
	TCHAR buffer = new TCHAR (getCodePage (), text, true);
	OS.SetWindowText (handle, buffer);
	applySegments ();
	/*
	* Bug in Windows.  When the widget is multi line
	* text widget, it does not send a WM_COMMAND with
	* control code EN_CHANGE from SetWindowText () to
	* notify the application that the text has changed.
	* The fix is to send the event.
	*/
	int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
	if ((bits & OS.ES_MULTILINE) != 0) {
		sendEvent (SWT.Modify);
		// widget could be disposed at this point
	}
}

/**
 * Sets the maximum number of characters that the receiver
 * is capable of holding to be the argument.
 * <p>
 * Instead of trying to set the text limit to zero, consider
 * creating a read-only text widget.
 * </p><p>
 * To reset this value to the default, use <code>setTextLimit(Text.LIMIT)</code>.
 * Specifying a limit value larger than <code>Text.LIMIT</code> sets the
 * receiver's limit to <code>Text.LIMIT</code>.
 * </p>
 *
 * @param limit new text limit
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
 * </ul>
 * @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>
 * 
 * @see #LIMIT
 */
public void setTextLimit (int limit) {
	checkWidget ();
	if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
	if (segments != null && limit > 0) {
		OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit + Math.min (segments.length, LIMIT - limit), 0);
	} else {
		OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit, 0);
	}
}

/**
 * Sets the zero-relative index of the line which is currently
 * at the top of the receiver. This index can change when lines
 * are scrolled or new lines are added and removed.
 *
 * @param index the index of the top item
 *
 * @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>
 */
public void setTopIndex (int index) {
	checkWidget ();
	if ((style & SWT.SINGLE) != 0) return;
	int count = (int)/*64*/OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
	index = Math.min (Math.max (index, 0), count - 1);
	int topIndex = (int)/*64*/OS.SendMessage (handle, OS.EM_GETFIRSTVISIBLELINE, 0, 0);
	OS.SendMessage (handle, OS.EM_LINESCROLL, 0, index - topIndex);
}

/**
 * Shows the selection.
 * <p>
 * If the selection is already showing
 * in the receiver, this method simply returns.  Otherwise,
 * lines are scrolled until the selection is visible.
 * </p>
 * 
 * @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>
 */
public void showSelection () {
	checkWidget ();
	OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
}

int translateOffset (int offset) {
	if (segments == null) return offset;
	for (int i = 0, nSegments = segments.length; i < nSegments && offset - i >= segments [i]; i++) {
		offset++;
	}	
	return offset;
}

int untranslateOffset (int offset) {
	if (segments == null) return offset;
	for (int i = 0, nSegments = segments.length; i < nSegments && offset > segments [i]; i++) {
		offset--;
	}
	return offset;
}

void updateMenuLocation (Event event) {
	Point point = display.map (this, null, getCaretLocation ());
	event.x = point.x;
	event.y = point.y + getLineHeight ();
}

void updateOrientation (){
	int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
	if ((style & SWT.RIGHT_TO_LEFT) != 0) {
		bits |= OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR;
	} else {
		bits &= ~(OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
	}
	OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
	fixAlignment ();
}

String verifyText (String string, int start, int end, Event keyEvent) {
	if (ignoreVerify) return string;
	Event event = new Event ();
	event.text = string;
	event.start = start;
	event.end = end;
	if (keyEvent != null) {
		event.character = keyEvent.character;
		event.keyCode = keyEvent.keyCode;
		event.stateMask = keyEvent.stateMask;
	}
	if (!OS.IsUnicode && OS.IsDBLocale) {
		event.start = mbcsToWcsPos (start);
		event.end = mbcsToWcsPos (end);
	}
	event.start = untranslateOffset (event.start);
	event.end = untranslateOffset (event.end);
	
	/*
	* It is possible (but unlikely), that application
	* code could have disposed the widget in the verify
	* event.  If this happens, answer null to cancel
	* the operation.
	*/
	sendEvent (SWT.Verify, event);
	if (!event.doit || isDisposed ()) return null;
	return event.text;
}

int wcsToMbcsPos (int wcsPos) {
	if (wcsPos <= 0) return 0;
	if (OS.IsUnicode) return wcsPos;
	int cp = getCodePage ();
	int wcsTotal = 0, mbcsTotal = 0;
	byte [] buffer = new byte [128];
	String delimiter = getLineDelimiter ();
	int delimiterSize = delimiter.length ();
	int count = (int)/*64*/OS.SendMessageA (handle, OS.EM_GETLINECOUNT, 0, 0);
	for (int line=0; line<count; line++) {
		int wcsSize = 0;
		int linePos = (int)/*64*/OS.SendMessageA (handle, OS.EM_LINEINDEX, line, 0);
		int mbcsSize = (int)/*64*/OS.SendMessageA (handle, OS.EM_LINELENGTH, linePos, 0);
		if (mbcsSize != 0) {
			if (mbcsSize + delimiterSize > buffer.length) {
				buffer = new byte [mbcsSize + delimiterSize];
			}
			//ENDIAN
			buffer [0] = (byte) (mbcsSize & 0xFF);
			buffer [1] = (byte) (mbcsSize >> 8);
			mbcsSize = (int)/*64*/OS.SendMessageA (handle, OS.EM_GETLINE, line, buffer);
			wcsSize = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer, mbcsSize, null, 0);
		}
		if (line - 1 != count) {
			for (int i=0; i<delimiterSize; i++) {
				buffer [mbcsSize++] = (byte) delimiter.charAt (i);
			}
			wcsSize += delimiterSize;
		}
		if ((wcsTotal + wcsSize) >= wcsPos) {
			wcsSize = 0;
			int index = 0;
			while (index < mbcsSize) {
				if ((wcsTotal + wcsSize) == wcsPos) {
					return mbcsTotal + index;
				}
				if (OS.IsDBCSLeadByte (buffer [index++])) index++;
				wcsSize++;
			}
			return mbcsTotal + mbcsSize;
		}
		wcsTotal += wcsSize;
		mbcsTotal += mbcsSize;
	}
	return mbcsTotal;
}

int widgetStyle () {
	int bits = super.widgetStyle () | OS.ES_AUTOHSCROLL;
	if ((style & SWT.PASSWORD) != 0) bits |= OS.ES_PASSWORD;
	if ((style & SWT.CENTER) != 0) bits |= OS.ES_CENTER;
	if ((style & SWT.RIGHT) != 0) bits |= OS.ES_RIGHT;
	if ((style & SWT.READ_ONLY) != 0) bits |= OS.ES_READONLY;
	if ((style & SWT.SINGLE) != 0) {
		/*
		* Feature in Windows.  When a text control is read-only,
		* uses COLOR_3DFACE for the background .  If the text
		* controls single-line and is within a tab folder or
		* some other themed control, using WM_ERASEBKGND and
		* WM_CTRCOLOR to draw the theme background results in
		* pixel corruption.  The fix is to use an ES_MULTILINE
		* text control instead.
		*/
		if ((style & SWT.READ_ONLY) != 0) {
			if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
				if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
					bits |= OS.ES_MULTILINE;
				}
			}
		}
		return bits;
	}
	bits |= OS.ES_MULTILINE | OS.ES_NOHIDESEL | OS.ES_AUTOVSCROLL;	
	if ((style & SWT.WRAP) != 0) bits &= ~(OS.WS_HSCROLL | OS.ES_AUTOHSCROLL);
	return bits;
}

TCHAR windowClass () {
	return EditClass;
}

long /*int*/ windowProc () {
	return EditProc;
}

long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /*int*/ lParam) {
	boolean processSegments = false, redraw = false;
	long /*int*/ code;
	if (hooks (SWT.Segments) || filters (SWT.Segments)) {
		switch (msg) {
			case OS.EM_UNDO:
			case OS.WM_UNDO:
			case OS.EM_CANUNDO:
				return 0;
			case OS.WM_KEYDOWN: 
				processSegments = wParam == OS.VK_DELETE;
				break;
			case OS.WM_COPY:
				processSegments = segments != null;
				break;
			case OS.WM_CHAR: 
				processSegments = !ignoreCharacter && OS.GetKeyState (OS.VK_CONTROL) >= 0 && OS.GetKeyState (OS.VK_MENU) >= 0;
				break;
			case OS.WM_PASTE:
			case OS.WM_CUT:
			case OS.WM_CLEAR:
				processSegments = true;
				break;
		}
	}
	if (processSegments) {
		if (getDrawing () && OS.IsWindowVisible (handle)) {
			redraw = true;
			OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
		}
		clearSegments (true);
	}
	if (msg == OS.EM_UNDO) {
		int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
		if ((bits & OS.ES_MULTILINE) == 0) {
			LRESULT result = wmClipboard (OS.EM_UNDO, wParam, lParam);
			if (result != null) return result.value;
			return callWindowProc (hwnd, OS.EM_UNDO, wParam, lParam);
		}
	}
	if (msg == OS.EM_SETPASSWORDCHAR) {
		if (!allowPasswordChar) {
			return 1;
		}
	}
	if (msg == Display.SWT_RESTORECARET) {
		callWindowProc (hwnd, OS.WM_KILLFOCUS, 0, 0);
		callWindowProc (hwnd, OS.WM_SETFOCUS, 0, 0);
		return 1;
	}
	code = super.windowProc (hwnd, msg, wParam, lParam);
	if (processSegments) {
		applySegments ();
		if (redraw) {
			OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
			OS.InvalidateRect (handle, null, true);
		}
		OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
	}
	return code;
}

LRESULT WM_CHAR (long /*int*/ wParam, long /*int*/ lParam) {
	if (ignoreCharacter) return null;
	LRESULT result = super.WM_CHAR (wParam, lParam);
	if (result != null) return result;
	
	/*
	* Bug in Windows.  When the user types CTRL and BS
	* in an edit control, a DEL character is generated.
	* Rather than deleting the text, the DEL character
	* is inserted into the control.  The fix is to detect
	* this case and not call the window proc.
	*/
	switch ((int)/*64*/wParam) {
		case SWT.DEL:
			if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
				return LRESULT.ZERO;
			}
	}
	
	/*
	* Feature in Windows.  For some reason, when the
	* widget is a single line text widget, when the
	* user presses tab, return or escape, Windows beeps.
	* The fix is to look for these keys and not call
	* the window proc.
	*/
	if ((style & SWT.SINGLE) != 0) {
		switch ((int)/*64*/wParam) {
			case SWT.CR:
				sendSelectionEvent (SWT.DefaultSelection);
				// FALL THROUGH
			case SWT.TAB:
			case SWT.ESC: return LRESULT.ZERO;
		}
	}
	return result;
}

LRESULT WM_CLEAR (long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.WM_CLEAR (wParam, lParam);
	if (result != null) return result;
	return wmClipboard (OS.WM_CLEAR, wParam, lParam);
}

LRESULT WM_CUT (long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.WM_CUT (wParam, lParam);
	if (result != null) return result;
	return wmClipboard (OS.WM_CUT, wParam, lParam);
}

LRESULT WM_ERASEBKGND (long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
	if ((style & SWT.READ_ONLY) != 0) {
		if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
			int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
			if ((bits & OS.ES_MULTILINE) != 0) {
				Control control = findBackgroundControl ();
				if (control == null && background == -1) {
					if ((state & THEME_BACKGROUND) != 0) {
						if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
							control = findThemeControl ();
							if (control != null) {
								RECT rect = new RECT ();
								OS.GetClientRect (handle, rect);
								fillThemeBackground (wParam, control, rect);
								return LRESULT.ONE;
							}
						}
					}
				}
			}
		}
	}
	return result;
}

LRESULT WM_GETDLGCODE (long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
	if (result != null) return result;
	
	/*
	* Bug in WinCE PPC.  For some reason, sending WM_GETDLGCODE
	* to a multi-line edit control causes it to ignore return and
	* tab keys.  The fix is to return the value which is normally
	* returned by the text window proc on other versions of Windows.
	*/
	if (OS.IsPPC) {
		if ((style & SWT.MULTI) != 0 && (style & SWT.READ_ONLY) == 0 && lParam == 0) {
			return new LRESULT (OS.DLGC_HASSETSEL | OS.DLGC_WANTALLKEYS | OS.DLGC_WANTCHARS);
		}
	}

	/*
	* Feature in Windows.  Despite the fact that the
	* edit control is read only, it still returns a
	* dialog code indicating that it wants all keys.  
	* The fix is to detect this case and clear the bits.
	* 
	* NOTE: A read only edit control processes arrow keys
	* so DLGC_WANTARROWS should not be cleared.
	*/
	if ((style & SWT.READ_ONLY) != 0) {
		long /*int*/ code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
		code &= ~(OS.DLGC_WANTALLKEYS | OS.DLGC_WANTTAB);
		return new LRESULT (code);
	}
	return null;
}

LRESULT WM_GETOBJECT (long /*int*/ wParam, long /*int*/ lParam) {
	/*
	* Ensure that there is an accessible object created for this
	* control because support for search text accessibility is
	* implemented in the accessibility package.
	*/
	if ((style & SWT.SEARCH) != 0) {
		if (accessible == null) accessible = new_Accessible (this);
	}
	return super.WM_GETOBJECT (wParam, lParam);
}

LRESULT WM_IME_CHAR (long /*int*/ wParam, long /*int*/ lParam) {

	/* Process a DBCS character */
	Display display = this.display;
	display.lastKey = 0;
	display.lastAscii = (int)/*64*/wParam;
	display.lastVirtual = display.lastNull = display.lastDead = false;
	if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) {
		return LRESULT.ZERO;
	}

	/*
	* Feature in Windows.  The Windows text widget uses
	* two 2 WM_CHAR's to process a DBCS key instead of
	* using WM_IME_CHAR.  The fix is to allow the text
	* widget to get the WM_CHAR's but ignore sending
	* them to the application.
	*/
	ignoreCharacter = true;
	long /*int*/ result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam);
	MSG msg = new MSG ();
	int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
	while (OS.PeekMessage (msg, handle, OS.WM_CHAR, OS.WM_CHAR, flags)) {
		OS.TranslateMessage (msg);
		OS.DispatchMessage (msg);
	}
	ignoreCharacter = false;
	
	sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam);
	// widget could be disposed at this point
	display.lastKey = display.lastAscii = 0;
	return new LRESULT (result);
}

LRESULT WM_LBUTTONDBLCLK (long /*int*/ wParam, long /*int*/ lParam) {
	/*
	* Prevent Windows from processing WM_LBUTTONDBLCLK
	* when double clicking behavior is disabled by not
	* calling the window proc.
	*/
	LRESULT result = null;
	sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
	if (!sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam)) {
		result = LRESULT.ZERO;
	}
	if (!display.captureChanged && !isDisposed ()) {
		if (OS.GetCapture () != handle) OS.SetCapture (handle);
	}
	if (!doubleClick) return LRESULT.ZERO;
		
	/*
	* Bug in Windows.  When the last line of text in the
	* widget is double clicked and the line is empty, Windows
	* hides the i-beam then moves it to the first line in
	* the widget but does not scroll to show the user.
	* If the user types without clicking the mouse, invalid
	* characters are displayed at the end of each line of
	* text in the widget.  The fix is to detect this case
	* and avoid calling the window proc.
	*/
	int [] start = new int [1], end = new int [1];
	OS.SendMessage (handle, OS.EM_GETSEL, start, end);
	if (start [0] == end [0]) {
		int length = OS.GetWindowTextLength (handle);
		if (length == start [0]) {
			int code = (int)/*64*/OS.SendMessage (handle, OS.EM_LINELENGTH, length, 0);
			if (code == 0) return LRESULT.ZERO;
		}
	}
	return result;
}

LRESULT WM_LBUTTONDOWN (long /*int*/ wParam, long /*int*/ lParam) {
	if (OS.IsPPC) {
		LRESULT result = null;
		Display display = this.display;
		display.captureChanged = false;
		boolean dispatch = sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
		/*
		* Note: On WinCE PPC, only attempt to recognize the gesture for
		* a context menu when the control contains a valid menu or there
		* are listeners for the MenuDetect event.
		* 
		* Note: On WinCE PPC, the gesture that brings up a popup menu
		* on the text widget must keep the current text selection.  As a
		* result, the window proc is only called if the menu is not shown.
		*/
		boolean hasMenu = menu != null && !menu.isDisposed ();
		if (hasMenu || hooks (SWT.MenuDetect)) {
			int x = OS.GET_X_LPARAM (lParam);
			int y = OS.GET_Y_LPARAM (lParam);
			SHRGINFO shrg = new SHRGINFO ();
			shrg.cbSize = SHRGINFO.sizeof;
			shrg.hwndClient = handle;
			shrg.ptDown_x = x;
			shrg.ptDown_y = y; 
			shrg.dwFlags = OS.SHRG_RETURNCMD;
			int type = OS.SHRecognizeGesture (shrg);
			if (type == OS.GN_CONTEXTMENU) {
				showMenu (x, y);
				return LRESULT.ONE;
			}
		}
		if (dispatch) {
			result = new LRESULT (callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam));
		} else {
			result = LRESULT.ZERO;
		}
		if (!display.captureChanged && !isDisposed ()) {
			if (OS.GetCapture () != handle) OS.SetCapture (handle);
		}
		return result;
	}
	 return super.WM_LBUTTONDOWN (wParam, lParam);
}

LRESULT WM_PASTE (long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.WM_PASTE (wParam, lParam);
	if (result != null) return result;
	return wmClipboard (OS.WM_PASTE, wParam, lParam);
}

LRESULT WM_UNDO (long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.WM_UNDO (wParam, lParam);
	if (result != null) return result;
	return wmClipboard (OS.WM_UNDO, wParam, lParam);
}

LRESULT wmClipboard (int msg, long /*int*/ wParam, long /*int*/ lParam) {
	if ((style & SWT.READ_ONLY) != 0) return null;
	if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
	boolean call = false;
	int [] start = new int [1], end = new int [1];
	String newText = null;
	switch (msg) {
		case OS.WM_CLEAR:
		case OS.WM_CUT:
			OS.SendMessage (handle, OS.EM_GETSEL, start, end);
			if (start [0] != end [0]) {
				newText = "";
				call = true;
			}
			break;
		case OS.WM_PASTE:
			OS.SendMessage (handle, OS.EM_GETSEL, start, end);
			newText = getClipboardText ();
			break;
		case OS.EM_UNDO:
		case OS.WM_UNDO:
			if (OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0) != 0) {
				ignoreModify = ignoreCharacter = true;
				callWindowProc (handle, msg, wParam, lParam);
				int length = OS.GetWindowTextLength (handle);
				int [] newStart = new int [1], newEnd = new int [1];
				OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
				if (length != 0 && newStart [0] != newEnd [0]) {
					TCHAR buffer = new TCHAR (getCodePage (), length + 1);
					OS.GetWindowText (handle, buffer, length + 1);
					newText = buffer.toString (newStart [0], newEnd [0] - newStart [0]);
				} else {
					newText = "";
				}
				callWindowProc (handle, msg, wParam, lParam);
				OS.SendMessage (handle, OS.EM_GETSEL, start, end);
				ignoreModify = ignoreCharacter = false;
			}
			break;
	}
	if (newText != null) {
		String oldText = newText;
		newText = verifyText (newText, start [0], end [0], null);
		if (newText == null) return LRESULT.ZERO;
		if (!newText.equals (oldText)) {
			if (call) {
				callWindowProc (handle, msg, wParam, lParam);
			}
			newText = Display.withCrLf (newText);
			TCHAR buffer = new TCHAR (getCodePage (), newText, true);
			/*
			* Feature in Windows.  When an edit control with ES_MULTILINE
			* style that does not have the WS_VSCROLL style is full (i.e.
			* there is no space at the end to draw any more characters),
			* EM_REPLACESEL sends a WM_CHAR with a backspace character
			* to remove any further text that is added.  This is an
			* implementation detail of the edit control that is unexpected
			* and can cause endless recursion when EM_REPLACESEL is sent
			* from a WM_CHAR handler.  The fix is to ignore calling the
			* handler from WM_CHAR.
			*/
			ignoreCharacter = true;
			OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
			ignoreCharacter = false;
			return LRESULT.ZERO;
		}
	}
	if (msg == OS.WM_UNDO) {
		ignoreVerify = ignoreCharacter = true;
		callWindowProc (handle, OS.WM_UNDO, wParam, lParam);
		ignoreVerify = ignoreCharacter = false;
		return LRESULT.ONE;
	}
	return null;
}

LRESULT wmColorChild (long /*int*/ wParam, long /*int*/ lParam) {
	if ((style & SWT.READ_ONLY) != 0) {
		if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
			int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
			if ((bits & OS.ES_MULTILINE) != 0) {
				Control control = findBackgroundControl ();
				if (control == null && background == -1) {
					if ((state & THEME_BACKGROUND) != 0) {
						if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
							control = findThemeControl ();
							if (control != null) {
								OS.SetTextColor (wParam, getForegroundPixel ());
								OS.SetBkColor (wParam, getBackgroundPixel ());
								OS.SetBkMode (wParam, OS.TRANSPARENT);
								return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH));
							}
						}
					}
				}
			}
		}
	}
	return super.wmColorChild (wParam, lParam);
}

LRESULT wmCommandChild (long /*int*/ wParam, long /*int*/ lParam) {
	int code = OS.HIWORD (wParam);
	switch (code) {
		case OS.EN_CHANGE:
			if (findImageControl () != null) {
				OS.InvalidateRect (handle, null, true);
			}
			if (ignoreModify) break;
			/*
			* It is possible (but unlikely), that application
			* code could have disposed the widget in the modify
			* event.  If this happens, end the processing of the
			* Windows message by returning zero as the result of
			* the window proc.
			*/
			sendEvent (SWT.Modify);
			if (isDisposed ()) return LRESULT.ZERO;
			break;
		case OS.EN_ALIGN_LTR_EC:
		case OS.EN_ALIGN_RTL_EC:
			int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
			if ((bits & OS.WS_EX_RTLREADING) != 0) {
				style &= ~SWT.LEFT_TO_RIGHT;
				style |= SWT.RIGHT_TO_LEFT;
			} else {
				style &= ~SWT.RIGHT_TO_LEFT;
				style |= SWT.LEFT_TO_RIGHT;
			}
			Event event = new Event();
			event.doit = true;
			sendEvent(SWT.OrientationChange, event);
			if (!event.doit) {
				if (code == OS.EN_ALIGN_LTR_EC) {
					bits |= (OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
					style &= ~SWT.LEFT_TO_RIGHT;
					style |= SWT.RIGHT_TO_LEFT;
				} else {
					bits &= ~(OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
					style &= ~SWT.RIGHT_TO_LEFT;
					style |= SWT.LEFT_TO_RIGHT;
				}	
				OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
			} else {
				clearSegments (true);
				applySegments ();
			}
			fixAlignment();
			break;
	}
	return super.wmCommandChild (wParam, lParam);
}

LRESULT wmKeyDown (long /*int*/ hwnd, long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
	if (result != null) return result;
	
	if (segments != null) {
		switch ((int)/*64*/wParam) {
		case OS.VK_LEFT:
		case OS.VK_UP:
		case OS.VK_RIGHT:
		case OS.VK_DOWN:
			long /*int*/ code = 0;
			int [] start = new int [1], end = new int [1], newStart = new int [1], newEnd = new int [1];
			OS.SendMessage (handle, OS.EM_GETSEL, start, end);
			while (true) {
				code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
				OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
				if (newStart [0] != start [0]) {
					if (untranslateOffset (newStart [0]) != untranslateOffset (start [0])) break;
				} else if (newEnd [0] != end [0]) {
					if (untranslateOffset (newEnd [0]) != untranslateOffset (end [0]))  break;
				} else {
					break;
				}
				start [0] = newStart [0];
				end [0] = newEnd [0]; 
			}
			result = code == 0 ? LRESULT.ZERO : new LRESULT (code);
		}
	}
	return result; 
}

}
