riched20: Implement EM_SETPASSWORDCHAR and EM_GETPASSWORDCHAR.
This commit is contained in:
parent
4961379d74
commit
2b92bf78d1
|
@ -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);
|
||||
|
@ -2514,7 +2526,13 @@ 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -320,6 +320,7 @@ typedef struct tagME_TextEditor
|
|||
int mode;
|
||||
BOOL bHideSelection;
|
||||
BOOL AutoURLDetect_bEnable;
|
||||
WCHAR cPasswordMask;
|
||||
} ME_TextEditor;
|
||||
|
||||
typedef struct tagME_Context
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
@ -553,21 +556,30 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
|
|||
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 *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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue