Sync to Wine-20050725:
Phil Krylov <phil@newstar.rinet.ru>
- Added some useful TRACEs.
- Allow NULL parameter for WM_SETTEXT in RichEdit.
- Implemented EM_LINELENGTH RichEdit message.
- Fixed EM_LINEINDEX handler and added EM_LINEFROMCHAR handler.
- Implemented EM_EXLINEFROMCHAR, EM_LINEINDEX, EM_FINDTEXT,
  EM_FINDTEXTW, EM_FINDTEXTEX, and EM_FINDTEXTEXW messages.
- Fixed a comment about EM_STREAMIN.
- Implemented EM_GETLINECOUNT RichEdit message.
- Fixed EM_GETCHARFORMAT for selection containing a single character.
- Fixed an off-by-one error in EM_GETLINECOUNT handler.
- Fixed an off-by-one error in EM_STREAMOUT handler for non-Unicode
  plain text output.
- Fixed another couple of EM_STREAMOUT bugs.
- Removed junk from UTF-8 RTF output.
- Added emulation of RichEdit 1.0 behaviour when the 1.0 window class is
  being used. This emulation (introduced in M$ RichEdit 3.0) counts
  paragraph endings as 2 characters (CR+LF) instead of 1 (CR).
- Added EM_GETZOOM and EM_SETZOOM RichEdit message handlers.
- Added some missing but useful items to the TODO list.
Felix Nawothnig <felix.nawothnig@t-online.de>
- Check structure size and fix return values in EM_GETCHARFORMAT.
Aric Stewart <aric@codeweavers.com>
- Implementation for EM_GETTEXTEX.
Daniel Remenak <dtremenak@gmail.com>
- Basic handling of EM_SETTEXTEX.
Stefan Huehner <stefan@huehner.org>
- Make functions static to fix -Wmissing-declarations warnings.
- Change some char* to const char* to fix warnigns.
- Make some function static.
- Fix -Wmissing-declarations warnings.
Modified: trunk/reactos/lib/riched20/caret.c
Modified: trunk/reactos/lib/riched20/editor.c
Modified: trunk/reactos/lib/riched20/editor.h
Modified: trunk/reactos/lib/riched20/editstr.h
Modified: trunk/reactos/lib/riched20/paint.c
Modified: trunk/reactos/lib/riched20/para.c
Modified: trunk/reactos/lib/riched20/row.c
Modified: trunk/reactos/lib/riched20/run.c
Modified: trunk/reactos/lib/riched20/style.c
Modified: trunk/reactos/lib/riched20/wrap.c
Modified: trunk/reactos/lib/riched20/writer.c
Modified: trunk/reactos/w32api/include/richedit.h

Modified: trunk/reactos/lib/riched20/caret.c
--- trunk/reactos/lib/riched20/caret.c	2005-08-12 17:34:06 UTC (rev 17334)
+++ trunk/reactos/lib/riched20/caret.c	2005-08-12 17:41:40 UTC (rev 17335)
@@ -192,6 +192,8 @@
       /* ME_SkipAndPropagateCharOffset(p->pRun, shift); */
       ME_CheckCharOffsets(editor);
       nChars--;
+      if (editor->bEmulateVersion10 && nChars)
+        nChars--;
       continue;
     }
     else
@@ -413,7 +415,7 @@
   }
 }
 
-BOOL ME_ArrowLeft(ME_TextEditor *editor, ME_Cursor *p)
+static BOOL ME_ArrowLeft(ME_TextEditor *editor, ME_Cursor *p)
 {
   if (p->nOffset) {
     p->nOffset = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, -1);
@@ -453,21 +455,26 @@
   return FALSE;
 }
 
-BOOL ME_ArrowRight(ME_TextEditor *editor, ME_Cursor *p)
+static BOOL ME_ArrowRight(ME_TextEditor *editor, ME_Cursor *p)
 {
-  int new_ofs = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, 1);
-  if (new_ofs<p->pRun->member.run.strText->nLen) {
-    p->nOffset = new_ofs;
-  }
-  else
+  ME_DisplayItem *pRun;
+  
+  if (!(p->pRun->member.run.nFlags & MERF_ENDPARA))
   {
-    ME_DisplayItem *pRun = ME_FindItemFwd(p->pRun, diRun);
-    if (pRun) {
-      p->pRun = pRun;
-      assert(p->pRun->type == diRun);
-      p->nOffset = 0;
+    int new_ofs = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, 1);
+    
+    if (new_ofs<p->pRun->member.run.strText->nLen)
+    {
+      p->nOffset = new_ofs;
+      return TRUE;
     }
   }
+  pRun = ME_FindItemFwd(p->pRun, diRun);
+  if (pRun) {
+    p->pRun = pRun;
+    assert(p->pRun->type == diRun);
+    p->nOffset = 0;
+  }
   return TRUE;
 }
 
@@ -698,7 +705,7 @@
   return x;
 }
 
-void ME_ArrowUp(ME_TextEditor *editor, ME_Cursor *pCursor)
+static void ME_ArrowUp(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *pRun = pCursor->pRun;
   ME_DisplayItem *pItem, *pItem2;
@@ -725,7 +732,7 @@
   pCursor->pRun = ME_FindRunInRow(editor, pItem2, x, &pCursor->nOffset, &editor->bCaretAtEnd);
 }
 
-void ME_ArrowDown(ME_TextEditor *editor, ME_Cursor *pCursor)
+static void ME_ArrowDown(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *pRun = pCursor->pRun;
   ME_DisplayItem *pItem;
@@ -749,7 +756,7 @@
   assert(pCursor->pRun->type == diRun);
 }
 
-void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
+static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *pRun = pCursor->pRun;
   ME_DisplayItem *pLast, *p;
@@ -804,7 +811,7 @@
    In such a situation, clicking the scrollbar restores its position back to the
    normal range (ie. sets it to (doclength-screenheight)). */
 
-void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
+static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *pRun = pCursor->pRun;
   ME_DisplayItem *pLast, *p;
@@ -852,7 +859,7 @@
   assert(pCursor->pRun->type == diRun);
 }
 
-void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
+static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow);
   if (pRow) {
@@ -871,7 +878,7 @@
   editor->bCaretAtEnd = FALSE;
 }
 
-void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor)
+static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diTextStart);
   if (pRow) {
@@ -883,7 +890,7 @@
   }
 }
 
-void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
+static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *pRow;
   
@@ -907,7 +914,7 @@
   editor->bCaretAtEnd = FALSE;
 }
       
-void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
+static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *p = ME_FindItemFwd(pCursor->pRun, diTextEnd);
   assert(p);
@@ -924,7 +931,7 @@
   return memcmp(&editor->pCursors[0], &editor->pCursors[1], sizeof(ME_Cursor))!=0;
 }
 
-int ME_GetSelCursor(ME_TextEditor *editor, int dir)
+static int ME_GetSelCursor(ME_TextEditor *editor, int dir)
 {
   int cdir = ME_GetCursorOfs(editor, 0) - ME_GetCursorOfs(editor, 1);
   
@@ -934,7 +941,7 @@
     return 1;
 }
       
-BOOL ME_CancelSelection(ME_TextEditor *editor, int dir)
+static BOOL ME_CancelSelection(ME_TextEditor *editor, int dir)
 {
   int cdir;
   
@@ -979,7 +986,7 @@
   return TRUE;
 }
 
-void ME_RepaintSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor)
+static void ME_RepaintSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor)
 {
   if (ME_UpdateSelection(editor, pTempCursor)) {
     ME_EnsureVisible(editor, editor->pCursors[0].pRun); 

Modified: trunk/reactos/lib/riched20/editor.c
--- trunk/reactos/lib/riched20/editor.c	2005-08-12 17:34:06 UTC (rev 17334)
+++ trunk/reactos/lib/riched20/editor.c	2005-08-12 17:41:40 UTC (rev 17335)
@@ -31,10 +31,10 @@
   + EM_EMPTYUNDOBUFFER
   + EM_EXGETSEL
   - EM_EXLIMITTEXT
-  - EM_EXLINEFROMCHAR
+  + EM_EXLINEFROMCHAR
   + EM_EXSETSEL
-  - EM_FINDTEXT
-  - EM_FINDTEXTEX
+  + EM_FINDTEXT (only FR_DOWN flag implemented)
+  + EM_FINDTEXTEX (only FR_DOWN flag implemented)
   - EM_FINDWORDBREAK
   - EM_FMTLINES
   - EM_FORMATRANGE
@@ -51,7 +51,7 @@
   - EM_GETLANGOPTIONS 2.0
   - EM_GETLIMITTEXT
   - EM_GETLINE        
-  - EM_GETLINECOUNT   returns number of rows, not of paragraphs
+  + EM_GETLINECOUNT   returns number of rows, not of paragraphs
   + EM_GETMODIFY
   - EM_GETOLEINTERFACE
   - EM_GETOPTIONS
@@ -73,12 +73,12 @@
   - EM_GETWORDBREAKPROC
   - EM_GETWORDBREAKPROCEX
   - EM_GETWORDWRAPMODE 1.0asian
-  - EM_SETZOOM 3.0
+  + EM_GETZOOM 3.0
   - EM_HIDESELECTION
   - EM_LIMITTEXT
-  - EM_LINEFROMCHAR
-  - EM_LINEINDEX
-  - EM_LINELENGTH
+  + EM_LINEFROMCHAR
+  + EM_LINEINDEX
+  + EM_LINELENGTH
   + EM_LINESCROLL
   - EM_PASTESPECIAL
   - EM_POSFROMCHARS
@@ -112,17 +112,17 @@
   - EM_SETSCROLLPOS 3.0
   - EM_SETTABSTOPS 3.0
   - EM_SETTARGETDEVICE
-  - EM_SETTEXTEX 3.0
+  + EM_SETTEXTEX 3.0 (unicode only, no rich text insertion handling, proper style?)
   - EM_SETTEXTMODE 2.0
   - EM_SETTYPOGRAPHYOPTIONS 3.0
   - EM_SETUNDOLIMIT 2.0
   - EM_SETWORDBREAKPROC
   - EM_SETWORDBREAKPROCEX
   - EM_SETWORDWRAPMODE 1.0asian
-  - EM_SETZOOM 3.0
+  + EM_SETZOOM 3.0
   - EM_SHOWSCROLLBAR 2.0
   - EM_STOPGROUPTYPING 2.0
-  + EM_STREAMIN (can't fall back to text when the RTF isn't really RTF)
+  + EM_STREAMIN
   + EM_STREAMOUT
   + EM_UNDO
   + WM_CHAR
@@ -205,6 +205,9 @@
  * - when should EN_SELCHANGE be sent after text change ? (before/after EN_UPDATE?)
  * - WM_SETTEXT may use wrong style (but I'm 80% sure it's OK)
  * - EM_GETCHARFORMAT with SCF_SELECTION may not behave 100% like in original (but very close)
+ * - full justification
+ * - hyphenation
+ * - tables
  *
  * Bugs that are probably fixed, but not so easy to verify:
  * - EN_UPDATE/EN_CHANGE are handled very incorrectly (should be OK now)
@@ -218,6 +221,7 @@
  */
 
 #include "editor.h"
+#include "commdlg.h"
 #include "ole2.h"
 #include "richole.h"
 #include "winreg.h"
@@ -231,7 +235,7 @@
 int me_debug = 0;
 HANDLE me_heap = NULL;
 
-ME_TextBuffer *ME_MakeText(void) {
+static ME_TextBuffer *ME_MakeText(void) {
   
   ME_TextBuffer *buf = ALLOC_OBJ(ME_TextBuffer);
 
@@ -295,7 +299,7 @@
   return 0;
 }
 
-void ME_RTFCharAttrHook(RTF_Info *info)
+static void ME_RTFCharAttrHook(RTF_Info *info)
 {
   CHARFORMAT2W fmt;
   fmt.cbSize = sizeof(fmt);
@@ -394,7 +398,7 @@
 
 /* FIXME this function doesn't get any information about context of the RTF tag, which is very bad,
    the same tags mean different things in different contexts */
-void ME_RTFParAttrHook(RTF_Info *info)
+static void ME_RTFParAttrHook(RTF_Info *info)
 {
   PARAFORMAT2 fmt;
   fmt.cbSize = sizeof(fmt);
@@ -459,7 +463,7 @@
   }
 }
 
-void ME_RTFReadHook(RTF_Info *info) {
+static void ME_RTFReadHook(RTF_Info *info) {
   switch(info->rtfClass)
   {
     case rtfGroup:
@@ -651,11 +655,75 @@
 }
 
 
+static int
+ME_FindText(ME_TextEditor *editor, DWORD flags, CHARRANGE *chrg, WCHAR *text, CHARRANGE *chrgText)
+{
+  int nStart = chrg->cpMin;
+  int nLen = lstrlenW(text);
+  ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
+  ME_DisplayItem *para;
+  
+  if (!item)
+    return -1;
+
+  if (!nLen)
+  {
+    if (chrgText)
+      chrgText->cpMin = chrgText->cpMax = chrg->cpMin;
+    return chrg->cpMin;
+  }
+ 
+  if (!(flags & FR_DOWN))
+    FIXME("Backward search not implemented\n");
+  if (!(flags & FR_MATCHCASE))
+    FIXME("Case-insensitive search not implemented\n");
+  if (flags & ~(FR_DOWN | FR_MATCHCASE))
+    FIXME("Flags 0x%08lx not implemented\n", flags & ~(FR_DOWN | FR_MATCHCASE));
+  
+  para = ME_GetParagraph(item);
+  while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart + nLen < chrg->cpMax)
+  {
+    ME_DisplayItem *pCurItem = item;
+    int nCurStart = nStart;
+    int nMatched = 0;
+    
+    while (pCurItem->member.run.strText->szData[nCurStart + nMatched] == text[nMatched])
+    {
+      nMatched++;
+      if (nMatched == nLen)
+      {
+        nStart += para->member.para.nCharOfs + item->member.run.nCharOfs;
+        if (chrgText)
+        {
+          chrgText->cpMin = nStart;
+          chrgText->cpMax = nStart + nLen;
+        }
+        return nStart;
+      }
+      if (nCurStart + nMatched == ME_StrLen(pCurItem->member.run.strText))
+      {
+        pCurItem = ME_FindItemFwd(pCurItem, diRun);
+        nCurStart = -nMatched;
+      }
+    }
+    nStart++;
+    if (nStart == ME_StrLen(item->member.run.strText))
+    {
+      item = ME_FindItemFwd(item, diRun);
+      para = ME_GetParagraph(item);
+      nStart = 0;
+    }
+  }
+  return -1;
+}
+
+
 ME_TextEditor *ME_MakeEditor(HWND hWnd) {
   ME_TextEditor *ed = ALLOC_OBJ(ME_TextEditor);
   HDC hDC;
   int i;
   ed->hWnd = hWnd;
+  ed->bEmulateVersion10 = FALSE;
   ed->pBuffer = ME_MakeText();
   hDC = GetDC(hWnd);
   ME_MakeFirstParagraph(hDC, ed->pBuffer);
@@ -679,6 +747,7 @@
   ed->nParagraphs = 1;
   ed->nLastSelStart = ed->nLastSelEnd = 0;
   ed->nScrollPosY = 0;
+  ed->nZoomNumerator = ed->nZoomDenominator = 0;
   for (i=0; i<HFONT_CACHE_SIZE; i++)
   {
     ed->pFontCache[i].nRefs = 0;
@@ -753,6 +822,7 @@
   return 0;
 }
 
+
 void ME_DestroyEditor(ME_TextEditor *editor)
 {
   ME_DisplayItem *pFirst = editor->pBuffer->pFirst;
@@ -808,6 +878,140 @@
     FIXME(#e ": stub\n"); \
     return DefWindowProcW(hWnd, msg, wParam, lParam);
 
+static const char * const edit_messages[] = {
+  "EM_GETSEL",
+  "EM_SETSEL",
+  "EM_GETRECT",
+  "EM_SETRECT",
+  "EM_SETRECTNP",
+  "EM_SCROLL",
+  "EM_LINESCROLL",
+  "EM_SCROLLCARET",
+  "EM_GETMODIFY",
+  "EM_SETMODIFY",
+  "EM_GETLINECOUNT",
+  "EM_LINEINDEX",
+  "EM_SETHANDLE",
+  "EM_GETHANDLE",
+  "EM_GETTHUMB",
+  "EM_UNKNOWN_BF",
+  "EM_UNKNOWN_C0",
+  "EM_LINELENGTH",
+  "EM_REPLACESEL",
+  "EM_UNKNOWN_C3",
+  "EM_GETLINE",
+  "EM_LIMITTEXT",
+  "EM_CANUNDO",
+  "EM_UNDO",
+  "EM_FMTLINES",
+  "EM_LINEFROMCHAR",
+  "EM_UNKNOWN_CA",
+  "EM_SETTABSTOPS",
+  "EM_SETPASSWORDCHAR",
+  "EM_EMPTYUNDOBUFFER",
+  "EM_GETFIRSTVISIBLELINE",
+  "EM_SETREADONLY",
+  "EM_SETWORDBREAKPROC",
+  "EM_GETWORDBREAKPROC",
+  "EM_GETPASSWORDCHAR",
+  "EM_SETMARGINS",
+  "EM_GETMARGINS",
+  "EM_GETLIMITTEXT",
+  "EM_POSFROMCHAR",
+  "EM_CHARFROMPOS"
+};
+
+static const char * const richedit_messages[] = {
+  "EM_CANPASTE",
+  "EM_DISPLAYBAND",
+  "EM_EXGETSEL",
+  "EM_EXLIMITTEXT",
+  "EM_EXLINEFROMCHAR",
+  "EM_EXSETSEL",
+  "EM_FINDTEXT",
+  "EM_FORMATRANGE",
+  "EM_GETCHARFORMAT",
+  "EM_GETEVENTMASK",
+  "EM_GETOLEINTERFACE",
+  "EM_GETPARAFORMAT",
+  "EM_GETSELTEXT",
+  "EM_HIDESELECTION",
+  "EM_PASTESPECIAL",
+  "EM_REQUESTRESIZE",
+  "EM_SELECTIONTYPE",
+  "EM_SETBKGNDCOLOR",
+  "EM_SETCHARFORMAT",
+  "EM_SETEVENTMASK",
+  "EM_SETOLECALLBACK",
+  "EM_SETPARAFORMAT",
+  "EM_SETTARGETDEVICE",
+  "EM_STREAMIN",
+  "EM_STREAMOUT",
+  "EM_GETTEXTRANGE",
+  "EM_FINDWORDBREAK",
+  "EM_SETOPTIONS",
+  "EM_GETOPTIONS",
+  "EM_FINDTEXTEX",
+  "EM_GETWORDBREAKPROCEX",
+  "EM_SETWORDBREAKPROCEX",
+  "EM_SETUNDOLIMIT",
+  "EM_UNKNOWN_USER_83",
+  "EM_REDO",
+  "EM_CANREDO",
+  "EM_GETUNDONAME",
+  "EM_GETREDONAME",
+  "EM_STOPGROUPTYPING",
+  "EM_SETTEXTMODE",
+  "EM_GETTEXTMODE",
+  "EM_AUTOURLDETECT",
+  "EM_GETAUTOURLDETECT",
+  "EM_SETPALETTE",
+  "EM_GETTEXTEX",
+  "EM_GETTEXTLENGTHEX",
+  "EM_SHOWSCROLLBAR",
+  "EM_SETTEXTEX",
+  "EM_UNKNOWN_USER_98",
+  "EM_UNKNOWN_USER_99",
+  "EM_SETPUNCTUATION",
+  "EM_GETPUNCTUATION",
+  "EM_SETWORDWRAPMODE",
+  "EM_GETWORDWRAPMODE",
+  "EM_SETIMECOLOR",
+  "EM_GETIMECOLOR",
+  "EM_SETIMEOPTIONS",
+  "EM_GETIMEOPTIONS",
+  "EM_CONVPOSITION",
+  "EM_UNKNOWN_USER_109",
+  "EM_UNKNOWN_USER_110",
+  "EM_UNKNOWN_USER_111",
+  "EM_UNKNOWN_USER_112",
+  "EM_UNKNOWN_USER_113",
+  "EM_UNKNOWN_USER_114",
+  "EM_UNKNOWN_USER_115",
+  "EM_UNKNOWN_USER_116",
+  "EM_UNKNOWN_USER_117",
+  "EM_UNKNOWN_USER_118",
+  "EM_UNKNOWN_USER_119",
+  "EM_SETLANGOPTIONS",
+  "EM_GETLANGOPTIONS",
+  "EM_GETIMECOMPMODE",
+  "EM_FINDTEXTW",
+  "EM_FINDTEXTEXW",
+  "EM_RECONVERSION",
+  "EM_SETIMEMODEBIAS",
+  "EM_GETIMEMODEBIAS"
+};
+
+static const char *
+get_msg_name(UINT msg)
+{
+  if (msg >= EM_GETSEL && msg <= EM_SETLIMITTEXT)
+    return edit_messages[msg - EM_GETSEL];
+  if (msg >= EM_CANPASTE && msg <= EM_GETIMEMODEBIAS)
+    return richedit_messages[msg - EM_CANPASTE];
+  return "";
+}
+
 /******************************************************************
  *        RichEditANSIWndProc (RICHED20.10)
  */
@@ -816,16 +1020,15 @@
   PAINTSTRUCT ps;
   SCROLLINFO si;
   ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongW(hWnd, 0);
-  TRACE("msg %d %08x %08lx\n", msg, wParam, lParam);
+  
+  TRACE("msg %d (%s) %08x %08lx\n", msg, get_msg_name(msg), wParam, lParam);
+  
   switch(msg) {
   
   UNSUPPORTED_MSG(EM_AUTOURLDETECT)
   UNSUPPORTED_MSG(EM_CHARFROMPOS)
   UNSUPPORTED_MSG(EM_DISPLAYBAND)
   UNSUPPORTED_MSG(EM_EXLIMITTEXT)
-  UNSUPPORTED_MSG(EM_EXLINEFROMCHAR)
-  UNSUPPORTED_MSG(EM_FINDTEXT)
-  UNSUPPORTED_MSG(EM_FINDTEXTEX)
   UNSUPPORTED_MSG(EM_FINDWORDBREAK)
   UNSUPPORTED_MSG(EM_FMTLINES)
   UNSUPPORTED_MSG(EM_FORMATRANGE)
@@ -838,25 +1041,19 @@
   UNSUPPORTED_MSG(EM_GETLANGOPTIONS)
   UNSUPPORTED_MSG(EM_GETLIMITTEXT)
   UNSUPPORTED_MSG(EM_GETLINE)
-  UNSUPPORTED_MSG(EM_GETLINECOUNT)
   /* UNSUPPORTED_MSG(EM_GETOLEINTERFACE) separate stub */
   UNSUPPORTED_MSG(EM_GETOPTIONS)
   UNSUPPORTED_MSG(EM_GETPASSWORDCHAR)
   UNSUPPORTED_MSG(EM_GETRECT)
   UNSUPPORTED_MSG(EM_GETREDONAME)
   UNSUPPORTED_MSG(EM_GETSCROLLPOS)
-  UNSUPPORTED_MSG(EM_GETTEXTEX)
   UNSUPPORTED_MSG(EM_GETTEXTMODE)
   UNSUPPORTED_MSG(EM_GETTYPOGRAPHYOPTIONS)
   UNSUPPORTED_MSG(EM_GETUNDONAME)
   UNSUPPORTED_MSG(EM_GETWORDBREAKPROC)
   UNSUPPORTED_MSG(EM_GETWORDBREAKPROCEX)
-  UNSUPPORTED_MSG(EM_GETZOOM)
   UNSUPPORTED_MSG(EM_HIDESELECTION)
   UNSUPPORTED_MSG(EM_LIMITTEXT) /* also known as EM_SETLIMITTEXT */
-  UNSUPPORTED_MSG(EM_LINEFROMCHAR)
-  UNSUPPORTED_MSG(EM_LINEINDEX)
-  UNSUPPORTED_MSG(EM_LINELENGTH)
   UNSUPPORTED_MSG(EM_PASTESPECIAL)
 /*  UNSUPPORTED_MSG(EM_POSFROMCHARS) missing in Wine headers */
   UNSUPPORTED_MSG(EM_REQUESTRESIZE)
@@ -876,14 +1073,12 @@
   UNSUPPORTED_MSG(EM_SETSCROLLPOS)
   UNSUPPORTED_MSG(EM_SETTABSTOPS)
   UNSUPPORTED_MSG(EM_SETTARGETDEVICE)
-  UNSUPPORTED_MSG(EM_SETTEXTEX)
   UNSUPPORTED_MSG(EM_SETTEXTMODE)
   UNSUPPORTED_MSG(EM_SETTYPOGRAPHYOPTIONS)
   UNSUPPORTED_MSG(EM_SETUNDOLIMIT)
   UNSUPPORTED_MSG(EM_SETWORDBREAKPROC)
   UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX)
   UNSUPPORTED_MSG(EM_SHOWSCROLLBAR)
-  UNSUPPORTED_MSG(EM_SETZOOM)
   UNSUPPORTED_MSG(WM_SETFONT)
   UNSUPPORTED_MSG(WM_STYLECHANGING)
   UNSUPPORTED_MSG(WM_STYLECHANGED)
@@ -905,6 +1100,7 @@
   case WM_NCCREATE:
   {
     CREATESTRUCTW *pcs = (CREATESTRUCTW *)lParam;
+    TRACE("WM_NCCREATE: style 0x%08lx\n", pcs->style);
     editor = ME_MakeEditor(hWnd);
     SetWindowLongW(hWnd, 0, (long)editor);
     pcs = 0; /* ignore */
@@ -928,6 +1124,7 @@
   {
     CHARRANGE *pRange = (CHARRANGE *)lParam;
     ME_GetSelection(editor, (int *)&pRange->cpMin, (int *)&pRange->cpMax);
+    TRACE("EM_EXGETSEL = (%ld,%ld)\n", pRange->cpMin, pRange->cpMax);
     return 0;
   }
   case EM_CANUNDO:
@@ -950,12 +1147,44 @@
   case EM_EXSETSEL:
   {
     CHARRANGE *pRange = (CHARRANGE *)lParam;
+    TRACE("EM_EXSETSEL (%ld,%ld)\n", pRange->cpMin, pRange->cpMax);
     ME_SetSelection(editor, pRange->cpMin, pRange->cpMax);
     /* FIXME optimize */
     ME_Repaint(editor);
     ME_SendSelChange(editor);
     return 0;
   }
+  case EM_SETTEXTEX:
+  {
+    LPWSTR wszText = (LPWSTR)lParam;
+    SETTEXTEX *pStruct = (SETTEXTEX *)wParam;
+    size_t len = lstrlenW(wszText);
+    int from, to;
+    ME_Style *style;
+    TRACE("EM_SETTEXEX - %s, flags %d, cp %d\n", debugstr_w(wszText), (int)pStruct->flags, pStruct->codepage);
+    if (pStruct->codepage != 1200) {
+      FIXME("EM_SETTEXTEX only supports unicode right now!\n"); 
+      return 0;
+    }
+    /* FIXME: this should support RTF strings too, according to MSDN */
+    if (pStruct->flags & ST_SELECTION) {
+      ME_GetSelection(editor, &from, &to);
+      style = ME_GetSelectionInsertStyle(editor);
+      ME_InternalDeleteText(editor, from, to - from);
+      ME_InsertTextFromCursor(editor, 0, wszText, len, style);
+      ME_ReleaseStyle(style);
+    }
+    else {
+      ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
+      ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
+      len = 1;
+    }
+    ME_CommitUndo(editor);
+    if (!(pStruct->flags & ST_KEEPUNDO))
+      ME_EmptyUndoStack(editor);
+    ME_UpdateRepaint(editor);
+    return len;
+  }
   case EM_SETBKGNDCOLOR:
   {
     LRESULT lColor = ME_GetBackColor(editor);
@@ -1002,7 +1231,7 @@
     if (!wParam)
       ME_SetDefaultCharFormat(editor, p);
     else if (wParam == (SCF_WORD | SCF_SELECTION))
-      FIXME("word selection not supported\n");
+      FIXME("EM_SETCHARFORMAT: word selection not supported\n");
     else if (wParam == SCF_ALL)
       ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), p);
     else {
@@ -1018,14 +1247,19 @@
   }
   case EM_GETCHARFORMAT:
   {
-    CHARFORMAT2W tmp;
+    CHARFORMAT2W tmp, *dst = (CHARFORMAT2W *)lParam;
+    if (dst->cbSize != sizeof(CHARFORMATA) &&
+        dst->cbSize != sizeof(CHARFORMATW) &&
+        dst->cbSize != sizeof(CHARFORMAT2A) &&
+        dst->cbSize != sizeof(CHARFORMAT2W))
+      return 0;
     tmp.cbSize = sizeof(tmp);
     if (!wParam)
       ME_GetDefaultCharFormat(editor, &tmp);
     else
       ME_GetSelectionCharFormat(editor, &tmp);
-    ME_CopyToCFAny((CHARFORMAT2W *)lParam, &tmp);
-    return 0;
+    ME_CopyToCFAny(dst, &tmp);
+    return tmp.dwMask;
   }
   case EM_SETPARAFORMAT:
     ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
@@ -1087,12 +1321,21 @@
   }
   case WM_SETTEXT:
   {
-    LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
-    TRACE("WM_SETTEXT - %s\n", (char *)(wszText)); /* debugstr_w() */
     ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
-    /* uses default style! */
-    ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
-    ME_EndToUnicode(hWnd, wszText);
+    if (lParam)
+    {
+      LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
+      TRACE("WM_SETTEXT lParam==%lx\n",lParam);
+      TRACE("WM_SETTEXT - %s\n", debugstr_w(wszText)); /* debugstr_w() */
+      if (lstrlenW(wszText) > 0)
+      {
+        /* uses default style! */
+        ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
+      }
+      ME_EndToUnicode(hWnd, wszText);
+    }
+    else
+      TRACE("WM_SETTEXT - NULL\n");
     ME_CommitUndo(editor);
     ME_EmptyUndoStack(editor);
     ME_UpdateRepaint(editor);
@@ -1184,6 +1427,29 @@
     tr.lpstrText = (WCHAR *)lParam;
     return RichEditANSIWndProc(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
   }
+  case EM_GETTEXTEX:
+  {
+    GETTEXTEX *ex = (GETTEXTEX*)wParam;
+
+    if (ex->flags != 0)
+        FIXME("Unhandled EM_GETTEXTEX flags 0x%lx\n",ex->flags);
+
+    if (IsWindowUnicode(hWnd))
+      return ME_GetTextW(editor, (LPWSTR)lParam, 0, ex->cb, FALSE);
+    else
+    {
+        LPWSTR buffer = HeapAlloc(GetProcessHeap(),0,ex->cb*sizeof(WCHAR));
+        DWORD buflen = ex->cb;
+        LRESULT rc;
+        DWORD flags = 0;
+
+        buflen = ME_GetTextW(editor, buffer, 0, buflen, FALSE);
+        rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefaultChar);
+
+        HeapFree(GetProcessHeap(),0,buffer);
+        return rc;
+    }
+  }
   case EM_GETSELTEXT:
   {
     int from, to;
@@ -1213,6 +1479,114 @@
     }
     return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, FALSE);
   }
+  case EM_GETLINECOUNT:
+  {
+    ME_DisplayItem *item = editor->pBuffer->pFirst->next;
+    int nRows = 0;
+
+    while (item != editor->pBuffer->pLast)
+    {
+      assert(item->type == diParagraph);
+      nRows += item->member.para.nRows;
+      item = item->member.para.next_para;
+    }
+    TRACE("EM_GETLINECOUNT: nRows==%d\n", nRows);
+    return max(1, nRows);
+  }
+  case EM_LINEFROMCHAR:
+  {
+    if (wParam == -1)
+      return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(editor, 1));
+    else
+      return ME_RowNumberFromCharOfs(editor, wParam);
+  }
+  case EM_EXLINEFROMCHAR:
+  {
+    return ME_RowNumberFromCharOfs(editor, lParam);
+  }
+  case EM_LINEINDEX:
+  {
+    ME_DisplayItem *item, *para;
+    int nCharOfs;
+    
+    if (wParam == -1)
+      item = ME_FindItemBack(editor->pCursors[0].pRun, diStartRow);
+    else
+      item = ME_FindRowWithNumber(editor, wParam);
+    if (!item)
+      return -1;
+    para = ME_GetParagraph(item);
+    item = ME_FindItemFwd(item, diRun);
+    nCharOfs = para->member.para.nCharOfs + item->member.run.nCharOfs;
+    TRACE("EM_LINEINDEX: nCharOfs==%d\n", nCharOfs);
+    return nCharOfs;
+  }
+  case EM_LINELENGTH:
+  {
+    ME_DisplayItem *item, *item_end;
+    int nChars = 0;
+    
+    if (wParam > ME_GetTextLength(editor))
+      return 0;
+    if (wParam == -1)
+    {
+      FIXME("EM_LINELENGTH: returning number of unselected characters on lines with selection unsupported.\n");
+      return 0;
+    }
+    item = ME_FindItemAtOffset(editor, diRun, wParam, NULL);
+    item = ME_RowStart(item);
+    item_end = ME_RowEnd(item);
+    if (!item_end)
+    {
+      /* Empty buffer, no runs */
+      nChars = 0;
+    }
+    else
+    {
+      nChars = ME_CharOfsFromRunOfs(editor, item_end, ME_StrLen(item_end->member.run.strText));
+      nChars -= ME_CharOfsFromRunOfs(editor, item, 0);
+    }
+    TRACE("EM_LINELENGTH(%d)==%d\n",wParam, nChars);
+    return nChars;
+  }
+  case EM_FINDTEXT:
+  {
+    FINDTEXTA *ft = (FINDTEXTA *)lParam;
+    int nChars = MultiByteToWideChar(CP_ACP, 0, ft->lpstrText, -1, NULL, 0);
+    WCHAR *tmp;
+    
+    if ((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL)
+      MultiByteToWideChar(CP_ACP, 0, ft->lpstrText, -1, tmp, nChars);
+    return ME_FindText(editor, wParam, &ft->chrg, tmp, NULL);
+  }
+  case EM_FINDTEXTEX:
+  {
+    FINDTEXTEXA *ex = (FINDTEXTEXA *)lParam;
+    int nChars = MultiByteToWideChar(CP_ACP, 0, ex->lpstrText, -1, NULL, 0);
+    WCHAR *tmp;
+    
+    if ((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL)
+      MultiByteToWideChar(CP_ACP, 0, ex->lpstrText, -1, tmp, nChars);
+    return ME_FindText(editor, wParam, &ex->chrg, tmp, &ex->chrgText);
+  }
+  case EM_FINDTEXTW:
+  {
+    FINDTEXTW *ft = (FINDTEXTW *)lParam;
+    return ME_FindText(editor, wParam, &ft->chrg, ft->lpstrText, NULL);
+  }
+  case EM_FINDTEXTEXW:
+  {
+    FINDTEXTEXW *ex = (FINDTEXTEXW *)lParam;
+    return ME_FindText(editor, wParam, &ex->chrg, ex->lpstrText, &ex->chrgText);
+  }
+  case EM_GETZOOM:
+    if (!wParam || !lParam)
+      return FALSE;
+    *(int *)wParam = editor->nZoomNumerator;
+    *(int *)lParam = editor->nZoomDenominator;
+    return TRUE;
+  case EM_SETZOOM:
+    return ME_SetZoom(editor, wParam, lParam);
   case WM_CREATE:
     ME_CommitUndo(editor);
     ME_WrapMarkedParagraphs(editor);
@@ -1369,10 +1743,7 @@
   }
   case WM_SIZE:
   {
-    ME_MarkAllForWrapping(editor);
-    ME_WrapMarkedParagraphs(editor);
-    ME_UpdateScrollBar(editor);
-    ME_Repaint(editor);
+    ME_RewrapRepaint(editor);
     return DefWindowProcW(hWnd, msg, wParam, lParam);
   }
   case EM_GETOLEINTERFACE:
@@ -1388,13 +1759,24 @@
   return 0L;
 }
 
+
 /******************************************************************
  *        RichEdit10ANSIWndProc (RICHED20.9)
  */
 LRESULT WINAPI RichEdit10ANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
+  LRESULT result;
+  
   /* FIXME: this is NOT the same as 2.0 version */
-  return RichEditANSIWndProc(hWnd, msg, wParam, lParam);
+  result = RichEditANSIWndProc(hWnd, msg, wParam, lParam);
+  if (msg == WM_NCCREATE)
+  {
+    ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongW(hWnd, 0);
+    
+    editor->bEmulateVersion10 = TRUE;
+    editor->pBuffer->pLast->member.para.nCharOfs = 2;
+  }
+  return result;
 }
 
 void ME_SendOldNotify(ME_TextEditor *editor, int nCode)

Modified: trunk/reactos/lib/riched20/editor.h
--- trunk/reactos/lib/riched20/editor.h	2005-08-12 17:34:06 UTC (rev 17334)
+++ trunk/reactos/lib/riched20/editor.h	2005-08-12 17:41:40 UTC (rev 17335)
@@ -100,6 +100,8 @@
 ME_DisplayItem *ME_RowStart(ME_DisplayItem *item);
 ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item);
 void ME_RenumberParagraphs(ME_DisplayItem *item); /* TODO */
+ME_DisplayItem *ME_FindRowWithNumber(ME_TextEditor *editor, int nRow);
+int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs);
 
 /* run.c */
 ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags);
@@ -189,6 +191,7 @@
 /* paint.c */
 void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, RECT *rcUpdate);
 void ME_Repaint(ME_TextEditor *editor);
+void ME_RewrapRepaint(ME_TextEditor *editor);
 void ME_UpdateRepaint(ME_TextEditor *editor);
 void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph);
 void ME_UpdateScrollBar(ME_TextEditor *editor);
@@ -196,6 +199,7 @@
 void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun);
 COLORREF ME_GetBackColor(ME_TextEditor *editor);
 void ME_Scroll(ME_TextEditor *editor, int cx, int cy);
+BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator);
 
 /* richole.c */
 extern LRESULT CreateIRichEditOle(LPVOID *);

Modified: trunk/reactos/lib/riched20/editstr.h
--- trunk/reactos/lib/riched20/editstr.h	2005-08-12 17:34:06 UTC (rev 17334)
+++ trunk/reactos/lib/riched20/editstr.h	2005-08-12 17:41:40 UTC (rev 17335)
@@ -147,6 +147,7 @@
   int nFlags;
   int nYPos, nHeight;
   int nLastPaintYPos, nLastPaintHeight;
+  int nRows;
   struct tagME_DisplayItem *prev_para, *next_para, *document;
 } ME_Paragraph;
 
@@ -246,6 +247,7 @@
 typedef struct tagME_TextEditor
 {
   HWND hWnd;
+  BOOL bEmulateVersion10;
   BOOL bCaretShown;
   ME_TextBuffer *pBuffer;
   ME_Cursor *pCursors;
@@ -267,6 +269,7 @@
   ME_OutStream *pStream;
   BOOL bScrollX, bScrollY;
   int nScrollPosY;
+  int nZoomNumerator, nZoomDenominator;
 } ME_TextEditor;
 
 typedef struct tagME_Context

Modified: trunk/reactos/lib/riched20/paint.c
--- trunk/reactos/lib/riched20/paint.c	2005-08-12 17:34:06 UTC (rev 17334)
+++ trunk/reactos/lib/riched20/paint.c	2005-08-12 17:41:40 UTC (rev 17335)
@@ -94,7 +94,7 @@
   ME_DestroyContext(&c);
 }
 
-void ME_MarkParagraphRange(ME_TextEditor *editor, ME_DisplayItem *p1,
+static void ME_MarkParagraphRange(ME_TextEditor *editor, ME_DisplayItem *p1,
                            ME_DisplayItem *p2, int nFlags)
 {
   ME_DisplayItem *p3;  
@@ -113,7 +113,7 @@
   } while (p1 != p2);
 }
 
-void ME_MarkOffsetRange(ME_TextEditor *editor, int from, int to, int nFlags)
+static void ME_MarkOffsetRange(ME_TextEditor *editor, int from, int to, int nFlags)
 {
   ME_Cursor c1, c2;
   ME_CursorFromCharOfs(editor, from, &c1);
@@ -122,7 +122,7 @@
   ME_MarkParagraphRange(editor, ME_GetParagraph(c1.pRun), ME_GetParagraph(c2.pRun), nFlags);
 }
 
-void ME_MarkSelectionForRepaint(ME_TextEditor *editor)
+static void ME_MarkSelectionForRepaint(ME_TextEditor *editor)
 {
   int from, to, from2, to2, end;
   
@@ -173,7 +173,18 @@
   ME_SendSelChange(editor);
 }
 
-void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChars, 
+
+void
+ME_RewrapRepaint(ME_TextEditor *editor)
+{
+  ME_MarkAllForWrapping(editor);
+  ME_WrapMarkedParagraphs(editor);
+  ME_UpdateScrollBar(editor);
+  ME_Repaint(editor);
+}
+
+
+static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChars, 
   ME_Style *s, int *width, int nSelFrom, int nSelTo, int ymin, int cy) {
   HDC hDC = c->hDC;
   HGDIOBJ hOldFont;
@@ -193,7 +204,17 @@
     if (s->fmt.dwEffects & CFE_SUBSCRIPT) yTwipsOffset = -s->fmt.yHeight/12;
   }
   if (yTwipsOffset)
-    yOffset = yTwipsOffset*GetDeviceCaps(hDC, LOGPIXELSY)/1440;
+  {
+    int numerator = 1;
+    int denominator = 1;
+    
+    if (c->editor->nZoomNumerator)
+    {
+      numerator = c->editor->nZoomNumerator;
+      denominator = c->editor->nZoomDenominator;
+    }
+    yOffset = yTwipsOffset * GetDeviceCaps(hDC, LOGPIXELSY) * numerator / denominator / 1440;
+  }
   ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, NULL);
[truncated at 1000 lines; 445 more skipped]