richedit: Handle ctrl-key shortcuts on WM_KEYDOWN.
This commit is contained in:
parent
aa3b75f6b7
commit
5bcb15dd7f
|
@ -1938,6 +1938,93 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
|
|||
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 */
|
||||
static BOOL
|
||||
ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam)
|
||||
|
@ -2023,6 +2110,49 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
|
|||
ME_UpdateRepaint(editor);
|
||||
ME_SendRequestResize(editor, FALSE);
|
||||
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:
|
||||
if (nKey != VK_SHIFT && nKey != VK_CONTROL && nKey && nKey != VK_MENU)
|
||||
|
@ -2270,48 +2400,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
|
|||
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)
|
||||
{
|
||||
ME_DisplayItem *pFirst = editor->pBuffer->pFirst;
|
||||
|
@ -3066,51 +3154,15 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
|
|||
return FALSE;
|
||||
}
|
||||
case WM_PASTE:
|
||||
{
|
||||
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();
|
||||
ME_Paste(editor);
|
||||
return 0;
|
||||
}
|
||||
case WM_CUT:
|
||||
case WM_COPY:
|
||||
{
|
||||
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, &range.cpMin, &range.cpMax);
|
||||
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);
|
||||
}
|
||||
if (SUCCEEDED(hr) && msg == WM_CUT)
|
||||
|
||||
if (ME_Copy(editor, &range) && msg == WM_CUT)
|
||||
{
|
||||
ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE);
|
||||
ME_CommitUndo(editor);
|
||||
|
@ -3657,36 +3709,11 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
|
|||
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) {
|
||||
MessageBeep(MB_ICONERROR);
|
||||
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)>=' '
|
||||
|| (wstr=='\r' && (GetWindowLongW(hWnd, GWL_STYLE) & ES_MULTILINE))
|
||||
|| wstr=='\t') {
|
||||
|
|
|
@ -4495,7 +4495,7 @@ static void test_WM_PASTE(void)
|
|||
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
/* Shouldn't paste because pasting is handled by WM_KEYDOWN */
|
||||
result = strcmp(buffer,"");
|
||||
todo_wine ok(result == 0,
|
||||
ok(result == 0,
|
||||
"test paste: strcmp = %i, actual = '%s'\n", result, buffer);
|
||||
|
||||
/* Send keystrokes with WM_KEYDOWN after setting the modifiers
|
||||
|
@ -4509,7 +4509,7 @@ static void test_WM_PASTE(void)
|
|||
release_key(VK_CONTROL);
|
||||
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
result = strcmp(buffer,"paste");
|
||||
todo_wine ok(result == 0,
|
||||
ok(result == 0,
|
||||
"test paste: strcmp = %i, actual = '%s'\n", result, buffer);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text1);
|
||||
|
@ -4523,7 +4523,7 @@ static void test_WM_PASTE(void)
|
|||
SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
|
||||
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
result = strcmp(buffer,"testing");
|
||||
todo_wine ok(result == 0,
|
||||
ok(result == 0,
|
||||
"test paste: strcmp = %i, actual = '%s'\n", result, buffer);
|
||||
|
||||
/* Cut with WM_KEYDOWN to simulate Ctrl-X */
|
||||
|
@ -4538,7 +4538,7 @@ static void test_WM_PASTE(void)
|
|||
release_key(VK_CONTROL);
|
||||
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
result = strcmp(buffer,"");
|
||||
todo_wine ok(result == 0,
|
||||
ok(result == 0,
|
||||
"test paste: strcmp = %i, actual = '%s'\n", result, buffer);
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) NULL);
|
||||
SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
|
||||
|
@ -4552,7 +4552,7 @@ static void test_WM_PASTE(void)
|
|||
(MapVirtualKey('Z', MAPVK_VK_TO_VSC) << 16) & 1);
|
||||
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
result = strcmp(buffer,"");
|
||||
todo_wine ok(result == 0,
|
||||
ok(result == 0,
|
||||
"test paste: strcmp = %i, actual = '%s'\n", result, buffer);
|
||||
/* Simulates redo (Ctrl-Y) */
|
||||
SendMessage(hwndRichEdit, WM_KEYDOWN, 'Y',
|
||||
|
|
Loading…
Reference in New Issue