[PATCH 4/5] riched20: Handle the client rect changes in the host.

Huw Davies huw at codeweavers.com
Wed Mar 17 03:45:27 CDT 2021


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/riched20/editor.c       | 81 ------------------------------------
 dlls/riched20/editstr.h      |  3 --
 dlls/riched20/tests/editor.c | 15 ++++++-
 dlls/riched20/txthost.c      | 76 +++++++++++++++++++++++++++++++--
 dlls/riched20/txtsrv.c       | 25 +++++++++++
 5 files changed, 112 insertions(+), 88 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 17b7d427d83..779472f1f04 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -2909,14 +2909,6 @@ static BOOL ME_SetCursor(ME_TextEditor *editor)
   return TRUE;
 }
 
-static void ME_SetDefaultFormatRect(ME_TextEditor *editor)
-{
-  ITextHost_TxGetClientRect(editor->texthost, &editor->rcFormat);
-  editor->rcFormat.top += editor->exStyleFlags & WS_EX_CLIENTEDGE ? 1 : 0;
-  editor->rcFormat.left += 1 + editor->selofs;
-  editor->rcFormat.right -= 1;
-}
-
 static LONG ME_GetSelectionType(ME_TextEditor *editor)
 {
     LONG sel_type = SEL_EMPTY;
@@ -2987,7 +2979,6 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
   ed->texthost = texthost;
   ed->reOle = NULL;
   ed->bEmulateVersion10 = bEmulateVersion10;
-  ed->exStyleFlags = 0;
   ed->total_rows = 0;
   ITextHost_TxGetPropertyBits( texthost, TXTBIT_RICHTEXT | TXTBIT_MULTILINE | TXTBIT_READONLY |
                                TXTBIT_USEPASSWORD | TXTBIT_HIDESELECTION | TXTBIT_SAVESELECTION |
@@ -3046,7 +3037,6 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
 
   ME_CheckCharOffsets(ed);
   SetRectEmpty(&ed->rcFormat);
-  ed->bDefaultFormatRect = TRUE;
   hr = ITextHost_TxGetSelectionBarWidth( ed->texthost, &selbarwidth );
   /* FIXME: Convert selbarwidth from HIMETRIC to pixels */
   if (hr == S_OK && selbarwidth) ed->selofs = SELECTIONBAR_WIDTH;
@@ -3227,8 +3217,6 @@ static LRESULT ME_WmCreate(ME_TextEditor *editor, LPARAM lParam, BOOL unicode)
   if (lParam)
     text = unicode ? (void*)createW->lpszName : (void*)createA->lpszName;
 
-  ME_SetDefaultFormatRect(editor);
-
   max = (editor->scrollbars & ES_DISABLENOSCROLL) ? 1 : 0;
   if (~editor->scrollbars & ES_DISABLENOSCROLL || editor->scrollbars & WS_VSCROLL)
     ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, 0, max, TRUE);
@@ -4212,78 +4200,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     }
     break;
   }
-  case EM_GETRECT:
-  {
-    *((RECT *)lParam) = editor->rcFormat;
-    if (editor->bDefaultFormatRect)
-      ((RECT *)lParam)->left -= editor->selofs;
-    return 0;
-  }
-  case EM_SETRECT:
-  case EM_SETRECTNP:
-  {
-    if (lParam)
-    {
-      int border = 0;
-      RECT clientRect;
-      RECT *rc = (RECT *)lParam;
-
-      border = editor->exStyleFlags & WS_EX_CLIENTEDGE ? 1 : 0;
-      ITextHost_TxGetClientRect(editor->texthost, &clientRect);
-      if (wParam == 0)
-      {
-        editor->rcFormat.top = max(0, rc->top - border);
-        editor->rcFormat.left = max(0, rc->left - border);
-        editor->rcFormat.bottom = min(clientRect.bottom, rc->bottom);
-        editor->rcFormat.right = min(clientRect.right, rc->right + border);
-      } else if (wParam == 1) {
-        /* MSDN incorrectly says a wParam value of 1 causes the
-         * lParam rect to be used as a relative offset,
-         * however, the tests show it just prevents min/max bound
-         * checking. */
-        editor->rcFormat.top = rc->top - border;
-        editor->rcFormat.left = rc->left - border;
-        editor->rcFormat.bottom = rc->bottom;
-        editor->rcFormat.right = rc->right + border;
-      } else {
-        return 0;
-      }
-      editor->bDefaultFormatRect = FALSE;
-    }
-    else
-    {
-      ME_SetDefaultFormatRect(editor);
-      editor->bDefaultFormatRect = TRUE;
-    }
-    editor_mark_rewrap_all( editor );
-    ME_WrapMarkedParagraphs(editor);
-    ME_UpdateScrollBar(editor);
-    if (msg != EM_SETRECTNP)
-      ME_Repaint(editor);
-    return 0;
-  }
   case EM_REQUESTRESIZE:
     ME_SendRequestResize(editor, TRUE);
     return 0;
-  case WM_SETREDRAW:
-    goto do_default;
-  case WM_WINDOWPOSCHANGED:
-  {
-    RECT clientRect;
-    WINDOWPOS *winpos = (WINDOWPOS *)lParam;
-
-    if (winpos->flags & SWP_NOCLIENTSIZE) goto do_default;
-    ITextHost_TxGetClientRect(editor->texthost, &clientRect);
-    if (editor->bDefaultFormatRect) {
-      ME_SetDefaultFormatRect(editor);
-    } else {
-      editor->rcFormat.right += clientRect.right - editor->prevClientRect.right;
-      editor->rcFormat.bottom += clientRect.bottom - editor->prevClientRect.bottom;
-    }
-    editor->prevClientRect = clientRect;
-    ME_RewrapRepaint(editor);
-    goto do_default;
-  }
   /* IME messages to make richedit controls IME aware */
   case WM_IME_SETCONTEXT:
   case WM_IME_CONTROL:
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index a3e5970bff8..1f277cbf6bc 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -383,7 +383,6 @@ typedef struct tagME_TextEditor
   BOOL bEmulateVersion10;
   ME_TextBuffer *pBuffer;
   ME_Cursor *pCursors;
-  DWORD exStyleFlags;
   DWORD props;
   DWORD scrollbars;
   int nCursors;
@@ -407,9 +406,7 @@ typedef struct tagME_TextEditor
   ME_Paragraph *last_sel_start_para, *last_sel_end_para;
   ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
   int nZoomNumerator, nZoomDenominator;
-  RECT prevClientRect;
   RECT rcFormat;
-  BOOL bDefaultFormatRect;
   BOOL bWordWrap;
   int nTextLimit;
   EDITWORDBREAKPROCW pfnWordBreak;
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index 1ce94f8ae64..19a1af25f73 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -7460,12 +7460,25 @@ static void test_format_rect(void)
     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
        wine_dbgstr_rect(&expected));
 
+    /* reset back to client rect and now try adding selection bar */
+    SendMessageA(hwnd, EM_SETRECT, 0, 0);
+    expected = clientRect;
+    InflateRect(&expected, -1, 0);
+    SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+    ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+       wine_dbgstr_rect(&expected));
+    SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR);
+    SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+    ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+       wine_dbgstr_rect(&expected));
+    SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_AND, ~ECO_SELECTIONBAR);
+
     /* Set the absolute value of the formatting rectangle. */
     rc = clientRect;
     SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
     expected = clientRect;
     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
-    ok(EqualRect(&rc, &expected), "[n=%d] rect %s != %s\n", n, wine_dbgstr_rect(&rc),
+    ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
        wine_dbgstr_rect(&expected));
 
     /* MSDN documents the EM_SETRECT message as using the rectangle provided in
diff --git a/dlls/riched20/txthost.c b/dlls/riched20/txthost.c
index 3ba522331b0..0325d5d41d8 100644
--- a/dlls/riched20/txthost.c
+++ b/dlls/riched20/txthost.c
@@ -43,8 +43,11 @@ struct host
     unsigned int dialog_mode : 1;
     unsigned int want_return : 1;
     unsigned int sel_bar : 1;
+    unsigned int client_edge : 1;
+    unsigned int use_set_rect : 1;
     PARAFORMAT2 para_fmt;
     DWORD props, scrollbars, event_mask;
+    RECT client_rect, set_rect;
 };
 
 static const ITextHostVtbl textHostVtbl;
@@ -76,6 +79,9 @@ static void host_init_props( struct host *host )
 
     host->sel_bar     = !!(style & ES_SELECTIONBAR);
     host->want_return = !!(style & ES_WANTRETURN);
+
+    style = GetWindowLongW( host->window, GWL_EXSTYLE );
+    host->client_edge = !!(style & WS_EX_CLIENTEDGE);
 }
 
 struct host *host_create( HWND hwnd, CREATESTRUCTW *cs, BOOL emulate_10 )
@@ -102,6 +108,9 @@ struct host *host_create( HWND hwnd, CREATESTRUCTW *cs, BOOL emulate_10 )
     texthost->editor = NULL;
     host_init_props( texthost );
     texthost->event_mask = 0;
+    texthost->use_set_rect = 0;
+    SetRectEmpty( &texthost->set_rect );
+    GetClientRect( hwnd, &texthost->client_rect );
 
     return texthost;
 }
@@ -301,8 +310,16 @@ DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect,8)
 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetClientRect( ITextHost *iface, RECT *rect )
 {
     struct host *host = impl_from_ITextHost( iface );
-    int ret = GetClientRect( host->window, rect );
-    return ret ? S_OK : E_FAIL;
+
+    if (!host->use_set_rect)
+    {
+        *rect = host->client_rect;
+        if (host->client_edge) rect->top += 1;
+        InflateRect( rect, -1, 0 );
+    }
+    else *rect = host->set_rect;
+
+    return S_OK;
 }
 
 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset,8)
@@ -701,7 +718,6 @@ static BOOL create_windowed_editor( HWND hwnd, CREATESTRUCTW *create, BOOL emula
     IUnknown_QueryInterface( unk, &IID_ITextServices, (void **)&host->text_srv );
     IUnknown_Release( unk );
 
-    host->editor->exStyleFlags = GetWindowLongW( hwnd, GWL_EXSTYLE );
     host->editor->hWnd = hwnd; /* FIXME: Remove editor's dependence on hWnd */
     host->editor->hwndParent = create->hwndParent;
 
@@ -829,6 +845,12 @@ static HRESULT set_options( struct host *host, DWORD op, DWORD value, LRESULT *r
     {
         host->sel_bar ^= 1;
         props_mask |= TXTBIT_SELBARCHANGE;
+        if (host->use_set_rect)
+        {
+            int width = SELECTIONBAR_WIDTH;
+            host->set_rect.left += host->sel_bar ? width : -width;
+            props_mask |= TXTBIT_CLIENTRECTCHANGE;
+        }
     }
     if (change & ECO_VERTICAL)
     {
@@ -939,6 +961,12 @@ static LRESULT RichEditWndProc_common( HWND hwnd, UINT msg, WPARAM wparam,
         hr = ITextServices_TxSendMessage( host->text_srv, msg, wc, lparam, &res );
         break;
     }
+
+    case WM_CREATE:
+        ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_CLIENTRECTCHANGE, 0 );
+        res = ME_HandleMessage( editor, msg, wparam, lparam, unicode, &hr );
+        break;
+
     case WM_DESTROY:
         ITextHost_Release( &host->ITextHost_iface );
         return 0;
@@ -1002,6 +1030,10 @@ static LRESULT RichEditWndProc_common( HWND hwnd, UINT msg, WPARAM wparam,
         else hr = get_lineA( host->text_srv, wparam, lparam, &res );
         break;
 
+    case EM_GETRECT:
+        hr = ITextHost_TxGetClientRect( &host->ITextHost_iface, (RECT *)lparam );
+        break;
+
     case EM_GETSELTEXT:
     {
         TEXTRANGEA range;
@@ -1149,6 +1181,27 @@ static LRESULT RichEditWndProc_common( HWND hwnd, UINT msg, WPARAM wparam,
         SendMessageW( hwnd, EM_SETOPTIONS, op, mask );
         return 1;
     }
+    case EM_SETRECT:
+    case EM_SETRECTNP:
+    {
+        RECT *rc = (RECT *)lparam;
+
+        if (!rc) host->use_set_rect = 0;
+        else
+        {
+            if (wparam >= 2) break;
+            host->set_rect = *rc;
+            if (host->client_edge)
+            {
+                InflateRect( &host->set_rect, 1, 0 );
+                host->set_rect.top -= 1;
+            }
+            if (!wparam) IntersectRect( &host->set_rect, &host->set_rect, &host->client_rect );
+            host->use_set_rect = 1;
+        }
+        ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_CLIENTRECTCHANGE, 0 );
+        break;
+    }
     case WM_SETTEXT:
     {
         char *textA = (char *)lparam;
@@ -1183,6 +1236,23 @@ static LRESULT RichEditWndProc_common( HWND hwnd, UINT msg, WPARAM wparam,
         res = 0;
         break;
     }
+    case WM_WINDOWPOSCHANGED:
+    {
+        RECT client;
+        WINDOWPOS *winpos = (WINDOWPOS *)lparam;
+
+        hr = S_FALSE; /* call defwndproc */
+        if (winpos->flags & SWP_NOCLIENTSIZE) break;
+        GetClientRect( hwnd, &client );
+        if (host->use_set_rect)
+        {
+            host->set_rect.right += client.right - host->client_rect.right;
+            host->set_rect.bottom += client.bottom - host->client_rect.bottom;
+        }
+        host->client_rect = client;
+        ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_CLIENTRECTCHANGE, 0 );
+        break;
+    }
     default:
         res = ME_HandleMessage( editor, msg, wparam, lparam, unicode, &hr );
     }
diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c
index df62a2dd7c5..3f7688e6b25 100644
--- a/dlls/riched20/txtsrv.c
+++ b/dlls/riched20/txtsrv.c
@@ -206,6 +206,25 @@ 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)
+    {
+        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, LPCRECT prcClient)
 {
@@ -365,6 +384,12 @@ DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxPropertyBitsChange( ITextServic
         }
     }
 
+    if (mask & TXTBIT_CLIENTRECTCHANGE)
+    {
+        hr = update_client_rect( services, NULL );
+        if (SUCCEEDED( hr )) repaint = TRUE;
+    }
+
     if (repaint) ME_RewrapRepaint( services->editor );
 
     return S_OK;
-- 
2.23.0




More information about the wine-devel mailing list