[2/2] richedit: Store an internal copy of the window style flags.

Dylan Smith dylan.ah.smith at gmail.com
Thu Jan 15 13:46:25 CST 2009


I initially suspected native richedit controls stored an internal copy
of the style flags, since windowless richedit controls would have no way
of modifying the style flags on the window to process EM_SETREADONLY and
EM_SETOPTIONS.  I wrote tests that confirmed this theory, and this patch
causes those failing tests to pass.
---
 dlls/riched20/caret.c        |    2 +-
 dlls/riched20/editor.c       |   60 +++++++++++++++++++++++-------------------
 dlls/riched20/editstr.h      |    1 +
 dlls/riched20/paint.c        |    6 ++--
 dlls/riched20/tests/editor.c |   12 ++++----
 dlls/riched32/tests/editor.c |    4 +-
 6 files changed, 46 insertions(+), 39 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 3df8566..ca355b2 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -57,7 +57,7 @@ int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how)
   
   length = ME_GetTextLength(editor);
 
-  if ((GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_MULTILINE)
+  if ((editor->styleFlags & ES_MULTILINE)
         && (how->flags & GTL_USECRLF)
         && !editor->bEmulateVersion10) /* Ignore GTL_USECRLF flag in 1.0 emulation */
     length += editor->nParagraphs - 1;
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index b6f30b0..b67ca60 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -2157,7 +2157,6 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
 {
   BOOL ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000;
   BOOL shift_is_down = GetKeyState(VK_SHIFT) & 0x8000;
-  DWORD dwStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
 
   if (nKey != VK_SHIFT && nKey != VK_CONTROL && nKey != VK_MENU)
       editor->nSelectionType = stPosition;
@@ -2181,7 +2180,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
     case VK_DELETE:
       editor->nUDArrowX = -1;
       /* FIXME backspace and delete aren't the same, they act different wrt paragraph style of the merged paragraph */
-      if (dwStyle & ES_READONLY)
+      if (editor->styleFlags & ES_READONLY)
         return FALSE;
       if (ME_IsSelection(editor))
       {
@@ -2217,7 +2216,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
       ME_SendRequestResize(editor, FALSE);
       return TRUE;
     case VK_RETURN:
-      if (dwStyle & ES_MULTILINE)
+      if (editor->styleFlags & ES_MULTILINE)
       {
         ME_Cursor cursor = editor->pCursors[0];
         ME_DisplayItem *para = ME_GetParagraph(cursor.pRun);
@@ -2225,7 +2224,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
         const WCHAR endl = '\r';
         ME_Style *style;
 
-        if (dwStyle & ES_READONLY) {
+        if (editor->styleFlags & ES_READONLY) {
           MessageBeep(MB_ICONERROR);
           return TRUE;
         }
@@ -2412,7 +2411,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode,
       MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1);
   }
 
-  if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY) {
+  if (editor->styleFlags & ES_READONLY) {
     MessageBeep(MB_ICONERROR);
     return 0; /* FIXME really 0 ? */
   }
@@ -2664,6 +2663,11 @@ static ME_TextEditor *ME_MakeEditor(HWND hWnd, BOOL bEmulateVersion10)
   int i;
   ed->hWnd = hWnd;
   ed->bEmulateVersion10 = bEmulateVersion10;
+  ed->styleFlags = GetWindowLongW(hWnd, GWL_STYLE);
+  if (ed->styleFlags & WS_VSCROLL)
+    ed->styleFlags |= ES_AUTOVSCROLL;
+  if (!ed->bEmulateVersion10 && (ed->styleFlags & WS_HSCROLL))
+    ed->styleFlags |= ES_AUTOHSCROLL;
   ed->pBuffer = ME_MakeText();
   ed->nZoomNumerator = ed->nZoomDenominator = 0;
   ME_MakeFirstParagraph(ed);
@@ -2698,10 +2702,7 @@ static ME_TextEditor *ME_MakeEditor(HWND hWnd, BOOL bEmulateVersion10)
   ed->nParagraphs = 1;
   ed->nLastSelStart = ed->nLastSelEnd = 0;
   ed->pLastSelStartPara = ed->pLastSelEndPara = ME_FindItemFwd(ed->pBuffer->pFirst, diParagraph);
-  if (ed->bEmulateVersion10)
-    ed->bWordWrap = (GetWindowLongW(hWnd, GWL_STYLE) & ES_AUTOHSCROLL) ? FALSE : TRUE;
-  else
-    ed->bWordWrap = (GetWindowLongW(hWnd, GWL_STYLE) & (WS_HSCROLL|ES_AUTOHSCROLL)) ? FALSE : TRUE;
+  ed->bWordWrap = !(ed->styleFlags & ES_AUTOHSCROLL);
   ed->bHideSelection = FALSE;
   ed->nInvalidOfs = -1;
   ed->pfnWordBreak = NULL;
@@ -2716,20 +2717,20 @@ static ME_TextEditor *ME_MakeEditor(HWND hWnd, BOOL bEmulateVersion10)
     ed->pFontCache[i].nAge = 0;
     ed->pFontCache[i].hFont = NULL;
   }
-  
+
   ME_CheckCharOffsets(ed);
-  if (GetWindowLongW(hWnd, GWL_STYLE) & ES_SELECTIONBAR)
+  if (ed->styleFlags & ES_SELECTIONBAR)
     ed->selofs = SELECTIONBAR_WIDTH;
   else
     ed->selofs = 0;
   ed->bDefaultFormatRect = TRUE;
   ed->nSelectionType = stPosition;
 
-  if (GetWindowLongW(hWnd, GWL_STYLE) & ES_PASSWORD)
+  if (ed->styleFlags & ES_PASSWORD)
     ed->cPasswordMask = '*';
   else
     ed->cPasswordMask = 0;
-  
+
   ed->notified_cr.cpMin = ed->notified_cr.cpMax = 0;
 
   /* Default scrollbar information */
@@ -3039,7 +3040,7 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
   case WM_GETDLGCODE:
   {
     UINT code = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL;
-    if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_MULTILINE)
+    if (editor->styleFlags & ES_MULTILINE)
       code |= DLGC_WANTMESSAGE;
     return code;
   }
@@ -3089,7 +3090,7 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     /* these flags are equivalent to the ES_* counterparts */
     DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
                  ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR;
-    DWORD settings = GetWindowLongW(editor->hWnd, GWL_STYLE) & mask;
+    DWORD settings = editor->styleFlags & mask;
 
     return settings;
   }
@@ -3101,8 +3102,7 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
      */
     DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
                  ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR;
-    DWORD raw = GetWindowLongW(editor->hWnd, GWL_STYLE);
-    DWORD settings = mask & raw;
+    DWORD settings = mask & editor->styleFlags;
     DWORD oldSettings = settings;
     DWORD changedSettings;
 
@@ -3120,14 +3120,17 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
       case ECOOP_XOR:
         settings ^= lParam;
     }
-    SetWindowLongW(editor->hWnd, GWL_STYLE, (raw & ~mask) | (settings & mask));
-
     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;
         editor->rcFormat.left += SELECTIONBAR_WIDTH;
@@ -3287,12 +3290,15 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
   }
   case EM_SETREADONLY:
   {
-    long nStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
-    if (wParam)
-      nStyle |= ES_READONLY;
-    else
-      nStyle &= ~ES_READONLY;
-    SetWindowLongW(editor->hWnd, GWL_STYLE, nStyle);
+    LONG winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
+    if (wParam) {
+      editor->styleFlags |= ES_READONLY;
+      winStyle |= ES_READONLY;
+    } else {
+      editor->styleFlags &= ~ES_READONLY;
+      winStyle &= ~ES_READONLY;
+    }
+    SetWindowLongW(editor->hWnd, GWL_STYLE, winStyle);
     return 0;
   }
   case EM_SETEVENTMASK:
@@ -3484,7 +3490,7 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
           int len = -1;
 
           /* uses default style! */
-          if (!(GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_MULTILINE))
+          if (!(editor->styleFlags & ES_MULTILINE))
           {
             WCHAR * p;
 
@@ -3877,7 +3883,7 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
 
     si.cbSize = sizeof(si);
     si.fMask = SIF_PAGE | SIF_RANGE;
-    if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
+    if (editor->styleFlags & ES_DISABLENOSCROLL)
       si.fMask |= SIF_DISABLENOSCROLL;
     si.nMax = (si.fMask & SIF_DISABLENOSCROLL) ? 1 : 0;
     si.nMin = 0;
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 68a316c..d289509 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -330,6 +330,7 @@ typedef struct tagME_TextEditor
   BOOL bEmulateVersion10;
   ME_TextBuffer *pBuffer;
   ME_Cursor *pCursors;
+  DWORD styleFlags;
   int nCursors;
   SIZE sizeWindow;
   int nTotalLength, nLastTotalLength;
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index 5d2540b..bc0441b 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -1063,13 +1063,13 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y)
   winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
   bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0;
   bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx)
-                            || (winStyle & ES_DISABLENOSCROLL);
+                            || (editor->styleFlags & ES_DISABLENOSCROLL);
   if (bScrollBarIsVisible != bScrollBarWillBeVisible)
     ShowScrollBar(editor->hWnd, SB_HORZ, bScrollBarWillBeVisible);
 
   bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0;
   bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy)
-                            || (winStyle & ES_DISABLENOSCROLL);
+                            || (editor->styleFlags & ES_DISABLENOSCROLL);
   if (bScrollBarIsVisible != bScrollBarWillBeVisible)
     ShowScrollBar(editor->hWnd, SB_VERT, bScrollBarWillBeVisible);
 
@@ -1119,7 +1119,7 @@ void ME_UpdateScrollBar(ME_TextEditor *editor)
 
   si.cbSize = sizeof(si);
   si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
-  if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
+  if (editor->styleFlags & ES_DISABLENOSCROLL)
     si.fMask |= SIF_DISABLENOSCROLL;
 
   /* Update horizontal scrollbar */
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index 11efb7b..ff5d598 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -1478,7 +1478,7 @@ static void test_EM_SETOPTIONS(void)
        RICHEDIT_CLASS, (int) GetLastError());
     options = SendMessage(hwndRichEdit, EM_GETOPTIONS, 0, 0);
     /* WS_[VH]SCROLL cause the ECO_AUTO[VH]SCROLL options to be set */
-    todo_wine ok(options == (ECO_AUTOVSCROLL|ECO_AUTOHSCROLL),
+    ok(options == (ECO_AUTOVSCROLL|ECO_AUTOHSCROLL),
        "Incorrect initial options %x\n", options);
 
     /* NEGATIVE TESTING - NO OPTIONS SET */
@@ -1508,17 +1508,17 @@ static void test_EM_SETOPTIONS(void)
     ok(dwStyle & ES_READONLY, "Readonly style not set by EM_SETOPTIONS\n");
     SetWindowLong(hwndRichEdit, GWL_STYLE, dwStyle & ~ES_READONLY);
     options = SendMessage(hwndRichEdit, EM_GETOPTIONS, 0, 0);
-    todo_wine ok(options & ES_READONLY, "Readonly option set by SetWindowLong\n");
+    ok(options & ES_READONLY, "Readonly option set by SetWindowLong\n");
     /* Confirm that the text is still read only. */
     SendMessage(hwndRichEdit, WM_CHAR, 'a', ('a' << 16) | 0x0001);
     SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
-    todo_wine ok(buffer[0]==text[0],
+    ok(buffer[0]==text[0],
        "EM_SETOPTIONS: Text changed! s1:%s s2:%s\n", text, buffer);
 
     oldOptions = options;
     SetWindowLong(hwndRichEdit, GWL_STYLE, dwStyle|optionStyles);
     options = SendMessage(hwndRichEdit, EM_GETOPTIONS, 0, 0);
-    todo_wine ok(options == oldOptions,
+    ok(options == oldOptions,
        "Options set by SetWindowLong (%x -> %x)\n", oldOptions, options);
 
     DestroyWindow(hwndRichEdit);
@@ -5916,8 +5916,8 @@ static void test_autoscroll(void)
                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS, (int) GetLastError());
     ret = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
-    todo_wine ok(ret & ECO_AUTOVSCROLL, "ECO_AUTOVSCROLL isn't set.\n");
-    todo_wine ok(ret & ECO_AUTOHSCROLL, "ECO_AUTOHSCROLL isn't set.\n");
+    ok(ret & ECO_AUTOVSCROLL, "ECO_AUTOVSCROLL isn't set.\n");
+    ok(ret & ECO_AUTOHSCROLL, "ECO_AUTOHSCROLL isn't set.\n");
     ret = GetWindowLong(hwnd, GWL_STYLE);
     ok(!(ret & ES_AUTOVSCROLL), "ES_AUTOVSCROLL is set.\n");
     ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
diff --git a/dlls/riched32/tests/editor.c b/dlls/riched32/tests/editor.c
index ccac356..d5a2149 100644
--- a/dlls/riched32/tests/editor.c
+++ b/dlls/riched32/tests/editor.c
@@ -905,7 +905,7 @@ static void test_EM_GETOPTIONS(void)
                         WS_POPUP|WS_VSCROLL|WS_HSCROLL,
                         0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
     options = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
-    todo_wine ok(options == ECO_AUTOVSCROLL,
+    ok(options == ECO_AUTOVSCROLL,
        "Incorrect initial options %x\n", options);
     DestroyWindow(hwnd);
 }
@@ -922,7 +922,7 @@ static void test_autoscroll(void)
                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS, (int) GetLastError());
     ret = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
-    todo_wine ok(ret & ECO_AUTOVSCROLL, "ECO_AUTOVSCROLL isn't set.\n");
+    ok(ret & ECO_AUTOVSCROLL, "ECO_AUTOVSCROLL isn't set.\n");
     ok(!(ret & ECO_AUTOHSCROLL), "ECO_AUTOHSCROLL is set.\n");
     ret = GetWindowLong(hwnd, GWL_STYLE);
     todo_wine ok(ret & ES_AUTOVSCROLL, "ES_AUTOVSCROLL isn't set.\n");


More information about the wine-patches mailing list