[RICHED20]
authorAmine Khaldi <amine.khaldi@reactos.org>
Mon, 6 Oct 2014 18:41:33 +0000 (18:41 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Mon, 6 Oct 2014 18:41:33 +0000 (18:41 +0000)
* Sync with Wine 1.7.27.
CORE-8540

svn path=/trunk/; revision=64571

reactos/dll/win32/riched20/caret.c
reactos/dll/win32/riched20/clipboard.c
reactos/dll/win32/riched20/editor.c
reactos/dll/win32/riched20/editor.h
reactos/dll/win32/riched20/editstr.h
reactos/dll/win32/riched20/reader.c
reactos/dll/win32/riched20/richole.c
reactos/dll/win32/riched20/string.c
reactos/dll/win32/riched20/txtsrv.c
reactos/media/doc/README.WINE

index 90b30a2..043a32a 100644 (file)
@@ -139,6 +139,7 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
   {
     ME_SetCursorToStart(editor, &editor->pCursors[1]);
     ME_SetCursorToEnd(editor, &editor->pCursors[0]);
   {
     ME_SetCursorToStart(editor, &editor->pCursors[1]);
     ME_SetCursorToEnd(editor, &editor->pCursors[0]);
+    editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len;
     ME_InvalidateSelection(editor);
     return len + 1;
   }
     ME_InvalidateSelection(editor);
     return len + 1;
   }
@@ -159,6 +160,11 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
       ME_GetSelectionOfs(editor, &start, &end);
       if (start != end)
       {
       ME_GetSelectionOfs(editor, &start, &end);
       if (start != end)
       {
+          if (end > len)
+          {
+              editor->pCursors[0].nOffset = 0;
+              end --;
+          }
           editor->pCursors[1] = editor->pCursors[0];
           ME_Repaint(editor);
       }
           editor->pCursors[1] = editor->pCursors[0];
           ME_Repaint(editor);
       }
@@ -200,7 +206,12 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
   if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA)
     editor->pCursors[1].nOffset = 0;
   if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA)
   if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA)
     editor->pCursors[1].nOffset = 0;
   if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA)
-    editor->pCursors[0].nOffset = 0;
+  {
+    if (to > len)
+      editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len;
+    else
+      editor->pCursors[0].nOffset = 0;
+  }
   return to;
 }
 
   return to;
 }
 
index f7514a2..250a233 100644 (file)
@@ -352,7 +352,7 @@ static HGLOBAL get_unicode_text(ME_TextEditor *editor, const ME_Cursor *start, i
 
     ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1));
     data = GlobalLock(ret);
 
     ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1));
     data = GlobalLock(ret);
-    ME_GetTextW(editor, data, nChars + pars, start, nChars, TRUE);
+    ME_GetTextW(editor, data, nChars + pars, start, nChars, TRUE, FALSE);
     GlobalUnlock(ret);
     return ret;
 }
     GlobalUnlock(ret);
     return ret;
 }
index 7ccdd49..834f710 100644 (file)
@@ -1618,7 +1618,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
          CR/LF counters, since RTF streaming presents only \para tokens, which
          are converted according to the standard rules: \r for 2.0, \r\n for 1.0
        */
          CR/LF counters, since RTF streaming presents only \para tokens, which
          are converted according to the standard rules: \r for 2.0, \r\n for 1.0
        */
-      if (stripLastCR) {
+      if (stripLastCR && !(format & SFF_SELECTION)) {
         int newto;
         ME_GetSelection(editor, &selStart, &selEnd);
         newto = ME_GetCursorOfs(selEnd);
         int newto;
         ME_GetSelection(editor, &selStart, &selEnd);
         newto = ME_GetCursorOfs(selEnd);
@@ -1628,7 +1628,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
           ME_Cursor linebreakCursor = *selEnd;
 
           ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize);
           ME_Cursor linebreakCursor = *selEnd;
 
           ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize);
-          ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE);
+          ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE, FALSE);
           if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) {
             ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE);
           }
           if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) {
             ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE);
           }
@@ -1966,7 +1966,7 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText)
     if (ex->codepage == CP_UNICODE)
     {
       return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1,
     if (ex->codepage == CP_UNICODE)
     {
       return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1,
-                         &start, nChars, ex->flags & GT_USECRLF);
+                         &start, nChars, ex->flags & GT_USECRLF, FALSE);
     }
     else
     {
     }
     else
     {
@@ -1983,7 +1983,7 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText)
       buflen = min(crlfmul * nChars, ex->cb - 1);
       buffer = heap_alloc((buflen + 1) * sizeof(WCHAR));
 
       buflen = min(crlfmul * nChars, ex->cb - 1);
       buffer = heap_alloc((buflen + 1) * sizeof(WCHAR));
 
-      nChars = ME_GetTextW(editor, buffer, buflen, &start, nChars, ex->flags & GT_USECRLF);
+      nChars = ME_GetTextW(editor, buffer, buflen, &start, nChars, ex->flags & GT_USECRLF, FALSE);
       rc = WideCharToMultiByte(ex->codepage, 0, buffer, nChars + 1,
                                (LPSTR)pText, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar);
       if (rc) rc--; /* do not count 0 terminator */
       rc = WideCharToMultiByte(ex->codepage, 0, buffer, nChars + 1,
                                (LPSTR)pText, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar);
       if (rc) rc--; /* do not count 0 terminator */
@@ -1998,12 +1998,12 @@ static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText,
 {
     if (!strText) return 0;
     if (unicode) {
 {
     if (!strText) return 0;
     if (unicode) {
-      return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE);
+      return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE, FALSE);
     } else {
       int nChars;
       WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1);
       if (!p) return 0;
     } else {
       int nChars;
       WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1);
       if (!p) return 0;
-      nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE);
+      nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE, FALSE);
       WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText,
                           nLen+1, NULL, NULL);
       FREE_OBJ(p);
       WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText,
                           nLen+1, NULL, NULL);
       FREE_OBJ(p);
@@ -2742,6 +2742,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
   ed->hwndParent = NULL;
   ed->sizeWindow.cx = ed->sizeWindow.cy = 0;
   ed->texthost = texthost;
   ed->hwndParent = NULL;
   ed->sizeWindow.cx = ed->sizeWindow.cy = 0;
   ed->texthost = texthost;
+  ed->reOle = NULL;
   ed->bEmulateVersion10 = bEmulateVersion10;
   ed->styleFlags = 0;
   ITextHost_TxGetPropertyBits(texthost,
   ed->bEmulateVersion10 = bEmulateVersion10;
   ed->styleFlags = 0;
   ITextHost_TxGetPropertyBits(texthost,
@@ -2884,6 +2885,11 @@ static void ME_DestroyEditor(ME_TextEditor *editor)
   if(editor->lpOleCallback)
     IRichEditOleCallback_Release(editor->lpOleCallback);
   ITextHost_Release(editor->texthost);
   if(editor->lpOleCallback)
     IRichEditOleCallback_Release(editor->lpOleCallback);
   ITextHost_Release(editor->texthost);
+  if (editor->reOle)
+  {
+    IRichEditOle_Release(editor->reOle);
+    editor->reOle = NULL;
+  }
   OleUninitialize();
 
   FREE_OBJ(editor->pBuffer);
   OleUninitialize();
 
   FREE_OBJ(editor->pBuffer);
@@ -3091,6 +3097,8 @@ static void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM
   if (cursor.pRun->member.run.style->fmt.dwMask & CFM_LINK &&
       cursor.pRun->member.run.style->fmt.dwEffects & CFE_LINK)
   { /* The clicked run has CFE_LINK set */
   if (cursor.pRun->member.run.style->fmt.dwMask & CFM_LINK &&
       cursor.pRun->member.run.style->fmt.dwEffects & CFE_LINK)
   { /* The clicked run has CFE_LINK set */
+    ME_DisplayItem *di;
+
     info.nmhdr.hwndFrom = NULL;
     info.nmhdr.idFrom = 0;
     info.nmhdr.code = EN_LINK;
     info.nmhdr.hwndFrom = NULL;
     info.nmhdr.idFrom = 0;
     info.nmhdr.code = EN_LINK;
@@ -3098,8 +3106,25 @@ static void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM
     info.wParam = wParam;
     info.lParam = lParam;
     cursor.nOffset = 0;
     info.wParam = wParam;
     info.lParam = lParam;
     cursor.nOffset = 0;
+
+    /* find the first contiguous run with CFE_LINK set */
     info.chrg.cpMin = ME_GetCursorOfs(&cursor);
     info.chrg.cpMin = ME_GetCursorOfs(&cursor);
-    info.chrg.cpMax = info.chrg.cpMin + cursor.pRun->member.run.len;
+    for (di = cursor.pRun->prev;
+         di && di->type == diRun && (di->member.run.style->fmt.dwMask & CFM_LINK) && (di->member.run.style->fmt.dwEffects & CFE_LINK);
+         di = di->prev)
+    {
+      info.chrg.cpMin -= di->member.run.len;
+    }
+
+    /* find the last contiguous run with CFE_LINK set */
+    info.chrg.cpMax = ME_GetCursorOfs(&cursor) + cursor.pRun->member.run.len;
+    for (di = cursor.pRun->next;
+         di && di->type == diRun && (di->member.run.style->fmt.dwMask & CFM_LINK) && (di->member.run.style->fmt.dwEffects & CFE_LINK);
+         di = di->next)
+    {
+      info.chrg.cpMax += di->member.run.len;
+    }
+
     ITextHost_TxNotify(editor->texthost, info.nmhdr.code, &info);
   }
 }
     ITextHost_TxNotify(editor->texthost, info.nmhdr.code, &info);
   }
 }
@@ -3452,7 +3477,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
       editor->styleFlags |= ES_READONLY;
     else
       editor->styleFlags &= ~ES_READONLY;
       editor->styleFlags |= ES_READONLY;
     else
       editor->styleFlags &= ~ES_READONLY;
-    return 0;
+    return 1;
   }
   case EM_SETEVENTMASK:
   {
   }
   case EM_SETEVENTMASK:
   {
@@ -4446,8 +4471,12 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
   }
   case EM_GETOLEINTERFACE:
   {
   }
   case EM_GETOLEINTERFACE:
   {
-    LPVOID *ppvObj = (LPVOID*) lParam;
-    return CreateIRichEditOle(editor, ppvObj);
+    if (!editor->reOle)
+      if (!CreateIRichEditOle(editor, (LPVOID *)&editor->reOle))
+        return 0;
+    *(LPVOID *)lParam = editor->reOle;
+    IRichEditOle_AddRef(editor->reOle);
+    return 1;
   }
   case EM_GETPASSWORDCHAR:
   {
   }
   case EM_GETPASSWORDCHAR:
   {
@@ -4716,7 +4745,8 @@ void ME_SendOldNotify(ME_TextEditor *editor, int nCode)
  * The written text is always NULL terminated.
  */
 int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
  * The written text is always NULL terminated.
  */
 int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
-                const ME_Cursor *start, int srcChars, BOOL bCRLF)
+                const ME_Cursor *start, int srcChars, BOOL bCRLF,
+                BOOL bEOP)
 {
   ME_DisplayItem *pRun, *pNextRun;
   const WCHAR *pStart = buffer;
 {
   ME_DisplayItem *pRun, *pNextRun;
   const WCHAR *pStart = buffer;
@@ -4734,7 +4764,6 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
   nLen = pRun->member.run.len - start->nOffset;
   str = get_text( &pRun->member.run, start->nOffset );
 
   nLen = pRun->member.run.len - start->nOffset;
   str = get_text( &pRun->member.run, start->nOffset );
 
-  /* No '\r' is appended to the last paragraph. */
   while (srcChars && buflen && pNextRun)
   {
     int nFlags = pRun->member.run.nFlags;
   while (srcChars && buflen && pNextRun)
   {
     int nFlags = pRun->member.run.nFlags;
@@ -4766,6 +4795,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
     nLen = pRun->member.run.len;
     str = get_text( &pRun->member.run, 0 );
   }
     nLen = pRun->member.run.len;
     str = get_text( &pRun->member.run, 0 );
   }
+  /* append '\r' to the last paragraph. */
+  if (pRun->next->type == diTextEnd && bEOP)
+  {
+    *buffer = '\r';
+    buffer ++;
+  }
   *buffer = 0;
   return buffer - pStart;
 }
   *buffer = 0;
   return buffer - pStart;
 }
@@ -5010,7 +5045,7 @@ static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, const ME_Cursor *start, i
   WCHAR bufferW[MAX_PREFIX_LEN + 1];
   unsigned int i;
 
   WCHAR bufferW[MAX_PREFIX_LEN + 1];
   unsigned int i;
 
-  ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, FALSE);
+  ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, FALSE, FALSE);
   for (i = 0; i < sizeof(prefixes) / sizeof(*prefixes); i++)
   {
     if (nChars < prefixes[i].length) continue;
   for (i = 0; i < sizeof(prefixes) / sizeof(*prefixes); i++)
   {
     if (nChars < prefixes[i].length) continue;
index 4c19c49..f778381 100644 (file)
@@ -286,7 +286,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
                          LPARAM lParam, BOOL unicode, HRESULT* phresult) DECLSPEC_HIDDEN;
 void ME_SendOldNotify(ME_TextEditor *editor, int nCode) DECLSPEC_HIDDEN;
 int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
                          LPARAM lParam, BOOL unicode, HRESULT* phresult) DECLSPEC_HIDDEN;
 void ME_SendOldNotify(ME_TextEditor *editor, int nCode) DECLSPEC_HIDDEN;
 int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
-                const ME_Cursor *start, int srcChars, BOOL bCRLF) DECLSPEC_HIDDEN;
+                const ME_Cursor *start, int srcChars, BOOL bCRLF, BOOL bEOP) DECLSPEC_HIDDEN;
 void ME_RTFCharAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
 void ME_RTFParAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
 void ME_RTFTblAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
 void ME_RTFCharAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
 void ME_RTFParAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
 void ME_RTFTblAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
index 5356b06..d9809db 100644 (file)
@@ -357,6 +357,7 @@ typedef struct tagME_TextEditor
 {
   HWND hWnd, hwndParent;
   ITextHost *texthost;
 {
   HWND hWnd, hwndParent;
   ITextHost *texthost;
+  IRichEditOle *reOle;
   BOOL bEmulateVersion10;
   ME_TextBuffer *pBuffer;
   ME_Cursor *pCursors;
   BOOL bEmulateVersion10;
   ME_TextBuffer *pBuffer;
   ME_Cursor *pCursors;
index 9e115b5..5e35d73 100644 (file)
@@ -699,7 +699,7 @@ static void _RTFGetToken2(RTF_Info *info)
 
 /*
  * Read the next character from the input.  This handles setting the
 
 /*
  * Read the next character from the input.  This handles setting the
- * current line and position-within-line variables.  Those variable are
+ * current line and position-within-line variables.  Those variables are
  * set correctly whether lines end with CR, LF, or CRLF (the last being
  * the tricky case).
  *
  * set correctly whether lines end with CR, LF, or CRLF (the last being
  * the tricky case).
  *
index e33bba5..eb7b1de 100644 (file)
@@ -37,6 +37,7 @@ DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0x
 
 typedef struct ITextSelectionImpl ITextSelectionImpl;
 typedef struct IOleClientSiteImpl IOleClientSiteImpl;
 
 typedef struct ITextSelectionImpl ITextSelectionImpl;
 typedef struct IOleClientSiteImpl IOleClientSiteImpl;
+typedef struct ITextRangeImpl ITextRangeImpl;
 
 typedef struct IRichEditOleImpl {
     IRichEditOle IRichEditOle_iface;
 
 typedef struct IRichEditOleImpl {
     IRichEditOle IRichEditOle_iface;
@@ -46,8 +47,18 @@ typedef struct IRichEditOleImpl {
     ME_TextEditor *editor;
     ITextSelectionImpl *txtSel;
     IOleClientSiteImpl *clientSite;
     ME_TextEditor *editor;
     ITextSelectionImpl *txtSel;
     IOleClientSiteImpl *clientSite;
+    struct list rangelist;
 } IRichEditOleImpl;
 
 } IRichEditOleImpl;
 
+struct ITextRangeImpl {
+    ITextRange ITextRange_iface;
+    LONG ref;
+    LONG start, end;
+    struct list entry;
+
+    IRichEditOleImpl *reOle;
+};
+
 struct ITextSelectionImpl {
     ITextSelection ITextSelection_iface;
     LONG ref;
 struct ITextSelectionImpl {
     ITextSelection ITextSelection_iface;
     LONG ref;
@@ -116,10 +127,13 @@ IRichEditOle_fnRelease(IRichEditOle *me)
 
     if (!ref)
     {
 
     if (!ref)
     {
+        ITextRangeImpl *txtRge;
         TRACE ("Destroying %p\n", This);
         This->txtSel->reOle = NULL;
         ITextSelection_Release(&This->txtSel->ITextSelection_iface);
         IOleClientSite_Release(&This->clientSite->IOleClientSite_iface);
         TRACE ("Destroying %p\n", This);
         This->txtSel->reOle = NULL;
         ITextSelection_Release(&This->txtSel->ITextSelection_iface);
         IOleClientSite_Release(&This->clientSite->IOleClientSite_iface);
+        LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, entry)
+            txtRge->reOle = NULL;
         heap_free(This);
     }
     return ref;
         heap_free(This);
     }
     return ref;
@@ -431,6 +445,722 @@ static const IRichEditOleVtbl revt = {
     IRichEditOle_fnImportDataObject
 };
 
     IRichEditOle_fnImportDataObject
 };
 
+/* ITextRange interface */
+static inline ITextRangeImpl *impl_from_ITextRange(ITextRange *iface)
+{
+    return CONTAINING_RECORD(iface, ITextRangeImpl, ITextRange_iface);
+}
+
+static HRESULT WINAPI ITextRange_fnQueryInterface(ITextRange *me, REFIID riid, void **ppvObj)
+{
+    *ppvObj = NULL;
+    if (IsEqualGUID(riid, &IID_IUnknown)
+        || IsEqualGUID(riid, &IID_IDispatch)
+        || IsEqualGUID(riid, &IID_ITextRange))
+    {
+        *ppvObj = me;
+        ITextRange_AddRef(me);
+        return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ITextRange_fnAddRef(ITextRange *me)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI ITextRange_fnRelease(ITextRange *me)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE ("%p ref=%u\n", This, ref);
+    if (ref == 0)
+    {
+        if (This->reOle)
+        {
+            list_remove(&This->entry);
+            This->reOle = NULL;
+        }
+        heap_free(This);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI ITextRange_fnGetTypeInfoCount(ITextRange *me, UINT *pctinfo)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetTypeInfo(ITextRange *me, UINT iTInfo, LCID lcid,
+                                               ITypeInfo **ppTInfo)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetIDsOfNames(ITextRange *me, REFIID riid, LPOLESTR *rgszNames,
+                                                 UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnInvoke(ITextRange *me, DISPID dispIdMember, REFIID riid,
+                                          LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
+                                          VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
+                                          UINT *puArgErr)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetText(ITextRange *me, BSTR *pbstr)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR bstr)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT range_GetChar(ME_TextEditor *editor, ME_Cursor *cursor, LONG *pch)
+{
+    WCHAR wch[2];
+
+    ME_GetTextW(editor, wch, 1, cursor, 1, FALSE, cursor->pRun->next->type == diTextEnd);
+    *pch = wch[0];
+
+    return S_OK;
+}
+
+static HRESULT WINAPI ITextRange_fnGetChar(ITextRange *me, LONG *pch)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    ME_Cursor cursor;
+
+    if (!This->reOle)
+        return CO_E_RELEASED;
+    TRACE("%p\n", pch);
+    if (!pch)
+        return E_INVALIDARG;
+
+    ME_CursorFromCharOfs(This->reOle->editor, This->start, &cursor);
+    return range_GetChar(This->reOle->editor, &cursor, pch);
+}
+
+static HRESULT WINAPI ITextRange_fnSetChar(ITextRange *me, LONG ch)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange);
+
+static HRESULT WINAPI ITextRange_fnGetDuplicate(ITextRange *me, ITextRange **ppRange)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    TRACE("%p %p\n", This, ppRange);
+    if (!ppRange)
+        return E_INVALIDARG;
+
+    return CreateITextRange(This->reOle, This->start, This->end, ppRange);
+}
+
+static HRESULT WINAPI ITextRange_fnGetFormattedText(ITextRange *me, ITextRange **ppRange)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnSetFormattedText(ITextRange *me, ITextRange *pRange)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetStart(ITextRange *me, LONG *pcpFirst)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    if (!pcpFirst)
+        return E_INVALIDARG;
+    *pcpFirst = This->start;
+    TRACE("%d\n", *pcpFirst);
+    return S_OK;
+}
+
+static HRESULT WINAPI ITextRange_fnSetStart(ITextRange *me, LONG cpFirst)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *pcpLim)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    if (!pcpLim)
+        return E_INVALIDARG;
+    *pcpLim = This->end;
+    TRACE("%d\n", *pcpLim);
+    return S_OK;
+}
+
+static HRESULT WINAPI ITextRange_fnSetEnd(ITextRange *me, LONG cpLim)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetFont(ITextRange *me, ITextFont **pFont)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *pFont)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetPara(ITextRange *me, ITextPara **ppPara)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnSetPara(ITextRange *me, ITextPara *pPara)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetStoryLength(ITextRange *me, LONG *pcch)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetStoryType(ITextRange *me, LONG *pValue)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT range_Collapse(LONG bStart, LONG *start, LONG *end)
+{
+  if (*end == *start)
+      return S_FALSE;
+
+  if (bStart == tomEnd || bStart == tomFalse)
+      *start = *end;
+  else
+      *end = *start;
+  return S_OK;
+}
+
+static HRESULT WINAPI ITextRange_fnCollapse(ITextRange *me, LONG bStart)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    return range_Collapse(bStart, &This->start, &This->end);
+}
+
+static HRESULT WINAPI ITextRange_fnExpand(ITextRange *me, LONG Unit, LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetIndex(ITextRange *me, LONG Unit, LONG *pIndex)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnSetIndex(ITextRange *me, LONG Unit, LONG Index,
+                                            LONG Extend)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnSetRange(ITextRange *me, LONG cpActive, LONG cpOther)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnInRange(ITextRange *me, ITextRange *pRange, LONG *pb)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnInStory(ITextRange *me, ITextRange *pRange, LONG *pb)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnIsEqual(ITextRange *me, ITextRange *pRange, LONG *pb)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnSelect(ITextRange *me)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnStartOf(ITextRange *me, LONG Unit, LONG Extend,
+                                           LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG Unit, LONG Extend,
+                                         LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMove(ITextRange *me, LONG Unit, LONG Count, LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMoveStart(ITextRange *me, LONG Unit, LONG Count,
+                                             LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMoveEnd(ITextRange *me, LONG Unit, LONG Count,
+                                           LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMoveWhile(ITextRange *me, VARIANT *Cset, LONG Count,
+                                             LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMoveStartWhile(ITextRange *me, VARIANT *Cset, LONG Count,
+                                                  LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMoveEndWhile(ITextRange *me, VARIANT *Cset, LONG Count,
+                                                LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMoveUntil(ITextRange *me, VARIANT *Cset, LONG Count,
+                                             LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMoveStartUntil(ITextRange *me, VARIANT *Cset, LONG Count,
+                                                  LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnMoveEndUntil(ITextRange *me, VARIANT *Cset, LONG Count,
+                                                LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnFindText(ITextRange *me, BSTR bstr, LONG cch, LONG Flags,
+                                            LONG *pLength)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnFindTextStart(ITextRange *me, BSTR bstr, LONG cch,
+                                                 LONG Flags, LONG *pLength)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnFindTextEnd(ITextRange *me, BSTR bstr, LONG cch,
+                                               LONG Flags, LONG *pLength)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnDelete(ITextRange *me, LONG Unit, LONG Count,
+                                          LONG *pDelta)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnCut(ITextRange *me, VARIANT *pVar)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnCopy(ITextRange *me, VARIANT *pVar)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnPaste(ITextRange *me, VARIANT *pVar, LONG Format)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnCanPaste(ITextRange *me, VARIANT *pVar, LONG Format,
+                                            LONG *pb)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnCanEdit(ITextRange *me, LONG *pb)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnChangeCase(ITextRange *me, LONG Type)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetPoint(ITextRange *me, LONG Type, LONG *cx, LONG *cy)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnSetPoint(ITextRange *me, LONG x, LONG y, LONG Type,
+                                            LONG Extend)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnScrollIntoView(ITextRange *me, LONG Value)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextRange_fnGetEmbeddedObject(ITextRange *me, IUnknown **ppv)
+{
+    ITextRangeImpl *This = impl_from_ITextRange(me);
+    if (!This->reOle)
+        return CO_E_RELEASED;
+
+    FIXME("not implemented %p\n", This);
+    return E_NOTIMPL;
+}
+
+static const ITextRangeVtbl trvt = {
+    ITextRange_fnQueryInterface,
+    ITextRange_fnAddRef,
+    ITextRange_fnRelease,
+    ITextRange_fnGetTypeInfoCount,
+    ITextRange_fnGetTypeInfo,
+    ITextRange_fnGetIDsOfNames,
+    ITextRange_fnInvoke,
+    ITextRange_fnGetText,
+    ITextRange_fnSetText,
+    ITextRange_fnGetChar,
+    ITextRange_fnSetChar,
+    ITextRange_fnGetDuplicate,
+    ITextRange_fnGetFormattedText,
+    ITextRange_fnSetFormattedText,
+    ITextRange_fnGetStart,
+    ITextRange_fnSetStart,
+    ITextRange_fnGetEnd,
+    ITextRange_fnSetEnd,
+    ITextRange_fnGetFont,
+    ITextRange_fnSetFont,
+    ITextRange_fnGetPara,
+    ITextRange_fnSetPara,
+    ITextRange_fnGetStoryLength,
+    ITextRange_fnGetStoryType,
+    ITextRange_fnCollapse,
+    ITextRange_fnExpand,
+    ITextRange_fnGetIndex,
+    ITextRange_fnSetIndex,
+    ITextRange_fnSetRange,
+    ITextRange_fnInRange,
+    ITextRange_fnInStory,
+    ITextRange_fnIsEqual,
+    ITextRange_fnSelect,
+    ITextRange_fnStartOf,
+    ITextRange_fnEndOf,
+    ITextRange_fnMove,
+    ITextRange_fnMoveStart,
+    ITextRange_fnMoveEnd,
+    ITextRange_fnMoveWhile,
+    ITextRange_fnMoveStartWhile,
+    ITextRange_fnMoveEndWhile,
+    ITextRange_fnMoveUntil,
+    ITextRange_fnMoveStartUntil,
+    ITextRange_fnMoveEndUntil,
+    ITextRange_fnFindText,
+    ITextRange_fnFindTextStart,
+    ITextRange_fnFindTextEnd,
+    ITextRange_fnDelete,
+    ITextRange_fnCut,
+    ITextRange_fnCopy,
+    ITextRange_fnPaste,
+    ITextRange_fnCanPaste,
+    ITextRange_fnCanEdit,
+    ITextRange_fnChangeCase,
+    ITextRange_fnGetPoint,
+    ITextRange_fnSetPoint,
+    ITextRange_fnScrollIntoView,
+    ITextRange_fnGetEmbeddedObject
+};
+/* ITextRange interface */
+
 static HRESULT WINAPI
 ITextDocument_fnQueryInterface(ITextDocument* me, REFIID riid,
     void** ppvObject)
 static HRESULT WINAPI
 ITextDocument_fnQueryInterface(ITextDocument* me, REFIID riid,
     void** ppvObject)
@@ -634,13 +1364,48 @@ ITextDocument_fnRedo(ITextDocument* me, LONG Count, LONG* prop)
     return E_NOTIMPL;
 }
 
     return E_NOTIMPL;
 }
 
+static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange)
+{
+    ITextRangeImpl *txtRge = heap_alloc(sizeof(ITextRangeImpl));
+
+    if (!txtRge)
+        return E_OUTOFMEMORY;
+    txtRge->ITextRange_iface.lpVtbl = &trvt;
+    txtRge->ref = 1;
+    txtRge->reOle = reOle;
+    txtRge->start = start;
+    txtRge->end = end;
+    list_add_head(&reOle->rangelist, &txtRge->entry);
+    *ppRange = &txtRge->ITextRange_iface;
+    return S_OK;
+}
+
 static HRESULT WINAPI
 ITextDocument_fnRange(ITextDocument* me, LONG cp1, LONG cp2,
     ITextRange** ppRange)
 {
     IRichEditOleImpl *This = impl_from_ITextDocument(me);
 static HRESULT WINAPI
 ITextDocument_fnRange(ITextDocument* me, LONG cp1, LONG cp2,
     ITextRange** ppRange)
 {
     IRichEditOleImpl *This = impl_from_ITextDocument(me);
-    FIXME("stub %p\n",This);
-    return E_NOTIMPL;
+    const int len = ME_GetTextLength(This->editor) + 1;
+
+    TRACE("%p %p %d %d\n", This, ppRange, cp1, cp2);
+    if (!ppRange)
+        return E_INVALIDARG;
+
+    cp1 = max(cp1, 0);
+    cp2 = max(cp2, 0);
+    cp1 = min(cp1, len);
+    cp2 = min(cp2, len);
+    if (cp1 > cp2)
+    {
+        LONG tmp;
+        tmp = cp1;
+        cp1 = cp2;
+        cp2 = tmp;
+    }
+    if (cp1 == len)
+        cp1 = cp2 = len - 1;
+
+    return CreateITextRange(This, cp1, cp2, ppRange);
 }
 
 static HRESULT WINAPI
 }
 
 static HRESULT WINAPI
@@ -771,11 +1536,34 @@ static HRESULT WINAPI ITextSelection_fnInvoke(
 static HRESULT WINAPI ITextSelection_fnGetText(ITextSelection *me, BSTR *pbstr)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
 static HRESULT WINAPI ITextSelection_fnGetText(ITextSelection *me, BSTR *pbstr)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
+    ME_Cursor *start = NULL, *end = NULL;
+    int nChars, endOfs;
+    BOOL bEOP;
+
     if (!This->reOle)
         return CO_E_RELEASED;
     if (!This->reOle)
         return CO_E_RELEASED;
+    TRACE("%p\n", pbstr);
+    if (!pbstr)
+        return E_INVALIDARG;
 
 
-    FIXME("not implemented\n");
-    return E_NOTIMPL;
+    ME_GetSelection(This->reOle->editor, &start, &end);
+    endOfs = ME_GetCursorOfs(end);
+    nChars = endOfs - ME_GetCursorOfs(start);
+    if (!nChars)
+    {
+        *pbstr = NULL;
+        return S_OK;
+    }
+
+    *pbstr = SysAllocStringLen(NULL, nChars);
+    if (!*pbstr)
+        return E_OUTOFMEMORY;
+
+    bEOP = (end->pRun->next->type == diTextEnd && endOfs > ME_GetTextLength(This->reOle->editor));
+    ME_GetTextW(This->reOle->editor, *pbstr, nChars, start, nChars, FALSE, bEOP);
+    TRACE("%s\n", wine_dbgstr_w(*pbstr));
+
+    return S_OK;
 }
 
 static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR bstr)
 }
 
 static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR bstr)
@@ -791,11 +1579,16 @@ static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR bstr)
 static HRESULT WINAPI ITextSelection_fnGetChar(ITextSelection *me, LONG *pch)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
 static HRESULT WINAPI ITextSelection_fnGetChar(ITextSelection *me, LONG *pch)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
+    ME_Cursor *start = NULL, *end = NULL;
+
     if (!This->reOle)
         return CO_E_RELEASED;
     if (!This->reOle)
         return CO_E_RELEASED;
+    TRACE("%p\n", pch);
+    if (!pch)
+        return E_INVALIDARG;
 
 
-    FIXME("not implemented\n");
-    return E_NOTIMPL;
+    ME_GetSelection(This->reOle->editor, &start, &end);
+    return range_GetChar(This->reOle->editor, start, pch);
 }
 
 static HRESULT WINAPI ITextSelection_fnSetChar(ITextSelection *me, LONG ch)
 }
 
 static HRESULT WINAPI ITextSelection_fnSetChar(ITextSelection *me, LONG ch)
@@ -841,11 +1634,15 @@ static HRESULT WINAPI ITextSelection_fnSetFormattedText(ITextSelection *me, ITex
 static HRESULT WINAPI ITextSelection_fnGetStart(ITextSelection *me, LONG *pcpFirst)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
 static HRESULT WINAPI ITextSelection_fnGetStart(ITextSelection *me, LONG *pcpFirst)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
+    LONG lim;
     if (!This->reOle)
         return CO_E_RELEASED;
 
     if (!This->reOle)
         return CO_E_RELEASED;
 
-    FIXME("not implemented\n");
-    return E_NOTIMPL;
+    if (!pcpFirst)
+        return E_INVALIDARG;
+    ME_GetSelectionOfs(This->reOle->editor, pcpFirst, &lim);
+    TRACE("%d\n", *pcpFirst);
+    return S_OK;
 }
 
 static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG cpFirst)
 }
 
 static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG cpFirst)
@@ -861,11 +1658,15 @@ static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG cpFirst
 static HRESULT WINAPI ITextSelection_fnGetEnd(ITextSelection *me, LONG *pcpLim)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
 static HRESULT WINAPI ITextSelection_fnGetEnd(ITextSelection *me, LONG *pcpLim)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
+    LONG first;
     if (!This->reOle)
         return CO_E_RELEASED;
 
     if (!This->reOle)
         return CO_E_RELEASED;
 
-    FIXME("not implemented\n");
-    return E_NOTIMPL;
+    if (!pcpLim)
+        return E_INVALIDARG;
+    ME_GetSelectionOfs(This->reOle->editor, &first, pcpLim);
+    TRACE("%d\n", *pcpLim);
+    return S_OK;
 }
 
 static HRESULT WINAPI ITextSelection_fnSetEnd(ITextSelection *me, LONG cpLim)
 }
 
 static HRESULT WINAPI ITextSelection_fnSetEnd(ITextSelection *me, LONG cpLim)
@@ -941,11 +1742,16 @@ static HRESULT WINAPI ITextSelection_fnGetStoryType(ITextSelection *me, LONG *pV
 static HRESULT WINAPI ITextSelection_fnCollapse(ITextSelection *me, LONG bStart)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
 static HRESULT WINAPI ITextSelection_fnCollapse(ITextSelection *me, LONG bStart)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
+    LONG start, end;
+    HRESULT hres;
     if (!This->reOle)
         return CO_E_RELEASED;
 
     if (!This->reOle)
         return CO_E_RELEASED;
 
-    FIXME("not implemented\n");
-    return E_NOTIMPL;
+    ME_GetSelectionOfs(This->reOle->editor, &start, &end);
+    hres = range_Collapse(bStart, &start, &end);
+    if (SUCCEEDED(hres))
+        ME_SetSelection(This->reOle->editor, start, end);
+    return hres;
 }
 
 static HRESULT WINAPI ITextSelection_fnExpand(ITextSelection *me, LONG Unit, LONG *pDelta)
 }
 
 static HRESULT WINAPI ITextSelection_fnExpand(ITextSelection *me, LONG Unit, LONG *pDelta)
@@ -1513,6 +2319,7 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj)
     }
     TRACE("Created %p\n",reo);
     *ppObj = reo;
     }
     TRACE("Created %p\n",reo);
     *ppObj = reo;
+    list_init(&reo->rangelist);
 
     return 1;
 }
 
     return 1;
 }
@@ -1551,7 +2358,12 @@ void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
     return;
   }
 
     return;
   }
 
-  IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido);
+  if (IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido) != S_OK)
+  {
+      FIXME("Query Interface IID_IDataObject failed!\n");
+      pSize->cx = pSize->cy = 0;
+      return;
+  }
   fmt.cfFormat = CF_BITMAP;
   fmt.ptd = NULL;
   fmt.dwAspect = DVASPECT_CONTENT;
   fmt.cfFormat = CF_BITMAP;
   fmt.ptd = NULL;
   fmt.dwAspect = DVASPECT_CONTENT;
index 12e4ad7..44726b3 100644 (file)
@@ -125,8 +125,7 @@ ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code)
   /* FIXME: Native also knows about punctuation */
   TRACE("s==%s, start==%d, len==%d, code==%d\n",
         debugstr_wn(s, len), start, len, code);
   /* FIXME: Native also knows about punctuation */
   TRACE("s==%s, start==%d, len==%d, code==%d\n",
         debugstr_wn(s, len), start, len, code);
-  /* convert number of bytes to number of characters. */
-  len /= sizeof(WCHAR);
+
   switch (code)
   {
     case WB_ISDELIMITER:
   switch (code)
   {
     case WB_ISDELIMITER:
@@ -154,7 +153,7 @@ int
 ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, INT code)
 {
   if (!editor->pfnWordBreak) {
 ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, INT code)
 {
   if (!editor->pfnWordBreak) {
-    return ME_WordBreakProc(str, start, len * sizeof(WCHAR), code);
+    return ME_WordBreakProc(str, start, len, code);
   } else if (!editor->bEmulateVersion10) {
     /* MSDN lied about the third parameter for EditWordBreakProc being the number
      * of characters, it is actually the number of bytes of the string. */
   } else if (!editor->bEmulateVersion10) {
     /* MSDN lied about the third parameter for EditWordBreakProc being the number
      * of characters, it is actually the number of bytes of the string. */
index fe4bf34..8cf4edd 100644 (file)
@@ -250,7 +250,7 @@ DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface, BSTR *p
          return E_OUTOFMEMORY;
 
       ME_CursorFromCharOfs(This->editor, 0, &start);
          return E_OUTOFMEMORY;
 
       ME_CursorFromCharOfs(This->editor, 0, &start);
-      ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE);
+      ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE, FALSE);
       *pbstrText = bstr;
    } else {
       *pbstrText = NULL;
       *pbstrText = bstr;
    } else {
       *pbstrText = NULL;
index 9238554..b3575a6 100644 (file)
@@ -169,7 +169,7 @@ reactos/dll/win32/qmgrprxy            # Synced to Wine-1.7.17
 reactos/dll/win32/query               # Synced to Wine-1.7.17
 reactos/dll/win32/rasapi32            # Synced to Wine-1.7.27
 reactos/dll/win32/resutils            # Synced to Wine-1.7.17
 reactos/dll/win32/query               # Synced to Wine-1.7.17
 reactos/dll/win32/rasapi32            # Synced to Wine-1.7.27
 reactos/dll/win32/resutils            # Synced to Wine-1.7.17
-reactos/dll/win32/riched20            # Synced to Wine-1.7.17
+reactos/dll/win32/riched20            # Synced to Wine-1.7.27
 reactos/dll/win32/riched32            # Synced to Wine-1.7.17
 reactos/dll/win32/rpcrt4              # Synced to Wine-1.7.17
 reactos/dll/win32/rsabase             # Synced to Wine-1.7.17
 reactos/dll/win32/riched32            # Synced to Wine-1.7.17
 reactos/dll/win32/rpcrt4              # Synced to Wine-1.7.17
 reactos/dll/win32/rsabase             # Synced to Wine-1.7.17