Commit 5bcb15dd authored by Dylan Smith's avatar Dylan Smith Committed by Alexandre Julliard

richedit: Handle ctrl-key shortcuts on WM_KEYDOWN.

parent aa3b75f6
...@@ -1938,6 +1938,93 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH ...@@ -1938,6 +1938,93 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
return -1; return -1;
} }
typedef struct tagME_GlobalDestStruct
{
HGLOBAL hData;
int nLength;
} ME_GlobalDestStruct;
static DWORD CALLBACK ME_ReadFromHGLOBALUnicode(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
{
ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
int i;
WORD *pSrc, *pDest;
cb = cb >> 1;
pDest = (WORD *)lpBuff;
pSrc = (WORD *)GlobalLock(pData->hData);
for (i = 0; i<cb && pSrc[pData->nLength+i]; i++) {
pDest[i] = pSrc[pData->nLength+i];
}
pData->nLength += i;
*pcb = 2*i;
GlobalUnlock(pData->hData);
return 0;
}
static DWORD CALLBACK ME_ReadFromHGLOBALRTF(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
{
ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
int i;
BYTE *pSrc, *pDest;
pDest = lpBuff;
pSrc = (BYTE *)GlobalLock(pData->hData);
for (i = 0; i<cb && pSrc[pData->nLength+i]; i++) {
pDest[i] = pSrc[pData->nLength+i];
}
pData->nLength += i;
*pcb = i;
GlobalUnlock(pData->hData);
return 0;
}
static BOOL ME_Paste(ME_TextEditor *editor)
{
DWORD dwFormat = 0;
EDITSTREAM es;
ME_GlobalDestStruct gds;
UINT nRTFFormat = RegisterClipboardFormatA("Rich Text Format");
UINT cf = 0;
if (IsClipboardFormatAvailable(nRTFFormat))
cf = nRTFFormat, dwFormat = SF_RTF;
else if (IsClipboardFormatAvailable(CF_UNICODETEXT))
cf = CF_UNICODETEXT, dwFormat = SF_TEXT|SF_UNICODE;
else
return FALSE;
if (!OpenClipboard(editor->hWnd))
return FALSE;
gds.hData = GetClipboardData(cf);
gds.nLength = 0;
es.dwCookie = (DWORD)&gds;
es.pfnCallback = dwFormat == SF_RTF ? ME_ReadFromHGLOBALRTF : ME_ReadFromHGLOBALUnicode;
ME_StreamIn(editor, dwFormat|SFF_SELECTION, &es, FALSE);
CloseClipboard();
return TRUE;
}
static BOOL ME_Copy(ME_TextEditor *editor, CHARRANGE *range)
{
LPDATAOBJECT dataObj = NULL;
HRESULT hr = S_OK;
if (editor->cPasswordMask)
return FALSE; /* Copying or Cutting masked text isn't allowed */
if(editor->lpOleCallback)
hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, range, RECO_COPY, &dataObj);
if(FAILED(hr) || !dataObj)
hr = ME_GetDataObject(editor, range, &dataObj);
if(SUCCEEDED(hr)) {
hr = OleSetClipboard(dataObj);
IDataObject_Release(dataObj);
}
return SUCCEEDED(hr) != 0;
}
/* helper to send a msg filter notification */ /* helper to send a msg filter notification */
static BOOL static BOOL
ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam) ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam)
...@@ -2023,6 +2110,49 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) ...@@ -2023,6 +2110,49 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
ME_UpdateRepaint(editor); ME_UpdateRepaint(editor);
ME_SendRequestResize(editor, FALSE); ME_SendRequestResize(editor, FALSE);
return TRUE; return TRUE;
case 'A':
if (ctrl_is_down)
{
ME_SetSelection(editor, 0, -1);
return TRUE;
}
break;
case 'V':
if (ctrl_is_down)
return ME_Paste(editor);
break;
case 'C':
case 'X':
if (ctrl_is_down)
{
CHARRANGE range;
BOOL result;
ME_GetSelection(editor, &range.cpMin, &range.cpMax);
result = ME_Copy(editor, &range);
if (result && nKey == 'X')
{
ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE);
ME_CommitUndo(editor);
ME_UpdateRepaint(editor);
}
return result;
}
break;
case 'Z':
if (ctrl_is_down)
{
ME_Undo(editor);
return TRUE;
}
break;
case 'Y':
if (ctrl_is_down)
{
ME_Redo(editor);
return TRUE;
}
break;
default: default:
if (nKey != VK_SHIFT && nKey != VK_CONTROL && nKey && nKey != VK_MENU) if (nKey != VK_SHIFT && nKey != VK_CONTROL && nKey && nKey != VK_MENU)
...@@ -2270,48 +2400,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) { ...@@ -2270,48 +2400,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
return ed; return ed;
} }
typedef struct tagME_GlobalDestStruct
{
HGLOBAL hData;
int nLength;
} ME_GlobalDestStruct;
static DWORD CALLBACK ME_ReadFromHGLOBALUnicode(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
{
ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
int i;
WORD *pSrc, *pDest;
cb = cb >> 1;
pDest = (WORD *)lpBuff;
pSrc = (WORD *)GlobalLock(pData->hData);
for (i = 0; i<cb && pSrc[pData->nLength+i]; i++) {
pDest[i] = pSrc[pData->nLength+i];
}
pData->nLength += i;
*pcb = 2*i;
GlobalUnlock(pData->hData);
return 0;
}
static DWORD CALLBACK ME_ReadFromHGLOBALRTF(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
{
ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
int i;
BYTE *pSrc, *pDest;
pDest = lpBuff;
pSrc = (BYTE *)GlobalLock(pData->hData);
for (i = 0; i<cb && pSrc[pData->nLength+i]; i++) {
pDest[i] = pSrc[pData->nLength+i];
}
pData->nLength += i;
*pcb = i;
GlobalUnlock(pData->hData);
return 0;
}
void ME_DestroyEditor(ME_TextEditor *editor) void ME_DestroyEditor(ME_TextEditor *editor)
{ {
ME_DisplayItem *pFirst = editor->pBuffer->pFirst; ME_DisplayItem *pFirst = editor->pBuffer->pFirst;
...@@ -3066,51 +3154,15 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ...@@ -3066,51 +3154,15 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
return FALSE; return FALSE;
} }
case WM_PASTE: case WM_PASTE:
{ ME_Paste(editor);
DWORD dwFormat = 0;
EDITSTREAM es;
ME_GlobalDestStruct gds;
UINT nRTFFormat = RegisterClipboardFormatA("Rich Text Format");
UINT cf = 0;
if (IsClipboardFormatAvailable(nRTFFormat))
cf = nRTFFormat, dwFormat = SF_RTF;
else if (IsClipboardFormatAvailable(CF_UNICODETEXT))
cf = CF_UNICODETEXT, dwFormat = SF_TEXT|SF_UNICODE;
else
return 0;
if (!OpenClipboard(hWnd))
return 0;
gds.hData = GetClipboardData(cf);
gds.nLength = 0;
es.dwCookie = (DWORD)&gds;
es.pfnCallback = dwFormat == SF_RTF ? ME_ReadFromHGLOBALRTF : ME_ReadFromHGLOBALUnicode;
ME_StreamIn(editor, dwFormat|SFF_SELECTION, &es, FALSE);
CloseClipboard();
return 0; return 0;
}
case WM_CUT: case WM_CUT:
case WM_COPY: case WM_COPY:
{ {
LPDATAOBJECT dataObj = NULL;
CHARRANGE range; CHARRANGE range;
HRESULT hr = S_OK;
if (editor->cPasswordMask)
return 0; /* Copying or Cutting masked text isn't allowed */
ME_GetSelection(editor, &range.cpMin, &range.cpMax); ME_GetSelection(editor, &range.cpMin, &range.cpMax);
if(editor->lpOleCallback)
hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, &range, RECO_COPY, &dataObj); if (ME_Copy(editor, &range) && msg == WM_CUT)
if(FAILED(hr) || !dataObj)
hr = ME_GetDataObject(editor, &range, &dataObj);
if(SUCCEEDED(hr)) {
hr = OleSetClipboard(dataObj);
IDataObject_Release(dataObj);
}
if (SUCCEEDED(hr) && msg == WM_CUT)
{ {
ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE); ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE);
ME_CommitUndo(editor); ME_CommitUndo(editor);
...@@ -3657,36 +3709,11 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ...@@ -3657,36 +3709,11 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1); MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1);
} }
switch (wstr)
{
case 1: /* Ctrl-A */
ME_SetSelection(editor, 0, -1);
return 0;
case 3: /* Ctrl-C */
SendMessageW(editor->hWnd, WM_COPY, 0, 0);
return 0;
}
if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY) { if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY) {
MessageBeep(MB_ICONERROR); MessageBeep(MB_ICONERROR);
return 0; /* FIXME really 0 ? */ return 0; /* FIXME really 0 ? */
} }
switch (wstr)
{
case 22: /* Ctrl-V */
SendMessageW(editor->hWnd, WM_PASTE, 0, 0);
return 0;
case 24: /* Ctrl-X */
SendMessageW(editor->hWnd, WM_CUT, 0, 0);
return 0;
case 25: /* Ctrl-Y */
SendMessageW(editor->hWnd, EM_REDO, 0, 0);
return 0;
case 26: /* Ctrl-Z */
SendMessageW(editor->hWnd, EM_UNDO, 0, 0);
return 0;
}
if (((unsigned)wstr)>=' ' if (((unsigned)wstr)>=' '
|| (wstr=='\r' && (GetWindowLongW(hWnd, GWL_STYLE) & ES_MULTILINE)) || (wstr=='\r' && (GetWindowLongW(hWnd, GWL_STYLE) & ES_MULTILINE))
|| wstr=='\t') { || wstr=='\t') {
......
...@@ -4495,7 +4495,7 @@ static void test_WM_PASTE(void) ...@@ -4495,7 +4495,7 @@ static void test_WM_PASTE(void)
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
/* Shouldn't paste because pasting is handled by WM_KEYDOWN */ /* Shouldn't paste because pasting is handled by WM_KEYDOWN */
result = strcmp(buffer,""); result = strcmp(buffer,"");
todo_wine ok(result == 0, ok(result == 0,
"test paste: strcmp = %i, actual = '%s'\n", result, buffer); "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
/* Send keystrokes with WM_KEYDOWN after setting the modifiers /* Send keystrokes with WM_KEYDOWN after setting the modifiers
...@@ -4509,7 +4509,7 @@ static void test_WM_PASTE(void) ...@@ -4509,7 +4509,7 @@ static void test_WM_PASTE(void)
release_key(VK_CONTROL); release_key(VK_CONTROL);
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
result = strcmp(buffer,"paste"); result = strcmp(buffer,"paste");
todo_wine ok(result == 0, ok(result == 0,
"test paste: strcmp = %i, actual = '%s'\n", result, buffer); "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text1); SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text1);
...@@ -4523,7 +4523,7 @@ static void test_WM_PASTE(void) ...@@ -4523,7 +4523,7 @@ static void test_WM_PASTE(void)
SendMessage(hwndRichEdit, WM_PASTE, 0, 0); SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
result = strcmp(buffer,"testing"); result = strcmp(buffer,"testing");
todo_wine ok(result == 0, ok(result == 0,
"test paste: strcmp = %i, actual = '%s'\n", result, buffer); "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
/* Cut with WM_KEYDOWN to simulate Ctrl-X */ /* Cut with WM_KEYDOWN to simulate Ctrl-X */
...@@ -4538,7 +4538,7 @@ static void test_WM_PASTE(void) ...@@ -4538,7 +4538,7 @@ static void test_WM_PASTE(void)
release_key(VK_CONTROL); release_key(VK_CONTROL);
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
result = strcmp(buffer,""); result = strcmp(buffer,"");
todo_wine ok(result == 0, ok(result == 0,
"test paste: strcmp = %i, actual = '%s'\n", result, buffer); "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) NULL); SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) NULL);
SendMessage(hwndRichEdit, WM_PASTE, 0, 0); SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
...@@ -4552,7 +4552,7 @@ static void test_WM_PASTE(void) ...@@ -4552,7 +4552,7 @@ static void test_WM_PASTE(void)
(MapVirtualKey('Z', MAPVK_VK_TO_VSC) << 16) & 1); (MapVirtualKey('Z', MAPVK_VK_TO_VSC) << 16) & 1);
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
result = strcmp(buffer,""); result = strcmp(buffer,"");
todo_wine ok(result == 0, ok(result == 0,
"test paste: strcmp = %i, actual = '%s'\n", result, buffer); "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
/* Simulates redo (Ctrl-Y) */ /* Simulates redo (Ctrl-Y) */
SendMessage(hwndRichEdit, WM_KEYDOWN, 'Y', SendMessage(hwndRichEdit, WM_KEYDOWN, 'Y',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment