#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 (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