#include "text_operations.h" struct EditStreamData { PBYTE pbBuff; int cbBuff; int iCurrent; }; static DWORD CALLBACK EditStreamOutRtf(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) { struct EditStreamData *esd = (struct EditStreamData*)dwCookie; esd->cbBuff += cb; esd->pbBuff = (PBYTE)realloc(esd->pbBuff, esd->cbBuff+sizeof(TCHAR)); CopyMemory(esd->pbBuff+esd->iCurrent, pbBuff, cb); esd->iCurrent += cb; esd->pbBuff[esd->iCurrent] = 0; esd->pbBuff[esd->iCurrent+1] = 0; *pcb = cb; return 0; } LPTSTR GeTStringFromStreamData(struct EditStreamData *esd) { LPTSTR ptszTemp, ptszOutText; DWORD i, k; ptszOutText = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); ptszTemp = (TCHAR*)esd->pbBuff; for (i = k = 0;i<_tcslen(ptszTemp);i++) if ((ptszTemp[i] == 0x0A)||(ptszTemp[i] == 0x2028)) ptszOutText[k++] = 0x0D; else if (ptszTemp[i] == 0x0D) { ptszOutText[k++] = 0x0D; if (ptszTemp[i+1] == 0x0A) i++; } else ptszOutText[k++] = ptszTemp[i]; ptszOutText[k] = 0; return ptszOutText; } BOOL CopyTextToClipboard(LPTSTR ptszText) { HGLOBAL hCopy; if (OpenClipboard(NULL)) { EmptyClipboard(); hCopy = GlobalAlloc(GMEM_MOVEABLE, (_tcslen(ptszText)+1)*sizeof(TCHAR)); _tcscpy((TCHAR*)GlobalLock(hCopy), ptszText); GlobalUnlock(hCopy); SetClipboardData(CF_UNICODETEXT, hCopy); CloseClipboard(); return TRUE; } else return FALSE; } LPSTR GetNameOfLayout(HKL hklLayout) { LPSTR ptszLayName = (LPSTR)mir_alloc(KL_NAMELENGTH+1); sprintf(ptszLayName, "%08x", hklLayout); return ptszLayName; } LPTSTR GetShortNameOfLayout(HKL hklLayout) { DWORD dwLcid; TCHAR szLI[20]; LPTSTR ptszLiShort; ptszLiShort = (LPTSTR)mir_alloc(3*sizeof(TCHAR)); dwLcid = MAKELCID(hklLayout, 0); GetLocaleInfo(dwLcid, LOCALE_SISO639LANGNAME , szLI, 10); ptszLiShort[0] = toupper(szLI[0]); ptszLiShort[1] = toupper(szLI[1]); ptszLiShort[2] = 0; return ptszLiShort; } HKL GetNextLayout(HKL hklCurLay) { DWORD i; for(i = 0; i < bLayNum; i++) if (hklLayouts[i] == hklCurLay) return hklLayouts[(i+1)%(bLayNum)]; return NULL; } LPTSTR GenerateLayoutString(HKL hklLayout) { LPTSTR ptszLayStr, ptszTemp; SHORT shVirtualKey; UINT iScanCode; BYTE bState[256] = {0}; DWORD i, j; int iRes; ptszLayStr = (LPTSTR)mir_alloc(100*sizeof(TCHAR)); ptszTemp = (LPTSTR)mir_alloc(3*sizeof(TCHAR)); ptszTemp[0] = 0; for(i = 0;i<_tcslen(ptszKeybEng);i++) { shVirtualKey = VkKeyScanEx(ptszKeybEng[i], hklEng); iScanCode = MapVirtualKeyEx(shVirtualKey&0x00FF, 0, hklEng); for (j = 0;j<256;j++) bState[j] = 0; if (shVirtualKey&0x0100) bState[VK_SHIFT] = 0x80; if (shVirtualKey&0x0200) bState[VK_CONTROL] = 0x80; if (shVirtualKey&0x0400) bState[VK_MENU] = 0x80; shVirtualKey = MapVirtualKeyEx(iScanCode, 1, hklLayout); bState[shVirtualKey&0x00FF] = 0x80; iRes = ToUnicodeEx(shVirtualKey, iScanCode, bState, ptszTemp, 3, 0, hklLayout); // Защита от дэд-кеев if (iRes<0) ToUnicodeEx(shVirtualKey, iScanCode, bState, ptszTemp, 3, 0, hklLayout); //Если нам вернули нулевой символ, или не вернули ничего, то присвоим "звоночек" if (ptszTemp[0] == 0) ptszLayStr[i] = 3; else ptszLayStr[i] = ptszTemp[0]; } ptszLayStr[i] = 0; mir_free(ptszTemp); return ptszLayStr; } LPTSTR GetLayoutString(HKL hklLayout) { DWORD i; for (i = 0;i=j) ptszOutText[i] = ptszKeybNext[j]; } if (TwoWay && (!Found)) for (j = 0;(j<_tcslen(ptszKeybNext) && (!Found));j++) if (ptszKeybNext[j] == ptszInText[i]) { Found = TRUE; if (_tcslen(ptszKeybCur)>=j) ptszOutText[i] = ptszKeybCur[j]; } }; return ptszOutText; } HKL GetLayoutOfText(LPCTSTR ptszInText) { DWORD i, j; LPTSTR ptszKeybBuff; DWORD dwCountSymbols, dwMaxSymbols, dwTemp; HKL hklCurLay; hklCurLay = hklLayouts[0]; ptszKeybBuff = ptszLayStrings[0]; dwMaxSymbols = dwTemp = 0; for (j = 0;j<_tcslen(ptszInText);j++) if (_tcschr(ptszKeybBuff, ptszInText[j]) != NULL) ++dwMaxSymbols; for(i = 1; i < bLayNum; i++) { ptszKeybBuff = ptszLayStrings[i]; dwCountSymbols = 0; for (j = 0;j<_tcslen(ptszInText);j++) if (_tcschr(ptszKeybBuff, ptszInText[j]) != NULL) ++dwCountSymbols; if (dwCountSymbols == dwMaxSymbols) dwTemp = dwCountSymbols; else if (dwCountSymbols>dwMaxSymbols) { dwMaxSymbols = dwCountSymbols; hklCurLay = hklLayouts[i]; } } if (dwMaxSymbols == dwTemp) hklCurLay = GetKeyboardLayout(0); return hklCurLay; } int ChangeLayout(HWND hTextWnd, BYTE TextOperation, BOOL CurrentWord) { HKL hklCurLay, hklToLay; LPTSTR ptszInText, ptszOutText, ptszMBox, ptszPopupText, ptszTemp; IEVIEWEVENT ieEvent; CHARRANGE crSelection, crTemp; DWORD dwStartWord, dwEndWord; int i, iRes; BYTE WindowType = WTYPE_Unknown; BOOL WindowIsReadOnly, TwoWay; EDITSTREAM esStream = {0}; struct EditStreamData esdData; POPUPDATAT_V2 pdtData; esStream.dwCookie = (DWORD)&esdData; esStream.pfnCallback = EditStreamOutRtf; if (hTextWnd == NULL) hTextWnd = GetFocus(); if (hTextWnd != NULL) { // --------------Определяем тип окна----------------- ZeroMemory((void *)&ieEvent, sizeof(ieEvent)); ieEvent.cbSize = sizeof(IEVIEWEVENT); ieEvent.dwFlags = 0; ieEvent.iType = IEE_GET_SELECTION; //event.codepage = 1200; if (ServiceExists(MS_HPP_EG_EVENT)) { //То же самое для History++ ieEvent.hwnd = hTextWnd; ptszInText = (TCHAR*)CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&ieEvent); if (!IsBadStringPtr(ptszInText, MaxTextSize)) WindowType = WTYPE_HistoryPP; } if ((WindowType == WTYPE_Unknown) && (ServiceExists(MS_IEVIEW_EVENT))) { // Извращенное определение хэндла IEView ieEvent.hwnd = GetParent(GetParent(hTextWnd)); ptszInText = (TCHAR*)CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&ieEvent); if (!IsBadStringPtr(ptszInText, MaxTextSize)) WindowType = WTYPE_IEView; } if (WindowType == WTYPE_Unknown) { ptszTemp = (LPTSTR)mir_alloc(255*sizeof(TCHAR)); i = GetClassName(hTextWnd, ptszTemp, 255); ptszTemp[i] = 0; if (_tcsstr(CharUpper(ptszTemp), _T("RICHEDIT")) != NULL ) { WindowType = WTYPE_RichEdit; SendMessage(hTextWnd, EM_EXGETSEL, 0, (LPARAM)&crSelection); } mir_free(ptszTemp); } if (WindowType == WTYPE_Unknown) { SendMessage(hTextWnd, EM_GETSEL, (WPARAM)&crSelection.cpMin, (LPARAM)&crSelection.cpMax); if ((SendMessage(hTextWnd, WM_GETDLGCODE, (WPARAM)NULL, (LPARAM)NULL)&(DLGC_HASSETSEL)) && (crSelection.cpMin>=0)) WindowType = WTYPE_Edit; } //Получим текст из Рича или обычного Едита if ((WindowType == WTYPE_RichEdit)||(WindowType == WTYPE_Edit)) { dwStartWord = dwEndWord = -1; SendMessage(hTextWnd, WM_SETREDRAW, FALSE, 0); //Бэкап выделения crTemp = crSelection; // Если имеется выделенный текст, то получим его if(crSelection.cpMin != crSelection.cpMax) { if (WindowType == WTYPE_RichEdit) { ZeroMemory(&esdData, sizeof(esdData)); if (SendMessage(hTextWnd, EM_STREAMOUT, SF_TEXT|SF_UNICODE|SFF_SELECTION, (LPARAM)&esStream)>0) ptszInText = GeTStringFromStreamData(&esdData); else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } if (WindowType == WTYPE_Edit) { ptszTemp = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); ptszInText = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); iRes = SendMessage(hTextWnd, WM_GETTEXT, (WPARAM)MaxTextSize, (LPARAM)ptszTemp); if (!IsBadStringPtr(ptszInText, MaxTextSize) && (iRes>0)) { _tcsncpy(ptszInText, &ptszTemp[crSelection.cpMin], crSelection.cpMax-crSelection.cpMin); ptszInText[crSelection.cpMax-crSelection.cpMin] = 0; mir_free(ptszTemp); } else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } } // Если выделения нет, то получим нужный текст else { // Получаем весь текст в поле if (WindowType == WTYPE_RichEdit) { ZeroMemory(&esdData, sizeof(esdData)); crTemp.cpMin = 0; crTemp.cpMax = -1; SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crTemp); if (SendMessage(hTextWnd, EM_STREAMOUT, SF_TEXT|SF_UNICODE|SFF_SELECTION, (LPARAM)&esStream) != 0) ptszInText = GeTStringFromStreamData(&esdData); else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } if (WindowType == WTYPE_Edit) { ptszInText = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); iRes = SendMessage(hTextWnd, WM_GETTEXT, (WPARAM)MaxTextSize, (LPARAM)ptszInText); if (!IsBadStringPtr(ptszInText, MaxTextSize) && (iRes>0)) { crTemp.cpMin = 0; crTemp.cpMax = (int)_tcslen(ptszInText); } else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } // Получаем текущее слово if (CurrentWord) { for (dwStartWord = crSelection.cpMin;(dwStartWord>0) && (_tcschr(ptszSeparators, ptszInText[dwStartWord-1]) == NULL);dwStartWord--); for (dwEndWord = crSelection.cpMin;(dwEndWord<(_tcslen(ptszInText))) && (_tcschr(ptszSeparators, ptszInText[dwEndWord]) == NULL);dwEndWord++); crTemp.cpMin = dwStartWord; crTemp.cpMax = dwEndWord; if (WindowType == WTYPE_RichEdit) { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crTemp); ZeroMemory(&esdData, sizeof(esdData)); if (SendMessage(hTextWnd, EM_STREAMOUT, SF_TEXT|SF_UNICODE|SFF_SELECTION, (LPARAM)&esStream) != 0) ptszInText = GeTStringFromStreamData(&esdData); else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } if (WindowType == WTYPE_Edit) { ptszTemp = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); _tcsncpy(ptszTemp, &ptszInText[crTemp.cpMin], crTemp.cpMax-crTemp.cpMin); ptszTemp[crTemp.cpMax-crTemp.cpMin] = 0; _tcscpy(ptszInText, ptszTemp); mir_free(ptszTemp); if (_tcslen(ptszInText) == 0) { mir_free(ptszInText); SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } } } } // ---------------Выдаем результаты-------------------- WindowIsReadOnly = FALSE; if ((WindowType == WTYPE_IEView)||(WindowType == WTYPE_HistoryPP)) WindowIsReadOnly = TRUE; //if ((SendMessage(hTextWnd, EM_GETOPTIONS, 0, 0)&ECO_READONLY)) if ((WindowType == WTYPE_RichEdit)||(WindowType == WTYPE_Edit)) if (GetWindowLongPtr(hTextWnd, GWL_STYLE)&ES_READONLY) WindowIsReadOnly = TRUE; // Лог Иевью и ХисториПП в режиме эмуляции Иевью и поля только для чтения. if ((WindowType != WTYPE_Unknown) && (!IsBadStringPtr(ptszInText, MaxTextSize))) if (WindowIsReadOnly) { ptszMBox = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); ptszMBox[0] = 0; if (TextOperation == TOT_Layout) { hklCurLay = GetLayoutOfText(ptszInText); hklToLay = GetNextLayout(hklCurLay); TwoWay = (moOptions.TwoWay) && (bLayNum == 2); if (bLayNum == 2) { ptszMBox = ChangeTextLayout(ptszInText, hklCurLay, hklToLay, TwoWay); } else { for (i = 0;i