New unicode edit control.

diff --git a/controls/edit.c b/controls/edit.c
index a7b52a2..a1484b4 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -21,6 +21,7 @@
 #include "win.h"
 #include "wine/winbase16.h"
 #include "wine/winuser16.h"
+#include "wine/unicode.h"
 #include "controls.h"
 #include "local.h"
 #include "debugtools.h"
@@ -33,9 +34,6 @@
 #define BUFLIMIT_MULTI		65534	/* maximum buffer size (not including '\0')
 					   FIXME: BTW, new specs say 65535 (do you dare ???) */
 #define BUFLIMIT_SINGLE		32766	/* maximum buffer size (not including '\0') */
-#define BUFSTART_MULTI		1024	/* starting size */
-#define BUFSTART_SINGLE		256	/* starting size */
-#define GROWLENGTH		64	/* buffers grow by this much */
 #define HSCROLL_FRACTION	3	/* scroll window by 1/3 width */
 
 /*
@@ -70,10 +68,10 @@
 
 typedef struct
 {
-	HANDLE heap;			/* our own heap */
-	LPSTR text;			/* the actual contents of the control */
-	UINT buffer_size;		/* the size of the buffer */
-	UINT buffer_limit;		/* the maximum size to which the buffer may grow */
+	BOOL is_unicode;		/* how the control was created */
+	LPWSTR text;			/* the actual contents of the control */
+	UINT buffer_size;		/* the size of the buffer in characters */
+	UINT buffer_limit;		/* the maximum size to which the buffer may grow in characters */
 	HFONT font;			/* NULL means standard system font */
 	INT x_offset;			/* scroll offset	for multi lines this is in pixels
 								for single lines it's in characters */
@@ -83,18 +81,18 @@
 	WORD flags;			/* flags that are not in es->style or wnd->flags (EF_XXX) */
 	INT undo_insert_count;	/* number of characters inserted in sequence */
 	UINT undo_position;		/* character index of the insertion and deletion */
-	LPSTR undo_text;		/* deleted text */
+	LPWSTR undo_text;		/* deleted text */
 	INT undo_buffer_size;		/* size of the deleted text buffer */
 	INT selection_start;		/* == selection_end if no selection */
 	INT selection_end;		/* == current caret position */
-	CHAR password_char;		/* == 0 if no password char, and for multi line controls */
+	WCHAR password_char;		/* == 0 if no password char, and for multi line controls */
 	INT left_margin;		/* in pixels */
 	INT right_margin;		/* in pixels */
 	RECT format_rect;
 	INT region_posx;		/* Position of cursor relative to region: */
 	INT region_posy;		/* -1: to left, 0: within, 1: to right */
 	EDITWORDBREAKPROC16 word_break_proc16;
-	EDITWORDBREAKPROCA word_break_proc32A;
+	void *word_break_proc;		/* 32-bit word break proc: ANSI or Unicode */
 	INT line_count;		/* number of lines */
 	INT y_offset;			/* scroll offset in number of lines */
 	BOOL bCaptureState; /* flag indicating whether mouse was captured */
@@ -108,8 +106,11 @@
 	LPINT tabs;
 	INT text_width;		/* width of the widest line in pixels */
 	LINEDEF *first_line_def;	/* linked list of (soft) linebreaks */
-	HLOCAL16 hloc16;		/* for controls receiving EM_GETHANDLE16 */
-	HLOCAL hloc32;		/* for controls receiving EM_GETHANDLE */
+	HLOCAL hloc32W;		/* our unicode local memory block */
+	HLOCAL16 hloc16;	/* alias for 16-bit control receiving EM_GETHANDLE16
+				   or EM_SETHANDLE16 */
+	HLOCAL hloc32A;		/* alias for ANSI control receiving EM_GETHANDLE
+				   or EM_SETHANDLE */
 } EDITSTATE;
 
 
@@ -125,24 +126,25 @@
 
 /* used for disabled or read-only edit control */
 #define EDIT_SEND_CTLCOLORSTATIC(wnd,hdc) \
-	(SendMessageA((wnd)->parent->hwndSelf, WM_CTLCOLORSTATIC, \
+	(SendMessageW((wnd)->parent->hwndSelf, WM_CTLCOLORSTATIC, \
 			(WPARAM)(hdc), (LPARAM)(wnd)->hwndSelf))
 #define EDIT_SEND_CTLCOLOR(wnd,hdc) \
-	(SendMessageA((wnd)->parent->hwndSelf, WM_CTLCOLOREDIT, \
+	(SendMessageW((wnd)->parent->hwndSelf, WM_CTLCOLOREDIT, \
 			(WPARAM)(hdc), (LPARAM)(wnd)->hwndSelf))
 #define EDIT_NOTIFY_PARENT(wnd, wNotifyCode, str) \
 	do {DPRINTF_EDIT_NOTIFY((wnd)->parent->hwndSelf, str); \
-	SendMessageA((wnd)->parent->hwndSelf, WM_COMMAND, \
+	SendMessageW((wnd)->parent->hwndSelf, WM_COMMAND, \
 		     MAKEWPARAM((wnd)->wIDmenu, wNotifyCode), \
 		     (LPARAM)(wnd)->hwndSelf);} while(0)
 #define DPRINTF_EDIT_MSG16(str) \
 	TRACE(\
 		     "16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
-		     (UINT)hwnd, (UINT)wParam, (UINT)lParam)
+		     (UINT)wnd->hwndSelf, (UINT)wParam, (UINT)lParam)
 #define DPRINTF_EDIT_MSG32(str) \
 	TRACE(\
-		     "32 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
-		     (UINT)hwnd, (UINT)wParam, (UINT)lParam)
+		     "32 bit %c : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
+		     unicode ? 'W' : 'A', \
+		     (UINT)wnd->hwndSelf, (UINT)wParam, (UINT)lParam)
 
 /*********************************************************************
  *
@@ -164,7 +166,7 @@
  *	Helper functions only valid for one type of control
  */
 static void	EDIT_BuildLineDefs_ML(WND *wnd, EDITSTATE *es);
-static LPSTR	EDIT_GetPasswordPointer_SL(EDITSTATE *es);
+static LPWSTR	EDIT_GetPasswordPointer_SL(EDITSTATE *es);
 static void	EDIT_MoveDown_ML(WND *wnd, EDITSTATE *es, BOOL extend);
 static void	EDIT_MovePageDown_ML(WND *wnd, EDITSTATE *es, BOOL extend);
 static void	EDIT_MovePageUp_ML(WND *wnd, EDITSTATE *es, BOOL extend);
@@ -191,7 +193,7 @@
 static void	EDIT_SetCaretPos(WND *wnd, EDITSTATE *es, INT pos, BOOL after_wrap); 
 static void	EDIT_SetRectNP(WND *wnd, EDITSTATE *es, LPRECT lprc);
 static void	EDIT_UnlockBuffer(WND *wnd, EDITSTATE *es, BOOL force);
-static INT	EDIT_WordBreakProc(LPSTR s, INT index, INT count, INT action);
+static INT CALLBACK EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action);
 /*
  *	EM_XXX message handlers
  */
@@ -199,7 +201,7 @@
 static BOOL	EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol);
 static HLOCAL	EDIT_EM_GetHandle(WND *wnd, EDITSTATE *es);
 static HLOCAL16	EDIT_EM_GetHandle16(WND *wnd, EDITSTATE *es);
-static INT	EDIT_EM_GetLine(EDITSTATE *es, INT line, LPSTR lpch);
+static INT	EDIT_EM_GetLine(EDITSTATE *es, INT line, LPWSTR lpch);
 static LRESULT	EDIT_EM_GetSel(EDITSTATE *es, LPUINT start, LPUINT end);
 static LRESULT	EDIT_EM_GetThumb(WND *wnd, EDITSTATE *es);
 static INT	EDIT_EM_LineFromChar(EDITSTATE *es, INT index);
@@ -207,31 +209,31 @@
 static INT	EDIT_EM_LineLength(EDITSTATE *es, INT index);
 static BOOL	EDIT_EM_LineScroll(WND *wnd, EDITSTATE *es, INT dx, INT dy);
 static LRESULT	EDIT_EM_PosFromChar(WND *wnd, EDITSTATE *es, INT index, BOOL after_wrap);
-static void	EDIT_EM_ReplaceSel(WND *wnd, EDITSTATE *es, BOOL can_undo, LPCSTR lpsz_replace, BOOL send_update);
+static void	EDIT_EM_ReplaceSel(WND *wnd, EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update);
 static LRESULT	EDIT_EM_Scroll(WND *wnd, EDITSTATE *es, INT action);
 static void	EDIT_EM_ScrollCaret(WND *wnd, EDITSTATE *es);
 static void	EDIT_EM_SetHandle(WND *wnd, EDITSTATE *es, HLOCAL hloc);
 static void	EDIT_EM_SetHandle16(WND *wnd, EDITSTATE *es, HLOCAL16 hloc);
 static void	EDIT_EM_SetLimitText(EDITSTATE *es, INT limit);
 static void	EDIT_EM_SetMargins(EDITSTATE *es, INT action, INT left, INT right);
-static void	EDIT_EM_SetPasswordChar(WND *wnd, EDITSTATE *es, CHAR c);
+static void	EDIT_EM_SetPasswordChar(WND *wnd, EDITSTATE *es, WCHAR c);
 static void	EDIT_EM_SetSel(WND *wnd, EDITSTATE *es, UINT start, UINT end, BOOL after_wrap);
 static BOOL	EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs);
 static BOOL	EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, LPINT16 tabs);
-static void	EDIT_EM_SetWordBreakProc(WND *wnd, EDITSTATE *es, EDITWORDBREAKPROCA wbp);
+static void	EDIT_EM_SetWordBreakProc(WND *wnd, EDITSTATE *es, LPARAM lParam);
 static void	EDIT_EM_SetWordBreakProc16(WND *wnd, EDITSTATE *es, EDITWORDBREAKPROC16 wbp);
 static BOOL	EDIT_EM_Undo(WND *wnd, EDITSTATE *es);
 /*
  *	WM_XXX message handlers
  */
-static void	EDIT_WM_Char(WND *wnd, EDITSTATE *es, CHAR c);
+static void	EDIT_WM_Char(WND *wnd, EDITSTATE *es, WCHAR c);
 static void	EDIT_WM_Command(WND *wnd, EDITSTATE *es, INT code, INT id, HWND conrtol);
 static void	EDIT_WM_ContextMenu(WND *wnd, EDITSTATE *es, INT x, INT y);
 static void	EDIT_WM_Copy(WND *wnd, EDITSTATE *es);
-static LRESULT	EDIT_WM_Create(WND *wnd, EDITSTATE *es, LPCREATESTRUCTA cs);
+static LRESULT	EDIT_WM_Create(WND *wnd, EDITSTATE *es, LPCWSTR name);
 static void	EDIT_WM_Destroy(WND *wnd, EDITSTATE *es);
 static LRESULT	EDIT_WM_EraseBkGnd(WND *wnd, EDITSTATE *es, HDC dc);
-static INT	EDIT_WM_GetText(EDITSTATE *es, INT count, LPSTR text);
+static INT	EDIT_WM_GetText(EDITSTATE *es, INT count, LPARAM lParam, BOOL unicode);
 static LRESULT	EDIT_WM_HScroll(WND *wnd, EDITSTATE *es, INT action, INT pos);
 static LRESULT	EDIT_WM_KeyDown(WND *wnd, EDITSTATE *es, INT key);
 static LRESULT	EDIT_WM_KillFocus(WND *wnd, EDITSTATE *es);
@@ -240,21 +242,20 @@
 static LRESULT	EDIT_WM_LButtonUp(HWND hwndSelf, EDITSTATE *es);
 static LRESULT	EDIT_WM_MButtonDown(WND *wnd);
 static LRESULT	EDIT_WM_MouseMove(WND *wnd, EDITSTATE *es, INT x, INT y);
-static LRESULT	EDIT_WM_NCCreate(WND *wnd, LPCREATESTRUCTA cs);
+static LRESULT	EDIT_WM_NCCreate(WND *wnd, DWORD style, HWND hwndParent, BOOL unicode);
 static void	EDIT_WM_Paint(WND *wnd, EDITSTATE *es, WPARAM wParam);
 static void	EDIT_WM_Paste(WND *wnd, EDITSTATE *es);
 static void	EDIT_WM_SetFocus(WND *wnd, EDITSTATE *es);
 static void	EDIT_WM_SetFont(WND *wnd, EDITSTATE *es, HFONT font, BOOL redraw);
-static void	EDIT_WM_SetText(WND *wnd, EDITSTATE *es, LPCSTR text);
+static void	EDIT_WM_SetText(WND *wnd, EDITSTATE *es, LPARAM lParam, BOOL unicode);
 static void	EDIT_WM_Size(WND *wnd, EDITSTATE *es, UINT action, INT width, INT height);
 static LRESULT	EDIT_WM_SysKeyDown(WND *wnd, EDITSTATE *es, INT key, DWORD key_data);
 static void	EDIT_WM_Timer(WND *wnd, EDITSTATE *es);
 static LRESULT	EDIT_WM_VScroll(WND *wnd, EDITSTATE *es, INT action, INT pos);
 static void EDIT_UpdateText(WND *wnd, LPRECT rc, BOOL bErase);
 
-LRESULT WINAPI EditWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
-
-
+LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+LRESULT WINAPI EditWndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
 /*********************************************************************
  * edit class descriptor
@@ -263,8 +264,8 @@
 {
     "Edit",               /* name */
     CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,   /* style */
-    EditWndProc,         /* procA */
-    NULL,                 /* procW (FIXME) */
+    EditWndProcA,         /* procA */
+    EditWndProcW,         /* procW */
     sizeof(EDITSTATE *),  /* extra */
     IDC_IBEAMA,           /* cursor */
     0                     /* brush */
@@ -278,7 +279,7 @@
  */
 static inline BOOL EDIT_EM_CanUndo(EDITSTATE *es)
 {
-	return (es->undo_insert_count || strlen(es->undo_text));
+	return (es->undo_insert_count || strlenW(es->undo_text));
 }
 
 
@@ -301,7 +302,9 @@
  */
 static inline void EDIT_WM_Clear(WND *wnd, EDITSTATE *es)
 {
-	EDIT_EM_ReplaceSel(wnd, es, TRUE, "", TRUE);
+	static const WCHAR empty_stringW[] = {0};
+
+	EDIT_EM_ReplaceSel(wnd, es, TRUE, empty_stringW, TRUE);
 
 	if (es->flags & EF_UPDATE) {
 		es->flags &= ~EF_UPDATE;
@@ -344,10 +347,10 @@
     if (!version)
     {
         DWORD dwEmulatedVersion;
-        OSVERSIONINFOA info;
+        OSVERSIONINFOW info;
         DWORD dwProcVersion = GetProcessVersion(0);
 
-        GetVersionExA( &info );
+        GetVersionExW( &info );
         dwEmulatedVersion = MAKELONG( info.dwMinorVersion, info.dwMajorVersion );
         /* fixme: this may not be 100% correct; see discussion on the
          * wine developer list in Nov 1999 */
@@ -359,7 +362,7 @@
 
 /*********************************************************************
  *
- *	EditWndProc   (USER32.@)
+ *	EditWndProc_locked
  *
  *	The messages are in the order of the actual integer values
  *	(which can be found in include/windows.h)
@@ -370,9 +373,9 @@
  *	names).
  *
  */
-LRESULT WINAPI EditWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
+static LRESULT WINAPI EditWndProc_locked( WND *wnd, UINT msg,
+                                          WPARAM wParam, LPARAM lParam, BOOL unicode )
 {
-	WND *wnd = WIN_FindWndPtr(hwnd);
 	EDITSTATE *es = *(EDITSTATE **)((wnd)->wExtra);
 	LRESULT result = 0;
 
@@ -385,13 +388,25 @@
 
 	case WM_NCCREATE:
 		DPRINTF_EDIT_MSG32("WM_NCCREATE");
-                result = EDIT_WM_NCCreate(wnd, (LPCREATESTRUCTA)lParam);
+		if(unicode)
+		{
+		    LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
+		    result = EDIT_WM_NCCreate(wnd, cs->style, cs->hwndParent, TRUE);
+		}
+		else
+		{
+		    LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
+		    result = EDIT_WM_NCCreate(wnd, cs->style, cs->hwndParent, FALSE);
+		}
                 goto END;
 	}
 
 	if (!es)
         {
-            result = DefWindowProcA(hwnd, msg, wParam, lParam);
+	    if(unicode)
+		result = DefWindowProcW(wnd->hwndSelf, msg, wParam, lParam);
+	    else
+		result = DefWindowProcA(wnd->hwndSelf, msg, wParam, lParam);
             goto END;
         }
 
@@ -564,7 +579,10 @@
 		/* fall through */
 	case 0x00bf:
 		DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report");
-		result = DefWindowProcA(hwnd, msg, wParam, lParam);
+		if(unicode)
+		    result = DefWindowProcW(wnd->hwndSelf, msg, wParam, lParam);
+		else
+		    result = DefWindowProcA(wnd->hwndSelf, msg, wParam, lParam);
 		break;
 
 	case WM_USER+16:
@@ -572,7 +590,10 @@
 		/* fall through */
 	case 0x00c0:
 		DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report");
-		result = DefWindowProcA(hwnd, msg, wParam, lParam);
+		if(unicode)
+		    result = DefWindowProcW(wnd->hwndSelf, msg, wParam, lParam);
+		else
+		    result = DefWindowProcA(wnd->hwndSelf, msg, wParam, lParam);
 		break;
 
 	case EM_LINELENGTH16:
@@ -588,15 +609,31 @@
 		lParam = (LPARAM)MapSL(lParam);
 		/* fall through */
 	case EM_REPLACESEL:
+	{
+		LPWSTR textW;
 		DPRINTF_EDIT_MSG32("EM_REPLACESEL");
-		EDIT_EM_ReplaceSel(wnd, es, (BOOL)wParam, (LPCSTR)lParam, TRUE);
+
+		if(unicode)
+		    textW = (LPWSTR)lParam;
+		else
+		{
+		    LPSTR textA = (LPSTR)lParam;
+		    INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
+		    if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
+			MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
+		}
+
+		EDIT_EM_ReplaceSel(wnd, es, (BOOL)wParam, textW, TRUE);
 		if (es->flags & EF_UPDATE) {
 			es->flags &= ~EF_UPDATE;
 			EDIT_NOTIFY_PARENT(wnd, EN_CHANGE, "EN_CHANGE");
 		}
 		result = 1;
-		break;
 
+		if(!unicode)
+		    HeapFree(GetProcessHeap(), 0, textW);
+		break;
+	}
 	/* message 0x00c3 missing from specs */
 
 	case WM_USER+19:
@@ -604,7 +641,10 @@
 		/* fall through */
 	case 0x00c3:
 		DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report");
-		result = DefWindowProcA(hwnd, msg, wParam, lParam);
+		if(unicode)
+		    result = DefWindowProcW(wnd->hwndSelf, msg, wParam, lParam);
+		else
+		    result = DefWindowProcA(wnd->hwndSelf, msg, wParam, lParam);
 		break;
 
 	case EM_GETLINE16:
@@ -613,7 +653,7 @@
 		/* fall through */
 	case EM_GETLINE:
 		DPRINTF_EDIT_MSG32("EM_GETLINE");
-		result = (LRESULT)EDIT_EM_GetLine(es, (INT)wParam, (LPSTR)lParam);
+		result = (LRESULT)EDIT_EM_GetLine(es, (INT)wParam, (LPWSTR)lParam);
 		break;
 
 	case EM_LIMITTEXT16:
@@ -665,7 +705,10 @@
 		/* fall through */
 	case 0x00ca:
 		DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report");
-		result = DefWindowProcA(hwnd, msg, wParam, lParam);
+		if(unicode)
+		    result = DefWindowProcW(wnd->hwndSelf, msg, wParam, lParam);
+		else
+		    result = DefWindowProcA(wnd->hwndSelf, msg, wParam, lParam);
 		break;
 
 	case EM_SETTABSTOPS16:
@@ -681,9 +724,21 @@
 		DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR");
 		/* fall through */
 	case EM_SETPASSWORDCHAR:
+	{
+		WCHAR charW = 0;
 		DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
-		EDIT_EM_SetPasswordChar(wnd, es, (CHAR)wParam);
+
+		if(unicode)
+		    charW = (WCHAR)wParam;
+		else
+		{
+		    CHAR charA = wParam;
+		    MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
+		}
+
+		EDIT_EM_SetPasswordChar(wnd, es, charW);
 		break;
+	}
 
 	case EM_EMPTYUNDOBUFFER16:
 		DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER");
@@ -723,7 +778,7 @@
 		break;
 	case EM_SETWORDBREAKPROC:
 		DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC");
-		EDIT_EM_SetWordBreakProc(wnd, es, (EDITWORDBREAKPROCA)lParam);
+		EDIT_EM_SetWordBreakProc(wnd, es, lParam);
 		break;
 
 	case EM_GETWORDBREAKPROC16:
@@ -732,16 +787,27 @@
 		break;
 	case EM_GETWORDBREAKPROC:
 		DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC");
-		result = (LRESULT)es->word_break_proc32A;
+		result = (LRESULT)es->word_break_proc;
 		break;
 
 	case EM_GETPASSWORDCHAR16:
 		DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR");
 		/* fall through */
 	case EM_GETPASSWORDCHAR:
+	{
 		DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
-		result = es->password_char;
+
+		if(unicode)
+		    result = es->password_char;
+		else
+		{
+		    WCHAR charW = es->password_char;
+		    CHAR charA = 0;
+		    WideCharToMultiByte(CP_ACP, 0, &charW, 1, &charA, 1, NULL, NULL);
+		    result = charA;
+		}
 		break;
+	}
 
 	/* The following EM_xxx are new to win95 and don't exist for 16 bit */
 
@@ -784,22 +850,34 @@
 		   }
 		   else if (es->hwndListBox && (vk == VK_RETURN || vk == VK_ESCAPE))
 		   {
-		      if (SendMessageA(wnd->parent->hwndSelf, CB_GETDROPPEDSTATE, 0, 0))
+		      if (SendMessageW(wnd->parent->hwndSelf, CB_GETDROPPEDSTATE, 0, 0))
 		         result |= DLGC_WANTMESSAGE;
 		   }
 		}
 		break;
 
 	case WM_CHAR:
+	{
+		WCHAR charW;
 		DPRINTF_EDIT_MSG32("WM_CHAR");
-		if (((CHAR)wParam == VK_RETURN || (CHAR)wParam == VK_ESCAPE) && es->hwndListBox)
+
+		if(unicode)
+		    charW = wParam;
+		else
 		{
-		   if (SendMessageA(wnd->parent->hwndSelf, CB_GETDROPPEDSTATE, 0, 0))
-		      SendMessageA(wnd->parent->hwndSelf, WM_KEYDOWN, wParam, 0);
+		    CHAR charA = wParam;
+		    MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
+		}
+
+		if ((charW == VK_RETURN || charW == VK_ESCAPE) && es->hwndListBox)
+		{
+		   if (SendMessageW(wnd->parent->hwndSelf, CB_GETDROPPEDSTATE, 0, 0))
+		      SendMessageW(wnd->parent->hwndSelf, WM_KEYDOWN, charW, 0);
 		   break;
 		}
-		EDIT_WM_Char(wnd, es, (CHAR)wParam);
+		EDIT_WM_Char(wnd, es, charW);
 		break;
+	}
 
 	case WM_CLEAR:
 		DPRINTF_EDIT_MSG32("WM_CLEAR");
@@ -823,7 +901,22 @@
 
 	case WM_CREATE:
 		DPRINTF_EDIT_MSG32("WM_CREATE");
-		result = EDIT_WM_Create(wnd, es, (LPCREATESTRUCTA)lParam);
+		if(unicode)
+		    result = EDIT_WM_Create(wnd, es, ((LPCREATESTRUCTW)lParam)->lpszName);
+		else
+		{
+		    LPCSTR nameA = ((LPCREATESTRUCTA)lParam)->lpszName;
+		    LPWSTR nameW = NULL;
+		    if(nameA)
+		    {
+			INT countW = MultiByteToWideChar(CP_ACP, 0, nameA, -1, NULL, 0);
+			if((nameW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
+			    MultiByteToWideChar(CP_ACP, 0, nameA, -1, nameW, countW);
+		    }
+		    result = EDIT_WM_Create(wnd, es, nameW);
+		    if(nameW)
+			HeapFree(GetProcessHeap(), 0, nameW);
+		}
 		break;
 
 	case WM_CUT:
@@ -849,12 +942,12 @@
 
 	case WM_GETTEXT:
 		DPRINTF_EDIT_MSG32("WM_GETTEXT");
-		result = (LRESULT)EDIT_WM_GetText(es, (INT)wParam, (LPSTR)lParam);
+		result = (LRESULT)EDIT_WM_GetText(es, (INT)wParam, lParam, unicode);
 		break;
 
 	case WM_GETTEXTLENGTH:
 		DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
-		result = strlen(es->text);
+		result = strlenW(es->text);
 		break;
 
 	case WM_HSCROLL:
@@ -884,7 +977,7 @@
 
 	case WM_LBUTTONUP:
 		DPRINTF_EDIT_MSG32("WM_LBUTTONUP");
-		result = EDIT_WM_LButtonUp(hwnd, es);
+		result = EDIT_WM_LButtonUp(wnd->hwndSelf, es);
 		break;
 
 	case WM_MBUTTONDOWN:                        
@@ -933,7 +1026,7 @@
 
 	case WM_SETTEXT:
 		DPRINTF_EDIT_MSG32("WM_SETTEXT");
-		EDIT_WM_SetText(wnd, es, (LPCSTR)lParam);
+		EDIT_WM_SetText(wnd, es, lParam, unicode);
 		result = TRUE;
 		break;
 
@@ -964,7 +1057,10 @@
                     SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
 
                     if (wParam & (MK_SHIFT | MK_CONTROL)) {
-                        result = DefWindowProcA(hwnd, msg, wParam, lParam);
+			if(unicode)
+			    result = DefWindowProcW(wnd->hwndSelf, msg, wParam, lParam);
+			else
+			    result = DefWindowProcA(wnd->hwndSelf, msg, wParam, lParam);
                         break;
                     }
                     gcWheelDelta -= SHIWORD(wParam);
@@ -972,21 +1068,51 @@
                     {
                         int cLineScroll= (int) min((UINT) es->line_count, pulScrollLines);
                         cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
-                    result = EDIT_EM_LineScroll(wnd, es, 0, cLineScroll);
+			result = EDIT_EM_LineScroll(wnd, es, 0, cLineScroll);
                     }
                 }
                 break;
 	default:
-		result = DefWindowProcA(hwnd, msg, wParam, lParam);
+		if(unicode)
+		    result = DefWindowProcW(wnd->hwndSelf, msg, wParam, lParam);
+		else
+		    result = DefWindowProcA(wnd->hwndSelf, msg, wParam, lParam);
 		break;
 	}
 	EDIT_UnlockBuffer(wnd, es, FALSE);
     END:
-        WIN_ReleaseWndPtr(wnd);
 	return result;
-        
 }
 
+/*********************************************************************
+ *
+ *	EditWndProcW   (USER32.@)
+ */
+LRESULT WINAPI EditWndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    LRESULT res;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    res = EditWndProc_locked(wndPtr, uMsg, wParam, lParam, TRUE);
+
+    WIN_ReleaseWndPtr(wndPtr);
+    return res;
+}
+
+/*********************************************************************
+ *
+ *	EditWndProcA   (USER32.@)
+ */
+LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    LRESULT res;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    res = EditWndProc_locked(wndPtr, uMsg, wParam, lParam, FALSE);
+
+    WIN_ReleaseWndPtr(wndPtr);
+    return res;
+}
 
 /*********************************************************************
  *
@@ -1001,7 +1127,7 @@
 {
 	HDC dc;
 	HFONT old_font = 0;
-	LPSTR start, cp;
+	LPWSTR start, cp;
 	INT fw;
 	LINEDEF *current_def;
 	LINEDEF **previous_next;
@@ -1009,7 +1135,7 @@
 	current_def = es->first_line_def;
 	do {
 		LINEDEF *next_def = current_def->next;
-		HeapFree(es->heap, 0, current_def);
+		HeapFree(GetProcessHeap(), 0, current_def);
 		current_def = next_def;
 	} while (current_def);
 	es->line_count = 0;
@@ -1023,7 +1149,7 @@
 	start = es->text;
 	previous_next = &es->first_line_def;
 	do {
-		current_def = HeapAlloc(es->heap, 0, sizeof(LINEDEF));
+		current_def = HeapAlloc(GetProcessHeap(), 0, sizeof(LINEDEF));
 		current_def->next = NULL;
 		cp = start;
 		while (*cp) {
@@ -1033,7 +1159,7 @@
 		}
 		if (!(*cp)) {
 			current_def->ending = END_0;
-			current_def->net_length = strlen(start);
+			current_def->net_length = strlenW(start);
 		} else if ((cp > start) && (*(cp - 1) == '\r')) {
 			current_def->ending = END_SOFT;
 			current_def->net_length = cp - start - 1;
@@ -1041,7 +1167,7 @@
 			current_def->ending = END_HARD;
 			current_def->net_length = cp - start;
 		}
-		current_def->width = (INT)LOWORD(GetTabbedTextExtentA(dc,
+		current_def->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
 					start, current_def->net_length,
 					es->tabs_count, es->tabs));
 		/* FIXME: check here for lines that are too wide even in AUTOHSCROLL (> 32767 ???) */
@@ -1052,7 +1178,7 @@
 				prev = next;
 				next = EDIT_CallWordBreakProc(wnd, es, start - es->text,
 						prev + 1, current_def->net_length, WB_RIGHT);
-				current_def->width = (INT)LOWORD(GetTabbedTextExtentA(dc,
+				current_def->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
 							start, next, es->tabs_count, es->tabs));
 			} while (current_def->width <= fw);
 			if (!prev) {
@@ -1060,7 +1186,7 @@
 				do {
 					prev = next;
 					next++;
-					current_def->width = (INT)LOWORD(GetTabbedTextExtentA(dc,
+					current_def->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
 								start, next, es->tabs_count, es->tabs));
 				} while (current_def->width <= fw);
 				if (!prev)
@@ -1068,7 +1194,7 @@
 			}
 			current_def->net_length = prev;
 			current_def->ending = END_WRAP;
-			current_def->width = (INT)LOWORD(GetTabbedTextExtentA(dc, start,
+			current_def->width = (INT)LOWORD(GetTabbedTextExtentW(dc, start,
 						current_def->net_length, es->tabs_count, es->tabs));
 		}
 		switch (current_def->ending) {
@@ -1113,24 +1239,56 @@
 /* ### stop build ### */
 static INT EDIT_CallWordBreakProc(WND *wnd, EDITSTATE *es, INT start, INT index, INT count, INT action)
 {
+    INT ret, iWndsLocks;
+
+    /* To avoid any deadlocks, all the locks on the windows structures
+       must be suspended before the control is passed to the application */
+    iWndsLocks = WIN_SuspendWndsLock();
+
 	if (es->word_break_proc16) {
-		HLOCAL16 hloc16 = EDIT_EM_GetHandle16(wnd, es);
-		SEGPTR segptr = LocalLock16(hloc16);
-		INT ret = (INT)EDIT_CallTo16_word_lwww(es->word_break_proc16,
-						segptr + start, index, count, action);
-		LocalUnlock16(hloc16);
-		return ret;
+	    HGLOBAL16 hglob16;
+	    SEGPTR segptr;
+	    INT countA;
+
+	    countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
+	    hglob16 = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, countA);
+	    segptr = WIN16_GlobalLock16(hglob16);
+	    WideCharToMultiByte(CP_ACP, 0, es->text + start, count, MapSL(segptr), countA, NULL, NULL);
+	    ret = (INT)EDIT_CallTo16_word_lwww(es->word_break_proc16,
+						segptr, index, countA, action);
+	    GlobalUnlock16(hglob16);
+	    GlobalFree16(hglob16);
 	}
-        else if (es->word_break_proc32A)
+	else if (es->word_break_proc)
         {
-            TRACE_(relay)("(wordbrk=%p,str='%s',idx=%d,cnt=%d,act=%d)\n",
-                           es->word_break_proc32A, es->text + start, index,
-                           count, action );
-            return (INT)es->word_break_proc32A( es->text + start, index,
-                                                  count, action );
+	    if(es->is_unicode)
+	    {
+		EDITWORDBREAKPROCW wbpW = (EDITWORDBREAKPROCW)es->word_break_proc;
+
+		TRACE_(relay)("(UNICODE wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
+			es->word_break_proc, debugstr_wn(es->text + start, count), index, count, action);
+		ret = wbpW(es->text + start, index, count, action);
+	    }
+	    else
+	    {
+		EDITWORDBREAKPROCA wbpA = (EDITWORDBREAKPROCA)es->word_break_proc;
+		INT countA;
+		CHAR *textA;
+
+		countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
+		textA = HeapAlloc(GetProcessHeap(), 0, countA);
+		WideCharToMultiByte(CP_ACP, 0, es->text + start, count, textA, countA, NULL, NULL);
+		TRACE_(relay)("(ANSI wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
+			es->word_break_proc, debugstr_an(textA, countA), index, countA, action);
+		ret = wbpA(textA, index, countA, action);
+		HeapFree(GetProcessHeap(), 0, textA);
+	    }
         }
 	else
-            return EDIT_WordBreakProc(es->text + start, index, count, action);
+            ret = EDIT_WordBreakProc(es->text + start, index, count, action);
+
+    WIN_RestoreWndsLock(iWndsLocks);
+    return ret;
 }
 
 
@@ -1179,7 +1337,7 @@
                     while (low < high - 1)
                     {
                         INT mid = (low + high) / 2;
-			if (LOWORD(GetTabbedTextExtentA(dc, es->text + line_index,mid - line_index, es->tabs_count, es->tabs)) > x) high = mid;
+			if (LOWORD(GetTabbedTextExtentW(dc, es->text + line_index,mid - line_index, es->tabs_count, es->tabs)) > x) high = mid;
                         else low = mid;
                     }
                     index = low;
@@ -1188,7 +1346,7 @@
 			*after_wrap = ((index == line_index + line_def->net_length) &&
 							(line_def->ending == END_WRAP));
 	} else {
-		LPSTR text;
+		LPWSTR text;
 		SIZE size;
 		if (after_wrap)
 			*after_wrap = FALSE;
@@ -1206,7 +1364,7 @@
                     while (low < high - 1)
                     {
                         INT mid = (low + high) / 2;
-                        GetTextExtentPoint32A( dc, text + mid,
+                        GetTextExtentPoint32W( dc, text + mid,
                                                es->x_offset - mid, &size );
                         if (size.cx > -x) low = mid;
                         else high = mid;
@@ -1216,11 +1374,11 @@
                 else
                 {
                     INT low = es->x_offset;
-                    INT high = strlen(es->text) + 1;
+                    INT high = strlenW(es->text) + 1;
                     while (low < high - 1)
                     {
                         INT mid = (low + high) / 2;
-                        GetTextExtentPoint32A( dc, text + es->x_offset,
+                        GetTextExtentPoint32W( dc, text + es->x_offset,
                                                mid - es->x_offset, &size );
                         if (size.cx > x) high = mid;
                         else low = mid;
@@ -1228,7 +1386,7 @@
                     index = low;
 		}
 		if (es->style & ES_PASSWORD)
-			HeapFree(es->heap, 0 ,text);
+			HeapFree(GetProcessHeap(), 0, text);
 	}
 	if (es->font)
 		SelectObject(dc, old_font);
@@ -1281,13 +1439,13 @@
  *	note: caller should free the (optionally) allocated buffer
  *
  */
-static LPSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
+static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
 {
 	if (es->style & ES_PASSWORD) {
-		INT len = strlen(es->text);
-		LPSTR text = HeapAlloc(es->heap, 0, len + 1);
-		RtlFillMemory(text, len, es->password_char);
+		INT len = strlenW(es->text);
+		LPWSTR text = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
 		text[len] = '\0';
+		while(--len) text[len] = es->password_char;
 		return text;
 	} else
 		return es->text;
@@ -1308,17 +1466,43 @@
 		ERR("no EDITSTATE ... please report\n");
 		return;
 	}
-	if (!(es->style & ES_MULTILINE))
-		return;
 	if (!es->text) {
-		if (es->hloc32)
-			es->text = LocalLock(es->hloc32);
-		else if (es->hloc16)
-			es->text = LOCAL_Lock(wnd->hInstance, es->hloc16);
-		else {
-			ERR("no buffer ... please report\n");
-			return;
+	    CHAR *textA = NULL;
+	    INT countA = 0;
+	    BOOL _16bit = FALSE;
+
+	    if(es->hloc32W)
+	    {
+		TRACE("Locking 32-bit UNICODE buffer\n");
+		es->text = LocalLock(es->hloc32W);
+
+		if(es->hloc32A)
+		{
+		    TRACE("Synchronizing with 32-bit ANSI buffer\n");
+		    countA = LocalSize(es->hloc32A);
+		    textA = LocalLock(es->hloc32A);
 		}
+		else if(es->hloc16)
+		{
+		    TRACE("Synchronizing with 16-bit ANSI buffer\n");
+		    countA = LOCAL_Size(wnd->hInstance, es->hloc16);
+		    textA = LOCAL_Lock(wnd->hInstance, es->hloc16);
+		    _16bit = TRUE;
+		}
+	    }
+	    else {
+		ERR("no buffer ... please report\n");
+		return;
+	    }
+
+	    if(textA)
+	    {
+		MultiByteToWideChar(CP_ACP, 0, textA, countA, es->text, es->buffer_size);
+		if(_16bit)
+		    LOCAL_Unlock(wnd->hInstance, es->hloc16);
+		else
+		    LocalUnlock(es->hloc32A);
+	    }
 	}
 	es->lock_count++;
 }
@@ -1422,7 +1606,7 @@
 		return;
 
 	if (end == -1)
-		end = strlen(es->text);
+		end = strlenW(es->text);
 
 	ORDER_INT(start, end);
 
@@ -1437,13 +1621,12 @@
  *
  *	EDIT_MakeFit
  *
- *	Try to fit size + 1 bytes in the buffer.  Constrain to limits.
+ *	Try to fit size + 1 characters in the buffer. Constrain to limits.
  *
  */
 static BOOL EDIT_MakeFit(WND *wnd, EDITSTATE *es, UINT size)
 {
-	HLOCAL hNew32;
-	HLOCAL16 hNew16;
+	HLOCAL hNew32W;
 
 	if (size <= es->buffer_size)
 		return TRUE;
@@ -1451,38 +1634,29 @@
 		EDIT_NOTIFY_PARENT(wnd, EN_MAXTEXT, "EN_MAXTEXT");
 		return FALSE;
 	}
-	size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
 	if (size > es->buffer_limit)
 		size = es->buffer_limit;
 
-	TRACE("trying to ReAlloc to %d+1\n", size);
+	TRACE("trying to ReAlloc to %d+1 characters\n", size);
 
+	/* Force edit to unlock it's buffer. es->text now NULL */
 	EDIT_UnlockBuffer(wnd, es, TRUE);
-	if (es->text) {
-		if ((es->text = HeapReAlloc(es->heap, 0, es->text, size + 1)))
-			es->buffer_size = min(HeapSize(es->heap, 0, es->text) - 1, es->buffer_limit);
-		else
-			es->buffer_size = 0;
-	} else if (es->hloc32) {
-		if ((hNew32 = LocalReAlloc(es->hloc32, size + 1, 0))) {
-			TRACE("Old 32 bit handle %08x, new handle %08x\n", es->hloc32, hNew32);
-			es->hloc32 = hNew32;
-			es->buffer_size = min(LocalSize(es->hloc32) - 1, es->buffer_limit);
-		}
-	} else if (es->hloc16) {
-		if ((hNew16 = LOCAL_ReAlloc(wnd->hInstance, es->hloc16, size + 1, LMEM_MOVEABLE))) {
-			TRACE("Old 16 bit handle %08x, new handle %08x\n", es->hloc16, hNew16);
-			es->hloc16 = hNew16;
-			es->buffer_size = min((UINT)LOCAL_Size(wnd->hInstance, es->hloc16) - 1, es->buffer_limit);
-		}
+
+	if (es->hloc32W) {
+	    if ((hNew32W = LocalReAlloc(es->hloc32W, (size + 1) * sizeof(WCHAR), LMEM_MOVEABLE | LMEM_ZEROINIT))) {
+		TRACE("Old 32 bit handle %08x, new handle %08x\n", es->hloc32W, hNew32W);
+		es->hloc32W = hNew32W;
+		es->buffer_size = LocalSize(hNew32W)/sizeof(WCHAR) - 1;
+	    }
 	}
+
+	EDIT_LockBuffer(wnd, es);
+
 	if (es->buffer_size < size) {
-		EDIT_LockBuffer(wnd, es);
 		WARN("FAILED !  We now have %d+1\n", es->buffer_size);
 		EDIT_NOTIFY_PARENT(wnd, EN_ERRSPACE, "EN_ERRSPACE");
 		return FALSE;
 	} else {
-		EDIT_LockBuffer(wnd, es);
 		TRACE("We now have %d+1\n", es->buffer_size);
 		return TRUE;
 	}
@@ -1500,19 +1674,18 @@
 {
 	if (size <= es->undo_buffer_size)
 		return TRUE;
-	size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
 
 	TRACE("trying to ReAlloc to %d+1\n", size);
 
-	if ((es->undo_text = HeapReAlloc(es->heap, 0, es->undo_text, size + 1))) {
-		es->undo_buffer_size = HeapSize(es->heap, 0, es->undo_text) - 1;
-		if (es->undo_buffer_size < size) {
-			WARN("FAILED !  We now have %d+1\n", es->undo_buffer_size);
-			return FALSE;
-		}
+	if ((es->undo_text = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, es->undo_text, (size + 1) * sizeof(WCHAR)))) {
+		es->undo_buffer_size = size;
 		return TRUE;
 	}
-	return FALSE;
+	else
+	{
+		WARN("FAILED !  We now have %d+1\n", es->undo_buffer_size);
+		return FALSE;
+	}
 }
 
 
@@ -1575,12 +1748,12 @@
 	BOOL after_wrap = FALSE;
 	INT e;
 
-	/* Pass a high value in x to make sure of receiving the en of the line */
+	/* Pass a high value in x to make sure of receiving the end of the line */
 	if (es->style & ES_MULTILINE)
 		e = EDIT_CharFromPos(wnd, es, 0x3fffffff,
 			HIWORD(EDIT_EM_PosFromChar(wnd, es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
 	else
-		e = strlen(es->text);
+		e = strlenW(es->text);
 	EDIT_EM_SetSel(wnd, es, extend ? es->selection_start : e, e, after_wrap);
 	EDIT_EM_ScrollCaret(wnd, es);
 }
@@ -1842,15 +2015,15 @@
 	}
 	li = EDIT_EM_LineIndex(es, line);
 	if (es->style & ES_MULTILINE) {
-		ret = (INT)LOWORD(TabbedTextOutA(dc, x, y, es->text + li + col, count,
+		ret = (INT)LOWORD(TabbedTextOutW(dc, x, y, es->text + li + col, count,
 					es->tabs_count, es->tabs, es->format_rect.left - es->x_offset));
 	} else {
-		LPSTR text = EDIT_GetPasswordPointer_SL(es);
-		TextOutA(dc, x, y, text + li + col, count);
-		GetTextExtentPoint32A(dc, text + li + col, count, &size);
+		LPWSTR text = EDIT_GetPasswordPointer_SL(es);
+		TextOutW(dc, x, y, text + li + col, count);
+		GetTextExtentPoint32W(dc, text + li + col, count, &size);
 		ret = size.cx;
 		if (es->style & ES_PASSWORD)
-			HeapFree(es->heap, 0, text);
+			HeapFree(GetProcessHeap(), 0, text);
 	}
 	if (rev) {
 		SetBkColor(dc, BkColor);
@@ -1929,8 +2102,6 @@
 		ERR("no EDITSTATE ... please report\n");
 		return;
 	}
-	if (!(es->style & ES_MULTILINE))
-		return;
 	if (!es->lock_count) {
 		ERR("lock_count == 0 ... please report\n");
 		return;
@@ -1939,14 +2110,43 @@
 		ERR("es->text == 0 ... please report\n");
 		return;
 	}
+
 	if (force || (es->lock_count == 1)) {
-		if (es->hloc32) {
-			LocalUnlock(es->hloc32);
-			es->text = NULL;
-		} else if (es->hloc16) {
-			LOCAL_Unlock(wnd->hInstance, es->hloc16);
-			es->text = NULL;
+	    if (es->hloc32W) {
+		CHAR *textA = NULL;
+		BOOL _16bit = FALSE;
+		INT countA = 0;
+
+		if(es->hloc32A)
+		{
+		    TRACE("Synchronizing with 32-bit ANSI buffer\n");
+		    countA = LocalSize(es->hloc32A);
+		    textA = LocalLock(es->hloc32A);
 		}
+		else if(es->hloc16)
+		{
+		    TRACE("Synchronizing with 16-bit ANSI buffer\n");
+		    countA = LOCAL_Size(wnd->hInstance, es->hloc16);
+		    textA = LOCAL_Lock(wnd->hInstance, es->hloc16);
+		    _16bit = TRUE;
+		}
+
+		if(textA)
+		{
+		    WideCharToMultiByte(CP_ACP, 0, es->text, es->buffer_size, textA, countA, NULL, NULL);
+		    if(_16bit)
+			LOCAL_Unlock(wnd->hInstance, es->hloc16);
+		    else
+			LocalUnlock(es->hloc32A);
+		}
+
+		LocalUnlock(es->hloc32W);
+		es->text = NULL;
+	    }
+	    else {
+		ERR("no buffer ... please report\n");
+		return;
+	    }
 	}
 	es->lock_count--;
 }
@@ -1963,12 +2163,13 @@
  *		internally, so we can decide this for ourselves.
  *
  */
-static INT EDIT_WordBreakProc(LPSTR s, INT index, INT count, INT action)
+static INT CALLBACK EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action)
 {
 	INT ret = 0;
 
-	TRACE("s=%p, index=%u, count=%u, action=%d\n", 
-		     s, index, count, action);
+	TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
+
+	if(!s) return 0;
 
 	switch (action) {
 	case WB_LEFT:
@@ -2068,53 +2269,43 @@
  *	EM_GETHANDLE
  *
  *	Hopefully this won't fire back at us.
- *	We always start with a fixed buffer in our own heap.
- *	However, with this message a 32 bit application requests
- *	a handle to 32 bit moveable local heap memory, where it expects
- *	to find the text.
- *	It's a pity that from this moment on we have to use this
- *	local heap, because applications may rely on the handle
- *	in the future.
- *
- *	In this function we'll try to switch to local heap.
+ *	We always start with a fixed buffer in the local heap.
+ *	Despite of the documenation says that the local heap is used
+ *	only if DS_LOCALEDIT flag is set, NT and 2000 always allocate
+ *	buffer on the local heap.
  *
  */
 static HLOCAL EDIT_EM_GetHandle(WND *wnd, EDITSTATE *es)
 {
-	HLOCAL newBuf;
-	LPSTR newText;
-	INT newSize;
+	HLOCAL hLocal;
 
 	if (!(es->style & ES_MULTILINE))
 		return 0;
 
-	if (es->hloc32)
-		return es->hloc32;
-	else if (es->hloc16)
-		return (HLOCAL)es->hloc16;
-
-	if (!(newBuf = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, strlen(es->text) + 1))) {
-		ERR("could not allocate new 32 bit buffer\n");
-		return 0;
+	if(es->is_unicode)
+	    hLocal = es->hloc32W;
+	else
+	{
+	    if(!es->hloc32A)
+	    {
+		CHAR *textA;
+		INT countA;
+		TRACE("Allocating 32-bit ANSI alias buffer\n");
+		countA = WideCharToMultiByte(CP_ACP, 0, es->text, es->buffer_size, NULL, 0, NULL, NULL);
+		if(!(es->hloc32A = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, countA)))
+		{
+		    ERR("Could not allocate %d bytes for 32-bit ANSI alias buffer\n", countA);
+		    return 0;
+		}
+		textA = LocalLock(es->hloc32A);
+		WideCharToMultiByte(CP_ACP, 0, es->text, es->buffer_size, textA, countA, NULL, NULL);
+		LocalUnlock(es->hloc32A);
+	    }
+	    hLocal = es->hloc32A;
 	}
-	newSize = min(LocalSize(newBuf) - 1, es->buffer_limit);
-	if (!(newText = LocalLock(newBuf))) {
-		ERR("could not lock new 32 bit buffer\n");
-		LocalFree(newBuf);
-		return 0;
-	}
-	strcpy(newText, es->text);
-	EDIT_UnlockBuffer(wnd, es, TRUE);
-	if (es->text)
-		HeapFree(es->heap, 0, es->text);
-	es->hloc32 = newBuf;
-	es->hloc16 = (HLOCAL16)NULL;
-	es->buffer_size = newSize;
-	es->text = newText;
-	EDIT_LockBuffer(wnd, es);
-	TRACE("switched to 32 bit local heap\n");
 
-	return es->hloc32;
+	TRACE("Returning %04X, LocalSize() = %d\n", hLocal, LocalSize(hLocal));
+	return hLocal;
 }
 
 
@@ -2135,9 +2326,8 @@
  */
 static HLOCAL16 EDIT_EM_GetHandle16(WND *wnd, EDITSTATE *es)
 {
-	HLOCAL16 newBuf;
-	LPSTR newText;
-	INT newSize;
+	CHAR *textA;
+	INT countA;
 
 	if (!(es->style & ES_MULTILINE))
 		return 0;
@@ -2153,31 +2343,26 @@
 		}
 		TRACE("local heap initialized\n");
 	}
-	if (!(newBuf = LOCAL_Alloc(wnd->hInstance, LMEM_MOVEABLE, strlen(es->text) + 1))) {
+
+	countA = WideCharToMultiByte(CP_ACP, 0, es->text, es->buffer_size, NULL, 0, NULL, NULL);
+
+	TRACE("Allocating 16-bit ANSI alias buffer\n");
+	if (!(es->hloc16 = LOCAL_Alloc(wnd->hInstance, LMEM_MOVEABLE | LMEM_ZEROINIT, countA))) {
 		ERR("could not allocate new 16 bit buffer\n");
 		return 0;
 	}
-	newSize = min((UINT)LOCAL_Size(wnd->hInstance, newBuf) - 1, es->buffer_limit);
-	if (!(newText = LOCAL_Lock(wnd->hInstance, newBuf))) {
+
+	if (!(textA = (LPSTR)LOCAL_Lock(wnd->hInstance, es->hloc16))) {
 		ERR("could not lock new 16 bit buffer\n");
-		LOCAL_Free(wnd->hInstance, newBuf);
+		LOCAL_Free(wnd->hInstance, es->hloc16);
+		es->hloc16 = 0;
 		return 0;
 	}
-	strcpy(newText, es->text);
-	EDIT_UnlockBuffer(wnd, es, TRUE);
-	if (es->text)
-		HeapFree(es->heap, 0, es->text);
-	else if (es->hloc32) {
-		while (LocalFree(es->hloc32)) ;
-		LocalFree(es->hloc32);
-	}
-	es->hloc32 = (HLOCAL)NULL;
-	es->hloc16 = newBuf;
-	es->buffer_size = newSize;
-	es->text = newText;
-	EDIT_LockBuffer(wnd, es);
-	TRACE("switched to 16 bit buffer\n");
 
+	WideCharToMultiByte(CP_ACP, 0, es->text, es->buffer_size, textA, countA, NULL, NULL);
+	LOCAL_Unlock(wnd->hInstance, es->hloc16);
+
+	TRACE("Returning %04X, LocalSize() = %d\n", es->hloc16, LOCAL_Size(wnd->hInstance, es->hloc16));
 	return es->hloc16;
 }
 
@@ -2187,9 +2372,9 @@
  *	EM_GETLINE
  *
  */
-static INT EDIT_EM_GetLine(EDITSTATE *es, INT line, LPSTR lpch)
+static INT EDIT_EM_GetLine(EDITSTATE *es, INT line, LPWSTR lpch)
 {
-	LPSTR src;
+	LPWSTR src;
 	INT len;
 	INT i;
 
@@ -2261,7 +2446,7 @@
 
 	if (!(es->style & ES_MULTILINE))
 		return 0;
-	if (index > (INT)strlen(es->text))
+	if (index > (INT)strlenW(es->text))
 		return es->line_count - 1;
 	if (index == -1)
 		index = min(es->selection_start, es->selection_end);
@@ -2323,7 +2508,7 @@
 	LINEDEF *line_def;
 
 	if (!(es->style & ES_MULTILINE))
-		return strlen(es->text);
+		return strlenW(es->text);
 
 	if (index == -1) {
 		/* get the number of remaining non-selected chars of selected lines */
@@ -2397,7 +2582,7 @@
  */
 static LRESULT EDIT_EM_PosFromChar(WND *wnd, EDITSTATE *es, INT index, BOOL after_wrap)
 {
-	INT len = strlen(es->text);
+	INT len = strlenW(es->text);
 	INT l;
 	INT li;
 	INT x;
@@ -2427,22 +2612,22 @@
 				li = EDIT_EM_LineIndex(es, l);
 			}
 		}
-		x = LOWORD(GetTabbedTextExtentA(dc, es->text + li, index - li,
+		x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
 				es->tabs_count, es->tabs)) - es->x_offset;
 	} else {
-		LPSTR text = EDIT_GetPasswordPointer_SL(es);
+		LPWSTR text = EDIT_GetPasswordPointer_SL(es);
 		if (index < es->x_offset) {
-			GetTextExtentPoint32A(dc, text + index,
+			GetTextExtentPoint32W(dc, text + index,
 					es->x_offset - index, &size);
 			x = -size.cx;
 		} else {
-			GetTextExtentPoint32A(dc, text + es->x_offset,
+			GetTextExtentPoint32W(dc, text + es->x_offset,
 					index - es->x_offset, &size);
 			 x = size.cx;
 		}
 		y = 0;
 		if (es->style & ES_PASSWORD)
-			HeapFree(es->heap, 0 ,text);
+			HeapFree(GetProcessHeap(), 0, text);
 	}
 	x += es->format_rect.left;
 	y += es->format_rect.top;
@@ -2460,15 +2645,18 @@
  *	FIXME: handle ES_NUMBER and ES_OEMCONVERT here
  *
  */
-static void EDIT_EM_ReplaceSel(WND *wnd, EDITSTATE *es, BOOL can_undo, LPCSTR lpsz_replace, BOOL send_update)
+static void EDIT_EM_ReplaceSel(WND *wnd, EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update)
 {
-	UINT strl = strlen(lpsz_replace);
-	UINT tl = strlen(es->text);
+	UINT strl = strlenW(lpsz_replace);
+	UINT tl = strlenW(es->text);
 	UINT utl;
 	UINT s;
 	UINT e;
 	UINT i;
-	LPSTR p;
+	LPWSTR p;
+
+	TRACE("%s, can_undo %d, send_update %d\n",
+	    debugstr_w(lpsz_replace), can_undo, send_update);
 
 	s = es->selection_start;
 	e = es->selection_end;
@@ -2484,11 +2672,11 @@
 	if (e != s) {
 		/* there is something to be deleted */
 		if (can_undo) {
-			utl = strlen(es->undo_text);
+			utl = strlenW(es->undo_text);
 			if (!es->undo_insert_count && (*es->undo_text && (s == es->undo_position))) {
 				/* undo-buffer is extended to the right */
 				EDIT_MakeUndoFit(es, utl + e - s);
-				lstrcpynA(es->undo_text + utl, es->text + s, e - s + 1);
+				strncpyW(es->undo_text + utl, es->text + s, e - s + 1);
 			} else if (!es->undo_insert_count && (*es->undo_text && (e == es->undo_position))) {
 				/* undo-buffer is extended to the left */
 				EDIT_MakeUndoFit(es, utl + e - s);
@@ -2500,7 +2688,7 @@
 			} else {
 				/* new undo-buffer */
 				EDIT_MakeUndoFit(es, e - s);
-				lstrcpynA(es->undo_text, es->text + s, e - s + 1);
+				strncpyW(es->undo_text, es->text + s, e - s + 1);
 				es->undo_position = s;
 			}
 			/* any deletion makes the old insertion-undo invalid */
@@ -2509,7 +2697,7 @@
 			EDIT_EM_EmptyUndoBuffer(es);
 
 		/* now delete */
-		strcpy(es->text + s, es->text + e);
+		strcpyW(es->text + s, es->text + e);
 	}
 	if (strl) {
 		/* there is an insertion */
@@ -2533,15 +2721,15 @@
 			EDIT_EM_EmptyUndoBuffer(es);
 
 		/* now insert */
-		tl = strlen(es->text);
+		tl = strlenW(es->text);
 		for (p = es->text + tl ; p >= es->text + s ; p--)
 			p[strl] = p[0];
 		for (i = 0 , p = es->text + s ; i < strl ; i++)
 			p[i] = lpsz_replace[i];
 		if(es->style & ES_UPPERCASE)
-			CharUpperBuffA(p, strl);
+			CharUpperBuffW(p, strl);
 		else if(es->style & ES_LOWERCASE)
-			CharLowerBuffA(p, strl);
+			CharLowerBuffW(p, strl);
 		s += strl;
 	}
 	/* FIXME: really inefficient */
@@ -2652,7 +2840,7 @@
 			EDIT_UpdateText(wnd, NULL, TRUE);
 		} else if (x > es->format_rect.right) {
 			INT x_last;
-			INT len = strlen(es->text);
+			INT len = strlenW(es->text);
 			goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
 			do {
 				es->x_offset++;
@@ -2684,18 +2872,51 @@
 	}
 
 	EDIT_UnlockBuffer(wnd, es, TRUE);
-	/*
-	 *	old buffer is freed by caller, unless
-	 *	it is still in our own heap.  (in that case
-	 *	we free it, correcting the buggy caller.)
-	 */
-	if (es->text)
-		HeapFree(es->heap, 0, es->text);
 
-	es->hloc16 = (HLOCAL16)NULL;
-	es->hloc32 = hloc;
-	es->text = NULL;
-	es->buffer_size = LocalSize(es->hloc32) - 1;
+	if(es->hloc16)
+	{
+	    LOCAL_Free(wnd->hInstance, es->hloc16);
+	    es->hloc16 = (HLOCAL16)NULL;
+	}
+
+	if(es->is_unicode)
+	{
+	    if(es->hloc32A)
+	    {
+		LocalFree(es->hloc32A);
+		es->hloc32A = (HLOCAL)NULL;
+	    }
+	    es->hloc32W = hloc;
+	}
+	else
+	{
+	    INT countW, countA;
+	    HLOCAL hloc32W_new;
+	    WCHAR *textW;
+	    CHAR *textA;
+
+	    countA = LocalSize(hloc);
+	    textA = LocalLock(hloc);
+	    countW = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
+	    if(!(hloc32W_new = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, countW * sizeof(WCHAR))))
+	    {
+		ERR("Could not allocate new unicode buffer\n");
+		return;
+	    }
+	    textW = LocalLock(hloc32W_new);
+	    MultiByteToWideChar(CP_ACP, 0, textA, countA, textW, countW);
+	    LocalUnlock(hloc32W_new);
+	    LocalUnlock(hloc);
+
+	    if(es->hloc32W)
+		LocalFree(es->hloc32W);
+
+	    es->hloc32W = hloc32W_new;
+	    es->hloc32A = hloc;
+	}
+
+	es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
+
 	EDIT_LockBuffer(wnd, es);
 
 	es->x_offset = es->y_offset = 0;
@@ -2718,6 +2939,11 @@
  */
 static void EDIT_EM_SetHandle16(WND *wnd, EDITSTATE *es, HLOCAL16 hloc)
 {
+	INT countW, countA;
+	HLOCAL hloc32W_new;
+	WCHAR *textW;
+	CHAR *textA;
+
 	if (!(es->style & ES_MULTILINE))
 		return;
 
@@ -2727,18 +2953,34 @@
 	}
 
 	EDIT_UnlockBuffer(wnd, es, TRUE);
-	/*
-	 *	old buffer is freed by caller, unless
-	 *	it is still in our own heap.  (in that case
-	 *	we free it, correcting the buggy caller.)
-	 */
-	if (es->text)
-		HeapFree(es->heap, 0, es->text);
 
+	if(es->hloc32A)
+	{
+	    LocalFree(es->hloc32A);
+	    es->hloc32A = (HLOCAL)NULL;
+	}
+
+	countA = LOCAL_Size(wnd->hInstance, hloc);
+	textA = LOCAL_Lock(wnd->hInstance, hloc);
+	countW = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
+	if(!(hloc32W_new = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, countW * sizeof(WCHAR))))
+	{
+	    ERR("Could not allocate new unicode buffer\n");
+	    return;
+	}
+	textW = LocalLock(hloc32W_new);
+	MultiByteToWideChar(CP_ACP, 0, textA, countA, textW, countW);
+	LocalUnlock(hloc32W_new);
+	LOCAL_Unlock(wnd->hInstance, hloc);
+
+	if(es->hloc32W)
+	    LocalFree(es->hloc32W);
+
+	es->hloc32W = hloc32W_new;
 	es->hloc16 = hloc;
-	es->hloc32 = (HLOCAL)NULL;
-	es->text = NULL;
-	es->buffer_size = LOCAL_Size(wnd->hInstance, es->hloc16) - 1;
+
+	es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
+
 	EDIT_LockBuffer(wnd, es);
 
 	es->x_offset = es->y_offset = 0;
@@ -2810,7 +3052,7 @@
  *	EM_SETPASSWORDCHAR
  *
  */
-static void EDIT_EM_SetPasswordChar(WND *wnd, EDITSTATE *es, CHAR c)
+static void EDIT_EM_SetPasswordChar(WND *wnd, EDITSTATE *es, WCHAR c)
 {
 	if (es->style & ES_MULTILINE)
 		return;
@@ -2843,7 +3085,7 @@
 {
 	UINT old_start = es->selection_start;
 	UINT old_end = es->selection_end;
-	UINT len = strlen(es->text);
+	UINT len = strlenW(es->text);
 
 	if (start == (UINT)-1) {
 		start = es->selection_end;
@@ -2899,12 +3141,12 @@
 	if (!(es->style & ES_MULTILINE))
 		return FALSE;
 	if (es->tabs)
-		HeapFree(es->heap, 0, es->tabs);
+		HeapFree(GetProcessHeap(), 0, es->tabs);
 	es->tabs_count = count;
 	if (!count)
 		es->tabs = NULL;
 	else {
-		es->tabs = HeapAlloc(es->heap, 0, count * sizeof(INT));
+		es->tabs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
 		memcpy(es->tabs, tabs, count * sizeof(INT));
 	}
 	return TRUE;
@@ -2921,13 +3163,13 @@
 	if (!(es->style & ES_MULTILINE))
 		return FALSE;
 	if (es->tabs)
-		HeapFree(es->heap, 0, es->tabs);
+		HeapFree(GetProcessHeap(), 0, es->tabs);
 	es->tabs_count = count;
 	if (!count)
 		es->tabs = NULL;
 	else {
 		INT i;
-		es->tabs = HeapAlloc(es->heap, 0, count * sizeof(INT));
+		es->tabs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
 		for (i = 0 ; i < count ; i++)
 			es->tabs[i] = *tabs++;
 	}
@@ -2940,13 +3182,14 @@
  *	EM_SETWORDBREAKPROC
  *
  */
-static void EDIT_EM_SetWordBreakProc(WND *wnd, EDITSTATE *es, EDITWORDBREAKPROCA wbp)
+static void EDIT_EM_SetWordBreakProc(WND *wnd, EDITSTATE *es, LPARAM lParam)
 {
-	if (es->word_break_proc32A == wbp)
+	if (es->word_break_proc == (void *)lParam)
 		return;
 
-	es->word_break_proc32A = wbp;
+	es->word_break_proc = (void *)lParam;
 	es->word_break_proc16 = NULL;
+
 	if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
 		EDIT_BuildLineDefs_ML(wnd, es);
 		EDIT_UpdateText(wnd, NULL, TRUE);
@@ -2964,7 +3207,7 @@
 	if (es->word_break_proc16 == wbp)
 		return;
 
-	es->word_break_proc32A = NULL;
+	es->word_break_proc = NULL;
 	es->word_break_proc16 = wbp;
 	if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
 		EDIT_BuildLineDefs_ML(wnd, es);
@@ -2980,22 +3223,22 @@
  */
 static BOOL EDIT_EM_Undo(WND *wnd, EDITSTATE *es)
 {
-	INT ulength = strlen(es->undo_text);
-	LPSTR utext = HeapAlloc(es->heap, 0, ulength + 1);
+	INT ulength = strlenW(es->undo_text);
+	LPWSTR utext = HeapAlloc(GetProcessHeap(), 0, (ulength + 1) * sizeof(WCHAR));
 
-	strcpy(utext, es->undo_text);
+	strcpyW(utext, es->undo_text);
 
 	TRACE("before UNDO:insertion length = %d, deletion buffer = %s\n",
-		     es->undo_insert_count, utext);
+		     es->undo_insert_count, debugstr_w(utext));
 
 	EDIT_EM_SetSel(wnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
 	EDIT_EM_EmptyUndoBuffer(es);
 	EDIT_EM_ReplaceSel(wnd, es, TRUE, utext, TRUE);
 	EDIT_EM_SetSel(wnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
-	HeapFree(es->heap, 0, utext);
+	HeapFree(GetProcessHeap(), 0, utext);
 
 	TRACE("after UNDO:insertion length = %d, deletion buffer = %s\n",
-			es->undo_insert_count, es->undo_text);
+			es->undo_insert_count, debugstr_w(es->undo_text));
 
 	if (es->flags & EF_UPDATE) {
 		es->flags &= ~EF_UPDATE;
@@ -3011,7 +3254,7 @@
  *	WM_CHAR
  *
  */
-static void EDIT_WM_Char(WND *wnd, EDITSTATE *es, CHAR c)
+static void EDIT_WM_Char(WND *wnd, EDITSTATE *es, WCHAR c)
 {
         BOOL control = GetKeyState(VK_CONTROL) & 0x8000;
 	switch (c) {
@@ -3025,7 +3268,8 @@
 				EDIT_MoveHome(wnd, es, FALSE);
 				EDIT_MoveDown_ML(wnd, es, FALSE);
 			} else {
-				EDIT_EM_ReplaceSel(wnd, es, TRUE, "\r\n", TRUE);
+				static const WCHAR cr_lfW[] = {'\r','\n',0};
+				EDIT_EM_ReplaceSel(wnd, es, TRUE, cr_lfW, TRUE);
 				if (es->flags & EF_UPDATE) {
 					es->flags &= ~EF_UPDATE;
 					EDIT_NOTIFY_PARENT(wnd, EN_CHANGE, "EN_CHANGE");
@@ -3036,7 +3280,8 @@
 	case '\t':
 		if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY))
 		{
-			EDIT_EM_ReplaceSel(wnd, es, TRUE, "\t", TRUE);
+			static const WCHAR tabW[] = {'\t',0};
+			EDIT_EM_ReplaceSel(wnd, es, TRUE, tabW, TRUE);
 			if (es->flags & EF_UPDATE) {
 				es->flags &= ~EF_UPDATE;
 				EDIT_NOTIFY_PARENT(wnd, EN_CHANGE, "EN_CHANGE");
@@ -3056,18 +3301,18 @@
 		}
 		break;
 	case 0x03: /* ^C */
-		SendMessageA(wnd->hwndSelf, WM_COPY, 0, 0);
+		SendMessageW(wnd->hwndSelf, WM_COPY, 0, 0);
 		break;
 	case 0x16: /* ^V */
-		SendMessageA(wnd->hwndSelf, WM_PASTE, 0, 0);
+		SendMessageW(wnd->hwndSelf, WM_PASTE, 0, 0);
 		break;
 	case 0x18: /* ^X */
-		SendMessageA(wnd->hwndSelf, WM_CUT, 0, 0);
+		SendMessageW(wnd->hwndSelf, WM_CUT, 0, 0);
 		break;
 	
 	default:
-		if (!(es->style & ES_READONLY) && ((BYTE)c >= ' ') && (c != 127)) {
-			char str[2];
+		if (!(es->style & ES_READONLY) && (c >= ' ') && (c != 127)) {
+			WCHAR str[2];
  			str[0] = c;
  			str[1] = '\0';
  			EDIT_EM_ReplaceSel(wnd, es, TRUE, str, TRUE);
@@ -3150,11 +3395,11 @@
 	/* copy */
 	EnableMenuItem(popup, 3, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) ? MF_ENABLED : MF_GRAYED));
 	/* paste */
-	EnableMenuItem(popup, 4, MF_BYPOSITION | (IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED));
+	EnableMenuItem(popup, 4, MF_BYPOSITION | (IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));
 	/* delete */
 	EnableMenuItem(popup, 5, MF_BYPOSITION | ((end - start) ? MF_ENABLED : MF_GRAYED));
 	/* select all */
-	EnableMenuItem(popup, 7, MF_BYPOSITION | (start || (end != strlen(es->text)) ? MF_ENABLED : MF_GRAYED));
+	EnableMenuItem(popup, 7, MF_BYPOSITION | (start || (end != strlenW(es->text)) ? MF_ENABLED : MF_GRAYED));
 
 	TrackPopupMenu(popup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, wnd->hwndSelf, NULL);
 	DestroyMenu(menu);
@@ -3171,18 +3416,19 @@
 	INT s = es->selection_start;
 	INT e = es->selection_end;
 	HGLOBAL hdst;
-	LPSTR dst;
+	LPWSTR dst;
 
 	if (e == s)
 		return;
 	ORDER_INT(s, e);
-	hdst = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(e - s + 1));
+	hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_DDESHARE, (DWORD)(e - s + 1) * sizeof(WCHAR));
 	dst = GlobalLock(hdst);
-	lstrcpynA(dst, es->text + s, e - s + 1);
+	strncpyW(dst, es->text + s, e - s);
+	TRACE("%s\n", debugstr_w(dst));
 	GlobalUnlock(hdst);
 	OpenClipboard(wnd->hwndSelf);
 	EmptyClipboard();
-	SetClipboardData(CF_TEXT, hdst);
+	SetClipboardData(CF_UNICODETEXT, hdst);
 	CloseClipboard();
 }
 
@@ -3192,8 +3438,9 @@
  *	WM_CREATE
  *
  */
-static LRESULT EDIT_WM_Create(WND *wnd, EDITSTATE *es, LPCREATESTRUCTA cs)
+static LRESULT EDIT_WM_Create(WND *wnd, EDITSTATE *es, LPCWSTR name)
 {
+	TRACE("%s\n", debugstr_w(name));
        /*
         *	To initialize some final structure members, we call some helper
         *	functions.  However, since the EDITSTATE is not consistent (i.e.
@@ -3203,8 +3450,8 @@
         EDIT_WM_SetFont(wnd, es, 0, FALSE);
         EDIT_EM_EmptyUndoBuffer(es);
 
-       if (cs->lpszName && *(cs->lpszName) != '\0') {
-	   EDIT_EM_ReplaceSel(wnd, es, FALSE, cs->lpszName, TRUE);
+       if (name && *name) {
+	   EDIT_EM_ReplaceSel(wnd, es, FALSE, name, TRUE);
 	   /* if we insert text to the editline, the text scrolls out
             * of the window, as the caret is placed after the insert
             * pos normally; thus we reset es->selection... to 0 and
@@ -3228,15 +3475,18 @@
  */
 static void EDIT_WM_Destroy(WND *wnd, EDITSTATE *es)
 {
-	if (es->hloc32) {
-		while (LocalUnlock(es->hloc32)) ;
-		LocalFree(es->hloc32);
+	if (es->hloc32W) {
+		while (LocalUnlock(es->hloc32W)) ;
+		LocalFree(es->hloc32W);
+	}
+	if (es->hloc32A) {
+		while (LocalUnlock(es->hloc32A)) ;
+		LocalFree(es->hloc32A);
 	}
 	if (es->hloc16) {
 		while (LOCAL_Unlock(wnd->hInstance, es->hloc16)) ;
 		LOCAL_Free(wnd->hInstance, es->hloc16);
 	}
-	HeapDestroy(es->heap);
 	HeapFree(GetProcessHeap(), 0, es);
 	*(EDITSTATE **)wnd->wExtra = NULL;
 }
@@ -3280,10 +3530,19 @@
  *	WM_GETTEXT
  *
  */
-static INT EDIT_WM_GetText(EDITSTATE *es, INT count, LPSTR text)
+static INT EDIT_WM_GetText(EDITSTATE *es, INT count, LPARAM lParam, BOOL unicode)
 {
-	lstrcpynA(text, es->text, count);
-	return strlen(text);
+    if(unicode)
+    {
+	LPWSTR textW = (LPWSTR)lParam;
+	strncpyW(textW, es->text, count);
+	return strlenW(textW);
+    }
+    else
+    {
+	LPSTR textA = (LPSTR)lParam;
+	return WideCharToMultiByte(CP_ACP, 0, es->text, es->buffer_size, textA, count, NULL, NULL);
+    }
 }
 
 
@@ -3463,11 +3722,11 @@
 
    if (key == VK_UP || key == VK_DOWN)
    {
-      if (SendMessageA(hCombo, CB_GETEXTENDEDUI, 0, 0))
+      if (SendMessageW(hCombo, CB_GETEXTENDEDUI, 0, 0))
          nEUI = 1;
 
       if (msg == WM_KEYDOWN || nEUI)
-          bDropped = (BOOL)SendMessageA(hCombo, CB_GETDROPPEDSTATE, 0, 0);
+          bDropped = (BOOL)SendMessageW(hCombo, CB_GETDROPPEDSTATE, 0, 0);
    }
 
    switch (msg)
@@ -3476,24 +3735,24 @@
          if (!bDropped && nEUI && (key == VK_UP || key == VK_DOWN))
          {
             /* make sure ComboLBox pops up */
-            SendMessageA(hCombo, CB_SETEXTENDEDUI, FALSE, 0);
+            SendMessageW(hCombo, CB_SETEXTENDEDUI, FALSE, 0);
             key = VK_F4;
             nEUI = 2;
          }
 
-         SendMessageA(hLBox, WM_KEYDOWN, (WPARAM)key, 0);
+         SendMessageW(hLBox, WM_KEYDOWN, (WPARAM)key, 0);
          break;
 
       case WM_SYSKEYDOWN: /* Handle Alt+up/down arrows */
          if (nEUI)
-            SendMessageA(hCombo, CB_SHOWDROPDOWN, bDropped ? FALSE : TRUE, 0);
+            SendMessageW(hCombo, CB_SHOWDROPDOWN, bDropped ? FALSE : TRUE, 0);
          else
-            SendMessageA(hLBox, WM_KEYDOWN, (WPARAM)VK_F4, 0);
+            SendMessageW(hLBox, WM_KEYDOWN, (WPARAM)VK_F4, 0);
          break;
    }
 
    if(nEUI == 2)
-      SendMessageA(hCombo, CB_SETEXTENDEDUI, TRUE, 0);
+      SendMessageW(hCombo, CB_SETEXTENDEDUI, TRUE, 0);
 
    return TRUE;
 }
@@ -3603,10 +3862,10 @@
 	    if(!(es->style & ES_WANTRETURN))
 	    {
 		HWND hwndParent = GetParent(wnd->hwndSelf);
-		DWORD dw = SendMessageA( hwndParent, DM_GETDEFID, 0, 0 );
+		DWORD dw = SendMessageW( hwndParent, DM_GETDEFID, 0, 0 );
 		if (HIWORD(dw) == DC_HASDEFID)
 		{
-		    SendMessageA( hwndParent, WM_COMMAND, 
+		    SendMessageW( hwndParent, WM_COMMAND, 
 				  MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
  			      (LPARAM)GetDlgItem( hwndParent, LOWORD(dw) ) );
 		}
@@ -3710,7 +3969,7 @@
  */
 static LRESULT EDIT_WM_MButtonDown(WND *wnd)
 {  
-    SendMessageA(wnd->hwndSelf,WM_PASTE,0,0);  
+    SendMessageW(wnd->hwndSelf,WM_PASTE,0,0);  
     return 0;
 }
 
@@ -3748,10 +4007,12 @@
  *	WM_NCCREATE
  *
  */
-static LRESULT EDIT_WM_NCCreate(WND *wnd, LPCREATESTRUCTA cs)
+static LRESULT EDIT_WM_NCCreate(WND *wnd, DWORD style, HWND hwndParent, BOOL unicode)
 {
 	EDITSTATE *es;
 
+	TRACE("Creating %s edit control\n", unicode ? "Unicode" : "ANSI");
+
 	if (!(es = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es))))
 		return FALSE;
 	*(EDITSTATE **)wnd->wExtra = es;
@@ -3762,12 +4023,11 @@
         *            WM_XXX messages before WM_NCCREATE is completed.
         */
 
- 	if (!(es->heap = HeapCreate(0, 0x10000, 0)))
- 		return FALSE;
- 	es->style = cs->style;
- 
-        es->bEnableState = !(cs->style & WS_DISABLED);
- 
+ 	es->is_unicode = unicode;
+ 	es->style = style;
+
+        es->bEnableState = !(style & WS_DISABLED);
+
 	/*
 	 * In Win95 look and feel, the WS_BORDER style is replaced by the 
 	 * WS_EX_CLIENTEDGE style for the edit control. This gives the edit 
@@ -3789,10 +4049,9 @@
 	}
 
 	if (es->style & ES_COMBO)
-	   es->hwndListBox = GetDlgItem(cs->hwndParent, ID_CB_LISTBOX);
+	   es->hwndListBox = GetDlgItem(hwndParent, ID_CB_LISTBOX);
 
 	if (es->style & ES_MULTILINE) {
-		es->buffer_size = BUFSTART_MULTI;
 		es->buffer_limit = BUFLIMIT_MULTI;
 		if (es->style & WS_VSCROLL)
 			es->style |= ES_AUTOVSCROLL;
@@ -3809,7 +4068,6 @@
 		/* FIXME: for now, all multi line controls are AUTOVSCROLL */
 		es->style |= ES_AUTOVSCROLL;
 	} else {
-		es->buffer_size = BUFSTART_SINGLE;
 		es->buffer_limit = BUFLIMIT_SINGLE;
 		es->style &= ~ES_CENTER;
 		es->style &= ~ES_RIGHT;
@@ -3828,15 +4086,17 @@
 		/* FIXME: for now, all single line controls are AUTOHSCROLL */
 		es->style |= ES_AUTOHSCROLL;
 	}
-	if (!(es->text = HeapAlloc(es->heap, 0, es->buffer_size + 1)))
+
+	if(!(es->hloc32W = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (es->buffer_size + 1) * sizeof(WCHAR))))
+	    return FALSE;
+	es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
+
+	if (!(es->undo_text = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (es->buffer_size + 1) * sizeof(WCHAR))))
 		return FALSE;
-	es->buffer_size = HeapSize(es->heap, 0, es->text) - 1;
-	if (!(es->undo_text = HeapAlloc(es->heap, 0, es->buffer_size + 1)))
-		return FALSE;
-	es->undo_buffer_size = HeapSize(es->heap, 0, es->undo_text) - 1;
-	*es->text = '\0';
+	es->undo_buffer_size = es->buffer_size;
+
 	if (es->style & ES_MULTILINE)
-		if (!(es->first_line_def = HeapAlloc(es->heap, HEAP_ZERO_MEMORY, sizeof(LINEDEF))))
+		if (!(es->first_line_def = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF))))
 			return FALSE;
 	es->line_count = 1;
 
@@ -3943,11 +4203,11 @@
 static void EDIT_WM_Paste(WND *wnd, EDITSTATE *es)
 {
 	HGLOBAL hsrc;
-	LPSTR src;
+	LPWSTR src;
 
 	OpenClipboard(wnd->hwndSelf);
-	if ((hsrc = GetClipboardData(CF_TEXT))) {
-		src = (LPSTR)GlobalLock(hsrc);
+	if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
+		src = (LPWSTR)GlobalLock(hsrc);
 		EDIT_EM_ReplaceSel(wnd, es, TRUE, src, TRUE);
 		GlobalUnlock(hsrc);
 
@@ -3989,7 +4249,7 @@
  */
 static void EDIT_WM_SetFont(WND *wnd, EDITSTATE *es, HFONT font, BOOL redraw)
 {
-	TEXTMETRICA tm;
+	TEXTMETRICW tm;
 	HDC dc;
 	HFONT old_font = 0;
 	RECT r;
@@ -3998,7 +4258,7 @@
 	dc = GetDC(wnd->hwndSelf);
 	if (font)
 		old_font = SelectObject(dc, font);
-	GetTextMetricsA(dc, &tm);
+	GetTextMetricsW(dc, &tm);
 	es->line_height = tm.tmHeight;
 	es->char_width = tm.tmAveCharWidth;
 	if (font)
@@ -4039,15 +4299,30 @@
  *  The modified flag is reset. EN_UPDATE and EN_CHANGE notifications are sent.
  *
  */
-static void EDIT_WM_SetText(WND *wnd, EDITSTATE *es, LPCSTR text)
+static void EDIT_WM_SetText(WND *wnd, EDITSTATE *es, LPARAM lParam, BOOL unicode)
 {
+    LPWSTR text;
+
+    if(unicode)
+	text = (LPWSTR)lParam;
+    else
+    {
+	LPCSTR textA = (LPCSTR)lParam;
+	INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
+	if((text = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
+	    MultiByteToWideChar(CP_ACP, 0, textA, -1, text, countW);
+    }
+
 	EDIT_EM_SetSel(wnd, es, 0, (UINT)-1, FALSE);
 	if (text) {
-		TRACE("\t'%p'\n", text);
+		TRACE("%s\n", debugstr_w(text));
 		EDIT_EM_ReplaceSel(wnd, es, FALSE, text, !(es->style & ES_MULTILINE));
+		if(!unicode)
+		    HeapFree(GetProcessHeap(), 0, text);
 	} else {
-		TRACE("\t<NULL>\n");
-		EDIT_EM_ReplaceSel(wnd, es, FALSE, "", !(es->style & ES_MULTILINE));
+		static const WCHAR empty_stringW[] = {0};
+		TRACE("<NULL>\n");
+		EDIT_EM_ReplaceSel(wnd, es, FALSE, empty_stringW, !(es->style & ES_MULTILINE));
 	}
 	es->x_offset = 0;
 	es->flags &= ~EF_MODIFIED;
@@ -4070,6 +4345,7 @@
 {
 	if ((action == SIZE_MAXIMIZED) || (action == SIZE_RESTORED)) {
 		RECT rc;
+		TRACE("width = %d, height = %d\n", width, height);
 		SetRect(&rc, 0, 0, width, height);
 		EDIT_SetRectNP(wnd, es, &rc);
 		EDIT_UpdateText(wnd, NULL, TRUE);
@@ -4092,7 +4368,7 @@
 		if (EDIT_CheckCombo(wnd, es, WM_SYSKEYDOWN, key))
 			return 0;
 	}
-	return DefWindowProcA(wnd->hwndSelf, WM_SYSKEYDOWN, (WPARAM)key, (LPARAM)key_data);
+	return DefWindowProcW(wnd->hwndSelf, WM_SYSKEYDOWN, (WPARAM)key, (LPARAM)key_data);
 }