[3/5] richedit: Prevented using NULL hwnd for certain operations.

Dylan Smith dylan.ah.smith at gmail.com
Tue Jan 20 00:41:36 CST 2009


Certain operations will simply not be done for windowless richedit
controls, such as WM_PAINT which isn't done for windowless richedit
controls since ITextServices provides a TxDraw method.
WM_ERASEBACKGROUND also seems to be similar in this way.

Instead of doing these operations that don't have any obvious way to be
done through the ITextHost interface, I just prevented them from
happening, or moved the code to the window proc for windowed richedit
controls.

Windowed richedit controls should still have the same behaviour.
---
 dlls/riched20/editor.c  |  207 ++++++++++++++++++++++++++---------------------
 dlls/riched20/editstr.h |    1 +
 dlls/riched20/paint.c   |   52 ++++++++-----
 dlls/riched20/txthost.c |    1 +
 4 files changed, 150 insertions(+), 111 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index ce47c8d..cd2312b 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -2546,23 +2546,26 @@ static BOOL ME_SetCursor(ME_TextEditor *editor)
   pt.x = (short)LOWORD(messagePos);
   pt.y = (short)HIWORD(messagePos);
 
-  sbi.cbSize = sizeof(sbi);
-  GetScrollBarInfo(editor->hWnd, OBJID_HSCROLL, &sbi);
-  if (!(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)) &&
-      PtInRect(&sbi.rcScrollBar, pt))
+  if (editor->hWnd)
   {
-      ITextHost_TxSetCursor(editor->texthost,
-                            LoadCursorW(NULL, (WCHAR*)IDC_ARROW), FALSE);
-      return TRUE;
-  }
-  sbi.cbSize = sizeof(sbi);
-  GetScrollBarInfo(editor->hWnd, OBJID_VSCROLL, &sbi);
-  if (!(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)) &&
-      PtInRect(&sbi.rcScrollBar, pt))
-  {
-      ITextHost_TxSetCursor(editor->texthost,
-                            LoadCursorW(NULL, (WCHAR*)IDC_ARROW), FALSE);
-      return TRUE;
+    sbi.cbSize = sizeof(sbi);
+    GetScrollBarInfo(editor->hWnd, OBJID_HSCROLL, &sbi);
+    if (!(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)) &&
+        PtInRect(&sbi.rcScrollBar, pt))
+    {
+        ITextHost_TxSetCursor(editor->texthost,
+                              LoadCursorW(NULL, (WCHAR*)IDC_ARROW), FALSE);
+        return TRUE;
+    }
+    sbi.cbSize = sizeof(sbi);
+    GetScrollBarInfo(editor->hWnd, OBJID_VSCROLL, &sbi);
+    if (!(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)) &&
+        PtInRect(&sbi.rcScrollBar, pt))
+    {
+        ITextHost_TxSetCursor(editor->texthost,
+                              LoadCursorW(NULL, (WCHAR*)IDC_ARROW), FALSE);
+        return TRUE;
+    }
   }
   ITextHost_TxScreenToClient(editor->texthost, &pt);
 
@@ -2630,10 +2633,8 @@ static BOOL ME_SetCursor(ME_TextEditor *editor)
 
 static void ME_SetDefaultFormatRect(ME_TextEditor *editor)
 {
-  DWORD exstyle = GetWindowLongW(editor->hWnd, GWL_EXSTYLE);
-
   ITextHost_TxGetClientRect(editor->texthost, &editor->rcFormat);
-  editor->rcFormat.top += (exstyle & WS_EX_CLIENTEDGE ? 1 : 0);
+  editor->rcFormat.top += editor->exStyleFlags & WS_EX_CLIENTEDGE ? 1 : 0;
   editor->rcFormat.left += 1 + editor->selofs;
   editor->rcFormat.right -= 1;
 }
@@ -2643,7 +2644,7 @@ static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y)
   CHARRANGE selrange;
   HMENU menu;
   int seltype = 0;
-  if(!editor->lpOleCallback)
+  if(!editor->lpOleCallback || !editor->hWnd)
     return FALSE;
   ME_GetSelection(editor, &selrange.cpMin, &selrange.cpMax);
   if(selrange.cpMin == selrange.cpMax)
@@ -3125,12 +3126,12 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
   }
   case EM_SETOPTIONS:
   {
-    /* these flags are equivalent to ES_* counterparts                      
-     * ECO_READONLY is already implemented in the code, only requires 
-     * setting the bit to work                                        
-     */
-    DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
-                 ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR;
+    /* these flags are equivalent to ES_* counterparts, except for
+     * ECO_AUTOWORDSELECTION that doesn't have an ES_* counterpart,
+     * but is still stored in editor->styleFlags. */
+    const DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
+                       ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN |
+                       ECO_SELECTIONBAR | ECO_AUTOWORDSELECTION;
     DWORD settings = mask & editor->styleFlags;
     DWORD oldSettings = settings;
     DWORD changedSettings;
@@ -3151,14 +3152,8 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     }
     changedSettings = oldSettings ^ settings;
 
-    if (settings & ECO_AUTOWORDSELECTION)
-      FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n");
-
     if (oldSettings ^ settings) {
-      DWORD dwStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
-
       editor->styleFlags = (editor->styleFlags & ~mask) | (settings & mask);
-      SetWindowLongW(editor->hWnd, GWL_STYLE, (dwStyle & ~mask) | (settings & mask));
 
       if (settings & ECO_SELECTIONBAR) {
         editor->selofs = SELECTIONBAR_WIDTH;
@@ -3180,6 +3175,8 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
       FIXME("ECO_NOHIDESEL not implemented yet!\n");
     if (settings & ECO_WANTRETURN)
       FIXME("ECO_WANTRETURN not implemented yet!\n");
+    if (settings & ECO_AUTOWORDSELECTION)
+      FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n");
 
     return settings;
   }
@@ -3333,15 +3330,10 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
   }
   case EM_SETREADONLY:
   {
-    LONG winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
-    if (wParam) {
+    if (wParam)
       editor->styleFlags |= ES_READONLY;
-      winStyle |= ES_READONLY;
-    } else {
+    else
       editor->styleFlags &= ~ES_READONLY;
-      winStyle &= ~ES_READONLY;
-    }
-    SetWindowLongW(editor->hWnd, GWL_STYLE, winStyle);
     return 0;
   }
   case EM_SETEVENTMASK:
@@ -3931,8 +3923,13 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     si.nMax = (si.fMask & SIF_DISABLENOSCROLL) ? 1 : 0;
     si.nMin = 0;
     si.nPage = 0;
-    SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
-    SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
+    if (editor->hWnd) {
+      SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
+      SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
+    } else {
+      ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, si.nMin, si.nMax, TRUE);
+      ITextHost_TxSetScrollRange(editor->texthost, SB_HORZ, si.nMin, si.nMax, TRUE);
+    }
 
     ME_CommitUndo(editor);
     ME_WrapMarkedParagraphs(editor);
@@ -4000,44 +3997,6 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     if (!ME_ShowContextMenu(editor, (short)LOWORD(lParam), (short)HIWORD(lParam)))
       goto do_default;
     break;
-  case WM_PAINT:
-    {
-      HDC hDC;
-      RECT rc;
-      PAINTSTRUCT ps;
-
-      hDC = BeginPaint(editor->hWnd, &ps);
-      /* Erase area outside of the formatting rectangle */
-      if (ps.rcPaint.top < editor->rcFormat.top)
-      {
-        rc = ps.rcPaint;
-        rc.bottom = editor->rcFormat.top;
-        FillRect(hDC, &rc, editor->hbrBackground);
-        ps.rcPaint.top = editor->rcFormat.top;
-      }
-      if (ps.rcPaint.bottom > editor->rcFormat.bottom) {
-        rc = ps.rcPaint;
-        rc.top = editor->rcFormat.bottom;
-        FillRect(hDC, &rc, editor->hbrBackground);
-        ps.rcPaint.bottom = editor->rcFormat.bottom;
-      }
-      if (ps.rcPaint.left < editor->rcFormat.left) {
-        rc = ps.rcPaint;
-        rc.right = editor->rcFormat.left;
-        FillRect(hDC, &rc, editor->hbrBackground);
-        ps.rcPaint.left = editor->rcFormat.left;
-      }
-      if (ps.rcPaint.right > editor->rcFormat.right) {
-        rc = ps.rcPaint;
-        rc.left = editor->rcFormat.right;
-        FillRect(hDC, &rc, editor->hbrBackground);
-        ps.rcPaint.right = editor->rcFormat.right;
-      }
-
-      ME_PaintContent(editor, hDC, FALSE, &ps.rcPaint);
-      EndPaint(editor->hWnd, &ps);
-    }
-    break;
   case WM_SETFOCUS:
     editor->bHaveFocus = TRUE;
     ME_ShowCaret(editor);
@@ -4049,16 +4008,6 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     ME_HideCaret(editor);
     ME_SendOldNotify(editor, EN_KILLFOCUS);
     return 0;
-  case WM_ERASEBKGND:
-  {
-    HDC hDC = (HDC)wParam;
-    RECT rc;
-    if (GetUpdateRect(editor->hWnd,&rc,TRUE))
-    {
-      FillRect(hDC, &rc, editor->hbrBackground);
-    }
-    return 1;
-  }
   case WM_COMMAND:
     TRACE("editor wnd command = %d\n", LOWORD(wParam));
     return 0;
@@ -4242,11 +4191,11 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
   {
     if (lParam)
     {
-      DWORD exstyle = GetWindowLongW(editor->hWnd, GWL_EXSTYLE);
-      int border = (exstyle & WS_EX_CLIENTEDGE) ? 1 : 0;
+      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)
       {
@@ -4467,7 +4416,81 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
     }
   }
 
-  lresult = ME_HandleMessage(editor, msg, wParam, lParam, unicode, &hresult);
+  switch (msg)
+  {
+    case WM_PAINT:
+    {
+      HDC hDC;
+      RECT rc;
+      PAINTSTRUCT ps;
+
+      hDC = BeginPaint(editor->hWnd, &ps);
+      /* Erase area outside of the formatting rectangle */
+      if (ps.rcPaint.top < editor->rcFormat.top)
+      {
+        rc = ps.rcPaint;
+        rc.bottom = editor->rcFormat.top;
+        FillRect(hDC, &rc, editor->hbrBackground);
+        ps.rcPaint.top = editor->rcFormat.top;
+      }
+      if (ps.rcPaint.bottom > editor->rcFormat.bottom) {
+        rc = ps.rcPaint;
+        rc.top = editor->rcFormat.bottom;
+        FillRect(hDC, &rc, editor->hbrBackground);
+        ps.rcPaint.bottom = editor->rcFormat.bottom;
+      }
+      if (ps.rcPaint.left < editor->rcFormat.left) {
+        rc = ps.rcPaint;
+        rc.right = editor->rcFormat.left;
+        FillRect(hDC, &rc, editor->hbrBackground);
+        ps.rcPaint.left = editor->rcFormat.left;
+      }
+      if (ps.rcPaint.right > editor->rcFormat.right) {
+        rc = ps.rcPaint;
+        rc.left = editor->rcFormat.right;
+        FillRect(hDC, &rc, editor->hbrBackground);
+        ps.rcPaint.right = editor->rcFormat.right;
+      }
+
+      ME_PaintContent(editor, hDC, FALSE, &ps.rcPaint);
+      EndPaint(editor->hWnd, &ps);
+      return 0;
+    }
+    case WM_ERASEBKGND:
+    {
+      HDC hDC = (HDC)wParam;
+      RECT rc;
+
+      if (GetUpdateRect(editor->hWnd, &rc, TRUE))
+        FillRect(hDC, &rc, editor->hbrBackground);
+      return 1;
+    }
+    case EM_SETOPTIONS:
+    {
+      DWORD dwStyle;
+      const DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
+                         ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN |
+                         ECO_SELECTIONBAR;
+      lresult = ME_HandleMessage(editor, msg, wParam, lParam, unicode, &hresult);
+      dwStyle = GetWindowLongW(hWnd, GWL_STYLE);
+      dwStyle = (dwStyle & ~mask) | (lresult & mask);
+      SetWindowLongW(hWnd, GWL_STYLE, dwStyle);
+      return lresult;
+    }
+    case EM_SETREADONLY:
+    {
+      DWORD dwStyle;
+      lresult = ME_HandleMessage(editor, msg, wParam, lParam, unicode, &hresult);
+      dwStyle = GetWindowLongW(hWnd, GWL_STYLE);
+      dwStyle &= ~ES_READONLY;
+      if (wParam)
+        dwStyle |= ES_READONLY;
+      SetWindowLongW(hWnd, GWL_STYLE, dwStyle);
+      return lresult;
+    }
+    default:
+      lresult = ME_HandleMessage(editor, msg, wParam, lParam, unicode, &hresult);
+  }
 
   if (hresult == S_FALSE)
     lresult = DefWindowProcW(hWnd, msg, wParam, lParam);
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 02fa828..7ac476d 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -338,6 +338,7 @@ typedef struct tagME_TextEditor
   ME_TextBuffer *pBuffer;
   ME_Cursor *pCursors;
   DWORD styleFlags;
+  DWORD exStyleFlags;
   int nCursors;
   SIZE sizeWindow;
   int nTotalLength, nLastTotalLength;
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index c5eafe1..728b623 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -1036,7 +1036,6 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
 
 void ME_ScrollAbs(ME_TextEditor *editor, int x, int y)
 {
-  LONG winStyle;
   BOOL bScrollBarIsVisible, bScrollBarWillBeVisible;
   int scrollX = 0, scrollY = 0;
 
@@ -1065,20 +1064,23 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y)
                                NULL, NULL, SW_INVALIDATE);
   ME_Repaint(editor);
 
-  winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
-  bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0;
-  bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx)
-                            || (editor->styleFlags & ES_DISABLENOSCROLL);
-  if (bScrollBarIsVisible != bScrollBarWillBeVisible)
-    ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ,
-                              bScrollBarWillBeVisible);
-
-  bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0;
-  bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy)
-                            || (editor->styleFlags & ES_DISABLENOSCROLL);
-  if (bScrollBarIsVisible != bScrollBarWillBeVisible)
-    ITextHost_TxShowScrollBar(editor->texthost, SB_VERT,
-                              bScrollBarWillBeVisible);
+  if (editor->hWnd)
+  {
+    LONG winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
+    bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0;
+    bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx)
+                              || (editor->styleFlags & ES_DISABLENOSCROLL);
+    if (bScrollBarIsVisible != bScrollBarWillBeVisible)
+      ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ,
+                                bScrollBarWillBeVisible);
+
+    bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0;
+    bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy)
+                              || (editor->styleFlags & ES_DISABLENOSCROLL);
+    if (bScrollBarIsVisible != bScrollBarWillBeVisible)
+      ITextHost_TxShowScrollBar(editor->texthost, SB_VERT,
+                                bScrollBarWillBeVisible);
+  }
   ME_UpdateScrollBar(editor);
 }
 
@@ -1152,8 +1154,14 @@ void ME_UpdateScrollBar(ME_TextEditor *editor)
     editor->horz_si.nMin = si.nMin;
     editor->horz_si.nMax = si.nMax;
     editor->horz_si.nPage = si.nPage;
-    if (bScrollBarWillBeVisible || bScrollBarWasVisible)
-      SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
+    if (bScrollBarWillBeVisible || bScrollBarWasVisible) {
+      if (editor->hWnd) {
+        SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
+      } else {
+        ITextHost_TxSetScrollRange(editor->texthost, SB_HORZ, si.nMin, si.nMax, FALSE);
+        ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, si.nPos, TRUE);
+      }
+    }
   }
 
   if (si.fMask & SIF_DISABLENOSCROLL)
@@ -1186,8 +1194,14 @@ void ME_UpdateScrollBar(ME_TextEditor *editor)
     editor->vert_si.nMin = si.nMin;
     editor->vert_si.nMax = si.nMax;
     editor->vert_si.nPage = si.nPage;
-    if (bScrollBarWillBeVisible || bScrollBarWasVisible)
-      SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
+    if (bScrollBarWillBeVisible || bScrollBarWasVisible) {
+      if (editor->hWnd) {
+        SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
+      } else {
+        ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, si.nMin, si.nMax, FALSE);
+        ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, si.nPos, TRUE);
+      }
+    }
   }
 
   if (si.fMask & SIF_DISABLENOSCROLL)
diff --git a/dlls/riched20/txthost.c b/dlls/riched20/txthost.c
index 6a4ed56..a8a47f6 100644
--- a/dlls/riched20/txthost.c
+++ b/dlls/riched20/txthost.c
@@ -58,6 +58,7 @@ ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10)
         texthost->bEmulateVersion10 = bEmulateVersion10;
 
         editor = ME_MakeEditor((ITextHost*)texthost, bEmulateVersion10);
+        editor->exStyleFlags = GetWindowLongW(hwnd, GWL_EXSTYLE);
         editor->hWnd = hwnd; /* FIXME: Remove editor's dependance on hWnd */
         SetWindowLongPtrW(hwnd, 0, (LONG_PTR)editor);
     }


More information about the wine-patches mailing list