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;
|
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)
|
||||||
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) {
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
(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',
|
||||||
|
|
Loading…
Reference in New Issue