From b2a2a423ce6d478f1d34408c5db559bffc482a17 Mon Sep 17 00:00:00 2001
From: Jactry Zeng <wine@jactry.com>
Date: Sun, 10 Aug 2014 22:17:57 +0800
Subject: riched20: Stub for ITextPara interface and implement
 ITextRange::GetPara.

---
 dlls/riched20/richole.c       | 202 ++++++++++++++++++++++++++++++++++++++++++
 dlls/riched20/tests/richole.c |  47 ++++++++++
 2 files changed, 249 insertions(+)

diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index 64809cc..c309292 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -3264,6 +3264,16 @@ static ULONG WINAPI TextPara_Release(ITextPara *iface)
     return ref;
 }
 
+static IRichEditOleImpl *para_get_reole(ITextParaImpl *This)
+{
+    if (This->range)
+    {
+        ITextRangeImpl *rng = impl_from_ITextRange(This->range);
+        return rng->child.reole;
+    }
+    return NULL;
+}
+
 static HRESULT WINAPI TextPara_GetTypeInfoCount(ITextPara *iface, UINT *pctinfo)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
@@ -3330,6 +3340,10 @@ static HRESULT WINAPI TextPara_GetDuplicate(ITextPara *iface, ITextPara **ret)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, ret);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3337,6 +3351,10 @@ static HRESULT WINAPI TextPara_SetDuplicate(ITextPara *iface, ITextPara *para)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, para);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3344,6 +3362,10 @@ static HRESULT WINAPI TextPara_CanChange(ITextPara *iface, LONG *ret)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, ret);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3351,6 +3373,10 @@ static HRESULT WINAPI TextPara_IsEqual(ITextPara *iface, ITextPara *para, LONG *
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p %p)\n", This, para, ret);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3358,6 +3384,10 @@ static HRESULT WINAPI TextPara_Reset(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3365,6 +3395,10 @@ static HRESULT WINAPI TextPara_GetStyle(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3372,6 +3406,10 @@ static HRESULT WINAPI TextPara_SetStyle(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3379,6 +3417,10 @@ static HRESULT WINAPI TextPara_GetAlignment(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3386,6 +3428,10 @@ static HRESULT WINAPI TextPara_SetAlignment(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3393,6 +3439,10 @@ static HRESULT WINAPI TextPara_GetHyphenation(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3400,6 +3450,10 @@ static HRESULT WINAPI TextPara_SetHyphenation(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3407,6 +3461,10 @@ static HRESULT WINAPI TextPara_GetFirstLineIndent(ITextPara *iface, FLOAT *value
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3414,6 +3472,10 @@ static HRESULT WINAPI TextPara_GetKeepTogether(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3421,6 +3483,10 @@ static HRESULT WINAPI TextPara_SetKeepTogether(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3428,6 +3494,10 @@ static HRESULT WINAPI TextPara_GetKeepWithNext(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3435,6 +3505,10 @@ static HRESULT WINAPI TextPara_SetKeepWithNext(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3442,6 +3516,10 @@ static HRESULT WINAPI TextPara_GetLeftIndent(ITextPara *iface, FLOAT *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3449,6 +3527,10 @@ static HRESULT WINAPI TextPara_GetLineSpacing(ITextPara *iface, FLOAT *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3456,6 +3538,10 @@ static HRESULT WINAPI TextPara_GetLineSpacingRule(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3463,6 +3549,10 @@ static HRESULT WINAPI TextPara_GetListAlignment(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3470,6 +3560,10 @@ static HRESULT WINAPI TextPara_SetListAlignment(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3477,6 +3571,10 @@ static HRESULT WINAPI TextPara_GetListLevelIndex(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3484,6 +3582,10 @@ static HRESULT WINAPI TextPara_SetListLevelIndex(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3491,6 +3593,10 @@ static HRESULT WINAPI TextPara_GetListStart(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3498,6 +3604,10 @@ static HRESULT WINAPI TextPara_SetListStart(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3505,6 +3615,10 @@ static HRESULT WINAPI TextPara_GetListTab(ITextPara *iface, FLOAT *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3512,6 +3626,10 @@ static HRESULT WINAPI TextPara_SetListTab(ITextPara *iface, FLOAT value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%.2f)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3519,6 +3637,10 @@ static HRESULT WINAPI TextPara_GetListType(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3526,6 +3648,10 @@ static HRESULT WINAPI TextPara_SetListType(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3533,6 +3659,10 @@ static HRESULT WINAPI TextPara_GetNoLineNumber(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3540,6 +3670,10 @@ static HRESULT WINAPI TextPara_SetNoLineNumber(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3547,6 +3681,10 @@ static HRESULT WINAPI TextPara_GetPageBreakBefore(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3554,6 +3692,10 @@ static HRESULT WINAPI TextPara_SetPageBreakBefore(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3561,6 +3703,10 @@ static HRESULT WINAPI TextPara_GetRightIndent(ITextPara *iface, FLOAT *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3568,6 +3714,10 @@ static HRESULT WINAPI TextPara_SetRightIndent(ITextPara *iface, FLOAT value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%.2f)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3575,6 +3725,10 @@ static HRESULT WINAPI TextPara_SetIndents(ITextPara *iface, FLOAT StartIndent, F
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%.2f %.2f %.2f)\n", This, StartIndent, LeftIndent, RightIndent);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3582,6 +3736,10 @@ static HRESULT WINAPI TextPara_SetLineSpacing(ITextPara *iface, LONG LineSpacing
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d %.2f)\n", This, LineSpacingRule, LineSpacing);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3589,6 +3747,10 @@ static HRESULT WINAPI TextPara_GetSpaceAfter(ITextPara *iface, FLOAT *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3596,6 +3758,10 @@ static HRESULT WINAPI TextPara_SetSpaceAfter(ITextPara *iface, FLOAT value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%.2f)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3603,6 +3769,10 @@ static HRESULT WINAPI TextPara_GetSpaceBefore(ITextPara *iface, FLOAT *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3610,6 +3780,10 @@ static HRESULT WINAPI TextPara_SetSpaceBefore(ITextPara *iface, FLOAT value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%.2f)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3617,6 +3791,10 @@ static HRESULT WINAPI TextPara_GetWidowControl(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3624,6 +3802,10 @@ static HRESULT WINAPI TextPara_SetWidowControl(ITextPara *iface, LONG value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3631,6 +3813,10 @@ static HRESULT WINAPI TextPara_GetTabCount(ITextPara *iface, LONG *value)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%p)\n", This, value);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3638,6 +3824,10 @@ static HRESULT WINAPI TextPara_AddTab(ITextPara *iface, FLOAT tbPos, LONG tbAlig
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%.2f %d %d)\n", This, tbPos, tbAlign, tbLeader);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3645,6 +3835,10 @@ static HRESULT WINAPI TextPara_ClearAllTabs(ITextPara *iface)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)\n", This);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3652,6 +3846,10 @@ static HRESULT WINAPI TextPara_DeleteTab(ITextPara *iface, FLOAT pos)
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%.2f)\n", This, pos);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
@@ -3659,6 +3857,10 @@ static HRESULT WINAPI TextPara_GetTab(ITextPara *iface, LONG iTab, FLOAT *ptbPos
 {
     ITextParaImpl *This = impl_from_ITextPara(iface);
     FIXME("(%p)->(%d %p %p %p)\n", This, iTab, ptbPos, ptbAlign, ptbLeader);
+
+    if (!para_get_reole(This))
+        return CO_E_RELEASED;
+
     return E_NOTIMPL;
 }
 
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index 5f8e1cc..c148034 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -3473,6 +3473,52 @@ static void test_ITextSelection_GetFont(void)
   ITextFont_Release(txtFont);
 }
 
+static void test_ITextRange_GetPara(void)
+{
+  HWND w;
+  IRichEditOle *reOle = NULL;
+  ITextDocument *txtDoc = NULL;
+  ITextRange *txtRge = NULL;
+  ITextPara *txtPara = NULL, *txtPara1 = NULL;
+  HRESULT hres;
+  int first, lim;
+  int refcount;
+  static const CHAR test_text1[] = "TestSomeText";
+  LONG value;
+
+  create_interfaces(&w, &reOle, &txtDoc, NULL);
+  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
+
+  first = 4, lim = 4;
+  ITextDocument_Range(txtDoc, first, lim, &txtRge);
+  refcount = get_refcount((IUnknown *)txtRge);
+  ok(refcount == 1, "got wrong ref count: %d\n", refcount);
+
+  hres = ITextRange_GetPara(txtRge, &txtPara);
+  ok(hres == S_OK, "ITextRange_GetPara\n");
+  refcount = get_refcount((IUnknown *)txtPara);
+  ok(refcount == 1, "got wrong ref count: %d\n", refcount);
+  refcount = get_refcount((IUnknown *)txtRge);
+  ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+
+  hres = ITextRange_GetPara(txtRge, &txtPara1);
+  ok(hres == S_OK, "ITextRange_GetPara\n");
+  ok(txtPara1 != txtPara, "A new pointer should be return\n");
+  refcount = get_refcount((IUnknown *)txtPara1);
+  ok(refcount == 1, "got wrong ref count: %d\n", refcount);
+  ITextPara_Release(txtPara1);
+  refcount = get_refcount((IUnknown *)txtRge);
+  ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+
+  ITextRange_Release(txtRge);
+  release_interfaces(&w, &reOle, &txtDoc, NULL);
+
+  hres = ITextPara_GetStyle(txtPara, &value);
+  ok(hres == CO_E_RELEASED, "ITextPara after ITextDocument destroyed\n");
+
+  ITextPara_Release(txtPara);
+}
+
 START_TEST(richole)
 {
   /* Must explicitly LoadLibrary(). The test has no references to functions in
@@ -3497,6 +3543,7 @@ START_TEST(richole)
   test_ITextRange_SetEnd();
   test_ITextRange_Collapse();
   test_ITextRange_GetFont();
+  test_ITextRange_GetPara();
   test_GetClientSite();
   test_IOleWindow_GetWindow();
   test_IOleInPlaceSite_GetWindow();
-- 
2.4.2

