Richedit Control

Robert Shearman R.J.Shearman at warwick.ac.uk
Wed Dec 4 18:36:44 CST 2002


This patch enables basic Richedit 1.0 functionality and is an attempt to be
as useful as the edit control version. I don't expect this patch to be
applied as it is still very messy, but wanted to share the progress with
anyone who is interested.

Notes:
Doesn't process multiple paragraphs yet (treats everything as one paragraph)
Doesn't display selection, although it will still handle this
Mouse control very limited and buggy
Many window messages unimplemented

Changelog:
- Made independent of edit control. Implemented basic structure, although
still many bugs and unimplemented features
-------------- next part --------------
Index: wine/dlls/richedit/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/richedit/Makefile.in,v
retrieving revision 1.12
diff -u -r1.12 Makefile.in
--- wine/dlls/richedit/Makefile.in	17 May 2002 03:37:14 -0000	1.12
+++ wine/dlls/richedit/Makefile.in	4 Dec 2002 22:37:02 -0000
@@ -3,7 +3,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = riched32.dll
-IMPORTS   = user32 kernel32
+IMPORTS   = user32 kernel32 gdi32
 
 LDDLLFLAGS = @LDDLLFLAGS@
 SYMBOLFILE = $(MODULE).tmp.o
@@ -17,3 +17,4 @@
 @MAKE_DLL_RULES@
 
 ### Dependencies:
+
Index: wine/dlls/richedit/richedit.c
===================================================================
RCS file: /home/wine/wine/dlls/richedit/richedit.c,v
retrieving revision 1.25
diff -u -r1.25 richedit.c
--- wine/dlls/richedit/richedit.c	2 Dec 2002 18:10:58 -0000	1.25
+++ wine/dlls/richedit/richedit.c	4 Dec 2002 22:37:03 -0000
@@ -5,7 +5,8 @@
  * At the point, it is good only for application who use the RICHEDIT
  * control to display RTF text.
  *
- * Copyright 2000 by Jean-Claude Batista
+ * Copyright 2000 by Jean-Claude Batista
+ * Copyrigth 2002 by Robert Shearman
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,6 +22,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#define _RICHEDIT_VER   0x0100
 
 #include <string.h>
 #include "windef.h"
@@ -36,21 +38,162 @@
 
 #include "rtf.h"
 #include "rtf2text.h"
-#include "wine/debug.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
 
-#define ID_EDIT      1
+//#define ID_EDIT      1
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 
 HANDLE RICHED32_hHeap = (HANDLE)NULL;
-/* LPSTR  RICHED32_aSubclass = (LPSTR)NULL; */
+
+typedef struct tagRICHTEXTSEG
+{
+	COMPCOLOR extras;
+	HFONT hSegFont;
+	LPWSTR pText;
+	int length;
+	struct tagRICHTEXTSEG * pNextSeg;
+} RICHTEXTSEG;
+
+typedef struct tagLINEDEF {
+	INT length;
+//	LINE_END ending;
+	INT width;
+	int startIndex;
+	int cachedHeight;
+	int cachedWidth;
+	int cachedYPos;
+	RICHTEXTSEG * pTextSeg;
+	struct tagLINEDEF *next;
+} LINEDEF;
+
+typedef struct tagPARAGRAPH {
+	PARAFORMAT format;
+	LINEDEF *pFirstLine;
+	struct tagPARAGRAPH * pNext;
+	int cachedHeight;
+	int cachedWidth;
+	LPWSTR wszBuffer;
+	UINT uBufferSize; // in characters
+	UINT uBufferLimit; // in characters
+} PARAGRAPH;
+
+typedef struct
+{
+	BOOL is_unicode;		/* how the control was created */
+	INT x_offset;			/* scroll offset this is in pixels*/
+	INT y_offset;			/* scroll offset in number of lines */
+//	INT char_width;			/* average character width in pixels */
+	DWORD style;			/* sane version of wnd->dwStyle */
+	WORD flags;			/* flags that are not in es->style or wnd->flags (EF_XXX) */
+	DWORD dwEventMask;
+//	INT undo_insert_count;		/* number of characters inserted in sequence */
+//	UINT undo_position;		/* character index of the insertion and deletion */
+//	LPWSTR undo_text;		/* deleted text */
+//	UINT undo_buffer_size;		/* size of the deleted text buffer */
+	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 text_width;			/* width of the widest line in pixels*/
+	INT region_posx;		/* Position of cursor relative to region: */
+	INT region_posy;		/* -1: to left, 0: within, 1: to right */
+//	EDITWORDBREAKPROC16 word_break_proc16;
+	void *word_break_proc;		/* 32-bit word break proc: ANSI or Unicode */
+//	INT line_count;			/* number of lines */
+//	BOOL bCaptureState; 		/* flag indicating whether mouse was captured */
+//	BOOL bEnableState;		/* flag keeping the enable state */
+	HWND hwndSelf;			/* the our window handle */
+	HWND hwndParent;		/* Handle of parent for sending EN_* messages.
+				           Even if parent will change, EN_* messages
+					   should be sent to the first parent. */
+	/*
+	 *	only for multi line controls
+	 */
+//	INT lock_count;			/* amount of re-entries in the EditWndProc */
+	INT nTabPositions;
+	LPINT lpnTabStopPositions;
+	PARAGRAPH *pFirstParagraph;
+	PARAGRAPH * pSelection;
+	CHARRANGE chrSelection;
+//	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 */
+} RICHEDITSTATE;
+
+/*
+ *	extra flags for EDITSTATE.flags field
+ */
+#define EF_MODIFIED		0x0001	/* text has been modified */
+#define EF_FOCUSED		0x0002	/* we have input focus */
+#define EF_UPDATE		0x0004	/* notify parent of changed state */
+//#define EF_VSCROLL_TRACK	0x0008	/* don't SetScrollPos() since we are tracking the thumb */
+//#define EF_HSCROLL_TRACK	0x0010	/* don't SetScrollPos() since we are tracking the thumb */
+#define EF_AFTER_WRAP		0x0080	/* the caret is displayed after the last character of a
+					   wrapped line, instead of in front of the next character */
+//#define EF_USE_SOFTBRK		0x0100	/* Enable soft breaks in text. */
 
 #define DPRINTF_EDIT_MSG32(str) \
         TRACE(\
                      "32 bit : " str ": hwnd=%p, wParam=%08x, lParam=%08x\n"\
                      , \
-                     hwnd, (UINT)wParam, (UINT)lParam)
-
+                     hwnd, (UINT)wParam, (UINT)lParam)
+
+#define FIXME_MSG(str) \
+		FIXME(\
+					 str ": hwnd=%p, wParam=%08x, lParam=%08x\n"\
+					 , \
+					 hwnd, (UINT)wParam, (UINT)lParam)
+
+// FIXME: only send messages that parent wants (see res->dwEventMask)
+#define RT_NOTIFY_PARENT(res, wNotifyCode, str) \
+	do \
+	{ /* Notify parent which has created this edit control */ \
+	    TRACE("notification " str " sent to hwnd=%p\n", res->hwndParent); \
+	    SendMessageW(res->hwndParent, WM_COMMAND, \
+		     MAKEWPARAM(GetWindowLongW((res->hwndSelf),GWL_ID), wNotifyCode), \
+		     (LPARAM)(res->hwndSelf)); \
+	} while(0)
+
+
+static void RICHED32_LockBuffer(RICHEDITSTATE * res);
+static void RICHED32_WM_Create(RICHEDITSTATE * res, HWND hwnd, LPCREATESTRUCTA lpcs);
+static LRESULT RICHED32_WM_Paint(RICHEDITSTATE * res, WPARAM wParam);
+static LRESULT RICHED32_WM_NCDestroy(RICHEDITSTATE * res);
+static LRESULT RICHED32_NCCreate(HWND hwnd, LPCREATESTRUCTA lpcs);
+static HFONT RichText_CHARFORMAT2ToHFONT(CHARFORMAT2W * pFormat);
+static DWORD RichTextParagraph_Draw(PARAGRAPH * pParagraph, HDC hDC, int startx, int starty, int nTabPositions, int * lpnTabStopPositions);
+static DWORD RichTextLine_Draw(LINEDEF * pLine, HDC hDC, int startx, int starty, int nTabPositions, int * lpnTabStopPositions);
+static void RichTextSeg_Draw(RICHTEXTSEG * textSeg, HDC hDC, int x, int y, int index, int charCount, int nTabPositions, int * lpnTabStopPositions);
+static DWORD RichTextSeg_GetExtent(RICHTEXTSEG * pTextSeg, HDC hDC, int index, int charCount, int nTabPositions, int * lpnTabStopPositions);
+static int RICHED32_WM_SetText(RICHEDITSTATE * res, LPCSTR szText);
+static void RichText_BuildLineDefs(RICHEDITSTATE * res, PARAGRAPH * para);
+static RICHTEXTSEG * RichTextSeg_SkipToChar(RICHTEXTSEG * pTextSeg, LONG pos, LONG * remaining);
+static void RICHED32_EM_SetCharFormat2A(RICHEDITSTATE * res, CHARFORMAT2A * pChf);
+static void RichText_ReplaceSel(RICHEDITSTATE * res, LPWSTR wszInsertion);
+static void RICHED32_EM_ReplaceSel(RICHEDITSTATE * res, BOOL bUndo, LPCSTR szText);
+static void RICHED32_CreateAndShowCaret(RICHEDITSTATE * res);
+static void RICHED32_UpdateScrollInfo(RICHEDITSTATE * res);
+static void RICHED32_WM_Char(RICHEDITSTATE * res, WCHAR charW);
+static LINEDEF * RichTextLine_SkipToChar(LINEDEF * pLine, LONG pos, LONG * remaining);
+static LRESULT RichText_EM_PosFromChar(RICHEDITSTATE * res, INT index);
+static INT RichText_CharFromPos(RICHEDITSTATE * res, POINTL * pPoint);
+static LRESULT RichText_EM_FindTextExW(RICHEDITSTATE * res, UINT fuFlags, FINDTEXTEXW * lpFindText);
+static LRESULT RichText_EM_FindTextExA(RICHEDITSTATE * res, UINT fuFlags, FINDTEXTEXA * lpFindText);
+static void RichTextParagraph_SetFormat2(PARAGRAPH * pParagraph, PARAFORMAT * pFormat);
+static void RichText_WM_Keydown(RICHEDITSTATE * res, int nVirtKey, long lKeyData);
+int RTFToBuffer(char* pBuffer, int nBufferSize);
+static void RICHED32_WM_Cut(RICHEDITSTATE * res);
+static void RICHED32_WM_Copy(RICHEDITSTATE * res);
+static void RICHED32_WM_Paste(RICHEDITSTATE * res);
+static void RICHED32_WM_Clear(RICHEDITSTATE * res);
+
+/* Support routines for window procedure */
+//   INT RICHEDIT_GetTextRange(HWND hwnd,TEXTRANGEA *tr);
+//   INT RICHEDIT_GetSelText(HWND hwnd,LPSTR lpstrBuffer);
 
 /***********************************************************************
  * DllMain [Internal] Initializes the internal 'RICHED32.DLL'.
@@ -64,7 +207,6 @@
  *     Success: TRUE
  *     Failure: FALSE
  */
-
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 {
     TRACE("\n");
@@ -78,7 +220,7 @@
         break;
 
     case DLL_PROCESS_DETACH:
-        /* unregister all common control classes */
+        /* unregister this class */
         RICHED32_Unregister ();
         HeapDestroy (RICHED32_hHeap);
         RICHED32_hHeap = (HANDLE)NULL;
@@ -87,11 +229,6 @@
     return TRUE;
 }
 
-/* Support routines for window procedure */
-   INT RICHEDIT_GetTextRange(HWND hwnd,TEXTRANGEA *tr);
-   INT RICHEDIT_GetSelText(HWND hwnd,LPSTR lpstrBuffer);
-
-
 /*
  *
  * DESCRIPTION:
@@ -101,76 +238,227 @@
 static LRESULT WINAPI RICHED32_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                    LPARAM lParam)
 {
-    int RTFToBuffer(char* pBuffer, int nBufferSize);
-    LONG newstyle = 0;
-    LONG style = 0;
-
-    static HWND hwndEdit;
-    static HWND hwndParent;
-    static char* rtfBuffer;
-    int rtfBufferSize;
-
-    CHARRANGE *cr;
-    TRACE("previous hwndEdit: %p hwndParent %p\n",hwndEdit,hwndParent);
-    hwndEdit = GetWindow(hwnd,GW_CHILD);
-    TRACE("uMsg: 0x%x hwnd: %p hwndEdit: %p\n",uMsg,hwnd,hwndEdit);
+    LRESULT result = 0;
+
+    RICHEDITSTATE *res = (RICHEDITSTATE *)GetWindowLongW( hwnd, 0 );
+
+    if (res) RICHED32_LockBuffer(res);
 
     switch (uMsg)
     {
-
+	
+		// Implemented messages appear first
     case WM_CREATE :
 	    DPRINTF_EDIT_MSG32("WM_CREATE");
-
-	    /* remove SCROLLBARS from the current window style */
-	    hwndParent = ((LPCREATESTRUCTA) lParam)->hwndParent;
-
-	    newstyle = style = ((LPCREATESTRUCTA) lParam)->style;
-            newstyle &= ~WS_HSCROLL;
-            newstyle &= ~WS_VSCROLL;
-            newstyle &= ~ES_AUTOHSCROLL;
-            newstyle &= ~ES_AUTOVSCROLL;
-
-    TRACE("previous hwndEdit: %p\n",hwndEdit);
-            hwndEdit = CreateWindowA ("edit", ((LPCREATESTRUCTA) lParam)->lpszName,
-                                   style, 0, 0, 0, 0,
-                                   hwnd, (HMENU) ID_EDIT,
-                                   ((LPCREATESTRUCTA) lParam)->hInstance, NULL) ;
-    TRACE("hwndEdit: %p hwnd: %p\n",hwndEdit,hwnd);
-
-	    SetWindowLongA(hwnd,GWL_STYLE, newstyle);
-            return 0 ;
-
+	    RICHED32_WM_Create(res, hwnd, (LPCREATESTRUCTA) lParam);
+        break;
     case WM_SETFOCUS :
-	    DPRINTF_EDIT_MSG32("WM_SETFOCUS");
-            SetFocus (hwndEdit) ;
-            return 0 ;
-
-    case WM_SIZE :
-            DPRINTF_EDIT_MSG32("WM_SIZE");
-            MoveWindow (hwndEdit, 0, 0, LOWORD (lParam), HIWORD (lParam), TRUE) ;
-            return 0 ;
-
-    case WM_COMMAND :
-        DPRINTF_EDIT_MSG32("WM_COMMAND");
-	switch(HIWORD(wParam)) {
-		case EN_CHANGE:
-		case EN_HSCROLL:
-		case EN_KILLFOCUS:
-		case EN_SETFOCUS:
-		case EN_UPDATE:
-		case EN_VSCROLL:
-			return SendMessageA(hwndParent, WM_COMMAND,
-				wParam, (LPARAM)(hwnd));
-
-		case EN_ERRSPACE:
-		case EN_MAXTEXT:
-			MessageBoxA (hwnd, "RichEdit control out of space.",
-                                  "ERROR", MB_OK | MB_ICONSTOP) ;
-			return 0 ;
-		}
-
-    case EM_STREAMIN:
-            DPRINTF_EDIT_MSG32("EM_STREAMIN");
+	    DPRINTF_EDIT_MSG32("WM_SETFOCUS");
+		RT_NOTIFY_PARENT(res, EN_SETFOCUS, "EN_SETFOCUS");
+		RICHED32_CreateAndShowCaret(res);
+		break;
+    case EM_EXSETSEL:
+        DPRINTF_EDIT_MSG32("EM_EXSETSEL");
+		CopyMemory(&(res->chrSelection), (void *) lParam, sizeof(CHARRANGE));
+		TRACE("CHARRANGE(cpMin = %ld, cpMax = %ld)\n", res->chrSelection.cpMin, res->chrSelection.cpMax);
+		FIXME("Update paragraph\n");
+        break;
+     case EM_SETSEL:
+        DPRINTF_EDIT_MSG32("EM_SETSEL");
+		res->chrSelection.cpMin = wParam;
+		res->chrSelection.cpMax = lParam;
+		break;
+	case WM_CHAR:
+	{
+		WCHAR charW;
+		DPRINTF_EDIT_MSG32("WM_CHAR");
+
+	    MultiByteToWideChar(CP_ACP, 0, (LPSTR) &wParam, 1, &charW, 1);
+		RICHED32_WM_Char(res, charW);
+		RT_NOTIFY_PARENT(res, EN_CHANGE, "EN_CHANGE");
+		break;
+	}
+	case WM_KEYDOWN:
+			DPRINTF_EDIT_MSG32("WM_KEYDOWN");
+			RichText_WM_Keydown(res, wParam, lParam);
+			break;
+     case EM_SETMODIFY:
+            DPRINTF_EDIT_MSG32("EM_SETMODIFY");
+			if (wParam)
+				res->flags |= EF_MODIFIED;
+			else
+				res->flags &= ~(EF_MODIFIED | EF_UPDATE);  /* reset pending updates */
+			break;
+     case EM_GETMODIFY:
+            DPRINTF_EDIT_MSG32("EM_GETMODIFY Passed to edit control");
+			result = ((res->flags & EF_MODIFIED) != 0);
+			break;
+     case WM_KILLFOCUS:
+			DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
+			DestroyCaret();
+			RT_NOTIFY_PARENT(res, EN_KILLFOCUS, "EN_KILLFOCUS");
+			return 0;
+     case WM_SETTEXT:
+            DPRINTF_EDIT_MSG32("WM_SETTEXT");
+			return RICHED32_WM_SetText(res, (LPCSTR)lParam);
+     case EM_REPLACESEL:
+            DPRINTF_EDIT_MSG32("EM_REPLACESEL");
+			RICHED32_EM_ReplaceSel(res, (BOOL) wParam, (LPCSTR) lParam);
+			return 0;
+     case EM_CHARFROMPOS:
+            DPRINTF_EDIT_MSG32("EM_CHARFROMPOS");
+			return RichText_CharFromPos(res, (POINTL *)lParam);
+    case EM_SETPARAFORMAT:
+            DPRINTF_EDIT_MSG32("EM_SETPARAFORMAT");
+			RichTextParagraph_SetFormat2(res->pSelection, (PARAFORMAT *) lParam);
+			InvalidateRect(res->hwndSelf, NULL, TRUE);
+            return 0;
+    case EM_GETPARAFORMAT:
+            DPRINTF_EDIT_MSG32("EM_GETPARAFORMAT");
+			res->pSelection->format.cbSize = sizeof(PARAFORMAT);
+			res->pSelection->format.dwMask = PFM_ALIGNMENT | PFM_NUMBERING | PFM_OFFSET | PFM_OFFSETINDENT | PFM_RIGHTINDENT | PFM_RTLPARA | PFM_STARTINDENT | PFM_TABSTOPS;
+			CopyMemory((void *) lParam, &res->pSelection->format, sizeof(PARAFORMAT));
+			FIXME("EM_GETPARAFORMAT - Do for rest of selection too\n");
+            return ((PARAFORMAT *)lParam)->dwMask;
+    case EM_FINDTEXT:
+			{
+				FINDTEXTEXA find;
+				ZeroMemory(&find, sizeof(find));
+	            DPRINTF_EDIT_MSG32("EM_FINDTEXT");
+				CopyMemory(&find, (const FINDTEXTA *) lParam, sizeof(FINDTEXTA));
+	            return RichText_EM_FindTextExA(res, (UINT) wParam, &find);
+			}
+    case EM_FINDTEXTEX:
+            DPRINTF_EDIT_MSG32("EM_FINDTEXTEX");
+			return RichText_EM_FindTextExA(res, (UINT) wParam, (FINDTEXTEXA *) lParam);
+
+    case EM_FINDTEXTEXW:
+            DPRINTF_EDIT_MSG32("EM_FINDTEXTEXW");
+            return RichText_EM_FindTextExW(res, (UINT) wParam, (FINDTEXTEXW *) lParam);
+    case EM_FINDTEXTW:
+		{
+				FINDTEXTEXW find;
+	            DPRINTF_EDIT_MSG32("EM_FINDTEXTW");
+				ZeroMemory(&find, sizeof(find));
+				CopyMemory(&find, (const FINDTEXTW *) lParam, sizeof(FINDTEXTW));
+	            return RichText_EM_FindTextExW(res, (UINT) wParam, &find);
+		}
+    case EM_EXGETSEL:
+            DPRINTF_EDIT_MSG32("EM_EXGETSEL");
+			CopyMemory((void *)lParam, &res->chrSelection, sizeof(res->chrSelection));
+            return 0;
+    case EM_SETREADONLY:
+            DPRINTF_EDIT_MSG32("EM_SETREADONLY");
+			if (wParam) {
+						SetWindowLongW( hwnd, GWL_STYLE,
+										GetWindowLongW( hwnd, GWL_STYLE ) | ES_READONLY );
+						res->style |= ES_READONLY;
+			} else {
+						SetWindowLongW( hwnd, GWL_STYLE,
+										GetWindowLongW( hwnd, GWL_STYLE ) & ~ES_READONLY );
+						res->style &= ~ES_READONLY;
+			}
+					result = 1;
+ 			break;
+    case EM_GETSCROLLPOS:
+			{
+				SCROLLINFO si;
+				DPRINTF_EDIT_MSG32("EM_GETSCROLLPOS");
+				si.fMask = SIF_POS;
+				GetScrollInfo(res->hwndSelf, SB_VERT, &si);
+				FIXME("GetScrollInfo returned %d. Convert this to coordinate\n", si.nPos);
+				return 0;
+			}
+    case EM_SETCHARFORMAT:
+            DPRINTF_EDIT_MSG32("EM_SETCHARFORMAT");
+			RICHED32_EM_SetCharFormat2A(res, (CHARFORMAT2A *) lParam);
+            return 1;
+	case WM_SETFONT:
+		{
+			RICHTEXTSEG * pTextSeg;
+	        DPRINTF_EDIT_MSG32("WM_SETFONT");
+			pTextSeg = RichTextSeg_SkipToChar(res->pSelection->pFirstLine->pTextSeg, res->chrSelection.cpMin, NULL);
+			DeleteObject(pTextSeg->hSegFont);
+			pTextSeg->hSegFont = (HFONT) wParam;
+			InvalidateRect(res->hwndSelf, NULL, TRUE);
+			RICHED32_CreateAndShowCaret(res);
+			break;
+		}
+	case WM_MOUSEACTIVATE:
+        DPRINTF_EDIT_MSG32("WM_MOUSEACTIVATE");
+		// FIXME: is handling this message needed?
+		SetFocus(hwnd);
+		result = MA_ACTIVATE;
+		break;
+	case WM_LBUTTONDOWN:
+		{
+			POINTL p;
+            DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN");
+			p.x = LOWORD(lParam);
+			p.y = HIWORD(lParam);
+			res->chrSelection.cpMin = RichText_CharFromPos(res, &p);
+			res->chrSelection.cpMax = res->chrSelection.cpMin;
+			RICHED32_CreateAndShowCaret(res);
+			break;
+		}
+   case WM_CUT:
+		 RICHED32_WM_Cut(res);
+//            FIXME_MSG("WM_CUT Passed to edit control");
+//	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+			break;
+     case WM_COPY:
+//            FIXME_MSG("WM_COPY Passed to edit control");
+		 RICHED32_WM_Copy(res);
+//	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+			break;
+    case WM_PASTE:
+		 RICHED32_WM_Paste(res);
+//            FIXME_MSG("WM_PASTE Passed to edit control");
+//	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);*/
+			break;
+    case WM_CLEAR:
+//        FIXME_MSG("WM_CLEAR Passed to default");
+//        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
+		RICHED32_WM_Clear(res);
+		break;
+    case WM_PAINT:
+        DPRINTF_EDIT_MSG32("WM_PAINT");
+        return RICHED32_WM_Paint(res, wParam);
+     case EM_POSFROMCHAR:
+            DPRINTF_EDIT_MSG32("EM_POSFROMCHAR Passed to edit control");
+			return RichText_EM_PosFromChar(res, wParam);
+    case EM_SETEVENTMASK:
+		{
+			DWORD dwOldMask = res->dwEventMask;
+			res->dwEventMask = (DWORD) lParam;
+            return dwOldMask;
+		}
+    case WM_NCDESTROY:
+//        DPRINTF_EDIT_MSG32("WM_NCDESTROY Passed to default");
+//        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
+		return RICHED32_WM_NCDestroy(res);
+
+	// Not implemented
+	case WM_RBUTTONDOWN:
+		FIXME_MSG("WM_RBUTTONDOWN - stub");
+		break;
+    case EM_GETCHARFORMAT:
+		FIXME_MSG("EM_GETCHARFORMAT");
+			{
+/*				RICHTEXTSEG * pTextSeg = RichTextSeg_SkipToChar(res->pSelection, res->chrSelection.cpMin
+				DPRINTF_EDIT_MSG32("EM_GETCHARFORMAT");
+				CopyMemory((void *) lParam, &pTextSeg->, ((CHARFORMAT *)lParam)->cbSize);
+				return (CHARFORMAT *)lParam)->dwMask;*/
+				return 0;
+			}
+
+
+	// This one is half-implemented
+    case EM_STREAMIN:
+		{
+			static char* rtfBuffer;
+			int rtfBufferSize;
+            DPRINTF_EDIT_MSG32("EM_STREAMIN");
 
 	    /* setup the RTF parser */
 	    RTFSetEditStream(( EDITSTREAM*)lParam);
@@ -187,469 +475,349 @@
 	    if(rtfBuffer)
 	    {
 	    	RTFToBuffer(rtfBuffer, rtfBufferSize);
-            	SetWindowTextA(hwndEdit,rtfBuffer);
+           	SetWindowTextA(res->hwndSelf,rtfBuffer);
 	    	HeapFree(RICHED32_hHeap, 0,rtfBuffer);
 	    }
 	    else
 		WARN("Not enough memory for a allocating rtfBuffer\n");
 
             return 0;
-
+		}
 /* Messages specific to Richedit controls */
 
     case EM_AUTOURLDETECT:
-            DPRINTF_EDIT_MSG32("EM_AUTOURLDETECT Ignored");
+            FIXME_MSG("EM_AUTOURLDETECT Ignored");
 	    return 0;
 
     case EM_CANPASTE:
-            DPRINTF_EDIT_MSG32("EM_CANPASTE Ignored");
+            FIXME_MSG("EM_CANPASTE Ignored");
 	    return 0;
 
     case EM_CANREDO:
-            DPRINTF_EDIT_MSG32("EM_CANREDO Ignored");
+            FIXME_MSG("EM_CANREDO Ignored");
 	    return 0;
 
     case EM_DISPLAYBAND:
-            DPRINTF_EDIT_MSG32("EM_DISPLAYBAND Ignored");
+            FIXME_MSG("EM_DISPLAYBAND Ignored");
 	    return 0;
 
-    case EM_EXGETSEL:
-            DPRINTF_EDIT_MSG32("EM_EXGETSEL -> EM_GETSEL");
-            cr = (VOID *) lParam;
-            if (hwndEdit) SendMessageA( hwndEdit, EM_GETSEL, (INT)&cr->cpMin, (INT)&cr->cpMax);
-            TRACE("cpMin: 0x%x cpMax: 0x%x\n",(INT)cr->cpMin,(INT)cr->cpMax);
-            return 0;
-
     case EM_EXLIMITTEXT:
         {
-           DWORD limit = lParam;
-           DPRINTF_EDIT_MSG32("EM_EXLIMITTEXT");
-           if (limit > 65534)
-           {
-                limit = 0xFFFFFFFF;
-           }
-           return SendMessageA(hwndEdit,EM_SETLIMITTEXT,limit,0);
+//           DWORD limit = lParam;
+           FIXME_MSG("EM_EXLIMITTEXT Ignored");
+//           if (limit > 65534)
+//           {
+//                limit = 0xFFFFFFFF;
+//           }
+//           return SendMessageA(hwndEdit,EM_SETLIMITTEXT,limit,0);
+		   return 0;
         }
 
     case EM_EXLINEFROMCHAR:
-            DPRINTF_EDIT_MSG32("EM_EXLINEFROMCHAR -> LINEFROMCHAR");
-            if (hwndEdit) return SendMessageA( hwndEdit, EM_LINEFROMCHAR, lParam, wParam);
-            return 0;
-
-    case EM_EXSETSEL:
-            DPRINTF_EDIT_MSG32("EM_EXSETSEL -> EM_SETSEL");
-            cr = (VOID *) lParam;
-            if (hwndEdit) SendMessageA( hwndEdit, EM_SETSEL, cr->cpMin, cr->cpMax);
-            return 0;
-
-    case EM_FINDTEXT:
-            DPRINTF_EDIT_MSG32("EM_FINDTEXT Ignored");
-            return 0;
-
-    case EM_FINDTEXTEX:
-            DPRINTF_EDIT_MSG32("EM_FINDTEXTEX Ignored");
-            return 0;
-
-    case EM_FINDTEXTEXW:
-            DPRINTF_EDIT_MSG32("EM_FINDTEXTEXW Ignored");
+            FIXME_MSG("EM_EXLINEFROMCHAR Ignored");
             return 0;
-
-    case EM_FINDTEXTW:
-            DPRINTF_EDIT_MSG32("EM_FINDTEXTW Ignored");
-            return 0;
-
     case EM_FINDWORDBREAK:
-            DPRINTF_EDIT_MSG32("EM_FINDWORDBREAK Ignored");
+            FIXME_MSG("EM_FINDWORDBREAK Ignored");
             return 0;
 
     case EM_FORMATRANGE:
-            DPRINTF_EDIT_MSG32("EM_FORMATRANGE Ignored");
+            FIXME_MSG("EM_FORMATRANGE Ignored");
             return 0;
 
     case EM_GETAUTOURLDETECT:
-            DPRINTF_EDIT_MSG32("EM_GETAUTOURLDETECT Ignored");
+            FIXME_MSG("EM_GETAUTOURLDETECT Ignored");
             return 0;
 
     case EM_GETBIDIOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_GETBIDIOPTIONS Ignored");
-            return 0;
-
-    case EM_GETCHARFORMAT:
-            DPRINTF_EDIT_MSG32("EM_GETCHARFORMAT Ignored");
+            FIXME_MSG("EM_GETBIDIOPTIONS Ignored");
             return 0;
 
     case EM_GETEDITSTYLE:
-            DPRINTF_EDIT_MSG32("EM_GETEDITSTYLE Ignored");
+            FIXME_MSG("EM_GETEDITSTYLE Ignored");
             return 0;
 
     case EM_GETEVENTMASK:
-            DPRINTF_EDIT_MSG32("EM_GETEVENTMASK Ignored");
+            FIXME_MSG("EM_GETEVENTMASK Ignored");
             return 0;
 
     case EM_GETIMECOLOR:
-            DPRINTF_EDIT_MSG32("EM_GETIMECOLOR Ignored");
+            FIXME_MSG("EM_GETIMECOLOR Ignored");
             return 0;
 
     case EM_GETIMECOMPMODE:
-            DPRINTF_EDIT_MSG32("EM_GETIMECOMPMODE Ignored");
+            FIXME_MSG("EM_GETIMECOMPMODE Ignored");
             return 0;
 
     case EM_GETIMEOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_GETIMEOPTIONS Ignored");
+            FIXME_MSG("EM_GETIMEOPTIONS Ignored");
             return 0;
 
     case EM_GETLANGOPTIONS:
-            DPRINTF_EDIT_MSG32("STUB: EM_GETLANGOPTIONS");
+            FIXME_MSG("STUB: EM_GETLANGOPTIONS");
             return 0;
 
     case EM_GETOLEINTERFACE:
-            DPRINTF_EDIT_MSG32("EM_GETOLEINTERFACE Ignored");
+            FIXME_MSG("EM_GETOLEINTERFACE Ignored");
             return 0;
 
     case EM_GETOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_GETOPTIONS Ignored");
-            return 0;
-
-    case EM_GETPARAFORMAT:
-            DPRINTF_EDIT_MSG32("EM_GETPARAFORMAT Ignored");
+            FIXME_MSG("EM_GETOPTIONS Ignored");
             return 0;
 
     case EM_GETPUNCTUATION:
-            DPRINTF_EDIT_MSG32("EM_GETPUNCTUATION Ignored");
+            FIXME_MSG("EM_GETPUNCTUATION Ignored");
             return 0;
 
     case EM_GETREDONAME:
-            DPRINTF_EDIT_MSG32("EM_GETREDONAME Ignored");
-            return 0;
-
-    case EM_GETSCROLLPOS:
-            DPRINTF_EDIT_MSG32("EM_GETSCROLLPOS Ignored");
+            FIXME_MSG("EM_GETREDONAME Ignored");
             return 0;
 
     case EM_GETSELTEXT:
-            DPRINTF_EDIT_MSG32("EM_GETSELTEXT");
-            return RICHEDIT_GetSelText(hwndEdit,(void *)lParam);
+            FIXME_MSG("EM_GETSELTEXT Ignored");
+//            return RICHEDIT_GetSelText(hwndEdit,(void *)lParam);
+			return 0;
+            
 
     case EM_GETTEXTEX:
-            DPRINTF_EDIT_MSG32("EM_GETTEXTEX Ignored");
+            FIXME_MSG("EM_GETTEXTEX Ignored");
             return 0;
 
     case EM_GETTEXTLENGTHEX:
-            DPRINTF_EDIT_MSG32("EM_GETTEXTLENGTHEX Ignored");
+            FIXME_MSG("EM_GETTEXTLENGTHEX Ignored");
             return 0;
 
     case EM_GETTEXTMODE:
-            DPRINTF_EDIT_MSG32("EM_GETTEXTMODE Ignored");
+            FIXME_MSG("EM_GETTEXTMODE Ignored");
             return 0;
 
     case EM_GETTEXTRANGE:
-            DPRINTF_EDIT_MSG32("EM_GETTEXTRANGE");
-            return RICHEDIT_GetTextRange(hwndEdit,(TEXTRANGEA *)lParam);
+            FIXME_MSG("EM_GETTEXTRANGE Ignored");
+//            return RICHEDIT_GetTextRange(hwndEdit,(TEXTRANGEA *)lParam);
+			return 0;
 
     case EM_GETTYPOGRAPHYOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_GETTYPOGRAPHYOPTIONS Ignored");
+            FIXME_MSG("EM_GETTYPOGRAPHYOPTIONS Ignored");
             return 0;
 
     case EM_GETUNDONAME:
-            DPRINTF_EDIT_MSG32("EM_GETUNDONAME Ignored");
+            FIXME_MSG("EM_GETUNDONAME Ignored");
             return 0;
 
     case EM_GETWORDBREAKPROCEX:
-            DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROCEX Ignored");
+            FIXME_MSG("EM_GETWORDBREAKPROCEX Ignored");
             return 0;
 
     case EM_GETWORDWRAPMODE:
-            DPRINTF_EDIT_MSG32("EM_GETWORDWRAPMODE Ignored");
+            FIXME_MSG("EM_GETWORDWRAPMODE Ignored");
             return 0;
 
     case EM_GETZOOM:
-            DPRINTF_EDIT_MSG32("EM_GETZOOM Ignored");
+            FIXME_MSG("EM_GETZOOM Ignored");
             return 0;
 
     case EM_HIDESELECTION:
-            DPRINTF_EDIT_MSG32("EM_HIDESELECTION Ignored");
+            FIXME_MSG("EM_HIDESELECTION Ignored");
             return 0;
 
     case EM_PASTESPECIAL:
-            DPRINTF_EDIT_MSG32("EM_PASTESPECIAL Ignored");
+            FIXME_MSG("EM_PASTESPECIAL Ignored");
             return 0;
 
     case EM_RECONVERSION:
-            DPRINTF_EDIT_MSG32("EM_RECONVERSION Ignored");
+            FIXME_MSG("EM_RECONVERSION Ignored");
             return 0;
 
     case EM_REDO:
-            DPRINTF_EDIT_MSG32("EM_REDO Ignored");
+            FIXME_MSG("EM_REDO Ignored");
             return 0;
 
     case EM_REQUESTRESIZE:
-            DPRINTF_EDIT_MSG32("EM_REQUESTRESIZE Ignored");
+            FIXME_MSG("EM_REQUESTRESIZE Ignored");
             return 0;
 
     case EM_SELECTIONTYPE:
-            DPRINTF_EDIT_MSG32("EM_SELECTIONTYPE Ignored");
+            FIXME_MSG("EM_SELECTIONTYPE Ignored");
             return 0;
 
     case EM_SETBIDIOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_SETBIDIOPTIONS Ignored");
+            FIXME_MSG("EM_SETBIDIOPTIONS Ignored");
             return 0;
 
     case EM_SETBKGNDCOLOR:
-            DPRINTF_EDIT_MSG32("EM_SETBKGNDCOLOR Ignored");
-            return 0;
-
-    case EM_SETCHARFORMAT:
-            DPRINTF_EDIT_MSG32("EM_SETCHARFORMAT Ignored");
+            FIXME_MSG("EM_SETBKGNDCOLOR Ignored");
             return 0;
 
     case EM_SETEDITSTYLE:
-            DPRINTF_EDIT_MSG32("EM_SETEDITSTYLE Ignored");
-            return 0;
-
-    case EM_SETEVENTMASK:
-            DPRINTF_EDIT_MSG32("EM_SETEVENTMASK Ignored");
+            FIXME_MSG("EM_SETEDITSTYLE Ignored");
             return 0;
 
     case EM_SETFONTSIZE:
-            DPRINTF_EDIT_MSG32("EM_SETFONTSIZE Ignored");
+            FIXME_MSG("EM_SETFONTSIZE Ignored");
             return 0;
 
     case EM_SETIMECOLOR:
-            DPRINTF_EDIT_MSG32("EM_SETIMECOLO Ignored");
+            FIXME_MSG("EM_SETIMECOLO Ignored");
             return 0;
 
     case EM_SETIMEOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_SETIMEOPTIONS Ignored");
+            FIXME_MSG("EM_SETIMEOPTIONS Ignored");
             return 0;
 
     case EM_SETLANGOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_SETLANGOPTIONS Ignored");
+            FIXME_MSG("EM_SETLANGOPTIONS Ignored");
             return 0;
 
     case EM_SETOLECALLBACK:
-            DPRINTF_EDIT_MSG32("EM_SETOLECALLBACK Ignored");
+            FIXME_MSG("EM_SETOLECALLBACK Ignored");
             return 0;
 
     case EM_SETOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_SETOPTIONS Ignored");
+            FIXME_MSG("EM_SETOPTIONS Ignored");
             return 0;
 
     case EM_SETPALETTE:
-            DPRINTF_EDIT_MSG32("EM_SETPALETTE Ignored");
-            return 0;
-
-    case EM_SETPARAFORMAT:
-            DPRINTF_EDIT_MSG32("EM_SETPARAFORMAT Ignored");
+            FIXME_MSG("EM_SETPALETTE Ignored");
             return 0;
 
     case EM_SETPUNCTUATION:
-            DPRINTF_EDIT_MSG32("EM_SETPUNCTUATION Ignored");
+            FIXME_MSG("EM_SETPUNCTUATION Ignored");
             return 0;
 
     case EM_SETSCROLLPOS:
-            DPRINTF_EDIT_MSG32("EM_SETSCROLLPOS Ignored");
+            FIXME_MSG("EM_SETSCROLLPOS Ignored");
             return 0;
 
     case EM_SETTARGETDEVICE:
-            DPRINTF_EDIT_MSG32("EM_SETTARGETDEVICE Ignored");
+            FIXME_MSG("EM_SETTARGETDEVICE Ignored");
             return 0;
 
     case EM_SETTEXTEX:
-            DPRINTF_EDIT_MSG32("EM_SETTEXTEX Ignored");
+            FIXME_MSG("EM_SETTEXTEX Ignored");
             return 0;
 
     case EM_SETTEXTMODE:
-            DPRINTF_EDIT_MSG32("EM_SETTEXTMODE Ignored");
+            FIXME_MSG("EM_SETTEXTMODE Ignored");
             return 0;
 
     case EM_SETTYPOGRAPHYOPTIONS:
-            DPRINTF_EDIT_MSG32("EM_SETTYPOGRAPHYOPTIONS Ignored");
+            FIXME_MSG("EM_SETTYPOGRAPHYOPTIONS Ignored");
             return 0;
 
     case EM_SETUNDOLIMIT:
-            DPRINTF_EDIT_MSG32("EM_SETUNDOLIMIT Ignored");
+            FIXME_MSG("EM_SETUNDOLIMIT Ignored");
             return 0;
 
     case EM_SETWORDBREAKPROCEX:
-            DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROCEX Ignored");
+            FIXME_MSG("EM_SETWORDBREAKPROCEX Ignored");
             return 0;
 
     case EM_SETWORDWRAPMODE:
-            DPRINTF_EDIT_MSG32("EM_SETWORDWRAPMODE Ignored");
+            FIXME_MSG("EM_SETWORDWRAPMODE Ignored");
             return 0;
 
     case EM_SETZOOM:
-            DPRINTF_EDIT_MSG32("EM_SETZOOM Ignored");
+            FIXME_MSG("EM_SETZOOM Ignored");
             return 0;
 
     case EM_SHOWSCROLLBAR:
-            DPRINTF_EDIT_MSG32("EM_SHOWSCROLLBAR Ignored");
+            FIXME_MSG("EM_SHOWSCROLLBAR Ignored");
             return 0;
 
     case EM_STOPGROUPTYPING:
-            DPRINTF_EDIT_MSG32("EM_STOPGROUPTYPING Ignored");
+            FIXME_MSG("EM_STOPGROUPTYPING Ignored");
             return 0;
 
     case EM_STREAMOUT:
-            DPRINTF_EDIT_MSG32("EM_STREAMOUT Ignored");
+            FIXME_MSG("EM_STREAMOUT Ignored");
             return 0;
 
-/* Messages dispatched to the edit control */
+/* Messages previously dispatched to the edit control */
      case EM_CANUNDO:
-            DPRINTF_EDIT_MSG32("EM_CANUNDO Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_CHARFROMPOS:
-            DPRINTF_EDIT_MSG32("EM_CHARFROMPOS Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_CANUNDO Ignored");
+			return 0;
      case EM_EMPTYUNDOBUFFER:
-            DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_FMTLINES:
-            DPRINTF_EDIT_MSG32("EM_FMTLINES Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_EMPTYUNDOBUFFER Ignored");
+			return 0;
      case EM_GETFIRSTVISIBLELINE:
-            DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_GETHANDLE:
-            DPRINTF_EDIT_MSG32("EM_GETHANDLE Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_GETFIRSTVISIBLELINE Ignored");
+			return 0;
  /*    case EM_GETIMESTATUS:*/
      case EM_GETLIMITTEXT:
-            DPRINTF_EDIT_MSG32("EM_GETLIMITTEXT Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_GETLIMITTEXT Ignored");
+			return 0;
      case EM_GETLINE:
-            DPRINTF_EDIT_MSG32("EM_GETLINE Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_GETLINE Ignored");
+			return 0;
      case EM_GETLINECOUNT:
-            DPRINTF_EDIT_MSG32("EM_GETLINECOUNT Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_GETMARGINS:
-            DPRINTF_EDIT_MSG32("EM_GETMARGINS Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_GETMODIFY:
-            DPRINTF_EDIT_MSG32("EM_GETMODIFY Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_GETPASSWORDCHAR:
-            DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_GETLINECOUNT Ignored");
+			return 0;
      case EM_GETRECT:
-            DPRINTF_EDIT_MSG32("EM_GETRECT Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_GETRECT Ignored");
+			return 0;
      case EM_GETSEL:
-            DPRINTF_EDIT_MSG32("EM_GETSEL Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_GETSEL Ignored");
+			return 0;
      case EM_GETTHUMB:
-            DPRINTF_EDIT_MSG32("EM_GETTHUMB Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_GETTHUMB Ignored");
+			return 0;
      case EM_GETWORDBREAKPROC:
-            DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_GETWORDBREAKPROC Ignored");
+			return 0;
      case EM_LINEFROMCHAR:
-            DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_LINEFROMCHAR Ignored");
+			return 0;
      case EM_LINEINDEX:
-            DPRINTF_EDIT_MSG32("EM_LINEINDEX Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_LINEINDEX Ignored");
+			return 0;
      case EM_LINELENGTH:
-            DPRINTF_EDIT_MSG32("EM_LINELENGTH Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_LINELENGTH Ignored");
+			return 0;
      case EM_LINESCROLL:
-            DPRINTF_EDIT_MSG32("EM_LINESCROLL Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_POSFROMCHAR:
-            DPRINTF_EDIT_MSG32("EM_POSFROMCHAR Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_REPLACESEL:
-            DPRINTF_EDIT_MSG32("case EM_REPLACESEL Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_LINESCROLL Ignored");
+			return 0;
      case EM_SCROLL:
-            DPRINTF_EDIT_MSG32("case EM_SCROLL Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_SCROLL Ignored");
+			return 0;
      case EM_SCROLLCARET:
-            DPRINTF_EDIT_MSG32("EM_SCROLLCARET Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_SETHANDLE:
-            DPRINTF_EDIT_MSG32("EM_SETHANDLE Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_SCROLLCARET Ignored");
+			return 0;
  /*    case EM_SETIMESTATUS:*/
      case EM_SETLIMITTEXT:
-            DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_SETMARGINS:
-            DPRINTF_EDIT_MSG32("case EM_SETMARGINS Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_SETMODIFY:
-            DPRINTF_EDIT_MSG32("EM_SETMODIFY Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_SETPASSWORDCHAR:
-            DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_SETREADONLY:
-            DPRINTF_EDIT_MSG32("EM_SETREADONLY Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_SETLIMITTEXT Ignored");
+			return 0;
      case EM_SETRECT:
-            DPRINTF_EDIT_MSG32("EM_SETRECT Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_SETRECTNP:
-            DPRINTF_EDIT_MSG32("EM_SETRECTNP Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_SETSEL:
-            DPRINTF_EDIT_MSG32("EM_SETSEL Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case EM_SETTABSTOPS:
-            DPRINTF_EDIT_MSG32("EM_SETTABSTOPS Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_SETRECT Ignored");
+			return 0;
      case EM_SETWORDBREAKPROC:
-            DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("EM_SETWORDBREAKPROC Ignored");
+			return 0;
      case EM_UNDO:
-            DPRINTF_EDIT_MSG32("EM_UNDO Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-
+            FIXME_MSG("EM_UNDO Ignored");
+			return 0;
      case WM_STYLECHANGING:
-            DPRINTF_EDIT_MSG32("WM_STYLECHANGING Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("WM_STYLECHANGING Ignored");
+			return 0;
      case WM_STYLECHANGED:
-            DPRINTF_EDIT_MSG32("WM_STYLECHANGED Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case WM_NCCALCSIZE:
-            DPRINTF_EDIT_MSG32("WM_NCCALCSIZE Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("WM_STYLECHANGED Ignored");
+			return 0;
      case WM_GETTEXT:
-            DPRINTF_EDIT_MSG32("WM_GETTEXT Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("WM_GETTEXT Ignored");
+	    return 0;
      case WM_GETTEXTLENGTH:
-            DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case WM_SETTEXT:
-            DPRINTF_EDIT_MSG32("WM_SETTEXT Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case WM_CUT:
-            DPRINTF_EDIT_MSG32("WM_CUT Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-     case WM_COPY:
-            DPRINTF_EDIT_MSG32("WM_COPY Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
-    case WM_PASTE:
-            DPRINTF_EDIT_MSG32("WM_PASTE Passed to edit control");
-	    return SendMessageA( hwndEdit, uMsg, wParam, lParam);
+            FIXME_MSG("WM_GETTEXTLENGTH Ignored");
+	    return 0;
 
     /* Messages passed to default handler. */
     case WM_NCPAINT:
         DPRINTF_EDIT_MSG32("WM_NCPAINT Passed to default");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_PAINT:
-        DPRINTF_EDIT_MSG32("WM_PAINT Passed to default");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
     case WM_ERASEBKGND:
         DPRINTF_EDIT_MSG32("WM_ERASEBKGND Passed to default");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_KILLFOCUS:
-        DPRINTF_EDIT_MSG32("WM_KILLFOCUS Passed to default");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
     case WM_DESTROY:
         DPRINTF_EDIT_MSG32("WM_DESTROY Passed to default");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
+//        return RICHED32_WM_Destroy(res);
     case WM_CHILDACTIVATE:
 	DPRINTF_EDIT_MSG32("WM_CHILDACTIVATE Passed to default");
 	return DefWindowProcA( hwnd,uMsg,wParam,lParam);
@@ -666,8 +834,9 @@
     case WM_CTLCOLOREDIT:
         DPRINTF_EDIT_MSG32("WM_CTLCOLOREDIT Passed to default");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_SETCURSOR:
-        DPRINTF_EDIT_MSG32("WM_SETCURSOR Passed to default");
+    case WM_SETCURSOR:
+		// FIXME: if cursor is in the margin show the cursor the opposite way round
+		// FIXME: otherwise show IBEAM
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
     case WM_MOVE:
         DPRINTF_EDIT_MSG32("WM_MOVE Passed to default");
@@ -676,48 +845,57 @@
         DPRINTF_EDIT_MSG32("WM_SHOWWINDOW Passed to default");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
     case WM_NCCREATE:
-        DPRINTF_EDIT_MSG32("WM_NCCREATE Passed to default");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
+//        DPRINTF_EDIT_MSG32("WM_NCCREATE Passed to default");
+//        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
+        return RICHED32_NCCreate(hwnd, (LPCREATESTRUCTA) lParam);
     case WM_PARENTNOTIFY:
         DPRINTF_EDIT_MSG32("WM_PARENTNOTIFY Passed to default");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
     case WM_SETREDRAW:
         DPRINTF_EDIT_MSG32("WM_SETREDRAW Passed to default");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_NCDESTROY:
-        DPRINTF_EDIT_MSG32("WM_NCDESTROY Passed to default");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_NCHITTEST:
-        DPRINTF_EDIT_MSG32("WM_NCHITTEST Passed to default");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_CTLCOLORSTATIC:
+/*    case WM_CTLCOLORSTATIC:
         DPRINTF_EDIT_MSG32("WM_CTLCOLORSTATIC Passed to default");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_NCMOUSEMOVE:
-        DPRINTF_EDIT_MSG32("WM_NCMOUSEMOVE Passed to default");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_CLEAR:
-        DPRINTF_EDIT_MSG32("WM_CLEAR Passed to default");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
+        return DefWindowProcA( hwnd,uMsg,wParam,lParam);*/
+	case WM_VSCROLL:
+		FIXME_MSG("WM_VSCROLL - stub");
+		RT_NOTIFY_PARENT(res, EN_VSCROLL, "EN_VSCROLL");
+		return 0;
+	case WM_HSCROLL:
+		FIXME_MSG("WM_HSCROLL - stub");
+		RT_NOTIFY_PARENT(res, EN_HSCROLL, "EN_VSCROLL");
+		return 0;
+
    /*
     * used by IE in the EULA box
     */
     case WM_ALTTABACTIVE:
-        DPRINTF_EDIT_MSG32("WM_ALTTABACTIVE");
+        FIXME_MSG("WM_ALTTABACTIVE");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
     case WM_GETDLGCODE:
-        DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
+        FIXME_MSG("WM_GETDLGCODE");
         return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-    case WM_SETFONT:
-        DPRINTF_EDIT_MSG32("WM_SETFONT");
-        return DefWindowProcA( hwnd,uMsg,wParam,lParam);
-
+
+		// Not supported in RichEdit
+     case EM_FMTLINES:
+     case EM_GETHANDLE:
+     case EM_GETMARGINS:
+     case EM_GETPASSWORDCHAR:
+     case EM_SETHANDLE:
+     case EM_SETMARGINS:
+     case EM_SETPASSWORDCHAR:
+     case EM_SETRECTNP:
+     case EM_SETTABSTOPS:
+	 case WM_CTLCOLOR:
+	 case WM_GETFONT:
+            FIXME_MSG("Edit message not supported - use a RichEdit equivalent");
+			return 0;
+
+    default:
+        return DefWindowProcA(hwnd, uMsg, wParam, lParam);
     }
 
-    FIXME("Unknown message 0x%x Passed to default hwnd=%p, wParam=%08x, lParam=%08x\n",
-           uMsg, hwnd, (UINT)wParam, (UINT)lParam);
-
-   return DefWindowProcA( hwnd,uMsg,wParam,lParam);
+    return result;
 }
 
 /***********************************************************************
@@ -768,18 +946,18 @@
 {
     WNDCLASSA wndClass;
 
-    TRACE("\n");
+    TRACE("()\n");
 
     ZeroMemory(&wndClass, sizeof(WNDCLASSA));
     wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
     wndClass.lpfnWndProc = (WNDPROC)RICHED32_WindowProc;
     wndClass.cbClsExtra = 0;
-    wndClass.cbWndExtra = 0; /*(sizeof(RICHED32_INFO *);*/
-    wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
+    wndClass.cbWndExtra = sizeof(RICHEDITSTATE *);
+    wndClass.hCursor = LoadCursorW(0, IDC_IBEAMW);
     wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
-    wndClass.lpszClassName = RICHEDIT_CLASS10A; /* WC_RICHED32A; */
+    wndClass.lpszClassName = RICHEDIT_CLASS;
 
-    RegisterClassA (&wndClass);
+    RegisterClassA(&wndClass);
 }
 
 /***
@@ -794,11 +972,16 @@
  */
 VOID RICHED32_Unregister(void)
 {
-    TRACE("\n");
+    TRACE("()\n");
 
     UnregisterClassA(RICHEDIT_CLASS, NULL);
 }
-
+
+/*
 INT RICHEDIT_GetTextRange(HWND hwnd,TEXTRANGEA *tr)
 {
     UINT alloc_size, text_size, range_size;
@@ -821,13 +1004,931 @@
     HeapFree(GetProcessHeap(), 0, text);
 
     return range_size;
-}
+}*/
 
-INT RICHEDIT_GetSelText(HWND hwnd,LPSTR lpstrBuffer)
+/*INT RICHEDIT_GetSelText(HWND hwnd,LPSTR lpstrBuffer)
 {
     TEXTRANGEA textrange;
 
     textrange.lpstrText = lpstrBuffer;
     SendMessageA(hwnd,EM_GETSEL,(INT)&textrange.chrg.cpMin,(INT)&textrange.chrg.cpMax);
     return RICHEDIT_GetTextRange(hwnd,&textrange);
+}*/
+
+static LRESULT RICHED32_WM_Paint(RICHEDITSTATE * res,  WPARAM wParam)
+{
+   PAINTSTRUCT ps;
+    PARAGRAPH * pParagraph;
+	HDC hdc;
+	TRACE("(%p, %d)\n", res, wParam);
+     if (!wParam)
+        hdc = BeginPaint(res->hwndSelf, &ps);
+	else
+		hdc = (HDC) wParam;
+
+    for (pParagraph = res->pFirstParagraph; pParagraph; pParagraph = pParagraph->pNext)
+    {
+		// FIXME: make work for multiple paragraphs
+        RichTextParagraph_Draw(pParagraph, hdc, 0, 0, 0, NULL);
+    }
+
+	if (!wParam)
+		EndPaint(res->hwndSelf, &ps);
+	return 1;
+}
+
+static LRESULT RICHED32_NCCreate(HWND hwnd, LPCREATESTRUCTA lpcs)
+{
+	RICHEDITSTATE * res;
+	CHARFORMAT2W chf;
+	if (!(res = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*res))))
+		return FALSE;
+        SetWindowLongW( hwnd, 0, (LONG)res );
+
+       /*
+        *      Note: since the RICHEDITSTATE has not been fully initialized yet,
+        *            we can't use any API calls that may send
+        *            WM_XXX messages before WM_NCCREATE is completed.
+        */
+
+// 	res->is_unicode = unicode;
+ 	res->style = lpcs->style;
+
+//    res->bEnableState = !(res->style & WS_DISABLED);
+
+	res->hwndSelf = hwnd;
+	/* Save parent, which will be notified by EN_* messages */
+	res->hwndParent = lpcs->hwndParent;
+
+	res->pFirstParagraph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARAGRAPH));
+	res->pFirstParagraph->pFirstLine = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF));
+	res->pFirstParagraph->pFirstLine->pTextSeg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RICHTEXTSEG));
+	res->pFirstParagraph->wszBuffer  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
+	res->pFirstParagraph->pFirstLine->pTextSeg->pText = res->pFirstParagraph->wszBuffer;
+	res->pSelection = res->pFirstParagraph;
+	res->chrSelection.cpMin = 0;
+	res->chrSelection.cpMax = 0;
+	res->dwEventMask = ENM_NONE;
+
+	ZeroMemory(&chf, sizeof(chf));
+	chf.cbSize = sizeof(chf);
+	res->pFirstParagraph->pFirstLine->pTextSeg->hSegFont = RichText_CHARFORMAT2ToHFONT(&chf);
+	return 1;
+}
+
+static void RICHED32_WM_Create(RICHEDITSTATE * res, HWND hwnd, LPCREATESTRUCTA lpcs)
+{
+	TRACE("(%p, %p)\n", res, lpcs);
+    res->hwndParent = lpcs->hwndParent;
+	RichText_BuildLineDefs(res, res->pFirstParagraph);
+	RICHED32_UpdateScrollInfo(res);
+}
+
+/*static int RichTextLine_GetMaxHeight(LINEDEF * pLine, int currentMax)
+{
+	if (pLine->next)
+		return RichTextLine_GetMaxHeight(pLine->next, max(currentMax, pLine->cachedHeight));
+	else
+		return max(currentMax, pLine->cachedHeight);
+}*/
+
+/*static int RichTextLine_GetMaxWidth(LINEDEF * pLine, int currentMax)
+{
+	if (pLine->next)
+		return RichTextLine_GetMaxWidth(pLine->next, max(currentMax, pLine->cachedWidth));
+	else
+		return max(currentMax, pLine->cachedHeight);
+}*/
+
+static void RichTextSeg_Draw(RICHTEXTSEG * textSeg, HDC hDC, int x, int y, int index, int charCount, int nTabPositions, int * lpnTabStopPositions)
+{
+//	if (!textSeg->pText)
+//		return;
+	if (charCount == -1)
+		charCount = textSeg->length - index;
+//	TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", textSeg, hDC, x, y, charCount, nTabPositions, lpnTabStopPositions);
+	TRACE("Drawing: %d, %s\n", charCount, debugstr_w(textSeg->pText + index));
+//	else if (charCount + index > textSeg->length
+	SelectObject(hDC, textSeg->hSegFont);
+	SetTextColor(hDC, textSeg->extras.crText);
+//	SetBkColor(hDC, textSeg->extras.crText);
+	TabbedTextOutW(hDC, x, y, textSeg->pText + index, charCount, nTabPositions, lpnTabStopPositions, 0);
+}
+
+static DWORD RichTextSeg_GetExtent(RICHTEXTSEG * pTextSeg, HDC hDC, int index, int charCount, int nTabPositions, int * lpnTabStopPositions)
+{
+	TRACE("(%p, %p, %d, %d, %d, %p)\n", pTextSeg, hDC, index, charCount, nTabPositions, lpnTabStopPositions);
+	if (!pTextSeg->pText)
+		return 0;
+	if (charCount == -1)
+		charCount = pTextSeg->length - index;
+	SelectObject(hDC, pTextSeg->hSegFont);
+	if (charCount == 0)
+	{
+		WCHAR str[] = {'0', '\0'};
+		return MAKELONG(0, HIWORD(GetTabbedTextExtentW(hDC, str, 1, nTabPositions, lpnTabStopPositions)));
+	}
+	else
+		return GetTabbedTextExtentW(hDC, pTextSeg->pText + index, charCount, nTabPositions, lpnTabStopPositions);
+}
+
+static DWORD RichTextLine_Draw(LINEDEF * pLine, HDC hDC, int startx, int starty, int nTabPositions, int * lpnTabStopPositions)
+{
+	DWORD extent;
+	int nextx = startx;
+	int nexty = starty;
+	RICHTEXTSEG * pTextSeg = pLine->pTextSeg;
+	int remaining = pLine->length - 1;
+	BOOL first = TRUE;
+//	TRACE("(%p, %p, %d, %d, %d, %p)\n", pLine, hDC, startx, starty, nTabPositions, lpnTabStopPositions);
+	while(pTextSeg)
+	{
+		if (remaining < pTextSeg->length)
+		{
+			extent = RichTextSeg_GetExtent(pTextSeg, hDC, first ? pLine->startIndex : 0, remaining, nTabPositions, lpnTabStopPositions);
+			RichTextSeg_Draw(pTextSeg, hDC, nextx, nexty, first ? pLine->startIndex : 0, remaining, nTabPositions, lpnTabStopPositions);
+			nextx += LOWORD(extent);
+			break;
+		}
+		else
+		{
+			extent = RichTextSeg_GetExtent(pTextSeg, hDC, first ? pLine->startIndex : 0, -1, nTabPositions, lpnTabStopPositions);
+			RichTextSeg_Draw(pTextSeg, hDC, nextx, nexty, first ? pLine->startIndex : 0, -1, nTabPositions, lpnTabStopPositions);
+			nextx += LOWORD(extent);
+			remaining -= pTextSeg->length;
+			pTextSeg = pTextSeg->pNextSeg;
+		}
+		first = FALSE;
+	}
+	nexty += pLine->cachedHeight;
+	pLine->cachedYPos = nexty;
+	pLine->cachedWidth = nextx - startx;
+//	TRACE("nexty: %d, nextx: %d\n", nexty, nextx);
+	return MAKELONG(nextx, nexty);
+}
+
+static DWORD RichTextParagraph_Draw(PARAGRAPH * pParagraph, HDC hDC, int startx, int starty, int nTabPositions, int * lpnTabStopPositions)
+{
+	DWORD extent;
+	int nextx = startx;
+	int nexty = starty;
+	LINEDEF * pLine;
+//	TRACE("(%p, %p, %d, %d, %d, %p)\n", pParagraph, hDC, startx, starty, nTabPositions, lpnTabStopPositions);
+	for (pLine = pParagraph->pFirstLine; pLine; pLine = pLine->next)
+	{
+		extent = RichTextLine_Draw(pLine, hDC, nextx, nexty, nTabPositions, lpnTabStopPositions);
+		pParagraph->cachedHeight = HIWORD(extent) - nexty;
+		nexty = HIWORD(extent);
+	}
+	return MAKELONG(nextx, nexty);
+}
+
+static HFONT RichText_CHARFORMAT2ToHFONT(CHARFORMAT2W * pFormat)
+{
+	LOGFONTW lf;
+
+	if (pFormat->dwMask & CFM_CHARSET)
+		lf.lfCharSet = pFormat->bCharSet;
+	else
+		lf.lfCharSet = '\0';
+
+	if (pFormat->dwMask & CFM_FACE)
+		lstrcpyW(lf.lfFaceName, pFormat->szFaceName);
+	else
+		*lf.lfFaceName = '\0';
+
+	if (pFormat->dwMask & CFM_OFFSET)
+		; // ignore
+
+	if (pFormat->dwMask & CFM_SIZE)
+		lf.lfHeight = pFormat->yHeight;
+	else
+		lf.lfHeight = 0;
+
+	if (pFormat->dwMask & CFM_UNDERLINE)
+		lf.lfUnderline = (pFormat->bUnderlineType != CFU_UNDERLINENONE);
+	else
+		lf.lfUnderline = FALSE;
+
+	if (pFormat->dwMask & CFM_WEIGHT)
+		lf.lfWeight = pFormat->wWeight;
+	else
+		lf.lfWeight = FW_DONTCARE;
+
+	if (!(pFormat->dwMask & CFM_BOLD))
+		pFormat->dwEffects &= ~CFE_BOLD;
+	if (!(pFormat->dwMask & CFM_DISABLED))
+		pFormat->dwEffects &= ~CFE_DISABLED;
+	if (!(pFormat->dwMask & CFM_ITALIC))
+		pFormat->dwEffects &= ~CFE_ITALIC;
+	if (!(pFormat->dwMask & CFM_LINK))
+		pFormat->dwEffects &= ~CFE_LINK;
+	if (!(pFormat->dwMask & CFM_PROTECTED))
+		pFormat->dwEffects &= ~CFE_PROTECTED;
+	if (!(pFormat->dwMask & CFM_REVISED))
+		pFormat->dwEffects &= ~CFE_REVISED;
+	if (!(pFormat->dwMask & (CFM_SUBSCRIPT | CFM_SUPERSCRIPT)))
+		pFormat->dwEffects &= (~CFE_SUBSCRIPT & ~CFE_SUPERSCRIPT);
+	if (!(pFormat->dwMask & CFM_UNDERLINE))
+		pFormat->dwEffects &= ~CFE_UNDERLINE;
+
+	if (pFormat->dwEffects & CFE_BOLD)
+		lf.lfWeight = FW_BOLD;
+	lf.lfItalic = (pFormat->dwEffects & CFE_ITALIC);
+	lf.lfUnderline = (pFormat->dwEffects & CFE_UNDERLINE);
+	lf.lfOrientation = 0;
+	lf.lfEscapement = 0;
+
+	return CreateFontIndirectW(&lf);
+}
+
+static void RichText_ReleaseHFONT(HFONT hFont)
+{
+	DeleteObject(hFont);
+}
+
+static void RichText_ReplaceSel(RICHEDITSTATE * res, LPWSTR wszInsertion)
+{
+	// FIXME: cope with multiple paragraphs
+	PARAGRAPH * pPara = res->pSelection;
+	LONG cpMin = res->chrSelection.cpMin;
+	LONG cpMax = res->chrSelection.cpMax;
+	LONG offset;
+	LONG lenInsertion = lstrlenW(wszInsertion);
+	LONG lenNew;
+	RICHTEXTSEG * pTextSeg;
+
+	// Fix selection parameters if necessary
+	TRACE("cpMin = %ld, cpMax = %ld\n", cpMin, cpMax);
+	if (res->chrSelection.cpMin < 0)
+	{
+		res->chrSelection.cpMin = 0;
+		cpMin = 0;
+	}
+	if (res->chrSelection.cpMax < 0)
+	{
+		res->chrSelection.cpMax = 0;
+		cpMax = 0;
+	}
+	if (cpMin != cpMax && cpMin > pPara->uBufferSize && cpMax > pPara->uBufferSize)
+	{
+		res->chrSelection.cpMin = res->chrSelection.cpMax;
+		cpMin = cpMax;
+	}
+
+	lenNew = pPara->uBufferSize + lenInsertion - (cpMax - cpMin);
+
+	TRACE("(%p, %s)\n", res, debugstr_w(wszInsertion));
+
+	if (lenNew < 0)
+		return;
+
+//	TRACE("Before: %s\n", debugstr_w(pPara->wszBuffer));
+
+	if (lenNew + 1 > pPara->uBufferLimit)
+	{
+		// Over our limit so make a new buffer
+		LPWSTR wszNewText  = HeapAlloc(GetProcessHeap(), 0, (lenNew + 1) * sizeof(WCHAR));
+		lstrcpyW(wszNewText, pPara->wszBuffer);
+		// Change all RICHTEXTSEGs over to new buffer
+		for (pTextSeg = pPara->pFirstLine->pTextSeg; pTextSeg; pTextSeg  = pTextSeg->pNextSeg)
+		{
+			pTextSeg->pText = pTextSeg->pText - pPara->wszBuffer + wszNewText;
+		}
+		HeapFree(GetProcessHeap(), 0, pPara->wszBuffer);
+		pPara->wszBuffer = wszNewText;
+		pPara->uBufferLimit = lenNew + 1;
+/*		if (pPara->uBufferSize == 0)
+			pPara->uBufferSize = 1;*/
+	}
+
+	// Move everything up after the insertion point to make way for insertion text
+	for (offset = pPara->uBufferSize - 1 - cpMax; offset >= 0; offset--)
+		pPara->wszBuffer[offset + cpMax + 1] = pPara->wszBuffer[offset + cpMin];
+	// Copy insertion text into buffer
+//	TRACE("Middle: %s, uBufferSize: %ld\n", debugstr_w(pPara->wszBuffer), pPara->uBufferSize);
+	for (offset = 0; offset < lenInsertion; offset++)
+		pPara->wszBuffer[((cpMin >= pPara->uBufferSize) ? pPara->uBufferSize  : cpMin) + offset] = wszInsertion[offset];
+	// Clean up
+	pPara->wszBuffer[lenNew] = '\0';
+	pPara->uBufferSize = lenNew;
+
+	// Find where we have to start updating the text segs
+	pTextSeg = RichTextSeg_SkipToChar(pPara->pFirstLine->pTextSeg, cpMin, NULL);
+	TRACE("Changing: %ld, %s\n", pTextSeg->length + lenInsertion - (cpMax - cpMin), debugstr_w(pTextSeg->pText));
+	pTextSeg->length += lenInsertion - (cpMax - cpMin);
+	pTextSeg = pTextSeg->pNextSeg;
+
+	// Update the text segs so that they are still pointing to the same chars
+	while (pTextSeg)
+	{
+		pTextSeg->pText += lenInsertion;
+		pTextSeg = pTextSeg->pNextSeg;
+	}
+
+	TRACE("After: %s\n", debugstr_w(pPara->wszBuffer));
+	RichText_BuildLineDefs(res, pPara);
+	res->chrSelection.cpMin = cpMin + lenInsertion;
+	res->chrSelection.cpMax = cpMin + lenInsertion;
+	RICHED32_UpdateScrollInfo(res);
+	RICHED32_CreateAndShowCaret(res);
+}
+
+static void RichText_BuildLineDefs(RICHEDITSTATE * res, PARAGRAPH * para)
+{
+	LPWSTR currentPosition;
+	LPWSTR previousPosition;
+	LINEDEF * currentLine;
+	LINEDEF * previousLine = NULL;
+	RICHTEXTSEG * currentTextSeg;
+	RICHTEXTSEG * tempSeg;
+	DWORD extent;
+	int index;
+	HDC dc = GetDC(res->hwndSelf);
+
+	currentLine = para->pFirstLine;
+	currentTextSeg = currentLine->pTextSeg;
+	
+	index = 0;
+	currentPosition = previousPosition = currentTextSeg->pText;
+	while (*currentPosition)
+	{
+		if (*currentPosition == '\n' || *currentPosition == '\r')
+		{
+			if (!currentLine->next)
+				currentLine->next  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF));
+			currentLine->length = (int)(currentPosition - previousPosition + 1);
+			currentLine->next->pTextSeg = currentTextSeg;
+			extent = RichTextSeg_GetExtent(currentLine->pTextSeg, dc, currentLine->startIndex, -1, res->nTabPositions, res->lpnTabStopPositions);
+			currentLine->cachedWidth += LOWORD(extent);
+			currentLine->cachedHeight = HIWORD(extent);
+			currentLine->cachedYPos = (previousLine ? previousLine->cachedYPos : 0) + currentLine->cachedHeight;
+			TRACE("Building: %d, %s\n", currentLine->length, debugstr_w(currentLine->pTextSeg->pText));
+			previousLine = currentLine;
+			currentLine = currentLine->next;
+			if (*currentPosition == '\r' && *(currentPosition + 1) == '\n')
+			{
+				currentPosition++;
+				index++;
+			}
+			// update these for what index and currentPosition *will* be next time round
+			currentLine->startIndex = index + 1;
+			previousPosition = currentPosition + 1;
+		}
+		if (index >= currentTextSeg->length)
+		{
+			extent = RichTextSeg_GetExtent(currentLine->pTextSeg, dc, 0, -1, res->nTabPositions, res->lpnTabStopPositions);
+			currentLine->cachedHeight = max(HIWORD(extent), currentLine->cachedHeight);
+			currentLine->cachedWidth += LOWORD(extent);
+			currentTextSeg = currentTextSeg->pNextSeg;
+			index = 0;
+		}
+		if (!currentTextSeg)
+		{
+			currentLine->length = index;
+			extent = RichTextSeg_GetExtent(currentLine->pTextSeg, dc, currentLine->startIndex, -1, res->nTabPositions, res->lpnTabStopPositions);
+			currentLine->cachedWidth += LOWORD(extent);
+			currentLine->cachedHeight = max(HIWORD(extent), currentLine->cachedHeight);
+			currentLine->cachedYPos = (previousLine ? previousLine->cachedYPos : 0) + currentLine->cachedHeight;
+			break;
+		}
+		if (currentTextSeg->pNextSeg && currentTextSeg->pNextSeg->length < 0)
+		{
+			tempSeg = currentTextSeg->pNextSeg;
+			currentTextSeg->pNextSeg = tempSeg->pNextSeg;
+			HeapFree(GetProcessHeap(), 0, tempSeg);
+		}
+		currentPosition++;
+		index++;
+	}
+	extent = RichTextSeg_GetExtent(currentLine->pTextSeg, dc, currentLine->startIndex, -1, res->nTabPositions, res->lpnTabStopPositions);
+	currentLine->cachedWidth += LOWORD(extent);
+	currentLine->cachedHeight = max(HIWORD(extent), currentLine->cachedHeight);
+	currentLine->cachedYPos = (previousLine ? previousLine->cachedYPos : 0) + currentLine->cachedHeight;
+	currentLine->length = (int)(currentPosition - previousPosition + 1);
+	previousLine = currentLine;
+	currentLine = currentLine->next;
+	previousLine->next = NULL;
+	while (currentLine)
+	{
+		previousLine = currentLine;
+		currentLine = currentLine->next;
+		HeapFree(GetProcessHeap(), 0, previousLine);
+	}
+	ReleaseDC(res->hwndSelf, dc);
+}
+
+static void RICHED32_LockBuffer(RICHEDITSTATE * res)
+{
+//	TRACE("(%p)\n", res);
+}
+
+static LRESULT RICHED32_WM_NCDestroy(RICHEDITSTATE *res)
+{
+//	HINSTANCE hInstance = (HINSTANCE)GetWindowLongW( res->hwndSelf, GWL_HINSTANCE );
+	PARAGRAPH * pParagraph, * pParagraphNext;
+	LINEDEF * pLine, * pLineNext;
+	RICHTEXTSEG * pText, * pTextNext;
+
+	TRACE("(%p)\n", res);
+/*	if (res->hloc32W) {
+		while (LocalUnlock(es->hloc32W)) ;
+		LocalFree(es->hloc32W);
+	}
+	if (es->hloc32A) {
+		while (LocalUnlock(es->hloc32A)) ;
+		LocalFree(es->hloc32A);
+	}
+	if (es->hloc16) {
+		while (LOCAL_Unlock(hInstance, es->hloc16)) ;
+		LOCAL_Free(hInstance, es->hloc16);
+	}*/
+
+	for (pParagraph = res->pFirstParagraph; pParagraph; pParagraph = pParagraphNext)
+	{
+		pParagraphNext = pParagraph->pNext;
+		for (pText = pParagraph->pFirstLine->pTextSeg; pText; pText = pTextNext)
+		{
+			pTextNext = pText->pNextSeg;
+			RichText_ReleaseHFONT(pText->hSegFont);
+			HeapFree(GetProcessHeap(), 0, pText);
+		}
+		for (pLine = pParagraph->pFirstLine; pLine; pLine = pLineNext)
+		{
+			pLineNext = pLine->next;
+			HeapFree(GetProcessHeap(), 0, pLine);
+		}
+		HeapFree(GetProcessHeap(), 0, pParagraph);
+	}
+
+    SetWindowLongW(res->hwndSelf, 0, 0);
+	HeapFree(GetProcessHeap(), 0, res);
+
+	return 0;
+}
+
+static int RICHED32_WM_SetText(RICHEDITSTATE * res, LPCSTR szText)
+{
+		LPWSTR wszInsertion = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(szText) + 1) * sizeof(WCHAR));
+		TRACE("(%p, %s)\n", res, debugstr_a(szText));
+		MultiByteToWideChar(CP_ACP,  MB_PRECOMPOSED, szText, strlen(szText), wszInsertion, strlen(szText));
+		RichText_ReplaceSel(res, wszInsertion);
+		HeapFree(GetProcessHeap(), 0, wszInsertion);
+		InvalidateRect(res->hwndSelf, NULL, TRUE);
+		return 1;
+}
+
+static void RICHED32_EM_ReplaceSel(RICHEDITSTATE * res, BOOL bUndo, LPCSTR szText)
+{
+		LPWSTR wszInsertion = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(szText) + 1) * sizeof(WCHAR));
+		TRACE("(%p, %s)\n", res, debugstr_a(szText));
+		MultiByteToWideChar(CP_ACP,  MB_PRECOMPOSED, szText, strlen(szText), wszInsertion, strlen(szText));
+		RichText_ReplaceSel(res, wszInsertion);
+		HeapFree(GetProcessHeap(), 0, wszInsertion);
+		InvalidateRect(res->hwndSelf, NULL, TRUE);
+}
+
+static void RICHED32_EM_SetCharFormat2W(RICHEDITSTATE * res, CHARFORMAT2W * pChf)
+{
+	HFONT font = RichText_CHARFORMAT2ToHFONT(pChf);
+	int length = res->chrSelection.cpMax - res->chrSelection.cpMin;
+	LONG remaining;
+	RICHTEXTSEG * pFirstSelTextSeg = RichTextSeg_SkipToChar(res->pSelection->pFirstLine->pTextSeg, res->chrSelection.cpMin, &remaining);
+	RICHTEXTSEG * pTextSeg = pFirstSelTextSeg;
+	RICHTEXTSEG * pPreviousSeg;
+	LPWSTR lpwstrLast;
+	TRACE("(%p, %p)\n", res, pChf);
+	
+	// Check if we should insert a new RICHTEXTSEG
+	if (remaining > pFirstSelTextSeg->length && pFirstSelTextSeg->pNextSeg == NULL)
+	{
+		pFirstSelTextSeg->pNextSeg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RICHTEXTSEG));
+		pFirstSelTextSeg->pNextSeg->pText = pFirstSelTextSeg->pText + pFirstSelTextSeg->length;
+		pFirstSelTextSeg = pFirstSelTextSeg->pNextSeg;
+		pTextSeg = pFirstSelTextSeg;
+	}
+
+	// Systematically remove RICHTEXTSEGs in the selection area and add them to the first one
+	if (length - res->chrSelection.cpMin > res->chrSelection.cpMax - res->chrSelection.cpMin)
+	{
+		lpwstrLast = pTextSeg->pText + pTextSeg->length;
+		length -= pTextSeg->length - res->chrSelection.cpMin;
+		pTextSeg = pTextSeg->pNextSeg;
+		while (pTextSeg && (length + pTextSeg->length < res->chrSelection.cpMax - res->chrSelection.cpMin))
+		{
+			lpwstrLast = pTextSeg->pText + pTextSeg->length;
+			length -= pTextSeg->length;
+			RichText_ReleaseHFONT(pTextSeg->hSegFont);
+			pPreviousSeg = pTextSeg;
+			pTextSeg = pTextSeg->pNextSeg;
+			HeapFree(GetProcessHeap(), 0, pPreviousSeg);
+		}
+	}
+	else
+		lpwstrLast = pFirstSelTextSeg->pText + pFirstSelTextSeg->length;
+	pFirstSelTextSeg->pNextSeg = pTextSeg;
+	if (pFirstSelTextSeg->pNextSeg == pFirstSelTextSeg)
+		pFirstSelTextSeg->pNextSeg = NULL;
+	pFirstSelTextSeg->hSegFont = font;
+	pFirstSelTextSeg->extras.crText = pChf->crTextColor;
+	pFirstSelTextSeg->extras.crBackground = pChf->crBackColor;
+	pFirstSelTextSeg->length = (int)(lpwstrLast - pFirstSelTextSeg->pText);
+//	while(pFirstSelTextSeg->pText[pFirstSelTextSeg->length - 1] == '\n' || pFirstSelTextSeg->pText[pFirstSelTextSeg->length - 1] == '\r')
+//		pFirstSelTextSeg->length--;
+//	pTextSeg->extras  = pChf->
+	RichText_BuildLineDefs(res, res->pSelection);
+	InvalidateRect(res->hwndSelf, NULL, TRUE);
+}
+
+static RICHTEXTSEG * RichTextSeg_SkipToChar(RICHTEXTSEG * pTextSeg, LONG pos, LONG * remaining)
+{
+	TRACE("pos = %ld, pTextSeg->length = %d\n", pos, pTextSeg->length);
+	// EXSETSEL with cpMax = -1 means whole selection
+	while ((pos == -1) || (pos > pTextSeg->length))
+	{
+		if (pTextSeg->pNextSeg)
+		{
+			pos -= (int)(pTextSeg->pNextSeg->pText - pTextSeg->pText);
+			pTextSeg = pTextSeg->pNextSeg;
+		}
+		else
+			break;
+	}
+	if (remaining)
+		*remaining = pos;
+	return pTextSeg;
+}
+
+static LINEDEF * RichTextLine_SkipToChar(LINEDEF * pLine, LONG pos, LONG * remaining)
+{
+	// EXSETSEL with cpMax = -1 means whole selection
+	while ((pos == -1) || (pos >= pLine->length) || (pLine->pTextSeg->pText[pos] == '\n') || (pLine->pTextSeg->pText[pos] == '\r'))
+	{
+		if (pLine->next)
+		{
+			pos -= pLine->pTextSeg->pText + pLine->startIndex - pLine->next->pTextSeg->pText - pLine->next->startIndex;
+			pLine = pLine->next;
+		}
+		else
+			break;
+	}
+	if (remaining)
+		*remaining = pos < 0 ? 0 : pos;
+	return pLine;
+}
+
+static void RICHED32_EM_SetCharFormat2A(RICHEDITSTATE * res, CHARFORMAT2A * pChf)
+{
+	CHARFORMAT2W chfW;
+	CopyMemory(&chfW, pChf, (int)(&(pChf->szFaceName)) - (int)pChf);
+	CopyMemory(&(chfW.wWeight), &(pChf->wWeight), (int)(&(pChf->bRevAuthor) + sizeof(BYTE)) - (int)&(pChf->wWeight));
+	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pChf->szFaceName, LF_FACESIZE, chfW.szFaceName, LF_FACESIZE);
+	RICHED32_EM_SetCharFormat2W(res, &chfW);
 }
+
+static void RICHED32_CreateAndShowCaret(RICHEDITSTATE * res)
+{
+	DWORD extent = RichText_EM_PosFromChar(res, res->chrSelection.cpMax);
+	LONG remaining;
+	LINEDEF * pLine = RichTextLine_SkipToChar(res->pSelection->pFirstLine, res->chrSelection.cpMax, &remaining);
+
+	TRACE("height: %d\n", pLine->cachedHeight);
+	CreateCaret(res->hwndSelf, 0, 1, pLine->cachedHeight);
+	TRACE("x = %d, y = %d\n", LOWORD(extent), pLine->cachedYPos - pLine->cachedHeight);
+	SetCaretPos(LOWORD(extent), pLine->cachedYPos - pLine->cachedHeight);
+	ShowCaret(res->hwndSelf);
+}
+
+static void RICHED32_UpdateScrollInfo(RICHEDITSTATE * res)
+{
+	int line_count = 0;
+	PARAGRAPH * pParagraph;
+	LINEDEF * pLine;
+	for (pParagraph = res->pFirstParagraph; pParagraph; pParagraph = pParagraph->pNext)
+	{
+		for (pLine = pParagraph->pFirstLine; pLine; pLine = pLine->next)
+		{
+			line_count++;
+		}
+	}
+    if ((res->style & WS_VSCROLL) /*&& !(res->flags & EF_VSCROLL_TRACK)*/)
+    {
+	SCROLLINFO si;
+	si.cbSize	= sizeof(SCROLLINFO);
+	si.fMask	= /*SIF_PAGE |*/ SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
+	si.nMin		= 0;
+	si.nMax		= line_count - 1;
+//	si.nPage	= (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+	si.nPos		= /*res->y_offset*/ 0;
+	TRACE("SB_VERT, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
+		si.nMin, si.nMax, si.nPage, si.nPos);
+	SetScrollInfo(res->hwndSelf, SB_VERT, &si, TRUE);
+    }
+
+/*    if ((es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK))
+    {
+	SCROLLINFO si;
+	si.cbSize	= sizeof(SCROLLINFO);
+	si.fMask	= SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
+	si.nMin		= 0;
+	si.nMax		= es->text_width - 1;
+	si.nPage	= es->format_rect.right - es->format_rect.left;
+	si.nPos		= es->x_offset;
+	TRACE("SB_HORZ, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
+		si.nMin, si.nMax, si.nPage, si.nPos);
+	SetScrollInfo(es->hwndSelf, SB_HORZ, &si, TRUE);
+    }*/
+}
+
+static void RICHED32_WM_Char(RICHEDITSTATE * res, WCHAR charW)
+{
+	if (res->style & ES_READONLY)
+	{
+		MessageBeep(0);
+		return;
+	}
+
+	switch (charW)
+	{
+	case 0x03: /* ^C */
+		SendMessageW(res->hwndSelf, WM_COPY, 0, 0);
+		break;
+	case 0x16: /* ^V */
+		SendMessageW(res->hwndSelf, WM_PASTE, 0, 0);
+		break;
+	case 0x18: /* ^X */
+		SendMessageW(res->hwndSelf, WM_CUT, 0, 0);
+		break;
+	case VK_BACK:
+		{
+			WCHAR wch = '\0';
+			if (res->chrSelection.cpMin == res->chrSelection.cpMax)
+			{
+				res->chrSelection.cpMin--;
+			}
+			RichText_ReplaceSel(res, &wch);
+			InvalidateRect(res->hwndSelf, NULL, TRUE);
+			break;
+		}
+		// FIXME: more handling here
+	default:
+		{
+			WCHAR str[2] = {charW, '\0'};
+			RichText_ReplaceSel(res, str);
+			InvalidateRect(res->hwndSelf, NULL, TRUE);
+		}
+	}
+}
+
+static LRESULT RichText_EM_PosFromChar(RICHEDITSTATE * res, INT index)
+{
+	LONG remaining;
+
+	// FIXME: Cope with multiple paragraphs
+	INT nextx = 0;
+	INT nexty = 0;
+	LINEDEF * pLine = RichTextLine_SkipToChar(res->pFirstParagraph->pFirstLine, index, &remaining);
+	HFONT old_font;
+
+	RICHTEXTSEG * pTextSeg = pLine->pTextSeg;
+	BOOL first = TRUE;
+	DWORD extent;
+	HDC dc = GetDC(res->hwndSelf);
+	old_font = SelectObject(dc, pTextSeg->hSegFont);
+	while(pTextSeg)
+	{
+		if (remaining < pTextSeg->length)
+		{
+			extent = RichTextSeg_GetExtent(pTextSeg, dc, first ? pLine->startIndex : 0, remaining, res->nTabPositions, res->lpnTabStopPositions);
+			nextx += LOWORD(extent);
+			nexty = max(HIWORD(extent), nexty);
+			break;
+		}
+		else
+		{
+			extent = RichTextSeg_GetExtent(pTextSeg, dc, first ? pLine->startIndex : 0, -1, res->nTabPositions, res->lpnTabStopPositions);
+			nextx += LOWORD(extent);
+			nexty = max(HIWORD(extent), nexty);
+			remaining -= pTextSeg->length;
+			pTextSeg = pTextSeg->pNextSeg;
+		}
+		first = FALSE;
+	}
+	SelectObject(dc, old_font);
+	ReleaseDC(res->hwndSelf, dc);
+	return MAKELONG(nextx, pLine->cachedHeight);
+}
+
+/*static void RichText_SetCaretPos(RICHEDITSTATE * res, INT pos)
+{
+//	DWORD extent = RichText_EM_PosFromChar(res, res->chrSelection.cpMax);
+//	SetCaretPos(LOWORD(extent), HIWORD(extent));
+	RICHED32_CreateAndShowCaret(res);
+}*/
+
+static INT RichText_CharFromPos(RICHEDITSTATE * res, POINTL * pPoint)
+{
+	// FIXME: handle margins and offsets
+	LONG x = pPoint->x;
+	LONG y = pPoint->y;
+	INT pos = 0;
+	INT linechar = 0;
+	PARAGRAPH * pParagraph;
+	LINEDEF * pLine;
+	INT extent;
+	INT oldextent;
+//	RICHTEXTSEG * pTextSeg;
+//	BOOL bStart = TRUE;
+	for (pParagraph = res->pFirstParagraph; pParagraph->pNext; pParagraph = pParagraph->pNext)
+	{
+		if (y < pParagraph->cachedHeight)
+			break;
+		else
+		{
+			y -= pParagraph->cachedHeight;
+			// FIXME: this is not quite right - buffer size takes into account linebreaks at the moment
+			pos += pParagraph->uBufferSize;
+		}
+	}
+	for (pLine = pParagraph->pFirstLine; pLine->next; pLine = pLine->next)
+	{
+		if (y < pLine->cachedHeight)
+			break;
+		else
+		{
+			y -= pLine->cachedHeight;
+			pos += pLine->length;
+		}
+	}
+	if (x >= pLine->cachedWidth)
+	{
+		pos +=  pLine->length;
+	}
+	else
+	{
+		HDC dc = GetDC(res->hwndSelf);
+		// FIXME: do for multiple text segs
+		oldextent = 0;
+		for (linechar = 1; linechar < pLine->pTextSeg->length - pLine->startIndex; linechar++)
+		{
+			extent = LOWORD(RichTextSeg_GetExtent(pLine->pTextSeg, dc, pLine->startIndex, linechar, res->nTabPositions, res->lpnTabStopPositions));
+			if (x < extent)
+			{
+				if (x - oldextent < extent - x)
+					linechar--;
+				break;
+			}
+			oldextent = extent;
+		}
+		pos += linechar;
+//		for (pTextSeg = pLine->pTextSeg; pTextSeg->pNextSeg && linechar < pLine->length; linechar += pTextSeg->length, pTextSeg = pTextSeg->pNextSeg)
+//			;
+//		x -= LOWORD(RichTextSeg_GetExtent(pTextSeg, dc, pLine->startIndex, -1, res->nTabPositions, res->lpnTabStops));
+//		while (x < LOWORD(RichTextSeg_GetExtent(pTextSeg, dc, pLine->startIndex, -1, res->nTabPositions
+		ReleaseDC(res->hwndSelf, dc);
+	}
+//	TRACE("returning: %d\n", pos);
+	return pos;
+}
+
+static LRESULT RichText_EM_FindTextExW(RICHEDITSTATE * res, UINT fuFlags, FINDTEXTEXW * lpFindText)
+{
+	FIXME("\n");
+	return -1;
+}
+
+static LRESULT RichText_EM_FindTextExA(RICHEDITSTATE * res, UINT fuFlags, FINDTEXTEXA * lpFindText)
+{
+	FINDTEXTEXW findTextW;
+	LRESULT result = -1;
+	findTextW.lpstrText = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(lpFindText->lpstrText) + 1) * sizeof(WCHAR));
+	TRACE("(%p, %s)\n", res, debugstr_a(lpFindText->lpstrText));
+	MultiByteToWideChar(CP_ACP,  MB_PRECOMPOSED, lpFindText->lpstrText, strlen(lpFindText->lpstrText), findTextW.lpstrText, strlen(lpFindText->lpstrText));
+	result = RichText_EM_FindTextExW(res, fuFlags, &findTextW);
+	HeapFree(GetProcessHeap(), 0, findTextW.lpstrText);
+	CopyMemory(&lpFindText->chrgText, &findTextW.chrgText, sizeof(CHARRANGE));
+	return result;
+}
+
+static void RichTextParagraph_SetFormat2(PARAGRAPH * pParagraph, PARAFORMAT * pFormat)
+{
+	int i;
+	if (pFormat->dwMask & PFM_ALIGNMENT)
+		pParagraph->format.wAlignment = pFormat->wAlignment;
+	if (pFormat->dwMask & PFM_NUMBERING)
+		pParagraph->format.wNumbering = pFormat->wNumbering;
+	if (pFormat->dwMask & PFM_OFFSET)
+		pParagraph->format.dxOffset = pFormat->dxOffset;
+	if (pFormat->dwMask & PFM_OFFSETINDENT)
+		pParagraph->format.dxStartIndent = pFormat->dxStartIndent;
+	if (pFormat->dwMask & PFM_RIGHTINDENT)
+		pParagraph->format.dxRightIndent = pFormat->dxRightIndent;
+	if (pFormat->dwMask & PFM_RTLPARA)
+		pParagraph->format.wEffects = pFormat->wEffects;
+	if (pFormat->dwMask & PFM_STARTINDENT)
+		pParagraph->format.dxStartIndent = pFormat->dxStartIndent;
+	if (pFormat->dwMask & PFM_TABSTOPS)
+	{
+		pParagraph->format.cTabCount = pFormat->cTabCount;
+		for (i = 0; i < pParagraph->format.cTabCount; i++)
+			pParagraph->format.rgxTabs[i] = pFormat->rgxTabs[i];
+	}
+//	if (pFormat->cbSize != sizeof(PARAFORMAT2))
+		return;
+
+//	FIXME("PARAFORMAT2 not supported yet\n");
+}
+
+static void RichText_WM_Keydown(RICHEDITSTATE * res, int nVirtKey, long lKeyData)
+{
+	BOOL shift = GetKeyState(VK_SHIFT) & 0x8000;
+
+	switch (nVirtKey)
+	{
+	case VK_LEFT:
+		if (!shift)
+			res->chrSelection.cpMax--;
+		res->chrSelection.cpMin--;
+		InvalidateRect(res->hwndSelf, NULL, TRUE);
+		RICHED32_CreateAndShowCaret(res);
+		break;
+	case VK_RIGHT:
+		if (!shift)
+			res->chrSelection.cpMax++;
+		res->chrSelection.cpMin++;
+		InvalidateRect(res->hwndSelf, NULL, TRUE);
+		RICHED32_CreateAndShowCaret(res);
+		break;
+	case VK_UP:
+		{
+			POINTL p;
+			DWORD extent = RichText_EM_PosFromChar(res, res->chrSelection.cpMin);
+			p.x = LOWORD(extent);
+			p.y = HIWORD(extent) - 1;
+			res->chrSelection.cpMax = RichText_CharFromPos(res, &p);
+			if (!shift)
+				res->chrSelection.cpMin = res->chrSelection.cpMax;
+			InvalidateRect(res->hwndSelf, NULL, TRUE);
+			RICHED32_CreateAndShowCaret(res);
+			break;
+		}
+	case VK_DOWN:
+		{
+			FIXME("VK_DOWN not handled yet\n");
+/*			POINTL p;
+			DWORD extent = RichText_EM_PosFromChar(res, res->chrSelection.cpMin);
+			p.x = LOWORD(extent);
+			p.y = HIWORD(extent) + 1; // this needs to be the line height really
+			res->chrSelection.cpMax = RichText_CharFromPos(res, &p);
+			if (!shift)
+				res->chrSelection.cpMin = res->chrSelection.cpMax;
+			InvalidateRect(res->hwndSelf, NULL, TRUE);
+			RICHED32_CreateAndShowCaret(res);*/
+			break;
+		}
+	case VK_HOME:
+		FIXME("VK_HOME not handled yet\n");
+		break;
+	case VK_END:
+		FIXME("VK_END not handled yet\n");
+		break;
+	case VK_DELETE:
+		{
+			WCHAR wch = '\0';
+			if (res->style & ES_READONLY)
+			{
+				MessageBeep(0);
+				break;
+			}
+			if (res->chrSelection.cpMin == res->chrSelection.cpMax)
+			{
+				res->chrSelection.cpMax++;
+			}
+			RichText_ReplaceSel(res, &wch);
+			InvalidateRect(res->hwndSelf, NULL, TRUE);
+			break;
+		}
+	default:
+	}
+}
+
+static void RICHED32_WM_Cut(RICHEDITSTATE * res)
+{
+	RICHED32_WM_Copy(res);
+	RICHED32_WM_Clear(res);
+}
+
+static void RICHED32_WM_Copy(RICHEDITSTATE * res)
+{
+	FIXME("stub\n");
+}
+
+static void RICHED32_WM_Paste(RICHEDITSTATE * res)
+{
+	FIXME("stub\n");
+}
+
+static void RICHED32_WM_Clear(RICHEDITSTATE * res)
+{
+	FIXME("stub\n");
+}
Index: wine/include/richedit.h
===================================================================
RCS file: /home/wine/wine/include/richedit.h,v
retrieving revision 1.14
diff -u -r1.14 richedit.h
--- wine/include/richedit.h	19 Nov 2002 00:44:05 -0000	1.14
+++ wine/include/richedit.h	4 Dec 2002 22:37:10 -0000
@@ -470,7 +470,7 @@
     UINT       cbSize;
     DWORD      dwMask;
     WORD       wNumbering;
-    WORD       wReserved;
+    WORD       wEffects; // was wReserved
     LONG       dxStartIndent;
     LONG       dxRightIndent;
     LONG       dxOffset;
@@ -546,7 +546,8 @@
 #define PFM_OFFSET            0x00000004
 #define PFM_ALIGNMENT         0x00000008
 #define PFM_TABSTOPS          0x00000010
-#define PFM_NUMBERING         0x00000020
+#define PFM_NUMBERING         0x00000020
+#define PFM_RTLPARA           0x00010000
 #define PFM_OFFSETINDENT      0x80000000
 
 /* numbering option */


More information about the wine-patches mailing list