/*
Miranda NG SmileyAdd Plugin
Copyright (C) 2012-20 Miranda NG team (https://miranda-ng.org)
Copyright (C) 2005-11 Boris Krasnovskiy All Rights Reserved
Copyright (C) 2003-04 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"
LIST menuHandleArray(5);
//implementation of service functions
SmileyPackType* GetSmileyPack(const char *proto, MCONTACT hContact, SmileyPackCType **smlc)
{
hContact = DecodeMetaContact(hContact);
if (smlc)
*smlc = opt.DisableCustom ? nullptr : g_SmileyPackCStore.GetSmileyPack(hContact);
if (proto != nullptr && IsBadStringPtrA(proto, 10))
return nullptr;
CMStringW categoryName;
if (hContact != 0) {
opt.ReadContactCategory(hContact, categoryName);
if (categoryName == L"") return nullptr;
if (!categoryName.IsEmpty() && g_SmileyCategories.GetSmileyCategory(categoryName) == nullptr) {
categoryName.Empty();
opt.WriteContactCategory(hContact, categoryName);
}
if (categoryName.IsEmpty() && !opt.UseOneForAll) {
char *protonam = Proto_GetBaseAccountName(hContact);
if (protonam != nullptr) {
DBVARIANT dbv;
if (db_get_ws(hContact, protonam, "Transport", &dbv) == 0) {
categoryName = dbv.pwszVal;
db_free(&dbv);
}
else if (opt.UsePhysProto && db_get_ws(0, protonam, "AM_BaseProto", &dbv) == 0) {
categoryName = L"AllProto";
categoryName += dbv.pwszVal;
db_free(&dbv);
CMStringW categoryFileName = g_SmileyCategories.GetSmileyCategory(categoryName) ? g_SmileyCategories.GetSmileyCategory(categoryName)->GetFilename() : L"";
if (categoryFileName.IsEmpty())
categoryName = _A2T(protonam);
}
else
categoryName = _A2T(protonam);
}
}
}
if (categoryName.IsEmpty()) {
if (proto == nullptr || proto[0] == 0)
categoryName = L"Standard";
else {
categoryName = _A2T(proto);
if (opt.UseOneForAll) {
SmileyCategoryType *smc = g_SmileyCategories.GetSmileyCategory(categoryName);
if (smc == nullptr || smc->IsProto())
categoryName = L"Standard";
}
}
}
return g_SmileyCategories.GetSmileyPack(categoryName);
}
INT_PTR ReplaceSmileysCommand(WPARAM, LPARAM lParam)
{
SMADD_RICHEDIT3 *smre = (SMADD_RICHEDIT3*)lParam;
if (smre == nullptr)
return FALSE;
SMADD_RICHEDIT3 smrec = { 0 };
memcpy(&smrec, smre, min(smre->cbSize, sizeof(smrec)));
static const CHARRANGE selection = { 0, LONG_MAX };
if (smre->rangeToReplace == nullptr) smrec.rangeToReplace = (CHARRANGE*)&selection;
else if (smrec.rangeToReplace->cpMax < 0) smrec.rangeToReplace->cpMax = LONG_MAX;
SmileyPackCType *smcp = nullptr;
SmileyPackType *SmileyPack = GetSmileyPack(smrec.Protocolname, smrec.hContact,
(smrec.flags & (SAFLRE_OUTGOING | SAFLRE_NOCUSTOM)) ? nullptr : &smcp);
ReplaceSmileys(smre->hwndRichEditControl, SmileyPack, smcp, *smrec.rangeToReplace,
smrec.hContact == 0, false, false, (smre->flags & SAFLRE_FIREVIEW) ? true : false);
return TRUE;
}
INT_PTR ShowSmileySelectionCommand(WPARAM, LPARAM lParam)
{
SMADD_SHOWSEL3 *smaddInfo = (SMADD_SHOWSEL3*)lParam;
if (smaddInfo == nullptr) return FALSE;
HWND parent = smaddInfo->hwndParent;
MCONTACT hContact = smaddInfo->hContact;
SmileyToolWindowParam *stwp = new SmileyToolWindowParam;
stwp->pSmileyPack = GetSmileyPack(smaddInfo->Protocolname, hContact);
stwp->hContact = hContact;
stwp->hWndParent = parent;
stwp->hWndTarget = smaddInfo->hwndTarget;
stwp->targetMessage = smaddInfo->targetMessage;
stwp->targetWParam = smaddInfo->targetWParam;
stwp->xPosition = smaddInfo->xPosition;
stwp->yPosition = smaddInfo->yPosition;
stwp->direction = smaddInfo->Direction;
mir_forkThread(SmileyToolThread, stwp);
return TRUE;
}
static int GetInfoCommandE(SMADD_INFO2 *smre, bool retDup)
{
if (smre == nullptr) return FALSE;
MCONTACT hContact = smre->hContact;
SmileyPackType *SmileyPack = GetSmileyPack(smre->Protocolname, hContact);
if (SmileyPack == nullptr || SmileyPack->SmileyCount() == 0) {
smre->ButtonIcon = nullptr;
smre->NumberOfSmileys = 0;
smre->NumberOfVisibleSmileys = 0;
return FALSE;
}
SmileyType *sml = FindButtonSmiley(SmileyPack);
if (sml != nullptr)
smre->ButtonIcon = retDup ? sml->GetIconDup() : sml->GetIcon();
else
smre->ButtonIcon = GetDefaultIcon(retDup);
smre->NumberOfSmileys = SmileyPack->SmileyCount();
smre->NumberOfVisibleSmileys = SmileyPack->VisibleSmileyCount();
return TRUE;
}
INT_PTR GetInfoCommand(WPARAM, LPARAM lParam)
{
return GetInfoCommandE((SMADD_INFO2*)lParam, false);
}
INT_PTR GetInfoCommand2(WPARAM, LPARAM lParam)
{
return GetInfoCommandE((SMADD_INFO2*)lParam, true);
}
INT_PTR ParseTextBatch(WPARAM, LPARAM lParam)
{
SMADD_BATCHPARSE2 *smre = (SMADD_BATCHPARSE2*)lParam;
if (smre == nullptr) return FALSE;
MCONTACT hContact = smre->hContact;
SmileyPackCType *smcp = nullptr;
SmileyPackType *SmileyPack = GetSmileyPack(smre->Protocolname, hContact,
(smre->flag & (SAFL_OUTGOING | SAFL_NOCUSTOM)) ? nullptr : &smcp);
SmileysQueueType smllist;
if (smre->flag & SAFL_UNICODE)
LookupAllSmileys(SmileyPack, smcp, smre->wstr, smllist, false);
else
LookupAllSmileys(SmileyPack, smcp, _A2T(smre->astr), smllist, false);
if (smllist.getCount() == 0)
return 0;
SMADD_BATCHPARSERES *res = new SMADD_BATCHPARSERES[smllist.getCount()];
SMADD_BATCHPARSERES *cres = res;
for (auto &it : smllist) {
cres->startChar = it->loc.cpMin;
cres->size = it->loc.cpMax - it->loc.cpMin;
if (it->sml) {
if (smre->flag & SAFL_PATH)
cres->filepath = it->sml->GetFilePath().c_str();
else
cres->hIcon = it->sml->GetIconDup();
}
else {
if (smre->flag & SAFL_PATH)
cres->filepath = it->smlc->GetFilePath().c_str();
else
cres->hIcon = it->smlc->GetIcon();
}
cres++;
}
smre->numSmileys = smllist.getCount();
smre->oflag = smre->flag | SAFL_UNICODE;
return (INT_PTR)res;
}
INT_PTR FreeTextBatch(WPARAM, LPARAM lParam)
{
delete[](SMADD_BATCHPARSERES*)lParam;
return TRUE;
}
INT_PTR RegisterPack(WPARAM, LPARAM lParam)
{
SMADD_REGCAT *smre = (SMADD_REGCAT*)lParam;
if (smre == nullptr || smre->cbSize < sizeof(SMADD_REGCAT)) return FALSE;
if (IsBadStringPtrA(smre->name, 50) || IsBadStringPtrA(smre->dispname, 50)) return FALSE;
CMStringW nmd(_A2T(smre->dispname));
CMStringW nm(_A2T(smre->name));
g_SmileyCategories.AddAndLoad(nm, nmd);
return TRUE;
}
INT_PTR CustomCatMenu(WPARAM hContact, LPARAM lParam)
{
if (lParam != 0) {
SmileyCategoryType *smct = g_SmileyCategories.GetSmileyCategory((unsigned)lParam - 3);
if (smct != nullptr)
opt.WriteContactCategory(hContact, smct->GetName());
else {
CMStringW empty;
if (lParam == 1) empty = L"";
opt.WriteContactCategory(hContact, empty);
}
NotifyEventHooks(hEvent1, hContact, 0);
}
for (auto &it : menuHandleArray)
Menu_RemoveItem((HGENMENU)it);
menuHandleArray.destroy();
return TRUE;
}
int RebuildContactMenu(WPARAM wParam, LPARAM)
{
SmileyCategoryListType::SmileyCategoryVectorType &smc = *g_SmileyCategories.GetSmileyCategoryList();
char *protnam = Proto_GetBaseAccountName(wParam);
bool haveMenu = IsSmileyProto(protnam);
if (haveMenu && opt.UseOneForAll) {
unsigned cnt = 0;
for (auto &it : smc)
cnt += it->IsCustom();
haveMenu = cnt != 0;
}
Menu_ShowItem(hContactMenuItem, haveMenu);
for (auto &it : menuHandleArray)
Menu_RemoveItem((HGENMENU)it);
menuHandleArray.destroy();
if (haveMenu) {
CMStringW cat;
opt.ReadContactCategory(wParam, cat);
CMenuItem mi(&g_plugin);
mi.root = hContactMenuItem;
mi.flags = CMIF_UNICODE | CMIF_SYSTEM;
mi.pszService = MS_SMILEYADD_CUSTOMCATMENU;
bool nonecheck = true;
HGENMENU hMenu;
for (int i = 0; i < smc.getCount(); i++) {
if (smc[i].IsExt() || (smc[i].IsProto() && opt.UseOneForAll) || smc[i].GetFilename().IsEmpty())
continue;
const int ind = i + 3;
mi.position = ind;
mi.name.w = (wchar_t*)smc[i].GetDisplayName().c_str();
if (cat == smc[i].GetName()) {
mi.flags |= CMIF_CHECKED;
nonecheck = false;
}
hMenu = Menu_AddContactMenuItem(&mi);
Menu_ConfigureItem(hMenu, MCI_OPT_EXECPARAM, ind);
menuHandleArray.insert(hMenu);
mi.flags &= ~CMIF_CHECKED;
}
mi.position = 1;
mi.name.w = L"";
if (cat == L"") {
mi.flags |= CMIF_CHECKED;
nonecheck = false;
}
hMenu = Menu_AddContactMenuItem(&mi);
Menu_ConfigureItem(hMenu, MCI_OPT_EXECPARAM, 1);
menuHandleArray.insert(hMenu);
mi.position = 2;
mi.name.w = LPGENW("Protocol specific");
if (nonecheck) mi.flags |= CMIF_CHECKED; else mi.flags &= ~CMIF_CHECKED;
hMenu = Menu_AddContactMenuItem(&mi);
Menu_ConfigureItem(hMenu, MCI_OPT_EXECPARAM, 2);
menuHandleArray.insert(hMenu);
}
return 0;
}
INT_PTR ReloadPack(WPARAM, LPARAM lParam)
{
if (lParam) {
CMStringW categoryName = _A2T((char*)lParam);
SmileyCategoryType *smc = g_SmileyCategories.GetSmileyCategory(categoryName);
if (smc != nullptr)
smc->Load();
}
else {
g_SmileyCategories.ClearAll();
g_SmileyCategories.AddAllProtocolsAsCategory();
g_SmileyCategories.ClearAndLoadAll();
}
NotifyEventHooks(hEvent1, 0, 0);
return 0;
}
INT_PTR LoadContactSmileys(WPARAM, LPARAM lParam)
{
if (opt.DisableCustom) return 0;
SMADD_CONT *cont = (SMADD_CONT*)lParam;
switch (cont->type) {
case 0:
g_SmileyPackCStore.AddSmileyPack(cont->hContact, cont->path);
NotifyEventHooks(hEvent1, (WPARAM)cont->hContact, 0);
break;
case 1:
g_SmileyPackCStore.AddSmiley(cont->hContact, cont->path);
NotifyEventHooks(hEvent1, (WPARAM)cont->hContact, 0);
break;
}
return 0;
}
int AccountListChanged(WPARAM wParam, LPARAM lParam)
{
PROTOACCOUNT *acc = (PROTOACCOUNT*)lParam;
switch (wParam) {
case PRAC_ADDED:
if (acc != nullptr) {
CMStringW catname(L"Standard");
const CMStringW &defaultFile = g_SmileyCategories.GetSmileyCategory(catname)->GetFilename();
g_SmileyCategories.AddAccountAsCategory(acc, defaultFile);
}
break;
case PRAC_CHANGED:
if (acc != nullptr && acc->szModuleName != nullptr) {
CMStringW name(_A2T(acc->szModuleName));
SmileyCategoryType *smc = g_SmileyCategories.GetSmileyCategory(name);
if (smc != nullptr) {
if (acc->tszAccountName) name = acc->tszAccountName;
smc->SetDisplayName(name);
}
}
break;
case PRAC_REMOVED:
g_SmileyCategories.DeleteAccountAsCategory(acc);
break;
case PRAC_CHECKED:
if (acc != nullptr) {
if (acc->bIsEnabled) {
CMStringW catname(L"Standard");
const CMStringW &defaultFile = g_SmileyCategories.GetSmileyCategory(catname)->GetFilename();
g_SmileyCategories.AddAccountAsCategory(acc, defaultFile);
}
else g_SmileyCategories.DeleteAccountAsCategory(acc);
}
break;
}
return 0;
}
int DbSettingChanged(WPARAM hContact, LPARAM lParam)
{
if (hContact == 0)
return 0;
DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
if (cws->value.type == DBVT_DELETED)
return 0;
if (strcmp(cws->szSetting, "Transport") == 0) {
CMStringW catname(L"Standard");
SmileyCategoryType *smc = g_SmileyCategories.GetSmileyCategory(catname);
if (smc != nullptr)
g_SmileyCategories.AddContactTransportAsCategory(hContact, smc->GetFilename());
}
return 0;
}
int ReloadColour(WPARAM, LPARAM)
{
opt.SelWndBkgClr = db_get_dw(0, "SmileyAdd", "SelWndBkgClr", GetSysColor(COLOR_WINDOW));
return 0;
}