/*
Copyright (c) 2005 Victor Pavlychko (nullbyte@sotline.net.ua)
Copyright (C) 2012-24 Miranda NG team (https://miranda-ng.org)
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"
#include
Bitmap* LoadImageFromResource(HINSTANCE hInst, int resourceId, const wchar_t *pwszType)
{
if (HRSRC hrsrc = FindResourceW(hInst, MAKEINTRESOURCE(resourceId), pwszType)) {
if (DWORD dwSize = SizeofResource(hInst, hrsrc)) {
if (HGLOBAL hRes = LoadResource(hInst, hrsrc)) {
void *pImage = LockResource(hRes);
if (HGLOBAL hGlobal = ::GlobalAlloc(GHND, dwSize)) {
void *pBuffer = ::GlobalLock(hGlobal);
if (pBuffer) {
memcpy(pBuffer, pImage, dwSize);
CComPtr pStream;
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
if (SUCCEEDED(hr))
return new Gdiplus::Bitmap(pStream);
}
GlobalFree(hGlobal); // free memory only if the function fails
}
}
}
}
return nullptr;
}
/////////////////////////////////////////////////////////////////////////////////////////
int SmartSendEvent(int iEventType, MCONTACT hContact, LPARAM hEvent)
{
if (HWND hwnd = WindowList_Find(g_hNewstoryLogs, hContact))
SendMessage(hwnd, iEventType, hContact, hEvent);
if (db_mc_isMeta(hContact)) {
// Send a message to a real contact too
MCONTACT cc = db_event_getContact(hEvent);
if (cc != hContact)
if (HWND hwnd = WindowList_Find(g_hNewstoryLogs, cc))
SendMessage(hwnd, iEventType, cc, hEvent);
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
uint32_t toggleBit(uint32_t dw, uint32_t bit)
{
if (dw & bit)
return dw & ~bit;
return dw | bit;
}
bool CheckFilter(wchar_t *buf, wchar_t *filter)
{
// MessageBox(0, buf, filter, MB_OK);
int l1 = (int)mir_wstrlen(buf);
int l2 = (int)mir_wstrlen(filter);
for (int i = 0; i < l1 - l2 + 1; i++)
if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, buf + i, l2, filter, l2) == CSTR_EQUAL)
return true;
return false;
}
int GetFontHeight(const LOGFONTA &lf)
{
return 2 * abs(lf.lfHeight) * 74 / g_iPixelY;
}
/////////////////////////////////////////////////////////////////////////////////////////
struct
{
wchar_t *pStart, *pEnd;
size_t cbStart, cbEnd;
}
static bbcodes[] =
{
{ L"[b]", nullptr },
{ L"[/b]", nullptr },
{ L"[i]", nullptr },
{ L"[/i]", nullptr },
{ L"[u]", nullptr },
{ L"[/u]", nullptr },
{ L"[s]", nullptr },
{ L"[/s]", nullptr },
{ L"[color=", L"]" },
{ L"[/color]", nullptr },
{ L"[c0]", nullptr },
{ L"[c1]", nullptr },
{ L"[c2]", nullptr },
{ L"[c3]", nullptr },
{ L"[c4]", nullptr },
{ L"[c5]", nullptr },
{ L"[c6]", nullptr },
{ L"[$hicon=", L"$]" },
{ L"[url]", L"[/url]" },
{ L"[url=", L"]", },
{ L"[img]", L"[/img]" },
{ L"[img=", L"]" },
};
void RemoveBbcodes(CMStringW &wszText)
{
if (wszText.IsEmpty())
return;
if (bbcodes[0].cbStart == 0)
for (auto &it : bbcodes) {
it.cbStart = wcslen(it.pStart);
if (it.pEnd)
it.cbEnd = wcslen(it.pEnd);
}
for (int idx = wszText.Find('[', 0); idx != -1; idx = wszText.Find('[', idx)) {
bool bFound = false;
for (auto &it : bbcodes) {
if (wcsncmp(wszText.c_str() + idx, it.pStart, it.cbStart))
continue;
wszText.Delete(idx, (int)it.cbStart);
if (it.pEnd) {
int idx2 = wszText.Find(it.pEnd, idx);
if (idx2 != -1) {
wszText.Delete(idx, idx2 - idx);
wszText.Delete(idx, (int)it.cbEnd);
}
}
bFound = true;
break;
}
// just an occasional square bracket? skip it
if (!bFound)
idx++;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
static int countNoWhitespace(const wchar_t *str)
{
int c;
for (c = 0; *str != '\n' && *str != '\r' && *str != '\t' && *str != ' ' && *str != '\0'; str++, c++);
return c;
}
static int DetectUrl(const wchar_t *text)
{
int i;
for (i = 0; text[i] != '\0'; i++)
if (!((text[i] >= '0' && text[i] <= '9') || iswalpha(text[i])))
break;
if (i <= 0 || wcsncmp(text + i, L"://", 3))
return 0;
i += countNoWhitespace(text + i);
for (; i > 0; i--)
if ((text[i - 1] >= '0' && text[i - 1] <= '9') || iswalpha(text[i - 1]) || text[i - 1] == '/')
break;
return i;
}
void UrlAutodetect(CMStringW &str)
{
int level = 0;
for (auto *p = str.c_str(); *p; p++) {
if (!wcsncmp(p, L"[img=", 5) || !wcsncmp(p, L"[img]", 5) || !wcsncmp(p, L"[url]", 5) || !wcsncmp(p, L"[url=", 5)) {
p += 4;
level++;
}
if (!wcsncmp(p, L"[/img]", 6) || !wcsncmp(p, L"[/url]", 6)) {
p += 5;
level--;
}
else if (int len = DetectUrl(p)) {
if (level == 0) {
int pos = p - str.c_str();
CMStringW url = str.Mid(pos, len);
str.Insert(pos + len, L"[/url]");
str.Insert(pos, L"[url]");
p = str.c_str() + pos + len + 11;
}
}
}
}