riched20: Implement EM_SETPASSWORDCHAR and EM_GETPASSWORDCHAR.

This commit is contained in:
Matt Finnicum 2006-08-04 15:47:44 -04:00 committed by Alexandre Julliard
parent 4961379d74
commit 2b92bf78d1
7 changed files with 132 additions and 16 deletions

View File

@ -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
@ -1146,6 +1146,12 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ed->pFontCache[i].hFont = NULL;
}
ME_CheckCharOffsets(ed);
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_PASSWORD)
ed->cPasswordMask = '*';
else
ed->cPasswordMask = 0;
return ed;
}
@ -1418,7 +1424,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
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)
@ -1432,7 +1437,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
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)
@ -1933,6 +1937,10 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
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);
@ -2473,6 +2481,10 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
LPVOID *ppvObj = (LPVOID*) lParam;
return CreateIRichEditOle(editor, ppvObj);
}
case EM_GETPASSWORDCHAR:
{
return editor->cPasswordMask;
}
case EM_SETOLECALLBACK:
if(editor->lpOleCallback)
IUnknown_Release(editor->lpOleCallback);
@ -2515,6 +2527,12 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
}
return ret;
}
case EM_SETPASSWORDCHAR:
{
editor->cPasswordMask = wParam;
ME_RewrapRepaint(editor);
return 0;
}
default:
do_default:
return DefWindowProcW(hWnd, msg, wParam, lParam);

View File

@ -75,6 +75,8 @@ const char *ME_GetDITypeName(ME_DIType type);
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);

View File

@ -320,6 +320,7 @@ typedef struct tagME_TextEditor
int mode;
BOOL bHideSelection;
BOOL AutoURLDetect_bEnable;
WCHAR cPasswordMask;
} ME_TextEditor;
typedef struct tagME_Context

View File

@ -222,7 +222,8 @@ void ME_DrawGraphics(ME_Context *c, int x, int y, ME_Run *run,
}
}
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, int x, int y, ME_DisplayItem *rundi, ME_Pa
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)

View File

@ -532,6 +532,9 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run)
*/
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;
@ -554,20 +557,29 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
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 *editor, ME_Run *pRun, int nOffset)
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 *editor, ME_Run *pRun, int nOffset)
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, ME_Paragraph *para, ME_Run *run, int nLe
* 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;

View File

@ -50,6 +50,32 @@ ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars)
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);

View File

@ -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.