From 3dfe76ebba2cc8264d5548db3446587fd08f032e Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Wed, 6 Jun 2012 19:11:34 +0000 Subject: ChangeKeyboardLayout added git-svn-id: http://svn.miranda-ng.org/main/trunk@333 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/ChangeKeyboardLayout/text_operations.c | 676 +++++++++++++++++++++++++ 1 file changed, 676 insertions(+) create mode 100644 plugins/ChangeKeyboardLayout/text_operations.c (limited to 'plugins/ChangeKeyboardLayout/text_operations.c') diff --git a/plugins/ChangeKeyboardLayout/text_operations.c b/plugins/ChangeKeyboardLayout/text_operations.c new file mode 100644 index 0000000000..1fdc62b4c7 --- /dev/null +++ b/plugins/ChangeKeyboardLayout/text_operations.c @@ -0,0 +1,676 @@ +#include "text_operations.h" + +struct EditStreamData { + PBYTE pbBuff; + int cbBuff; + int iCurrent; +}; + +static DWORD CALLBACK EditStreamOutRtf(DWORD 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; + #if defined (_UNICODE) + esd->pbBuff[esd->iCurrent+1]=0; + #endif + *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(GlobalLock(hCopy),ptszText); + GlobalUnlock(hCopy); + + #if defined (_UNICODE) + SetClipboardData(CF_UNICODETEXT,hCopy); + #else + SetClipboardData(CF_TEXT,hCopy); + #endif + + CloseClipboard(); + return TRUE; + } + else + return FALSE; +} + +LPTSTR GetNameOfLayout(HKL hklLayout) +{ + LPTSTR ptszLayName; + ptszLayName=mir_alloc((KL_NAMELENGTH+1)*sizeof(TCHAR)); + 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; + + #if defined (_UNICODE) + iRes=ToUnicodeEx(shVirtualKey,iScanCode,bState,ptszTemp,3,0,hklLayout); + // Защита от дэд-кеев + if (iRes<0) ToUnicodeEx(shVirtualKey,iScanCode,bState,ptszTemp,3,0,hklLayout); + #else + iRes=ToAsciiEx(shVirtualKey,iScanCode,bState,ptszTemp,0,hklLayout); + // Защита от дэд-кеев + if (iRes<0) ToAsciiEx(shVirtualKey,iScanCode,bState,ptszTemp,0,hklLayout); + #endif + + //Если нам вернули нулевой символ, или не вернули ничего, то присвоим "звоночек" + 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 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 !defined(_UNICODE) + ieEvent.dwFlags |= IEEF_NO_UNICODE; + #endif + + 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 defined (_UNICODE) + if (SendMessage(hTextWnd,EM_STREAMOUT,SF_TEXT|SF_UNICODE|SFF_SELECTION,(LPARAM)&esStream)>0) + #else + if (SendMessage(hTextWnd,EM_STREAMOUT,SF_TEXT|SFF_SELECTION,(LPARAM)&esStream)>0) + #endif + 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 defined (_UNICODE) + if (SendMessage(hTextWnd,EM_STREAMOUT,SF_TEXT|SF_UNICODE|SFF_SELECTION,(LPARAM)&esStream)!=0) + #else + if (SendMessage(hTextWnd,EM_STREAMOUT,SF_TEXT|SFF_SELECTION,(LPARAM)&esStream)!=0) + #endif + 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=_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 defined (_UNICODE) + if (SendMessage(hTextWnd,EM_STREAMOUT,SF_TEXT|SF_UNICODE|SFF_SELECTION,(LPARAM)&esStream)!=0) + #else + if (SendMessage(hTextWnd,EM_STREAMOUT,SF_TEXT|SFF_SELECTION,(LPARAM)&esStream)!=0) + #endif + 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 (GetWindowLong(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