/* Miranda SmileyAdd Plugin Copyright (C) 2005 - 2012 Boris Krasnovskiy All Rights Reserved Copyright (C) 2003 - 2004 Rein-Peter de Boer 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 version 2 of the License. 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, see . */ #include "stdafx.h" static mir_cs csWndList; // type definitions struct MsgWndData : public MZeroedObject { HWND hwnd, hwndLog, hwndInput; int idxLastChar; bool doSmileyReplace, doSmileyButton; MCONTACT hContact; char ProtocolName[52]; void CreateSmileyButton(void) { doSmileyButton = opt.ButtonStatus != 0; SmileyPackType *SmileyPack = GetSmileyPack(ProtocolName, hContact); doSmileyButton &= SmileyPack != nullptr && SmileyPack->VisibleSmileyCount() != 0; doSmileyReplace = true; if (ProtocolName[0] != 0) { INT_PTR cap = CallProtoService(ProtocolName, PS_GETCAPS, PFLAGNUM_1, 0); doSmileyButton &= ((cap & (PF1_IMSEND | PF1_CHAT)) != 0); doSmileyReplace &= ((cap & (PF1_IMRECV | PF1_CHAT)) != 0); } BBButton bbd = {}; bbd.pszModuleName = MODULENAME; if (!doSmileyButton) bbd.bbbFlags = BBBF_DISABLED; else if (!opt.PluginSupportEnabled) bbd.bbbFlags = BBBF_HIDDEN; Srmm_SetButtonState(hContact, &bbd); } }; static LIST g_MsgWndList(10, HandleKeySortT); int UpdateSrmmDlg(WPARAM wParam, LPARAM) { mir_cslock lck(csWndList); for (auto &it : g_MsgWndList) { if (wParam == 0 || it->hContact == wParam) { SendMessage(it->hwnd, WM_SETREDRAW, FALSE, 0); SendMessage(it->hwnd, DM_OPTIONSAPPLIED, 0, 0); SendMessage(it->hwnd, WM_SETREDRAW, TRUE, 0); } } return 0; } // find the dialog info in the stored list static MsgWndData* IsMsgWnd(HWND hwnd) { mir_cslock lck(csWndList); return g_MsgWndList.find((MsgWndData*)&hwnd); } // global subclass function for all dialogs static LRESULT CALLBACK MessageDlgSubclass(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { MsgWndData *dat = IsMsgWnd(hwnd); if (dat == nullptr) return 0; switch (uMsg) { case DM_OPTIONSAPPLIED: dat->CreateSmileyButton(); break; case DM_APPENDTOLOG: if (opt.PluginSupportEnabled) { // get length of text now before things can get added... GETTEXTLENGTHEX gtl; gtl.codepage = 1200; gtl.flags = GTL_PRECISE | GTL_NUMCHARS; dat->idxLastChar = (int)SendMessage(dat->hwndLog, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); } break; } LRESULT result = mir_callNextSubclass(hwnd, MessageDlgSubclass, uMsg, wParam, lParam); if (!opt.PluginSupportEnabled) return result; switch (uMsg) { case WM_DESTROY: { mir_cslock lck(csWndList); int ind = g_MsgWndList.getIndex((MsgWndData*)&hwnd); if (ind != -1) { delete g_MsgWndList[ind]; g_MsgWndList.remove(ind); } } break; case DM_APPENDTOLOG: if (dat->doSmileyReplace) { SmileyPackCType *smcp; SmileyPackType *SmileyPack = GetSmileyPack(dat->ProtocolName, dat->hContact, &smcp); if (SmileyPack != nullptr) { const CHARRANGE sel = { dat->idxLastChar, LONG_MAX }; ReplaceSmileys(dat->hwndLog, SmileyPack, smcp, sel, false, false, false); } } break; case DM_REMAKELOG: if (dat->doSmileyReplace) { SmileyPackCType *smcp; SmileyPackType *SmileyPack = GetSmileyPack(dat->ProtocolName, dat->hContact, &smcp); if (SmileyPack != nullptr) { static const CHARRANGE sel = { 0, LONG_MAX }; ReplaceSmileys(dat->hwndLog, SmileyPack, smcp, sel, false, false, false); } } break; } return result; } ///////////////////////////////////////////////////////////////////////////////////////// // toolbar button processing int SmileyButtonCreate(WPARAM, LPARAM) { // create a hotkey for the button first HOTKEYDESC desc = {}; desc.pszName = "srmm_smileyadd"; desc.szSection.a = BB_HK_SECTION; desc.szDescription.a = LPGEN("Smiley selector"); desc.DefHotKey = HOTKEYCODE(HOTKEYF_ALT, 'E'); desc.lParam = LPARAM(g_hInst); Hotkey_Register(&desc); BBButton bbd = {}; bbd.pszModuleName = MODULENAME; bbd.pwszTooltip = LPGENW("Show smiley selection window"); bbd.dwDefPos = 31; bbd.hIcon = IcoLib_GetIconHandle("SmileyAdd_ButtonSmiley"); bbd.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON; bbd.pszHotkey = desc.pszName; Srmm_AddButton(&bbd); return 0; } int SmileyButtonPressed(WPARAM, LPARAM lParam) { CustomButtonClickData *pcbc = (CustomButtonClickData*)lParam; if (mir_strcmp(pcbc->pszModule, MODULENAME)) return 0; MsgWndData *dat = IsMsgWnd(pcbc->hwndFrom); if (dat == nullptr) return 0; SmileyToolWindowParam *stwp = new SmileyToolWindowParam; stwp->pSmileyPack = GetSmileyPack(dat->ProtocolName, dat->hContact); stwp->hWndParent = pcbc->hwndFrom; stwp->hWndTarget = dat->hwndInput; stwp->targetMessage = EM_REPLACESEL; stwp->targetWParam = TRUE; stwp->direction = 0; stwp->xPosition = pcbc->pt.x; stwp->yPosition = pcbc->pt.y; mir_forkThread(SmileyToolThread, stwp); return 0; } ///////////////////////////////////////////////////////////////////////////////////////// // window hook static int MsgDlgHook(WPARAM, LPARAM lParam) { const MessageWindowEventData *wndEvtData = (MessageWindowEventData*)lParam; switch (wndEvtData->uType) { case MSG_WINDOW_EVT_OPENING: { MsgWndData *msgwnd = new MsgWndData(); msgwnd->hwnd = wndEvtData->hwndWindow; msgwnd->hContact = wndEvtData->hContact; msgwnd->hwndLog = wndEvtData->hwndLog; msgwnd->hwndInput = wndEvtData->hwndInput; // Get the protocol for this contact to display correct smileys. char *protonam = GetContactProto(DecodeMetaContact(msgwnd->hContact)); if (protonam) strncpy_s(msgwnd->ProtocolName, protonam, _TRUNCATE); mir_subclassWindow(msgwnd->hwnd, MessageDlgSubclass); msgwnd->CreateSmileyButton(); mir_cslock lck(csWndList); g_MsgWndList.insert(msgwnd); } SetRichOwnerCallback(wndEvtData->hwndWindow, wndEvtData->hwndInput, wndEvtData->hwndLog); if (wndEvtData->hwndLog) SetRichCallback(wndEvtData->hwndLog, wndEvtData->hContact, false, false); if (wndEvtData->hwndInput) SetRichCallback(wndEvtData->hwndInput, wndEvtData->hContact, false, false); break; case MSG_WINDOW_EVT_OPEN: SetRichOwnerCallback(wndEvtData->hwndWindow, wndEvtData->hwndInput, wndEvtData->hwndLog); if (wndEvtData->hwndLog) SetRichCallback(wndEvtData->hwndLog, wndEvtData->hContact, true, true); if (wndEvtData->hwndInput) { SetRichCallback(wndEvtData->hwndInput, wndEvtData->hContact, true, true); SendMessage(wndEvtData->hwndInput, WM_REMAKERICH, 0, 0); } break; case MSG_WINDOW_EVT_CLOSE: if (wndEvtData->hwndLog) { CloseRichCallback(wndEvtData->hwndLog); CloseRichOwnerCallback(wndEvtData->hwndWindow); } mir_unsubclassWindow(wndEvtData->hwndWindow, MessageDlgSubclass); break; } return 0; } void InstallDialogBoxHook(void) { HookEvent(ME_MSG_WINDOWEVENT, MsgDlgHook); } void RemoveDialogBoxHook(void) { mir_cslock lck(csWndList); for (auto &it : g_MsgWndList) delete it; g_MsgWndList.destroy(); }