/* Miranda Text Control - Plugin for Miranda IM Copyright (C) 2005 Victor Pavlychko (nullbie@gmail.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdafx.h" static HANDLE hService[11] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; INT_PTR MText_Register(WPARAM, LPARAM); INT_PTR MText_Create(WPARAM, LPARAM); INT_PTR MText_CreateW(WPARAM, LPARAM); INT_PTR MText_CreateEx(WPARAM, LPARAM); INT_PTR MText_Measure(WPARAM, LPARAM); INT_PTR MText_Display(WPARAM, LPARAM); INT_PTR MText_SetParent(WPARAM, LPARAM); INT_PTR MText_SendMessage(WPARAM, LPARAM); INT_PTR MText_CreateProxy(WPARAM, LPARAM); INT_PTR MText_Destroy(WPARAM, LPARAM); INT_PTR MText_GetInterface(WPARAM, LPARAM); struct TextObject { DWORD options; IFormattedTextDraw *ftd; TextObject() : options(0), ftd(nullptr) {} ~TextObject() { if (ftd) delete ftd; } }; //--------------------------------------------------------------------------- // elper functions void MText_InitFormatting0(IFormattedTextDraw *ftd, DWORD) { LRESULT lResult; // urls ftd->getTextService()->TxSendMessage(EM_AUTOURLDETECT, TRUE, 0, &lResult); } void MText_InitFormatting1(TextObject *text) { // bbcodes bbCodeParse(text->ftd); // smilies // HWND hwnd = (HWND)CallServiceSync(MS_TEXT_CREATEPROXY, (WPARAM)text, 0); HWND hwnd = CreateProxyWindow(text->ftd->getTextService()); SMADD_RICHEDIT3 sm = { 0 }; sm.cbSize = sizeof(sm); sm.hwndRichEditControl = hwnd; sm.rangeToReplace = nullptr; sm.Protocolname = nullptr; sm.flags = SAFLRE_INSERTEMF; CallService(MS_SMILEYADD_REPLACESMILEYS, RGB(0xff, 0xff, 0xff), (LPARAM)&sm); DestroyWindow(hwnd); // text->ftd->getTextService()->TxSendMessage(EM_SETSEL, 0, -1, &lResult); /* // rtl stuff PARAFORMAT2 pf2; pf2.cbSize = sizeof(pf2); pf2.dwMask = PFM_ALIGNMENT|PFM_RTLPARA; pf2.wEffects = PFE_RTLPARA; pf2.wAlignment = PFA_RIGHT; text->ftd->getTextService()->TxSendMessage(EM_SETSEL, 0, -1, &lResult); text->ftd->getTextService()->TxSendMessage(EM_SETPARAFORMAT, 0, (LPARAM)&pf2, &lResult); text->ftd->getTextService()->TxSendMessage(EM_SETSEL, 0, 0, &lResult); */ } //--------------------------------------------------------------------------- // NEW mtextcontrol interface: // // obtain the full mtextcontrol interface from the library. it is much faster as use of // miranda core CallService to access to mtextcontrol (no core traffic). // This interface provides full access to mtextcontrol internal functions, // thus enabling devs to fully utilize the mtextcontrol API. // All functions will be exported as miranda services for compatibility. // // the interface is populated during the Load(void) handler, so you can assume it is ready when Miranda // throw the ME_SYSTEM_MODULESLOADED event and you can generate a warning in your ModulesLoaded() when // it depends on the mtextcontrol interface and the mtextcontrol plugin is missing. // // example: // // MTEXT_INTERFACE MText = {0}; // // mir_getMTI(&MText); // // all interface function designed as old mtextcontrol helper functions. // therefore it is easy to convert your old plugin code to new interface. // // example: // // old code: MTextCreate (... // new code: MText.Create(... //--------------------------------------------------------------------------- // subscribe to MText services INT_PTR MText_Register(WPARAM wParam, LPARAM lParam) { DWORD userOptions = (DWORD)wParam; char *userTitle = (char *)lParam; return (INT_PTR)MTI_TextUserAdd(userTitle, userOptions); } //--------------------------------------------------------------------------- // allocate text object (unicode) HANDLE DLL_CALLCONV MTI_MTextCreateW(HANDLE userHandle, WCHAR *text) { TextObject *result = new TextObject; result->options = TextUserGetOptions(userHandle); result->ftd = new CFormattedTextDraw; result->ftd->Create(); InitRichEdit(result->ftd->getTextService()); MText_InitFormatting0(result->ftd, result->options); result->ftd->putTextW(text); MText_InitFormatting1(result); return (HANDLE)result; } INT_PTR MText_CreateW(WPARAM wParam, LPARAM lParam) { //HANDLE userHandle = (HANDLE)wParam; //WCHAR *wtext = (WCHAR *)lParam; return (INT_PTR)(HANDLE)MTI_MTextCreateW((HANDLE)wParam, (WCHAR *)lParam); } //--------------------------------------------------------------------------- // allocate text object (advanced) HANDLE DLL_CALLCONV MTI_MTextCreateEx(HANDLE userHandle, void *text, DWORD flags) { TextObject *result = new TextObject; result->options = TextUserGetOptions(userHandle); result->ftd = new CFormattedTextDraw; result->ftd->Create(); InitRichEdit(result->ftd->getTextService()); MText_InitFormatting0(result->ftd, result->options); if (flags & MTEXT_FLG_WCHAR) result->ftd->putTextW((WCHAR *)text); else result->ftd->putTextA((char *)text); MText_InitFormatting1(result); delete result; return nullptr; } INT_PTR MText_CreateEx(WPARAM wParam, LPARAM lParam) { HANDLE userHandle = (HANDLE)wParam; MTEXTCREATE *textCreate = (MTEXTCREATE *)lParam; MTI_MTextCreateEx(userHandle, textCreate->text, textCreate->flags); return 0; } //--------------------------------------------------------------------------- // measure text object int DLL_CALLCONV MTI_MTextMeasure(HDC dc, SIZE *sz, HANDLE text) { if (!text) return 0; long lWidth = sz->cx, lHeight = sz->cy; ((TextObject *)text)->ftd->get_NaturalSize(dc, &lWidth, &lHeight); sz->cx = lWidth; sz->cy = lHeight; // FancyMeasure(((TextObject *)text)->fancy, displayInfo); return 0; } INT_PTR MText_Measure(WPARAM wParam, LPARAM) { LPMTEXTDISPLAY displayInfo = (LPMTEXTDISPLAY)wParam; if (!displayInfo) return 0; if (!(TextObject *)displayInfo->text) return 0; MTI_MTextMeasure(displayInfo->dc, &displayInfo->sz, displayInfo->text); return 0; } int DLL_CALLCONV //--------------------------------------------------------------------------- // display text object MTI_MTextDisplay(HDC dc, POINT pos, SIZE sz, HANDLE text) { if (!text) return 0; COLORREF cl = GetTextColor(dc); // if (GetTextColor(dc)&0xffffff != 0) { LRESULT lResult; CHARFORMAT cf = { 0 }; cf.cbSize = sizeof(cf); cf.dwMask = CFM_COLOR; cf.crTextColor = cl; ((TextObject *)text)->ftd->getTextService()->TxSendMessage(EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf, &lResult); } SetBkMode(dc, TRANSPARENT); long lWidth = sz.cx, lHeight; ((TextObject *)text)->ftd->get_NaturalSize(dc, &lWidth, &lHeight); RECT rt; rt.left = pos.x; rt.top = pos.y; rt.right = pos.x + lWidth; rt.bottom = pos.y + lHeight; ((TextObject *)text)->ftd->Draw(dc, &rt); return 0; } INT_PTR MText_Display(WPARAM wParam, LPARAM) { LPMTEXTDISPLAY displayInfo = (LPMTEXTDISPLAY)wParam; if (!displayInfo) return 0; if (!displayInfo->text) return 0; MTI_MTextDisplay(displayInfo->dc, displayInfo->pos, displayInfo->sz, displayInfo->text); return 0; } int DLL_CALLCONV //--------------------------------------------------------------------------- // set parent window for text object (this is required for mouse handling, etc) MTI_MTextSetParent(HANDLE text, HWND hwnd, RECT rect) { if (!text) return 0; ((TextObject *)text)->ftd->setParentWnd(hwnd, rect); return 0; } INT_PTR MText_SetParent(WPARAM wParam, LPARAM) { LPMTEXTSETPARENT info = (LPMTEXTSETPARENT)wParam; //TextObject *text = (TextObject *)info->text; if (!info) return 0; if (!info->text) return 0; MTI_MTextSetParent(info->text, info->hwnd, info->rc); return 0; } //--------------------------------------------------------------------------- // send message to an object int DLL_CALLCONV MTI_MTextSendMessage(HWND hwnd, HANDLE text, UINT msg, WPARAM wParam, LPARAM lParam) { LRESULT lResult; if (!text) return 0; ((TextObject *)text)->ftd->getTextService()->TxSendMessage(msg, wParam, lParam, &lResult); if (hwnd && (msg == WM_MOUSEMOVE)) { HDC hdc = GetDC(hwnd); ((TextObject *)text)->ftd->getTextService()->OnTxSetCursor(DVASPECT_CONTENT, 0, nullptr, nullptr, hdc, nullptr, nullptr, LOWORD(0), HIWORD(0)); ReleaseDC(hwnd, hdc); } return lResult; } INT_PTR MText_SendMessage(WPARAM wParam, LPARAM) { LPMTEXTMESSAGE message = (LPMTEXTMESSAGE)wParam; if (!message->text) return 0; return (INT_PTR)MTI_MTextSendMessage(message->hwnd, message->text, message->msg, message->wParam, message->lParam); } //--------------------------------------------------------------------------- // create a proxy window HWND DLL_CALLCONV MTI_MTextCreateProxy(HANDLE text) { if (!text) return nullptr; return CreateProxyWindow(((TextObject *)text)->ftd->getTextService()); } INT_PTR MText_CreateProxy(WPARAM wParam, LPARAM) { if (!wParam) return 0; return (INT_PTR)MTI_MTextCreateProxy((HANDLE)wParam); } int DLL_CALLCONV //--------------------------------------------------------------------------- // destroy text object MTI_MTextDestroy(HANDLE text) { //HANDLE textHandle = (HANDLE)wParam; //TextObject *text = (TextObject *)textHandle; if (text) delete (TextObject *)text; return 0; } INT_PTR MText_Destroy(WPARAM wParam, LPARAM) { HANDLE textHandle = (HANDLE)wParam; TextObject *text = (TextObject *)textHandle; if (text) delete text; return 0; } //--------------------------------------------------------------------------- // populate the interface INT_PTR MText_GetInterface(WPARAM, LPARAM lParam) { MTEXT_INTERFACE *MText = (MTEXT_INTERFACE *)lParam; if (MText == nullptr) return CALLSERVICE_NOTFOUND; MText->version = PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM); MText->Register = MTI_TextUserAdd; MText->Create = MTI_MTextCreateW; MText->CreateEx = MTI_MTextCreateEx; MText->Measure = MTI_MTextMeasure; MText->Display = MTI_MTextDisplay; MText->SetParent = MTI_MTextSetParent; MText->SendMsg = MTI_MTextSendMessage; MText->CreateProxy = MTI_MTextCreateProxy; MText->Destroy = MTI_MTextDestroy; return S_OK; } //--------------------------------------------------------------------------- // Load / Unload services void LoadServices() { CreateServiceFunction(MS_TEXT_REGISTER, MText_Register); CreateServiceFunction(MS_TEXT_CREATEW, MText_CreateW); CreateServiceFunction(MS_TEXT_CREATEEX, MText_CreateEx); CreateServiceFunction(MS_TEXT_MEASURE, MText_Measure); CreateServiceFunction(MS_TEXT_DISPLAY, MText_Display); CreateServiceFunction(MS_TEXT_SETPARENT, MText_SetParent); CreateServiceFunction(MS_TEXT_SENDMESSAGE, MText_SendMessage); CreateServiceFunction(MS_TEXT_CREATEPROXY, MText_CreateProxy); CreateServiceFunction(MS_TEXT_DESTROY, MText_Destroy); CreateServiceFunction(MS_TEXT_GETINTERFACE, MText_GetInterface); }