[PATCH 5/5] riched20: Implement TxDraw().

Huw Davies huw at codeweavers.com
Tue Mar 23 08:04:07 CDT 2021


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/riched20/editor.h       |  3 +-
 dlls/riched20/paint.c        | 19 +++++----
 dlls/riched20/tests/txtsrv.c | 55 ++++++++++++++++++-------
 dlls/riched20/txthost.c      |  2 +-
 dlls/riched20/txtsrv.c       | 79 ++++++++++++++++++++++++------------
 dlls/riched20/wrap.c         | 13 ++++--
 6 files changed, 116 insertions(+), 55 deletions(-)

diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index bad48ba54da..075fe534783 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -202,6 +202,7 @@ void ME_DestroyContext(ME_Context *c) DECLSPEC_HIDDEN;
 BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) DECLSPEC_HIDDEN;
 void para_range_invalidate( ME_TextEditor *editor, ME_Paragraph *start_para, ME_Paragraph *last_para ) DECLSPEC_HIDDEN;
 void ME_SendRequestResize(ME_TextEditor *editor, BOOL force) DECLSPEC_HIDDEN;
+BOOL wrap_marked_paras_dc( ME_TextEditor *editor, HDC hdc ) DECLSPEC_HIDDEN;
 
 /* para.c */
 void editor_get_selection_paras(ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end ) DECLSPEC_HIDDEN;
@@ -237,7 +238,7 @@ static inline ME_DisplayItem *para_get_di(ME_Paragraph *para)
 }
 
 /* paint.c */
-void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate) DECLSPEC_HIDDEN;
+void editor_draw( ME_TextEditor *editor, HDC hDC, const RECT *update ) DECLSPEC_HIDDEN;
 void ME_Repaint(ME_TextEditor *editor) DECLSPEC_HIDDEN;
 void ME_RewrapRepaint(ME_TextEditor *editor) DECLSPEC_HIDDEN;
 void ME_UpdateRepaint(ME_TextEditor *editor, BOOL update_now) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index e6eef7a0acd..4be76e441d0 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -25,17 +25,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 
 static void draw_paragraph( ME_Context *c, ME_Paragraph *para );
 
-void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate)
+void editor_draw( ME_TextEditor *editor, HDC hDC, const RECT *update )
 {
   ME_Paragraph *para;
   ME_Context c;
   ME_Cell *cell;
   int ys, ye;
   HRGN oldRgn;
-  RECT rc;
+  RECT rc, client;
   HBRUSH brush = CreateSolidBrush( ITextHost_TxGetSysColor( editor->texthost, COLOR_WINDOW ) );
 
   ME_InitContext( &c, editor, hDC );
+  if (!update)
+  {
+      client = c.rcView;
+      client.left -= editor->selofs;
+      update = &client;
+  }
 
   oldRgn = CreateRectRgn(0, 0, 0, 0);
   if (!GetClipRgn(hDC, oldRgn))
@@ -43,8 +49,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate)
     DeleteObject(oldRgn);
     oldRgn = NULL;
   }
-  IntersectClipRect(hDC, rcUpdate->left, rcUpdate->top,
-                     rcUpdate->right, rcUpdate->bottom);
+  IntersectClipRect( hDC, update->left, update->top, update->right, update->bottom );
 
   brush = SelectObject( hDC, brush );
   SetBkMode(hDC, TRANSPARENT);
@@ -69,7 +74,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate)
     }
 
     /* Draw the paragraph if any of the paragraph is in the update region. */
-    if (ys < rcUpdate->bottom && ye > rcUpdate->top)
+    if (ys < update->bottom && ye > update->top)
       draw_paragraph( &c, para );
     para = para_next( para );
   }
@@ -79,7 +84,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate)
     rc.left = c.rcView.left;
     rc.bottom = c.rcView.bottom;
     rc.right = c.rcView.right;
-    if (IntersectRect( &rc, &rc, rcUpdate ))
+    if (IntersectRect( &rc, &rc, update ))
       PatBlt(hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
   }
   if (editor->selofs)
@@ -88,7 +93,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate)
     rc.top = c.rcView.top;
     rc.right = c.rcView.left;
     rc.bottom = c.rcView.bottom;
-    if (IntersectRect( &rc, &rc, rcUpdate ))
+    if (IntersectRect( &rc, &rc, update ))
       PatBlt( hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
   }
   if (editor->nTotalLength != editor->nLastTotalLength || editor->nTotalWidth != editor->nLastTotalWidth)
diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c
index 20eb318d464..7ca6074587d 100644
--- a/dlls/riched20/tests/txtsrv.c
+++ b/dlls/riched20/tests/txtsrv.c
@@ -764,26 +764,51 @@ static void test_TxDraw(void)
 {
     ITextServices *txtserv;
     ITextHost *host;
-    HDC tmphdc = GetDC(NULL);
-    DWORD dwAspect = DVASPECT_CONTENT;
-    HDC hicTargetDev = NULL; /* Means "default" device */
-    DVTARGETDEVICE *ptd = NULL;
-    void *pvAspect = NULL;
-    HRESULT result;
-    RECTL client = {0,0,100,100};
-
+    HRESULT hr;
+    RECT client = {0, 0, 100, 100};
+    ITextHostTestImpl *host_impl;
+    HDC hdc;
 
     if (!init_texthost(&txtserv, &host))
         return;
 
-    todo_wine {
-        result = ITextServices_TxDraw(txtserv, dwAspect, 0, pvAspect, ptd,
-                                      tmphdc, hicTargetDev, &client, NULL,
-                                      NULL, NULL, 0, 0);
-        ok(result == S_OK, "TxDraw failed (result = %x)\n", result);
-    }
-
+    host_impl = impl_from_ITextHost( host );
+    host_impl->window = CreateWindowExA( 0, "static", NULL, WS_POPUP | WS_VISIBLE,
+                                         0, 0, 400, 400, 0, 0, 0, NULL );
+    host_impl->client_rect = client;
+    host_impl->props = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP;
+    ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_CLIENTRECTCHANGE | TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP,
+                                          host_impl->props );
+    hdc = GetDC( host_impl->window );
+
+    hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, 0, TXTVIEW_INACTIVE );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+    hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, NULL, NULL,
+                               NULL, NULL, 0, TXTVIEW_INACTIVE );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+    hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, (RECTL *)&client, NULL,
+                               NULL, NULL, 0, TXTVIEW_INACTIVE );
+    ok( hr == E_FAIL, "got %08x\n", hr );
+    hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, (RECTL *)&client, NULL,
+                               NULL, NULL, 0, TXTVIEW_INACTIVE );
+    ok( hr == S_OK, "got %08x\n", hr );
+    hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, (RECTL *)&client, NULL,
+                               NULL, NULL, 0, TXTVIEW_ACTIVE );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = ITextServices_OnTxInPlaceActivate( txtserv, &client );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, 0, TXTVIEW_INACTIVE );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = ITextServices_OnTxInPlaceDeactivate( txtserv );
+
+    ReleaseDC( host_impl->window, hdc );
     ITextServices_Release(txtserv);
+    DestroyWindow( host_impl->window );
     ITextHost_Release(host);
 }
 
diff --git a/dlls/riched20/txthost.c b/dlls/riched20/txthost.c
index cda9b35b199..ab13879c664 100644
--- a/dlls/riched20/txthost.c
+++ b/dlls/riched20/txthost.c
@@ -1222,7 +1222,7 @@ static LRESULT RichEditWndProc_common( HWND hwnd, UINT msg, WPARAM wparam,
             ps.rcPaint.right = editor->rcFormat.right;
         }
 
-        ME_PaintContent( editor, hdc, &ps.rcPaint );
+        editor_draw( editor, hdc, &ps.rcPaint );
         DeleteObject( SelectObject( hdc, brush ) );
         EndPaint( editor->hWnd, &ps );
         return 0;
diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c
index bab52269db6..6ef7b7ef029 100644
--- a/dlls/riched20/txtsrv.c
+++ b/dlls/riched20/txtsrv.c
@@ -142,17 +142,62 @@ DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSendMessage( ITextServices *iface
     return hr;
 }
 
+static HRESULT update_client_rect( struct text_services *services, const RECT *client )
+{
+    RECT rect;
+    HRESULT hr;
+
+    if (!client)
+    {
+        if (!services->editor->in_place_active) return E_INVALIDARG;
+        hr = ITextHost_TxGetClientRect( services->host, &rect );
+        if (FAILED( hr )) return hr;
+    }
+    else rect = *client;
+
+    rect.left += services->editor->selofs;
+
+    if (EqualRect( &rect, &services->editor->rcFormat )) return S_FALSE;
+    services->editor->rcFormat = rect;
+    return S_OK;
+}
+
 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52)
-DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxDraw(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
-                                                    void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, HDC hdcTargetDev,
-                                                    LPCRECTL lprcBounds, LPCRECTL lprcWBounds, LPRECT lprcUpdate,
-                                                    BOOL (CALLBACK * pfnContinue)(DWORD), DWORD dwContinue,
-                                                    LONG lViewId)
+DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxDraw( ITextServices *iface, DWORD aspect, LONG index, void *aspect_info,
+                                                     DVTARGETDEVICE *td, HDC draw, HDC target,
+                                                     const RECTL *bounds, const RECTL *mf_bounds, RECT *update,
+                                                     BOOL (CALLBACK *continue_fn)(DWORD), DWORD continue_param,
+                                                     LONG view_id )
 {
     struct text_services *services = impl_from_ITextServices( iface );
+    HRESULT hr;
+    HDC dc = draw;
+    BOOL rewrap = FALSE;
 
-    FIXME( "%p: STUB\n", services );
-    return E_NOTIMPL;
+    TRACE( "%p: aspect %d, %d, %p, %p, draw %p, target %p, bounds %s, mf_bounds %s, update %s, %p, %d, view %d\n",
+           services, aspect, index, aspect_info, td, draw, target, wine_dbgstr_rect( (RECT *)bounds ),
+           wine_dbgstr_rect( (RECT *)mf_bounds ), wine_dbgstr_rect( update ), continue_fn, continue_param, view_id );
+
+    if (aspect != DVASPECT_CONTENT || aspect_info || td || target || mf_bounds || continue_fn )
+        FIXME( "Many arguments are ignored\n" );
+
+    hr = update_client_rect( services, (RECT *)bounds );
+    if (FAILED( hr )) return hr;
+    if (hr == S_OK) rewrap = TRUE;
+
+    if (!dc && services->editor->in_place_active)
+        dc = ITextHost_TxGetDC( services->host );
+    if (!dc) return E_FAIL;
+
+    if (rewrap)
+    {
+        editor_mark_rewrap_all( services->editor );
+        wrap_marked_paras_dc( services->editor, dc );
+    }
+    editor_draw( services->editor, dc, update );
+
+    if (!draw) ITextHost_TxReleaseDC( services->host, dc );
+    return S_OK;
 }
 
 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24)
@@ -213,26 +258,6 @@ DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxQueryHitPoint(ITextServices *ifac
     return E_NOTIMPL;
 }
 
-static HRESULT update_client_rect( struct text_services *services, const RECT *client )
-{
-    RECT rect;
-    HRESULT hr = S_OK;
-
-    if (!client)
-    {
-        if (!services->editor->in_place_active) return E_INVALIDARG;
-        hr = ITextHost_TxGetClientRect( services->host, &rect );
-        client = ▭
-    }
-
-    if (SUCCEEDED( hr ))
-    {
-        services->editor->rcFormat = *client;
-        services->editor->rcFormat.left += services->editor->selofs;
-    }
-    return hr;
-}
-
 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInPlaceActivate,8)
 DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInPlaceActivate( ITextServices *iface, const RECT *client )
 {
diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c
index 3d7e030fe50..468b267ceae 100644
--- a/dlls/riched20/wrap.c
+++ b/dlls/riched20/wrap.c
@@ -1020,18 +1020,16 @@ static void adjust_para_y( ME_Paragraph *para, ME_Context *c, struct repaint_ran
     }
 }
 
-BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
+BOOL wrap_marked_paras_dc( ME_TextEditor *editor, HDC hdc )
 {
   ME_Paragraph *para, *next;
   struct wine_rb_entry *entry, *next_entry = NULL;
   ME_Context c;
   int totalWidth = editor->nTotalWidth, prev_width;
   struct repaint_range repaint = { NULL, NULL };
-  HDC hdc;
 
   if (!editor->marked_paras.root) return FALSE;
 
-  hdc = ITextHost_TxGetDC( editor->texthost );
   ME_InitContext( &c, editor, hdc );
 
   entry = wine_rb_head( editor->marked_paras.root );
@@ -1087,13 +1085,20 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
   editor->nTotalWidth = totalWidth;
 
   ME_DestroyContext(&c);
-  ITextHost_TxReleaseDC( editor->texthost, hdc );
 
   if (repaint.start || editor->nTotalLength < editor->nLastTotalLength)
     para_range_invalidate( editor, repaint.start, repaint.end);
   return !!repaint.start;
 }
 
+BOOL ME_WrapMarkedParagraphs( ME_TextEditor *editor )
+{
+    HDC hdc = ITextHost_TxGetDC( editor->texthost );
+    BOOL ret = wrap_marked_paras_dc( editor, hdc );
+    ITextHost_TxReleaseDC( editor->texthost, hdc );
+    return ret;
+}
+
 void para_range_invalidate( ME_TextEditor *editor, ME_Paragraph *start_para,
                             ME_Paragraph *last_para )
 {
-- 
2.23.0




More information about the wine-devel mailing list