riched20: Implement EM_SETPASSWORDCHAR and EM_GETPASSWORDCHAR

Matt Finnicum mattfinn at gmail.com
Thu Aug 3 22:21:23 CDT 2006


Hi,
This patch implements EM_SETPASSWORDCHAR and EM_GETPASSWORDCHAR. It
also adds two needed string creation functions to string.c.
--Matt

---
 dlls/riched20/editor.c       |   22 ++++++++++++++++----
 dlls/riched20/editor.h       |    2 ++
 dlls/riched20/editstr.h      |    1 +
 dlls/riched20/paint.c        |   20 +++++++++++++++---
 dlls/riched20/run.c          |   46 ++++++++++++++++++++++++++++++++++++------
 dlls/riched20/string.c       |   26 ++++++++++++++++++++++++
 dlls/riched20/tests/editor.c |   25 +++++++++++++++++++++++
 7 files changed, 126 insertions(+), 16 deletions(-)
-------------- next part --------------
From 59aa6600243455d5eb8df6eae5ec7431280ba204 Mon Sep 17 00:00:00 2001
From: Matthew Finnicum <MattFinn at gmail.com>
Date: Thu, 3 Aug 2006 20:41:01 -0400
Subject: [PATCH] riched20: Implement EM_SETPASSWORDCHAR and EM_GETPASSWORDCHAR
---
 dlls/riched20/editor.c       |   22 ++++++++++++++++----
 dlls/riched20/editor.h       |    2 ++
 dlls/riched20/editstr.h      |    1 +
 dlls/riched20/paint.c        |   20 +++++++++++++++---
 dlls/riched20/run.c          |   46 ++++++++++++++++++++++++++++++++++++------
 dlls/riched20/string.c       |   26 ++++++++++++++++++++++++
 dlls/riched20/tests/editor.c |   25 +++++++++++++++++++++++
 7 files changed, 126 insertions(+), 16 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 390ac3b..cee0ace 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -58,7 +58,7 @@
   - EM_GETOLEINTERFACE
   + EM_GETOPTIONS
   + EM_GETPARAFORMAT
-  - EM_GETPASSWORDCHAR 2.0
+  + EM_GETPASSWORDCHAR 2.0
   - EM_GETPUNCTUATION 1.0asian
   + EM_GETRECT
   - EM_GETREDONAME 2.0
@@ -105,7 +105,7 @@
   + EM_SETOPTIONS (partially implemented)
   - EM_SETPALETTE 2.0
   + EM_SETPARAFORMAT
-  - EM_SETPASSWORDCHAR 2.0
+  + EM_SETPASSWORDCHAR 2.0
   - EM_SETPUNCTUATION 1.0asian
   + EM_SETREADONLY no beep on modification attempt
   + EM_SETRECT
@@ -1412,7 +1412,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   UNSUPPORTED_MSG(EM_GETLANGOPTIONS)
   UNSUPPORTED_MSG(EM_GETLIMITTEXT)
   /* UNSUPPORTED_MSG(EM_GETOLEINTERFACE) separate stub */
-  UNSUPPORTED_MSG(EM_GETPASSWORDCHAR)
   UNSUPPORTED_MSG(EM_GETREDONAME)
   UNSUPPORTED_MSG(EM_GETTEXTMODE)
   UNSUPPORTED_MSG(EM_GETTYPOGRAPHYOPTIONS)
@@ -1426,7 +1425,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   UNSUPPORTED_MSG(EM_SETFONTSIZE)
   UNSUPPORTED_MSG(EM_SETLANGOPTIONS)
   UNSUPPORTED_MSG(EM_SETPALETTE)
-  UNSUPPORTED_MSG(EM_SETPASSWORDCHAR)
   UNSUPPORTED_MSG(EM_SETSCROLLPOS)
   UNSUPPORTED_MSG(EM_SETTABSTOPS)
   UNSUPPORTED_MSG(EM_SETTARGETDEVICE)
@@ -1927,6 +1925,10 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     LPDATAOBJECT dataObj = NULL;
     CHARRANGE range;
     HRESULT hr = S_OK;
+    
+    if (editor->cPasswordMask)
+      return 0; /* Copying or Cutting masked text isn't allowed */
+    
     ME_GetSelection(editor, (int*)&range.cpMin, (int*)&range.cpMax);
     if(editor->lpOleCallback)
         hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, &range, RECO_COPY, &dataObj);
@@ -2463,6 +2465,10 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     LPVOID *ppvObj = (LPVOID*) lParam;
     return CreateIRichEditOle(editor, ppvObj);
   }
+  case EM_GETPASSWORDCHAR:
+  {
+    return editor->cPasswordMask;
+  }
   case EM_SETOLECALLBACK:
     if(editor->lpOleCallback)
       IUnknown_Release(editor->lpOleCallback);
@@ -2504,7 +2510,13 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
       }
     }
     return ret;
-  }      
+  }
+  case EM_SETPASSWORDCHAR:
+  {
+    editor->cPasswordMask = wParam;
+    ME_RewrapRepaint(editor);
+    return 0;
+  }
   default:
   do_default:
     return DefWindowProcW(hWnd, msg, wParam, lParam);
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index a4d4980..93952fd 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -75,6 +75,8 @@ const char *ME_GetDITypeName(ME_DIType t
 int ME_GetOptimalBuffer(int nLen);
 ME_String *ME_MakeString(LPCWSTR szText);
 ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars);
+ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars);
+ME_String *ME_MakeStringB(int nMaxChars);
 ME_String *ME_StrDup(ME_String *s);
 void ME_DestroyString(ME_String *s);
 void ME_AppendString(ME_String *s1, ME_String *s2);
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 10e4be2..7d096e8 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -320,6 +320,7 @@ typedef struct tagME_TextEditor
   int mode;
   BOOL bHideSelection;
   BOOL AutoURLDetect_bEnable;
+  WCHAR cPasswordMask;
 } ME_TextEditor;
 
 typedef struct tagME_Context
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index f3f5ac1..f26583c 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -222,7 +222,8 @@ void ME_DrawGraphics(ME_Context *c, int 
   }
 }
 
-static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) {
+static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) 
+{
   ME_Run *run = &rundi->member.run;
   ME_DisplayItem *start = ME_FindItemBack(rundi, diStartRow);
   int runofs = run->nCharOfs+para->nCharOfs;
@@ -247,9 +248,20 @@ static void ME_DrawRun(ME_Context *c, in
   if (run->nFlags & MERF_GRAPHICS)
     ME_DrawGraphics(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo));
   else
-    ME_DrawTextWithStyle(c, x, y, 
-      run->strText->szData, ME_StrVLen(run->strText), run->style, NULL, 
-        nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight);
+  {
+    if (c->editor->cPasswordMask)
+    {
+      ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText));
+      ME_DrawTextWithStyle(c, x, y, 
+        szMasked->szData, ME_StrVLen(szMasked), run->style, NULL, 
+	nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight);
+      ME_DestroyString(szMasked);
+    }
+    else
+      ME_DrawTextWithStyle(c, x, y, 
+        run->strText->szData, ME_StrVLen(run->strText), run->style, NULL, 
+	nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight);
+    }
 }
 
 COLORREF ME_GetBackColor(ME_TextEditor *editor)
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index a2c121a..d74d68f 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -532,6 +532,9 @@ int ME_CharFromPoint(ME_TextEditor *edit
  */     
 int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
 {
+  ME_String *strRunText;
+  /* This could point to either the run's real text, or it's masked form in a password control */
+	
   int fit = 0, fit1 = 0;
   HGDIOBJ hOldFont;
   HDC hDC;
@@ -553,21 +556,30 @@ int ME_CharFromPointCursor(ME_TextEditor
       return 0;
     return 1;
   }
+  
+  if (editor->cPasswordMask)
+    strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(run->strText));
+  else
+    strRunText = run->strText;
 
   hDC = GetDC(editor->hWnd);
   hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
-  GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
+  GetTextExtentExPointW(hDC, strRunText->szData, strRunText->nLen,
     cx, &fit, NULL, &sz);
-  if (fit != run->strText->nLen)
+  if (fit != strRunText->nLen)
   {
     int chars = 1;
 
-    GetTextExtentPoint32W(hDC, run->strText->szData, fit, &sz2);
-    fit1 = ME_StrRelPos(run->strText, fit, &chars);
-    GetTextExtentPoint32W(hDC, run->strText->szData, fit1, &sz3);
+    GetTextExtentPoint32W(hDC, strRunText->szData, fit, &sz2);
+    fit1 = ME_StrRelPos(strRunText, fit, &chars);
+    GetTextExtentPoint32W(hDC, strRunText->szData, fit1, &sz3);
     if (cx >= (sz2.cx+sz3.cx)/2)
       fit = fit1;
   }
+  
+  if (editor->cPasswordMask)
+    ME_DestroyString(strRunText);
+  
   ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
   ReleaseDC(editor->hWnd, hDC);
   return fit;
@@ -584,6 +596,8 @@ int ME_PointFromChar(ME_TextEditor *edit
   SIZE size;
   HDC hDC = GetDC(editor->hWnd);
   HGDIOBJ hOldFont;
+  ME_String *strRunText;
+  /* This could point to either the run's real text, or it's masked form in a password control */
 
   if (pRun->nFlags & MERF_GRAPHICS)
   {
@@ -591,10 +605,18 @@ int ME_PointFromChar(ME_TextEditor *edit
     ME_GetGraphicsSize(editor, pRun, &size);
     return 1;
   }
+  
+   if (editor->cPasswordMask)
+    strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(pRun->strText));
+  else
+    strRunText = pRun->strText;
+  
   hOldFont = ME_SelectStyleFont(editor, hDC, pRun->style);
-  GetTextExtentPoint32W(hDC, pRun->strText->szData, nOffset, &size);
+  GetTextExtentPoint32W(hDC, strRunText->szData, nOffset, &size);
   ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont);
   ReleaseDC(editor->hWnd, hDC);
+  if (editor->cPasswordMask)
+    ME_DestroyString(strRunText);
   return size.cx;
 }
 
@@ -631,7 +653,17 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, 
    * this is wasteful for MERF_NONTEXT runs, but that shouldn't matter
    * in practice
    */
-  ME_GetTextExtent(c, run->strText->szData, nLen, run->style, &size);
+  
+  if (c->editor->cPasswordMask)
+  {
+    ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,nLen);
+    ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size); 
+    ME_DestroyString(szMasked);
+  }
+  else
+  {
+    ME_GetTextExtent(c, run->strText->szData, nLen, run->style, &size);
+  }
   *pAscent = run->style->tm.tmAscent;
   *pDescent = run->style->tm.tmDescent;
   size.cy = *pAscent + *pDescent;
diff --git a/dlls/riched20/string.c b/dlls/riched20/string.c
index b529373..57a304a 100644
--- a/dlls/riched20/string.c
+++ b/dlls/riched20/string.c
@@ -50,6 +50,32 @@ ME_String *ME_MakeStringN(LPCWSTR szText
   return s;
 }
 
+ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars)
+{ /* Make a string by repeating a char nMaxChars times */
+  int i;
+   ME_String *s = ALLOC_OBJ(ME_String);
+  
+  s->nLen = nMaxChars;
+  s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
+  s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
+
+  for (i = 0;i<nMaxChars;i++)
+    s->szData[i] = cRepeat;
+  s->szData[s->nLen] = 0;
+  return s;
+}
+
+ME_String *ME_MakeStringB(int nMaxChars)
+{ /* Create a buffer (uninitialized string) of size nMaxChars */
+  ME_String *s = ALLOC_OBJ(ME_String);
+  
+  s->nLen = nMaxChars;
+  s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
+  s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
+  s->szData[s->nLen] = 0;
+  return s;
+}
+
 ME_String *ME_StrDup(ME_String *s)
 {
   return ME_MakeStringN(s->szData, s->nLen);
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index dd4f2dd..3424626 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -873,6 +873,30 @@ static void test_EM_SETUNDOLIMIT()
   DestroyWindow(hwndRichEdit);
 }
 
+static void test_ES_PASSWORD()
+{
+  /* This isn't hugely testable, so we're just going to run it through it's paces. */
+	
+  HWND hwndRichEdit = new_richedit(NULL);
+  WCHAR result;
+	
+  /* First, check the default of a regular control */
+  result = SendMessage(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
+  ok (result == 0,
+	"EM_GETPASSWORDCHAR returned %c by default, instead of NULL\n",result);
+  
+  /* Now, set it to something normal */
+  SendMessage(hwndRichEdit, EM_SETPASSWORDCHAR, 'x', 0);
+  result = SendMessage(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
+  ok (result == 120,
+	"EM_GETPASSWORDCHAR returned %c (%d) when set to 'x', instead of x (120)\n",result,result);
+	
+  /* Now, set it to something odd */	
+  SendMessage(hwndRichEdit, EM_SETPASSWORDCHAR, (WCHAR)1234, 0);
+  result = SendMessage(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
+  ok (result == 1234,
+	"EM_GETPASSWORDCHAR returned %c (%d) when set to 'x', instead of x (120)\n",result,result);
+}
 
 START_TEST( editor )
 {
@@ -893,6 +917,7 @@ START_TEST( editor )
   test_WM_GETTEXT();
   test_EM_AUTOURLDETECT();
   test_EM_SETUNDOLIMIT();
+  test_ES_PASSWORD();
 
   /* Set the environment variable WINETEST_RICHED20 to keep windows
    * responsive and open for 30 seconds. This is useful for debugging.
-- 
1.4.1.1


More information about the wine-patches mailing list