From f920ef497f3299ae24fe783ce03bdd93b419f764 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Fri, 18 May 2012 22:02:50 +0000 Subject: plugins folders renaming git-svn-id: http://svn.miranda-ng.org/main/trunk@60 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/SmileyAdd/AniSmileyObject.cpp | 450 +++++ plugins/SmileyAdd/Res/smiley.ico | Bin 0 -> 2550 bytes plugins/SmileyAdd/SmileyAdd_10.sln | 26 + plugins/SmileyAdd/SmileyAdd_10.vcxproj | 352 ++++ plugins/SmileyAdd/SmileyAdd_10.vcxproj.filters | 148 ++ plugins/SmileyAdd/SmileyBase.cpp | 391 +++++ plugins/SmileyAdd/SmileyBase.h | 127 ++ plugins/SmileyAdd/anim.cpp | 184 +++ plugins/SmileyAdd/anim.h | 87 + plugins/SmileyAdd/bkstring.cpp | 215 +++ plugins/SmileyAdd/bkstring.h | 270 +++ plugins/SmileyAdd/customsmiley.cpp | 172 ++ plugins/SmileyAdd/customsmiley.h | 85 + plugins/SmileyAdd/dlgboxsubclass.cpp | 568 +++++++ .../SmileyAdd/docs/smileyadd_msl_specification.txt | 142 ++ plugins/SmileyAdd/docs/smileyadd_readme.txt | 1136 +++++++++++++ plugins/SmileyAdd/docs/smileyadd_screenshot.jpg | Bin 0 -> 32442 bytes plugins/SmileyAdd/docs/smileyadd_translation.txt | 125 ++ plugins/SmileyAdd/download.cpp | 292 ++++ plugins/SmileyAdd/download.h | 28 + plugins/SmileyAdd/general.cpp | 315 ++++ plugins/SmileyAdd/general.h | 252 +++ plugins/SmileyAdd/imagecache.cpp | 777 +++++++++ plugins/SmileyAdd/imagecache.h | 166 ++ plugins/SmileyAdd/main.cpp | 261 +++ plugins/SmileyAdd/mingw-comp.bat | 3 + plugins/SmileyAdd/options.cpp | 729 ++++++++ plugins/SmileyAdd/options.h | 60 + plugins/SmileyAdd/regexp/Matcher.cpp | 178 ++ plugins/SmileyAdd/regexp/Matcher.h | 248 +++ plugins/SmileyAdd/regexp/Pattern.cpp | 1709 +++++++++++++++++++ plugins/SmileyAdd/regexp/Pattern.h | 1663 +++++++++++++++++++ plugins/SmileyAdd/regexp/WCMatcher.cpp | 181 ++ plugins/SmileyAdd/regexp/WCMatcher.h | 234 +++ plugins/SmileyAdd/regexp/WCPattern.cpp | 1747 ++++++++++++++++++++ plugins/SmileyAdd/regexp/WCPattern.h | 1663 +++++++++++++++++++ plugins/SmileyAdd/regexp/test.cpp | 38 + plugins/SmileyAdd/resource.h | 49 + plugins/SmileyAdd/resource.rc | 214 +++ plugins/SmileyAdd/richcall.cpp | 554 +++++++ plugins/SmileyAdd/services.cpp | 597 +++++++ plugins/SmileyAdd/services.h | 48 + plugins/SmileyAdd/smileyroutines.cpp | 654 ++++++++ plugins/SmileyAdd/smileyroutines.h | 49 + plugins/SmileyAdd/smileys.cpp | 1152 +++++++++++++ plugins/SmileyAdd/smileys.h | 287 ++++ plugins/SmileyAdd/smltool.cpp | 785 +++++++++ plugins/SmileyAdd/smltool.h | 45 + plugins/SmileyAdd/version.h | 3 + 49 files changed, 19459 insertions(+) create mode 100644 plugins/SmileyAdd/AniSmileyObject.cpp create mode 100644 plugins/SmileyAdd/Res/smiley.ico create mode 100644 plugins/SmileyAdd/SmileyAdd_10.sln create mode 100644 plugins/SmileyAdd/SmileyAdd_10.vcxproj create mode 100644 plugins/SmileyAdd/SmileyAdd_10.vcxproj.filters create mode 100644 plugins/SmileyAdd/SmileyBase.cpp create mode 100644 plugins/SmileyAdd/SmileyBase.h create mode 100644 plugins/SmileyAdd/anim.cpp create mode 100644 plugins/SmileyAdd/anim.h create mode 100644 plugins/SmileyAdd/bkstring.cpp create mode 100644 plugins/SmileyAdd/bkstring.h create mode 100644 plugins/SmileyAdd/customsmiley.cpp create mode 100644 plugins/SmileyAdd/customsmiley.h create mode 100644 plugins/SmileyAdd/dlgboxsubclass.cpp create mode 100644 plugins/SmileyAdd/docs/smileyadd_msl_specification.txt create mode 100644 plugins/SmileyAdd/docs/smileyadd_readme.txt create mode 100644 plugins/SmileyAdd/docs/smileyadd_screenshot.jpg create mode 100644 plugins/SmileyAdd/docs/smileyadd_translation.txt create mode 100644 plugins/SmileyAdd/download.cpp create mode 100644 plugins/SmileyAdd/download.h create mode 100644 plugins/SmileyAdd/general.cpp create mode 100644 plugins/SmileyAdd/general.h create mode 100644 plugins/SmileyAdd/imagecache.cpp create mode 100644 plugins/SmileyAdd/imagecache.h create mode 100644 plugins/SmileyAdd/main.cpp create mode 100644 plugins/SmileyAdd/mingw-comp.bat create mode 100644 plugins/SmileyAdd/options.cpp create mode 100644 plugins/SmileyAdd/options.h create mode 100644 plugins/SmileyAdd/regexp/Matcher.cpp create mode 100644 plugins/SmileyAdd/regexp/Matcher.h create mode 100644 plugins/SmileyAdd/regexp/Pattern.cpp create mode 100644 plugins/SmileyAdd/regexp/Pattern.h create mode 100644 plugins/SmileyAdd/regexp/WCMatcher.cpp create mode 100644 plugins/SmileyAdd/regexp/WCMatcher.h create mode 100644 plugins/SmileyAdd/regexp/WCPattern.cpp create mode 100644 plugins/SmileyAdd/regexp/WCPattern.h create mode 100644 plugins/SmileyAdd/regexp/test.cpp create mode 100644 plugins/SmileyAdd/resource.h create mode 100644 plugins/SmileyAdd/resource.rc create mode 100644 plugins/SmileyAdd/richcall.cpp create mode 100644 plugins/SmileyAdd/services.cpp create mode 100644 plugins/SmileyAdd/services.h create mode 100644 plugins/SmileyAdd/smileyroutines.cpp create mode 100644 plugins/SmileyAdd/smileyroutines.h create mode 100644 plugins/SmileyAdd/smileys.cpp create mode 100644 plugins/SmileyAdd/smileys.h create mode 100644 plugins/SmileyAdd/smltool.cpp create mode 100644 plugins/SmileyAdd/smltool.h create mode 100644 plugins/SmileyAdd/version.h (limited to 'plugins/SmileyAdd') diff --git a/plugins/SmileyAdd/AniSmileyObject.cpp b/plugins/SmileyAdd/AniSmileyObject.cpp new file mode 100644 index 0000000000..42a63d3549 --- /dev/null +++ b/plugins/SmileyAdd/AniSmileyObject.cpp @@ -0,0 +1,450 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2008 - 2011 Boris Krasnovskiy All Rights Reserved + +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 "general.h" +#include "SmileyBase.h" +#include "m_smileyadd.h" +#include "smileys.h" +#include "options.h" + +#include + + +class CAniSmileyObject; + +static int CompareAniSmiley(const CAniSmileyObject* p1, const CAniSmileyObject* p2) +{ + return (int)((char*)p2 - (char*)p1); +} + +static LIST regAniSmileys(10, CompareAniSmiley); + +static UINT_PTR timerId; +static void CALLBACK timerProc(HWND, UINT, UINT_PTR, DWORD); + +static void CALLBACK sttMainThreadCallback( PVOID ) +{ + if (timerId == 0xffffffff) + timerId = SetTimer(NULL, 0, 100, (TIMERPROC)timerProc); +} + + +class CAniSmileyObject : public ISmileyBase +{ +private: + typedef enum { animStdOle, animDrctRichEd, animHpp } AnimType; + + POINTL m_rectOrig; + SIZEL m_rectExt; + + COLORREF m_bkg; + + SmileyType* m_sml; + ImageBase* m_img; + unsigned m_nFramePosition; + + long m_counter; + unsigned m_richFlags; + long m_lastObjNum; + + AnimType m_animtype; + bool m_allowAni; + +public: + CAniSmileyObject(SmileyType* sml, COLORREF clr, bool ishpp) + { + m_allowAni = false; + m_animtype = ishpp ? animHpp : animStdOle; + m_bkg = clr; + + m_rectOrig.x = 0; + m_rectOrig.y = 0; + m_rectExt.cx = 0; + m_rectExt.cy = 0; + + m_richFlags = 0; + m_lastObjNum = 0; + + m_sml = sml; + m_img = NULL; + m_nFramePosition = 0; + m_counter = 0; + } + + ~CAniSmileyObject(void) + { + UnloadSmiley(); + } + + void LoadSmiley(void) + { + if (m_img != NULL) return; + + m_img = m_sml->CreateCachedImage(); + if (m_img && m_img->IsAnimated() && opt.AnimateDlg) + { + m_nFramePosition = 0; + m_img->SelectFrame(m_nFramePosition); + long frtm = m_img->GetFrameDelay(); + m_counter = frtm / 10 + ((frtm % 10) >= 5); + + regAniSmileys.insert(this); + if (timerId == 0) + { + timerId = 0xffffffff; + CallFunctionAsync(sttMainThreadCallback, NULL); + } + } + else + m_nFramePosition = m_sml->GetStaticFrame(); + } + + void UnloadSmiley(void) + { + regAniSmileys.remove(this); + + if (timerId && (timerId+1) && regAniSmileys.getCount() == 0) + { + KillTimer(NULL, timerId); + timerId = 0; + } + if (m_img) m_img->Release(); + m_img = NULL; + } + + void GetDrawingProp(void) + { + if (m_hwnd == NULL) return; + + IRichEditOle* RichEditOle; + if (SendMessage(m_hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&RichEditOle) == 0) + return; + + REOBJECT reObj = {0}; + reObj.cbStruct = sizeof(REOBJECT); + + HRESULT hr = RichEditOle->GetObject(m_lastObjNum, &reObj, REO_GETOBJ_NO_INTERFACES); + if (hr == S_OK && reObj.dwUser == (DWORD)(ISmileyBase*)this && reObj.clsid == CLSID_NULL) + { + m_richFlags = reObj.dwFlags; + } + else + { + long objectCount = RichEditOle->GetObjectCount(); + for (long i = objectCount; i--; ) + { + HRESULT hr = RichEditOle->GetObject(i, &reObj, REO_GETOBJ_NO_INTERFACES); + if (FAILED(hr)) continue; + + if (reObj.dwUser == (DWORD)(ISmileyBase*)this && reObj.clsid == CLSID_NULL) + { + m_lastObjNum = i; + m_richFlags = reObj.dwFlags; + break; + } + } + } + RichEditOle->Release(); + + if ((m_richFlags & REO_SELECTED) == 0) + { + CHARRANGE sel; + SendMessage(m_hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (reObj.cp >= sel.cpMin && reObj.cp < sel.cpMax) + m_richFlags |= REO_INVERTEDSELECT; + else + m_richFlags &= ~REO_INVERTEDSELECT; + } + } + + + void DoDirectDraw(HDC hdc) + { + HBITMAP hBmp = CreateCompatibleBitmap(hdc, m_rectExt.cx, m_rectExt.cy); + HDC hdcMem = CreateCompatibleDC(hdc); + HANDLE hOld = SelectObject(hdcMem, hBmp); + + RECT rc; + rc.left = m_rectExt.cx - m_sizeExtent.cx; + rc.top = m_rectExt.cy - m_sizeExtent.cy; + rc.right = rc.left + m_sizeExtent.cx; + rc.bottom = rc.top + m_sizeExtent.cy; + + HBRUSH hbr = CreateSolidBrush(m_bkg); + RECT frc = { 0, 0, m_rectExt.cx, m_rectExt.cy }; + FillRect(hdcMem, &frc, hbr); + DeleteObject(hbr); + + m_img->DrawInternal(hdcMem, rc.left, rc.top, m_sizeExtent.cx - 1, m_sizeExtent.cy - 1); + + if (m_richFlags & REO_SELECTED) + { + HBRUSH hbr = CreateSolidBrush(m_bkg ^ 0xFFFFFF); + FrameRect(hdcMem, &rc, hbr); + DeleteObject(hbr); + } + + if (m_richFlags & REO_INVERTEDSELECT) + InvertRect(hdcMem, &rc); + + BitBlt(hdc, m_rectOrig.x, m_rectOrig.y, m_rectExt.cx, m_rectExt.cy, hdcMem, 0, 0, SRCCOPY); + + SelectObject(hdcMem, hOld); + DeleteObject(hBmp); + DeleteDC(hdcMem); + } + + void DrawOnRichEdit(void) + { + HDC hdc = GetDC(m_hwnd); + if (RectVisible(hdc, &m_orect)) + { + RECT crct; + GetClientRect(m_hwnd, &crct); + + HRGN hrgnOld = CreateRectRgnIndirect(&crct); + int res = GetClipRgn(hdc, hrgnOld); + + HRGN hrgn = CreateRectRgnIndirect(&crct); + SelectClipRgn(hdc, hrgn); + DeleteObject(hrgn); + + DoDirectDraw(hdc); + + SelectClipRgn(hdc, res < 1 ? NULL : hrgnOld); + DeleteObject(hrgnOld); + } + else + { + m_visible = false; + m_allowAni = false; + UnloadSmiley(); + } + ReleaseDC(m_hwnd, hdc); + } + + void DrawOnHPP(void) + { + FVCNDATA_NMHDR nmh = {0}; + nmh.code = NM_FIREVIEWCHANGE; + nmh.hwndFrom = m_hwnd; + + nmh.cbSize = sizeof(nmh); + nmh.bEvent = FVCN_PREFIRE; + nmh.bAction = FVCA_DRAW; + nmh.rcRect = m_orect; + SendMessage(GetParent(m_hwnd), WM_NOTIFY, (WPARAM)m_hwnd, (LPARAM)&nmh); + + switch (nmh.bAction) + { + case FVCA_DRAW: + // support for pseudo-edit mode and event details + m_animtype = m_dirAniAllow ? animDrctRichEd : animStdOle; + GetDrawingProp(); + DrawOnRichEdit(); + break; + + case FVCA_CUSTOMDRAW: + m_rectExt.cy = nmh.rcRect.bottom - nmh.rcRect.top; + m_rectExt.cx = nmh.rcRect.right - nmh.rcRect.left; + m_rectOrig.x = nmh.rcRect.left; + m_rectOrig.y = nmh.rcRect.top; + + m_bkg = nmh.clrBackground; + + DoDirectDraw(nmh.hDC); + + nmh.bEvent = FVCN_POSTFIRE; + SendMessage(GetParent(m_hwnd), WM_NOTIFY, (WPARAM)m_hwnd, (LPARAM)&nmh); + break; + + case FVCA_SKIPDRAW: + break; + + case FVCA_NONE: + m_visible = false; + break; + + default: + break; + } + } + + void ProcessTimerTick(void) + { + if (m_visible && m_img && --m_counter <= 0) + { + m_nFramePosition = m_img->SelectNextFrame(m_nFramePosition); + long frtm = m_img->GetFrameDelay(); + m_counter = frtm / 10 + ((frtm % 10) >= 5); + + switch (m_animtype) + { + case animStdOle: + if (m_allowAni) SendOnViewChange(); + else + { + m_visible = false; + UnloadSmiley(); + } + m_allowAni = false; + break; + + case animDrctRichEd: + DrawOnRichEdit(); + break; + + case animHpp: + DrawOnHPP(); + break; + } + } + } + + void SetPosition(HWND hwnd, LPCRECT lpRect) + { + ISmileyBase::SetPosition(hwnd, lpRect); + + m_allowAni = m_visible; + + if (m_visible) LoadSmiley(); + else UnloadSmiley(); + + if (lpRect == NULL) return; + if (m_animtype == animStdOle) + { + m_animtype = animDrctRichEd; + GetDrawingProp(); + } + + if (lpRect->top == -1) + { + m_rectOrig.x = lpRect->left; + m_rectOrig.y = lpRect->bottom - m_sizeExtent.cy; + m_rectExt.cy = m_sizeExtent.cy; + } + else if (lpRect->bottom == -1) + { + m_rectOrig.x = lpRect->left; + m_rectOrig.y = lpRect->top; + } + else + { + m_rectOrig.x = lpRect->left; + m_rectOrig.y = lpRect->top; + m_rectExt.cy = lpRect->bottom - lpRect->top; + } + } + + STDMETHOD(Close)(DWORD dwSaveOption) + { + m_visible = false; + UnloadSmiley(); + + return ISmileyBase::Close(dwSaveOption); + } + + STDMETHOD(Draw)(DWORD dwAspect, LONG, void*, DVTARGETDEVICE*, HDC, + HDC hdc, LPCRECTL pRectBounds, LPCRECTL /* pRectWBounds */, + BOOL (__stdcall *)(ULONG_PTR), ULONG_PTR) + { + if (dwAspect != DVASPECT_CONTENT) return DV_E_DVASPECT; + if (pRectBounds == NULL) return E_INVALIDARG; + + LoadSmiley(); + + if (m_img == NULL) return E_FAIL; + + m_sizeExtent.cx = pRectBounds->right - pRectBounds->left; + m_sizeExtent.cy = pRectBounds->bottom - pRectBounds->top; + + m_rectExt = m_sizeExtent; + + switch (m_animtype) + { + case animDrctRichEd: + { + m_rectExt.cy = pRectBounds->bottom - m_rectOrig.y; + RECT frc = { 0, 0, m_sizeExtent.cx - 1, m_sizeExtent.cy - 1 }; + + HBITMAP hBmp = CreateCompatibleBitmap(hdc, frc.right, frc.bottom); + HDC hdcMem = CreateCompatibleDC(hdc); + HANDLE hOld = SelectObject(hdcMem, hBmp); + + HBRUSH hbr = CreateSolidBrush(m_bkg); + FillRect(hdcMem, &frc, hbr); + DeleteObject(hbr); + + m_img->DrawInternal(hdcMem, 0, 0, frc.right, frc.bottom); + + BitBlt(hdc, pRectBounds->left, pRectBounds->top, frc.right, frc.bottom, hdcMem, 0, 0, SRCCOPY); + + SelectObject(hdcMem, hOld); + DeleteObject(hBmp); + DeleteDC(hdcMem); + } + GetDrawingProp(); + break; + + case animHpp: + m_orect = *(LPRECT)pRectBounds; + + default: + m_img->DrawInternal(hdc, pRectBounds->left, pRectBounds->top, + m_sizeExtent.cx - 1, m_sizeExtent.cy - 1); + break; + } + + m_allowAni = true; + m_visible = true; + + return S_OK; + } + + STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL* psizel) + { + HRESULT hr = ISmileyBase::SetExtent(dwDrawAspect, psizel); + if (hr == S_OK) m_rectExt = m_sizeExtent; + return hr; + } +}; + +ISmileyBase* CreateAniSmileyObject(SmileyType* sml, COLORREF clr, bool ishpp) +{ + if (!sml->IsValid()) return NULL; + + CAniSmileyObject *obj = new CAniSmileyObject(sml, clr, ishpp); + return obj; +} + +static void CALLBACK timerProc(HWND, UINT, UINT_PTR, DWORD) +{ + for (int i=0; iProcessTimerTick(); +} + +void DestroyAniSmileys(void) +{ + if (timerId && (timerId+1)) + { + KillTimer(NULL, timerId); + timerId = 0; + } + regAniSmileys.destroy(); +} + diff --git a/plugins/SmileyAdd/Res/smiley.ico b/plugins/SmileyAdd/Res/smiley.ico new file mode 100644 index 0000000000..b6e4190f7c Binary files /dev/null and b/plugins/SmileyAdd/Res/smiley.ico differ diff --git a/plugins/SmileyAdd/SmileyAdd_10.sln b/plugins/SmileyAdd/SmileyAdd_10.sln new file mode 100644 index 0000000000..1010540c7f --- /dev/null +++ b/plugins/SmileyAdd/SmileyAdd_10.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmileyAdd", "SmileyAdd_10.vcxproj", "{5BBA7E51-B494-4462-BC4F-1AE5F57F9857}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857}.Debug|Win32.ActiveCfg = Debug|Win32 + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857}.Debug|Win32.Build.0 = Debug|Win32 + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857}.Debug|x64.ActiveCfg = Debug|x64 + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857}.Debug|x64.Build.0 = Debug|x64 + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857}.Release|Win32.ActiveCfg = Release|Win32 + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857}.Release|Win32.Build.0 = Release|Win32 + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857}.Release|x64.ActiveCfg = Release|x64 + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/SmileyAdd/SmileyAdd_10.vcxproj b/plugins/SmileyAdd/SmileyAdd_10.vcxproj new file mode 100644 index 0000000000..4828e65473 --- /dev/null +++ b/plugins/SmileyAdd/SmileyAdd_10.vcxproj @@ -0,0 +1,352 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + SmileyAdd + {5BBA7E51-B494-4462-BC4F-1AE5F57F9857} + SmileyAdd + + + + DynamicLibrary + false + false + Unicode + true + + + DynamicLibrary + false + false + Unicode + + + DynamicLibrary + false + false + Unicode + true + + + DynamicLibrary + false + false + Unicode + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + true + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + true + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + false + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + false + $(ProjectName)W + $(ProjectName)W + $(ProjectName)W + $(ProjectName)W + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/help.tlb + + + Disabled + ../../include;../ExternalAPI;regexp;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;_WIN32_WINDOWS=0x0410;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + EnableFastChecks + false + MultiThreadedDebug + true + Fast + false + Level4 + EditAndContinue + Default + + + _DEBUG;%(PreprocessorDefinitions) + + + comctl32.lib;Delayimp.lib;gdiplus.lib;%(AdditionalDependencies) + 0.2.3.16 + gdiplus.dll;%(DelayLoadDLLs) + true + Windows + 0x28110000 + false + true + MachineX86 + $(IntDir)$(TargetName).lib + $(TargetDir)$(TargetName).pdb + + + + $(IntDir)$(TargetName).bsc + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Debug/help.tlb + + + Disabled + ../../include;../ExternalAPI;regexp;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + EnableFastChecks + false + MultiThreadedDebug + true + Fast + false + Level4 + ProgramDatabase + Default + + + _DEBUG;%(PreprocessorDefinitions) + + + comctl32.lib;Delayimp.lib;gdiplus.lib;%(AdditionalDependencies) + 0.2.3.16 + gdiplus.dll;%(DelayLoadDLLs) + true + 0x28110000 + false + true + MachineX64 + $(IntDir)$(TargetName).lib + $(TargetDir)$(TargetName).pdb + + + + $(IntDir)$(TargetName).bsc + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/help.tlb + + + Full + OnlyExplicitInline + true + Size + false + ../../include;../ExternalAPI;regexp;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;_WIN32_WINDOWS=0x0410;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + false + MultiThreadedDLL + false + false + Fast + false + false + + + true + Level4 + Cdecl + Default + + + NDEBUG;%(PreprocessorDefinitions) + + + false + + + comctl32.lib;Delayimp.lib;gdiplus.lib;%(AdditionalDependencies) + 0.2.3.16 + gdiplus.dll;%(DelayLoadDLLs) + false + true + true + 0x28110000 + false + true + true + MachineX86 + $(IntDir)$(TargetName).lib + + + true + $(TargetDir)$(TargetName).pdb + + + + $(IntDir)$(TargetName).bsc + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Release/help.tlb + + + Full + OnlyExplicitInline + true + Size + ../../include;../ExternalAPI;regexp;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;_WIN32_WINDOWS=0x0410;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + false + MultiThreadedDLL + false + false + Fast + false + true + Level4 + Cdecl + Default + + + NDEBUG;%(PreprocessorDefinitions) + + + false + + + comctl32.lib;Delayimp.lib;gdiplus.lib;%(AdditionalDependencies) + 0.2.3.16 + gdiplus.dll;%(DelayLoadDLLs) + $(TargetDir)$(TargetName).pdb + true + true + 0x28110000 + false + true + MachineX64 + $(IntDir)$(TargetName).lib + + + true + + + + $(IntDir)$(TargetName).bsc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/SmileyAdd/SmileyAdd_10.vcxproj.filters b/plugins/SmileyAdd/SmileyAdd_10.vcxproj.filters new file mode 100644 index 0000000000..a78673b586 --- /dev/null +++ b/plugins/SmileyAdd/SmileyAdd_10.vcxproj.filters @@ -0,0 +1,148 @@ + + + + + {293a7f44-7469-4a9f-8f6e-5615ff66771a} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {bf1493ea-a6cc-4923-befa-2586a750c0fd} + h;hpp;hxx;hm;inl + + + {f30ee13d-9b85-424d-bdb9-c991748ed97c} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {8efee3ee-a59a-4e9b-a0a4-b82a7481a40f} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + Documents + + + Documents + + + Documents + + + \ No newline at end of file diff --git a/plugins/SmileyAdd/SmileyBase.cpp b/plugins/SmileyAdd/SmileyBase.cpp new file mode 100644 index 0000000000..28bd767153 --- /dev/null +++ b/plugins/SmileyAdd/SmileyBase.cpp @@ -0,0 +1,391 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2008 - 2011 Boris Krasnovskiy All Rights Reserved + +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 "general.h" +#include "SmileyBase.h" + +#include + +static void HiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix) +{ + HDC hDCScreen = GetDC(NULL); + const int nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX); + const int nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY); + ReleaseDC(NULL, hDCScreen); + + lpSizeInPix->cx = (lpSizeInHiMetric->cx * nPixelsPerInchX + (2540/2)) / 2540; + lpSizeInPix->cy = (lpSizeInHiMetric->cy * nPixelsPerInchY + (2540/2)) / 2540; +} + +static int CompareISmileyBase(const ISmileyBase* p1, const ISmileyBase* p2) +{ + return (int)((char*)p2 - (char*)p1); +} + +static LIST regSmileys(10, CompareISmileyBase); + +// {105C56DF-6455-4705-A501-51F1CCFCF688} +const GUID IID_ISmileyAddSmiley = +{ 0x105c56df, 0x6455, 0x4705, { 0xa5, 0x1, 0x51, 0xf1, 0xcc, 0xfc, 0xf6, 0x88 } }; + +// {58B32D03-1BD2-4840-992E-9AE799FD4ADE} +const GUID IID_ITooltipData = +{ 0x58b32d03, 0x1bd2, 0x4840, { 0x99, 0x2e, 0x9a, 0xe7, 0x99, 0xfd, 0x4a, 0xde } }; + +ISmileyBase::ISmileyBase(void) +{ + m_spAdviseSink = NULL; + m_spClientSite = NULL; + m_spAdviseHolder = NULL; + m_lRefCount = 1; + m_advf = 0; + m_smltxt = NULL; + m_hwnd = NULL; + m_visible = false; + m_dirAniAllow = false; + + memset(&m_sizeExtent, 0, sizeof(m_sizeExtent)); + memset(&m_sizeExtentHiM, 0, sizeof(m_sizeExtentHiM)); + memset(&m_orect, 0, sizeof(m_orect)); + + regSmileys.insert(this); +} + +ISmileyBase::~ISmileyBase(void) +{ + free(m_smltxt); + + Close(OLECLOSE_NOSAVE); + + if (m_spClientSite) + { + m_spClientSite->Release(); + m_spClientSite = NULL; + } + if (m_spAdviseHolder) + { + m_spAdviseHolder->Release(); + m_spAdviseHolder = NULL; + } +} + +void ISmileyBase::OnClose(void) +{ + if (m_spAdviseHolder) m_spAdviseHolder->SendOnClose(); +} + +void ISmileyBase::SendOnViewChange(void) +{ + if (m_spAdviseSink) m_spAdviseSink->OnViewChange(DVASPECT_CONTENT, -1); + if (m_advf & ADVF_ONLYONCE) + { + m_spAdviseSink->Release(); + m_spAdviseSink = NULL; + m_advf = 0; + } +} + +bool ISmileyBase::QueryHitPointSpecial(int x, int y, HWND hwnd, TCHAR** smltxt) +{ + bool result = m_visible && m_hwnd == hwnd; + if (result) + { + result = x >= m_orect.left && x <= m_orect.right && + y >= m_orect.top && y <= m_orect.bottom; + } + if (result) *smltxt = m_smltxt; + return result; +} + +void ISmileyBase::SetHint(TCHAR* smltxt) +{ + m_smltxt = _tcsdup(smltxt); +} + + +void ISmileyBase::SetPosition(HWND hwnd, LPCRECT lpRect) +{ + m_hwnd = hwnd; + if (lpRect == NULL || (lpRect->top == -1 && lpRect->bottom == -1)) + { + m_visible = false; + } + else + { + m_visible = true; + m_dirAniAllow = true; + m_orect.left = lpRect->left; + m_orect.right = lpRect->left + m_sizeExtent.cx; + if (lpRect->top == -1) + { + m_orect.top = lpRect->bottom - m_sizeExtent.cy; + m_orect.bottom = lpRect->bottom; + } + else if (lpRect->bottom == -1) + { + m_orect.top = lpRect->top; + m_orect.bottom = lpRect->top + m_sizeExtent.cy;; + } + else + { + m_orect.top = lpRect->bottom - m_sizeExtent.cy; + m_orect.bottom = lpRect->bottom; + } + } +} + + +// +// IUnknown members +// +ULONG ISmileyBase::AddRef(void) +{ return InterlockedIncrement(&m_lRefCount); } + +ULONG ISmileyBase::Release(void) +{ + LONG count = InterlockedDecrement(&m_lRefCount); + if(count == 0) + delete this; + return count; +} + + +HRESULT ISmileyBase::QueryInterface(REFIID iid, void ** ppvObject) +{ + // check to see what interface has been requested + if (ppvObject == NULL) return E_POINTER; + if (iid == IID_ISmileyAddSmiley) + *ppvObject = this; + else if (iid == IID_ITooltipData) + *ppvObject = static_cast(this); + else if (iid == IID_IViewObject) + *ppvObject = static_cast(this); + else if (iid == IID_IOleObject) + *ppvObject = static_cast(this); + else if (iid == IID_IUnknown) + *ppvObject = this; + else if (iid == IID_IViewObject2) + *ppvObject = static_cast(this); + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +// +// IOleObject members +// +HRESULT ISmileyBase::SetClientSite(IOleClientSite *pClientSite) +{ + if (m_spClientSite != NULL) m_spClientSite->Release(); + m_spClientSite = pClientSite; + if (m_spClientSite != NULL) m_spClientSite->AddRef(); + return S_OK; +} + +HRESULT ISmileyBase::GetClientSite(IOleClientSite **ppClientSite) +{ + if (ppClientSite == NULL) return E_POINTER; + *ppClientSite = m_spClientSite; + if (m_spClientSite != NULL) m_spClientSite->AddRef(); + return S_OK; +} + +HRESULT ISmileyBase::SetHostNames(LPCOLESTR /* szContainerApp */, LPCOLESTR /* szContainerObj */) +{ return S_OK; } + +HRESULT ISmileyBase::Close(DWORD /* dwSaveOption */) +{ + regSmileys.remove(this); + + if (m_spAdviseSink) m_spAdviseSink->Release(); + m_spAdviseSink = NULL; + + return S_OK; +} + +HRESULT ISmileyBase::SetMoniker(DWORD /* dwWhichMoniker */, IMoniker* /* pmk */) +{ return E_NOTIMPL; } + +HRESULT ISmileyBase::GetMoniker(DWORD /* dwAssign */, DWORD /* dwWhichMoniker */, IMoniker** /* ppmk */) +{ return E_NOTIMPL; } + +HRESULT ISmileyBase::InitFromData(IDataObject* /* pDataObject */, BOOL /* fCreation */, DWORD /* dwReserved */) +{ return E_NOTIMPL; } + +HRESULT ISmileyBase::GetClipboardData(DWORD /* dwReserved */, IDataObject** /* ppDataObject */) +{ return E_NOTIMPL; } + +HRESULT ISmileyBase::DoVerb(LONG /* iVerb */, LPMSG /* pMsg */, IOleClientSite* /* pActiveSite */, LONG /* lindex */, + HWND /* hwndParent */, LPCRECT /* lprcPosRect */) +{ + return E_NOTIMPL; +} + +HRESULT ISmileyBase::EnumVerbs(IEnumOLEVERB** /*ppEnumOleVerb*/) { return E_NOTIMPL; } +HRESULT ISmileyBase::Update(void) { return S_OK; } +HRESULT ISmileyBase::IsUpToDate(void) { return S_OK; } + +HRESULT ISmileyBase::GetUserClassID(CLSID *pClsid) +{ + if (!pClsid) return E_POINTER; + *pClsid = CLSID_NULL; + return S_OK; +} + +HRESULT ISmileyBase::GetUserType(DWORD /*dwFormOfType*/, LPOLESTR* /*pszUserType*/) +{ return E_NOTIMPL; } + +HRESULT ISmileyBase::SetExtent(DWORD dwDrawAspect, SIZEL* psizel) +{ + if (dwDrawAspect != DVASPECT_CONTENT) return E_FAIL; + if (psizel == NULL) return E_POINTER; + + HiMetricToPixel(psizel, &m_sizeExtent); + m_sizeExtentHiM = *psizel; + return S_OK; +} + +HRESULT ISmileyBase::GetExtent(DWORD dwDrawAspect, SIZEL *psizel) +{ + if (dwDrawAspect != DVASPECT_CONTENT) return E_FAIL; + if (psizel == NULL) return E_POINTER; + + *psizel = m_sizeExtentHiM; + return S_OK; +} + +HRESULT ISmileyBase::Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection) +{ + HRESULT hr = S_OK; + if (m_spAdviseHolder == NULL) + hr = CreateOleAdviseHolder(&m_spAdviseHolder); + if (SUCCEEDED(hr)) + hr = m_spAdviseHolder->Advise(pAdvSink, pdwConnection); + else + m_spAdviseHolder = NULL; + return hr; +} + +HRESULT ISmileyBase::Unadvise(DWORD dwConnection) +{ + return m_spAdviseHolder ? m_spAdviseHolder->Unadvise(dwConnection) : E_FAIL; +} + +HRESULT ISmileyBase::EnumAdvise(IEnumSTATDATA **ppEnumAdvise) +{ + if (ppEnumAdvise == NULL) return E_POINTER; + return m_spAdviseHolder ? m_spAdviseHolder->EnumAdvise(ppEnumAdvise) : E_FAIL; +} + +HRESULT ISmileyBase::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus) +{ + if (pdwStatus == NULL) return E_POINTER; + if (dwAspect == DVASPECT_CONTENT) + { + *pdwStatus = OLEMISC_STATIC | OLEMISC_INVISIBLEATRUNTIME | + OLEMISC_CANTLINKINSIDE | OLEMISC_NOUIACTIVATE; + return S_OK; + } + else + { + *pdwStatus = 0; + return E_FAIL; + } +} + +HRESULT ISmileyBase::SetColorScheme(LOGPALETTE* /* pLogpal */) +{ return E_NOTIMPL; } + +// +// IViewObject members +// +HRESULT ISmileyBase::SetAdvise(DWORD aspect, DWORD advf, IAdviseSink* pAdvSink) +{ + if (aspect != DVASPECT_CONTENT) return DV_E_DVASPECT; + m_advf = advf; + if (m_spAdviseSink) m_spAdviseSink->Release(); + m_spAdviseSink = pAdvSink; + if (advf & ADVF_PRIMEFIRST) SendOnViewChange(); + return S_OK; +} +HRESULT ISmileyBase::GetAdvise(DWORD* /*pAspects*/, DWORD* /*pAdvf*/, IAdviseSink** ppAdvSink) +{ + if (!ppAdvSink) return E_POINTER; + *ppAdvSink = m_spAdviseSink; + if (m_spAdviseSink) m_spAdviseSink->AddRef(); + return S_OK; +} +HRESULT ISmileyBase::Freeze(DWORD, long, void*, DWORD*) { return E_NOTIMPL; } +HRESULT ISmileyBase::Unfreeze(DWORD) { return E_NOTIMPL; } +HRESULT ISmileyBase::GetColorSet(DWORD, long, void*, DVTARGETDEVICE*, HDC, + LOGPALETTE**) { return E_NOTIMPL; } + +// +// IViewObject2 members +// +HRESULT ISmileyBase::GetExtent(DWORD aspect, long, DVTARGETDEVICE*, SIZEL* pSize) +{ + if (pSize == NULL) return E_POINTER; + if (aspect != DVASPECT_CONTENT) return DV_E_DVASPECT; + *pSize = m_sizeExtent; + return S_OK; +} + + +// +// ITooltipData members +// +HRESULT ISmileyBase::SetTooltip(BSTR /* bstrHint */) +{ + return S_OK; +} + +HRESULT ISmileyBase::GetTooltip(BSTR *bstrHint) +{ + if (bstrHint == NULL) return E_POINTER; + *bstrHint = SysAllocString(T2W_SM(m_smltxt)); + return S_OK; +} + + +void CloseSmileys(void) +{ + for (int i=regSmileys.getCount(); i--;) + { + regSmileys[i]->OnClose(); + regSmileys[i]->Close(OLECLOSE_NOSAVE); + } +} + +int CheckForTip(int x, int y, HWND hwnd, TCHAR** smltxt) +{ + for (int i=0; iQueryHitPointSpecial(x, y, hwnd, smltxt)) return i; + + return -1; +} + +void DestroySmileyBase(void) +{ + regSmileys.destroy(); +} + diff --git a/plugins/SmileyAdd/SmileyBase.h b/plugins/SmileyAdd/SmileyBase.h new file mode 100644 index 0000000000..3cdf244007 --- /dev/null +++ b/plugins/SmileyAdd/SmileyBase.h @@ -0,0 +1,127 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2008 - 2011 Boris Krasnovskiy All Rights Reserved + +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 . +*/ + +#pragma once +#include +#include + +#define OLEIVERB_SETOWNER (-24) + +EXTERN_C const IID IID_ITooltipData; + +class ITooltipData : public IUnknown +{ +public: + STDMETHOD(SetTooltip) (BSTR bstrHint) PURE; + STDMETHOD(GetTooltip) (BSTR * bstrHint) PURE; +}; + + +EXTERN_C const IID IID_ISmileyAddSmiley; + +class ISmileyBase : + public IOleObject, public IViewObject2, public ITooltipData +{ +protected: + IOleAdviseHolder* m_spAdviseHolder; + IAdviseSink* m_spAdviseSink; + IOleClientSite* m_spClientSite; + DWORD m_advf; + LONG m_lRefCount; + + SIZEL m_sizeExtent; + SIZEL m_sizeExtentHiM; + RECT m_orect; + + TCHAR* m_smltxt; + HWND m_hwnd; + + bool m_visible; + bool m_dirAniAllow; + +public: + ISmileyBase(void); + virtual ~ISmileyBase(void); + + void OnClose(void); + void SendOnViewChange(void); + + bool QueryHitPointSpecial(int x, int y, HWND hwnd, TCHAR** smltxt); + void SetHint(TCHAR* smltxt); + + virtual void SetPosition(HWND hwnd, LPCRECT lpRect); + + // + // IUnknown members + // + STDMETHOD_(ULONG, AddRef)(void); + STDMETHOD_(ULONG, Release)(void); + STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject); + + // + // IOleObject members + // + STDMETHOD(SetClientSite)(IOleClientSite *pClientSite); + STDMETHOD(GetClientSite)(IOleClientSite **ppClientSite); + STDMETHOD(SetHostNames)(LPCOLESTR /* szContainerApp */, LPCOLESTR /* szContainerObj */); + STDMETHOD(Close)(DWORD /* dwSaveOption */); + STDMETHOD(SetMoniker)(DWORD /* dwWhichMoniker */, IMoniker* /* pmk */); + STDMETHOD(GetMoniker)(DWORD /* dwAssign */, DWORD /* dwWhichMoniker */, IMoniker** /* ppmk */); + STDMETHOD(InitFromData)(IDataObject* /* pDataObject */, BOOL /* fCreation */, DWORD /* dwReserved */); + STDMETHOD(GetClipboardData)(DWORD /* dwReserved */, IDataObject** /* ppDataObject */); + STDMETHOD(DoVerb)(LONG /*iVerb*/, LPMSG /* pMsg */, IOleClientSite* /* pActiveSite */, LONG /* lindex */, + HWND /*hwndParent*/, LPCRECT /*lprcPosRect*/); + STDMETHOD(EnumVerbs)(IEnumOLEVERB** /*ppEnumOleVerb*/); + STDMETHOD(Update)(void); + STDMETHOD(IsUpToDate)(void); + STDMETHOD(GetUserClassID)(CLSID *pClsid); + STDMETHOD(GetUserType)(DWORD /*dwFormOfType*/, LPOLESTR* /*pszUserType*/); + STDMETHOD(SetExtent)(DWORD /*dwDrawAspect*/, SIZEL* /*psizel*/); + STDMETHOD(GetExtent)(DWORD dwDrawAspect, SIZEL *psizel); + STDMETHOD(Advise)(IAdviseSink *pAdvSink, DWORD *pdwConnection); + STDMETHOD(Unadvise)(DWORD dwConnection); + STDMETHOD(EnumAdvise)(IEnumSTATDATA **ppEnumAdvise); + STDMETHOD(GetMiscStatus)(DWORD dwAspect, DWORD *pdwStatus); + STDMETHOD(SetColorScheme)(LOGPALETTE* /* pLogpal */); + + // + // IViewObject members + // + STDMETHOD(SetAdvise)(DWORD aspect, DWORD advf, IAdviseSink* pAdvSink); + STDMETHOD(GetAdvise)(DWORD* /*pAspects*/, DWORD* /*pAdvf*/, IAdviseSink** ppAdvSink); + STDMETHOD(Freeze)(DWORD, long, void*, DWORD*); + STDMETHOD(Unfreeze)(DWORD); + STDMETHOD(GetColorSet)(DWORD, long, void*, DVTARGETDEVICE*, HDC, + LOGPALETTE**); + + // + // IViewObject2 members + // + STDMETHOD(GetExtent)(DWORD aspect, long, DVTARGETDEVICE*, SIZEL* pSize); + + // + // ITooltipData members + // + STDMETHOD(SetTooltip)(BSTR bstrHint); + STDMETHOD(GetTooltip)(BSTR * bstrHint); + +}; + +int CheckForTip(int x, int y, HWND hwnd, TCHAR** smltxt); +void CloseSmileys(void); + diff --git a/plugins/SmileyAdd/anim.cpp b/plugins/SmileyAdd/anim.cpp new file mode 100644 index 0000000000..5352383821 --- /dev/null +++ b/plugins/SmileyAdd/anim.cpp @@ -0,0 +1,184 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2006 - 2011 Boris Krasnovskiy All Rights Reserved + +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 "general.h" +#include "anim.h" + +#include + +Animate::Animate(SmileyType *sml, RECT& rect, HDC hdcMem, HBRUSH hbr, bool clip) + : m_sml(sml), m_img(NULL), + m_nFramePosition(0), m_sel(false), m_clip(clip), + m_offset(0), m_running(false), + m_hdcMem(hdcMem), m_hbr(hbr) +{ + m_cliprect = rect; +} + + +Animate::~Animate() +{ + if (m_img) m_img->Release(); +} + + +void Animate::StartAnimation(void) +{ + m_img = m_sml->CreateCachedImage(); + + if (m_img && m_img->IsAnimated()) + { + m_img->SelectFrame(m_nFramePosition); + long frtm = m_img->GetFrameDelay(); + m_counter = frtm / 10 + ((frtm % 10) >= 5); + } +} + + +void Animate::ProcessTimerTick(HWND hwnd) +{ + if (m_running && m_img->IsAnimated() && --m_counter <= 0) + { + m_nFramePosition = m_img->SelectNextFrame(m_nFramePosition); + + long frtm = m_img->GetFrameDelay(); + m_counter = frtm / 10 + ((frtm % 10) >= 5); + + HDC hdc = GetDC(hwnd); + DrawFrame(hdc); + ReleaseDC(hwnd, hdc); + } +} + + +void Animate::DrawFrame(HDC hdc) +{ + long width = m_cliprect.right - m_cliprect.left; + long height = m_cliprect.bottom - m_cliprect.top; + + RECT frc = { 0, 0, width, height }; + FillRect(m_hdcMem, &frc, m_hbr); + + m_img->Draw(m_hdcMem, frc, m_clip); + + BitBlt(hdc, m_cliprect.left, m_cliprect.top, width, height, m_hdcMem, 0, 0, SRCCOPY); + + if (m_sel) + DrawFocusRect(hdc, &m_cliprect); +} + + +void Animate::Draw(HDC hdc) +{ + if (m_running) + { + m_img->Draw(hdc, m_cliprect, m_clip); + + if (m_sel) + DrawFocusRect(hdc, &m_cliprect); + } +} + + +void Animate::SetOffset(int off, int wsize) +{ + const int dy = m_offset - off; + + m_cliprect.top += dy; + m_cliprect.bottom += dy; + + m_offset = off; + + m_running = m_cliprect.top >= 0 && m_cliprect.top < wsize; + if (m_running) + { + if (m_img == NULL) + { + StartAnimation(); + if (m_img == NULL) m_running = false; + } + } + else + { + if (m_img) m_img->Release(); + m_img = NULL; + } +} + + +void Animate::SetSel(int x, int y) +{ + m_sel = x >= m_cliprect.left && x < m_cliprect.right && + y >= m_cliprect.top && y < m_cliprect.bottom; +} + + +AnimatedPack::AnimatedPack(HWND hwnd, int wsize, SIZE& sel, COLORREF bkg) + : m_AniList(40), m_hwnd(hwnd), m_wsize(wsize) +{ + HDC hdc = GetDC(hwnd); + + m_hBmp = CreateCompatibleBitmap(hdc, sel.cx, sel.cy); + m_hdcMem = CreateCompatibleDC(hdc); + m_hOld = (HBITMAP)SelectObject(m_hdcMem, m_hBmp); + m_hbr = CreateSolidBrush(bkg); + + ReleaseDC(hwnd, hdc); +} + + +AnimatedPack::~AnimatedPack() +{ + DeleteObject(m_hbr); + SelectObject(m_hdcMem, m_hOld); + DeleteObject(m_hBmp); + DeleteDC(m_hdcMem); +} + + +void AnimatedPack::Add(SmileyType *sml, RECT rect, bool clip) +{ + m_AniList.insert(new Animate(sml, rect, m_hdcMem, m_hbr, clip)); +} + + +void AnimatedPack::Draw(HDC hdc) +{ + for (int i=0; i. +*/ + +#ifndef anim_h +#define anim_h + +#include "smileys.h" + +class Animate +{ +private: + + ImageBase *m_img; + SmileyType *m_sml; + + HDC m_hdcMem; + HBRUSH m_hbr; + + RECT m_cliprect; + + unsigned m_nFramePosition; + int m_offset; + int m_counter; + bool m_running; + bool m_sel; + bool m_clip; + + void DrawFrame(HDC hdc); + +public: + + Animate(SmileyType *sml, RECT &rect, HDC hdcMem, HBRUSH hbr, bool clip); + Animate(const Animate& an); + ~Animate(); + + void Draw(HDC hdc); + + void StartAnimation(void); + void SetOffset(int off, int wsize); + void SetSel(int x, int y); + + void ProcessTimerTick(HWND hwnd); +}; + +class AnimatedPack +{ +private: + OBJLIST m_AniList; + + HWND m_hwnd; + int m_wsize; + + HBRUSH m_hbr; + HBITMAP m_hBmp; + HDC m_hdcMem; + HBITMAP m_hOld; + + static unsigned CALLBACK AnimateThreadFunc ( void* arg ); + +public: + AnimatedPack(HWND hwnd, int wsize, SIZE& sel, COLORREF bkg); + ~AnimatedPack(); + + void Add(SmileyType *sml, RECT rect, bool clip); + void Draw(HDC hdc); + void SetOffset(int off); + void SetSel(RECT& rect); + + void ProcessTimerTick(HWND hwnd); +}; + +#endif diff --git a/plugins/SmileyAdd/bkstring.cpp b/plugins/SmileyAdd/bkstring.cpp new file mode 100644 index 0000000000..2973783abc --- /dev/null +++ b/plugins/SmileyAdd/bkstring.cpp @@ -0,0 +1,215 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2008 - 2011 Boris Krasnovskiy All Rights Reserved + +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 . +*/ + +#ifndef __GNUC__ +# ifdef _DEBUG +# define _CRTDBG_MAP_ALLOC +# include +# include +# else +# include +# endif +#endif + +#include +#include + +#include "bkstring.h" + + +bkstring::~bkstring() { if (sizeAlloced) free(buf); } + +void bkstring::reserve(size_type len) +{ + if (len >= sizeAlloced || sizeAlloced == 0) + { + if (sizeAlloced == 0) buf = NULL; + buf = (value_type*)realloc(buf, (len+1) * sizeof(value_type)); + if (sizeAlloced == 0) buf[0] = 0; + sizeAlloced = len+1; + } +} + +void bkstring::appendfmt(const value_type *fmt, ...) +{ + areserve(_tcslen(fmt)*2); + + va_list vararg; + va_start(vararg, fmt); + for (;;) + { + int len = _vsntprintf(buf + lenBuf, sizeAlloced - lenBuf - 1, fmt, vararg); + if (len < 0) + reserve(sizeAlloced + 256); + else + { + lenBuf += len; + buf[lenBuf] = 0; + break; + } + } + va_end(vararg); +} + +bkstring& bkstring::append(const value_type* _Ptr) +{ + size_type len = _tcslen(_Ptr); + areserve(len); + memcpy(buf+lenBuf, _Ptr, (len+1)*sizeof(value_type)); + lenBuf += len; + return *this; +} + +bkstring& bkstring::append(const value_type* _Ptr, size_type _Count) +{ + size_type len = min(_tcslen(_Ptr), _Count); + areserve(len); + memcpy(buf+lenBuf, _Ptr, len*sizeof(value_type)); + lenBuf += len; + buf[lenBuf] = 0; + return *this; +} + +bkstring& bkstring::append(const bkstring& _Str, size_type _Off, size_type _Count) +{ + size_type len = min(_Count, _Str.size() - _Off); + areserve(len); + memcpy(buf+lenBuf, _Str.c_str()+_Off, len*sizeof(value_type)); + lenBuf += len; + buf[lenBuf] = 0; + return *this; +} + +bkstring& bkstring::append(const bkstring& _Str) +{ + size_type len = _Str.size(); + areserve(len); + memcpy(buf+lenBuf, _Str.c_str(), len*sizeof(value_type)); + lenBuf += len; + buf[lenBuf] = 0; + return *this; +} + +bkstring& bkstring::append(size_type _Count, value_type _Ch) +{ + areserve(_Count); + for(size_type i=0; i<_Count; ++i) buf[lenBuf+i] = _Ch; + lenBuf += _Count; + buf[lenBuf] = 0; + return *this; +} + + +bkstring& bkstring::assign(const value_type* _Ptr, size_type _Count) +{ + if (_Count == 0 && sizeAlloced == 0) + { + buf = (TCHAR*)_T(""); + } + else + { + reserve(_Count); + memcpy(buf, _Ptr, _Count*sizeof(value_type)); + buf[_Count] = 0; + lenBuf = _Count; + } + return *this; +} + +bkstring& bkstring::assign(const bkstring& _Str, size_type _Off, size_type _Count) +{ + size_type len = min(_Count, _Str.size() - _Off); + if (len == 0 && sizeAlloced == 0) + { + buf = (TCHAR*)_T(""); + } + else + { + reserve(len); + memcpy(buf, _Str.c_str() + _Off, len*sizeof(value_type)); + lenBuf = len; + buf[len] = 0; + } + return *this; +} + +bkstring& bkstring::assign(size_type _Count, value_type _Ch) +{ + reserve(_Count); + for(size_type i=0; i<_Count; ++i) buf[i] = _Ch; + buf[_Count] = 0; + lenBuf = _Count; + return *this; +} + +bkstring::size_type bkstring::find(value_type _Ch, size_type _Off) const +{ + for (size_type i=_Off; i<=lenBuf; ++i) + if (buf[i] == _Ch) return i; + return (size_type)npos; +} + +bkstring::size_type bkstring::find(const value_type* _Ptr, size_type _Off) const +{ + if (_Off > lenBuf) return (size_type)npos; + + value_type* pstr = _tcsstr(buf+_Off, _Ptr); + return pstr ? pstr - buf : npos; +} + +bkstring::size_type bkstring::find_last_of(value_type _Ch, size_type _Off) const +{ + for (size_type i=(_Off == npos ? lenBuf : _Off); i--;) + if (buf[i] == _Ch) return i; + return (size_type)npos; +} + +bkstring& bkstring::insert(size_type _P0, const value_type* _Ptr, size_type _Count) +{ + size_type len = _tcslen(_Ptr); + if (_Count < len) len = _Count; + areserve(len); + value_type *p = buf + _P0; + memmove(p+len, p, (lenBuf-_P0+1)*sizeof(value_type)); + memcpy(p, _Ptr, _Count*sizeof(value_type)); + lenBuf += len; + return *this; +} + +bkstring& bkstring::insert(size_type _P0, size_type _Count, value_type _Ch) +{ + areserve(_Count); + value_type *p = buf + _P0; + memmove(p+_Count, p, (lenBuf-_P0+1)*sizeof(value_type)); + for(size_type i=0; i<_Count; ++i) p[i] = _Ch; + lenBuf += _Count; + return *this; +} + +bkstring& bkstring::erase(size_type _Pos, size_type _Count) +{ + if (_Pos < lenBuf) + { + const size_type len = min(lenBuf - _Pos, _Count); + value_type *p = buf + _Pos; + lenBuf -= len; + memmove(p, p+len, (lenBuf - _Pos)*sizeof(value_type)); + buf[lenBuf] = 0; + } + return *this; +} diff --git a/plugins/SmileyAdd/bkstring.h b/plugins/SmileyAdd/bkstring.h new file mode 100644 index 0000000000..eb164f74e2 --- /dev/null +++ b/plugins/SmileyAdd/bkstring.h @@ -0,0 +1,270 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2008 - 2011 Boris Krasnovskiy All Rights Reserved + +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 . +*/ + +#pragma once + +#include +#include + +#ifndef min +#define min(A, B) ((A) < (B) ? (A) : (B)) +#endif + +class bkstring +{ +public: + typedef size_t size_type; + typedef TCHAR value_type; + typedef value_type* iterator; + typedef const value_type* const_iterator; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + enum { npos = -1 }; +#else + static const size_type npos = size_type(-1); +#endif + +private: + value_type* buf; + size_type sizeAlloced; + size_type lenBuf; + + void areserve(size_type len) { reserve(lenBuf + len); } + +public: + + explicit bkstring() : buf((TCHAR*)_T("")), sizeAlloced(0), lenBuf(0) + {} + + bkstring(const value_type* _Ptr, size_type _Count) : sizeAlloced(0), lenBuf(0) + { assign(_Ptr, _Count); } + + bkstring(const value_type* _Ptr) : sizeAlloced(0), lenBuf(0) + { assign(_Ptr); } + + bkstring(size_type _Count, value_type _Ch) : sizeAlloced(0), lenBuf(0) + { assign(_Count, _Ch); } + + bkstring(const bkstring& _Str) : sizeAlloced(0), lenBuf(0) + { assign(_Str); } + + bkstring(const bkstring& _Str, size_type _Off, size_type _Count) : sizeAlloced(0), lenBuf(0) + { assign(_Str, _Off, _Count); } + + ~bkstring(); + + size_type size(void) const { return lenBuf; } + const value_type* c_str(void) const { return buf; } + + void clear(void) { if (lenBuf) { lenBuf = 0; buf[0] = 0; } } + void insert(const value_type *txt); + void reserve(size_type len); + + bkstring& assign(const value_type* _Ptr) + { return assign(_Ptr, _tcslen(_Ptr)); } + + bkstring& assign(const bkstring& _Str) + { return assign(_Str, 0, (size_type)npos); } + + bkstring& assign(const value_type* _Ptr, size_type _Count); + bkstring& assign(const bkstring& _Str, size_type off, size_type _Count); + bkstring& assign(size_type _Count, value_type _Ch); + + bkstring& append(const value_type* _Ptr); + bkstring& append(const value_type* _Ptr, size_type _Count); + bkstring& append(const bkstring& _Str, size_type _Off, size_type _Count); + bkstring& append(const bkstring& _Str); + bkstring& append(size_type _Count, value_type _Ch); + + int compare(const bkstring& _Str) const + { return _tcscmp(buf, _Str.c_str()); } + + int compare(size_type _Pos1, size_type _Num1, const bkstring& _Str) const + { return _tcsncmp(&buf[_Pos1], _Str.c_str(), _Num1); } + + int compare(size_type _Pos1, size_type _Num1, const bkstring& _Str, size_type _Off, size_type _Count) const + { return _tcsncmp(&buf[_Pos1], _Str.c_str()+_Off, min(_Num1, _Count)); } + + int compare(const value_type* _Ptr) const + { return _tcscmp(buf, _Ptr); } + + int compare(size_type _Pos1, size_type _Num1, const value_type* _Ptr) const + { return _tcsncmp(&buf[_Pos1], _Ptr, _Num1); } + + int compare(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2) const + { return _tcsncmp(&buf[_Pos1], _Ptr, min(_Num1, _Num2)); } + + int comparei(const bkstring& _Str) const + { return _tcsicmp(buf, _Str.c_str()); } + + int comparei(size_type _Pos1, size_type _Num1, const bkstring& _Str) const + { return _tcsnicmp(&buf[_Pos1], _Str.c_str(), _Num1); } + + int comparei(size_type _Pos1, size_type _Num1, const bkstring& _Str, size_type _Off, size_type _Count) const + { return _tcsnicmp(&buf[_Pos1], _Str.c_str()+_Off, min(_Num1, _Count)); } + + int comparei(const value_type* _Ptr) const + { return _tcsicmp(buf, _Ptr); } + + int comparei(size_type _Pos1, size_type _Num1, const value_type* _Ptr) const + { return _tcsnicmp(&buf[_Pos1], _Ptr, _Num1); } + + int comparei(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2) const + { return _tcsnicmp(&buf[_Pos1], _Ptr, min(_Num1, _Num2)); } + + bool empty(void) const { return lenBuf == 0; }; + bkstring& erase(size_type _Pos = 0, size_type _Count = npos); + + size_type find(value_type _Ch, size_type _Off = 0) const; + size_type find(const value_type* _Ptr, size_type _Off = 0) const; + size_type find(bkstring& _Str, size_type _Off = 0) const + { return find(_Str.c_str(), _Off); } + + size_type find_last_of(value_type _Ch, size_type _Off = npos) const; + + bkstring& insert(size_type _P0, const value_type* _Ptr) + { return insert(_P0, _Ptr, _tcslen(_Ptr)); } + + bkstring& insert(size_type _P0, const bkstring& _Str) + { return insert(_P0, _Str.c_str(), _Str.size()); }; + + bkstring& insert(size_type _P0, const value_type* _Ptr, size_type _Count); + bkstring& insert(size_type _P0, size_type _Count, value_type _Ch); + + bkstring substr(size_type _Off = 0, size_type _Count = npos) const + { return bkstring(*this, _Off, _Count); } + + bkstring& operator = (const bkstring& _Str) + { return assign(_Str); } + + bkstring& operator =(const value_type* _Ptr) + { return assign(_Ptr); } + + bkstring& operator = (const value_type _Ch) + { return assign(1, _Ch); } + + bkstring& operator +=(const bkstring& _Str) + { return append(_Str); } + + bkstring& operator += (const value_type* _Ptr) + { return append(_Ptr); } + + bkstring& operator += (const value_type _Ch) + { return append(1, _Ch); } + + value_type& operator[] (int ind) const + { return buf[ind]; } + + friend bkstring operator+ (const bkstring& _Str1, const bkstring& _Str2) + { bkstring s(_Str1); return s.append(_Str2); } + + friend bkstring operator+ (const bkstring& _Str1, const value_type* _Ptr2) + { bkstring s(_Str1); return s.append(_Ptr2); } + + friend bkstring operator+(const value_type* _Ptr1, const bkstring& _Str2) + { bkstring s(_Ptr1); return s.append(_Str2); } + + friend bkstring operator+ (const bkstring& _Str1, const value_type _Ch) + { bkstring s(_Str1); return s.append(1, _Ch); } + + friend bool operator==(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) == 0; } + + friend bool operator==(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) == 0; } + + friend bool operator==(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) == 0; } + + friend bool operator!=(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) != 0; } + + friend bool operator!=(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) != 0; } + + friend bool operator!=(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) != 0; } + + friend bool operator<(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) < 0; } + + friend bool operator<(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) < 0; } + + friend bool operator<(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) > 0; } + + friend bool operator>(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) > 0; } + + friend bool operator>(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) > 0; } + + friend bool operator>(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) < 0; } + + friend bool operator<=(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) <= 0; } + + friend bool operator<=(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) <= 0; } + + friend bool operator<=(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) >= 0; } + + friend bool operator>=(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) >= 0; } + + friend bool operator>=(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) >= 0; } + + friend bool operator>=(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) <= 0; } + + friend bool operator==(const value_type _Ch1, const bkstring& _Str2) + { return (_Str2.size() == 1) && (_Str2[0] == _Ch1); } + + friend bool operator==(const bkstring& _Str1, const value_type _Ch2) + { return (_Str1.size() == 1) && (_Str1[0] == _Ch2); } + + friend bool operator!=(const value_type _Ch1, const bkstring& _Str2) + { return (_Str2.size() != 1) || (_Str2[0] != _Ch1); } + + friend bool operator!=(const bkstring& _Str1, const value_type _Ch2) + { return (_Str1.size() != 1) || (_Str1[0] != _Ch2); } + + iterator begin(void) + { return buf; } + + const_iterator begin(void) const + { return buf; } + + iterator end(void) + { return buf + lenBuf; } + + const_iterator end(void) const + { return buf + lenBuf; } + + // Custom extentions + + void appendfmt(const value_type *fmt, ...); + + size_type sizebytes(void) const { return lenBuf * sizeof(value_type); } +}; + +//const bkstring::size_type bkstring::npos = -1; diff --git a/plugins/SmileyAdd/customsmiley.cpp b/plugins/SmileyAdd/customsmiley.cpp new file mode 100644 index 0000000000..f125f015db --- /dev/null +++ b/plugins/SmileyAdd/customsmiley.cpp @@ -0,0 +1,172 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2008 - 2011 Boris Krasnovskiy All Rights Reserved + +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 "customsmiley.h" + +SmileyPackCListType g_SmileyPackCStore; + + +bool SmileyPackCListType::AddSmileyPack(HANDLE hContact, TCHAR* dir) +{ + bool res = true; + if (GetSmileyPack(hContact) == NULL) + { + SmileyPackCType *smileyPack = new SmileyPackCType; + + res = smileyPack->LoadSmileyDir(dir); + if (res) + { + smileyPack->SetId(hContact); + m_SmileyPacks.insert(smileyPack); + } + else + delete smileyPack; + } + return res; +} + + +bool SmileyPackCListType::AddSmiley(HANDLE hContact, TCHAR* path) +{ + SmileyPackCType* smpack = GetSmileyPack(hContact); + if (smpack == NULL) + { + smpack = new SmileyPackCType; + + smpack->SetId(hContact); + m_SmileyPacks.insert(smpack); + } + return smpack->LoadSmiley(path); +} + + +SmileyPackCType* SmileyPackCListType::GetSmileyPack(HANDLE id) +{ + for (int i = 0; i < m_SmileyPacks.getCount(); i++) + { + if (m_SmileyPacks[i].GetId() == id) return &m_SmileyPacks[i]; + } + return NULL; +} + + +SmileyCType::SmileyCType(const bkstring& fullpath, const TCHAR* filepath) +{ + LoadFromResource(fullpath, 0); + CreateTriggerText(T2A_SM(filepath)); +} + +bool SmileyCType::CreateTriggerText(char* text) +{ + UrlDecode(text); + + int len = (int)strlen(text); + if (len == 0) return false; + + int reslen = Netlib_GetBase64DecodedBufferSize(len)+1; + char* res = (char*)alloca(reslen); + + NETLIBBASE64 nlb = { text, len, ( PBYTE )res, reslen }; + if (!CallService(MS_NETLIB_BASE64DECODE, 0, LPARAM( &nlb ))) return false; + res[nlb.cbDecoded] = 0; + + TCHAR *txt = mir_utf8decodeT(res); + + if (txt == NULL) return false; + + m_TriggerText = txt; + mir_free(txt); + + return true; +} + + +// +// SmileyPackCType +// + +bool SmileyPackCType::LoadSmileyDir(TCHAR* dir) +{ + bkstring dirs = dir; + dirs += _T("\\*.*"); + + _tfinddata_t c_file; + INT_PTR hFile = _tfindfirst((TCHAR*)dirs.c_str(), &c_file); + if (hFile > -1L) + { + do { + if (c_file.name[0] != '.') + { + bkstring fullpath = dir; + fullpath = fullpath + _T("\\") + c_file.name; + TCHAR* div = _tcsrchr(c_file.name, '.'); + if (div) + { + *div = 0; + SmileyCType *smlc = new SmileyCType(fullpath, c_file.name); + if (smlc->GetTriggerText().empty()) + delete smlc; + else + m_SmileyList.insert(smlc); + } + } + } while( _tfindnext( hFile, &c_file ) == 0 ); + _findclose( hFile ); + AddTriggersToSmileyLookup(); + return true; + } + return false; +} + + +bool SmileyPackCType::LoadSmiley(TCHAR* path) +{ + bkstring dirs = path; + bkstring::size_type slash = dirs.find_last_of('\\'); + bkstring::size_type dot = dirs.find_last_of('.'); + + bkstring name = dirs.substr(slash+1, dot - slash - 1); + + for (int i=0; i < m_SmileyList.getCount(); i++) + { + if (m_SmileyList[i].GetTriggerText() == name) + { + m_SmileyList[i].LoadFromResource(dirs, 0); + return true; + } + } + + m_SmileyList.insert(new SmileyCType(dirs, (TCHAR*)name.c_str())); + + bkstring empty; + m_SmileyLookup.insert(new SmileyLookup( + m_SmileyList[m_SmileyList.getCount()-1].GetTriggerText(), false, m_SmileyList.getCount()-1, empty)); + + return true; +} + + +void SmileyPackCType::AddTriggersToSmileyLookup(void) +{ + bkstring empty; + for (int dist=0; dist. +*/ + +#include "general.h" +#include "smileys.h" + +#ifndef SMILEYADD_CUSTOMSMILEY_H_ +#define SMILEYADD_CUSTOMSMILEY_H_ + +class SmileyCType : public SmileyType +{ +public: + SmileyCType(const bkstring& fullpath, const TCHAR* filepath); + + bool CreateTriggerText(char* text); +}; + +class SmileyPackCType +{ +public: + typedef SMOBJLIST SmileyVectorType; + typedef SMOBJLIST SmileyLookupType; + +private: + SmileyVectorType m_SmileyList; + SmileyLookupType m_SmileyLookup; + + HANDLE m_id; + + void InsertLookup(SmileyCType& sml, bkstring& lk, bool first); + void AddTriggersToSmileyLookup(void); + +public: + SmileyVectorType& GetSmileyList(void) { return m_SmileyList; } + SmileyLookupType& GetSmileyLookup(void) { return m_SmileyLookup; } + + int SmileyCount(void) const { return m_SmileyList.getCount(); } + + SmileyCType* GetSmiley(unsigned index) { return &m_SmileyList[index]; } + + HANDLE GetId(void) { return m_id; } + void SetId(HANDLE id) { m_id = id; } + + bool LoadSmileyDir(TCHAR* dir); + bool LoadSmiley(TCHAR* path); +}; + + +class SmileyPackCListType +{ +public: + typedef SMOBJLIST SmileyPackVectorType; + +private: + SmileyPackVectorType m_SmileyPacks; + +public: + int NumberOfSmileyPacks(void) { return m_SmileyPacks.getCount(); } + + bool AddSmileyPack(HANDLE hContact, TCHAR* dir); + bool AddSmiley(HANDLE hContact, TCHAR* path); + + void ClearAndFreeAll(void) { m_SmileyPacks.destroy(); } + + SmileyPackCType* GetSmileyPack(HANDLE id); +}; + +extern SmileyPackCListType g_SmileyPackCStore; + +#endif diff --git a/plugins/SmileyAdd/dlgboxsubclass.cpp b/plugins/SmileyAdd/dlgboxsubclass.cpp new file mode 100644 index 0000000000..8da22c6cb1 --- /dev/null +++ b/plugins/SmileyAdd/dlgboxsubclass.cpp @@ -0,0 +1,568 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2005 - 2011 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 "general.h" +#include "smileyroutines.h" +#include "services.h" +#include "options.h" + +//***************************************************// +// DISCLAIMER!!! +// we are not supposed to use this object, so be aware +typedef struct NewMessageWindowLParam +{ + HANDLE hContact; + int isSend; + const char *szInitialText; +} +msgData; +// this is an undocumented object!!!!!!! +// subject to change in miranda versions...!!!!!! +// DISCLAIMER!!! +//***************************************************// + +extern HINSTANCE g_hInst; + +static HHOOK g_hMessageHookPre = NULL; +static HANDLE g_hMutex = NULL; +static HANDLE g_hHookMsgWnd = NULL; + +static LRESULT CALLBACK MessageDlgSubclas(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + +//type definitions +class MsgWndData +{ +public: + HWND hwnd; + char ProtocolName[52]; + HWND REdit; + HWND QuoteB; + HWND MEdit; + HWND MOK; + HWND LButton; + mutable HWND hSmlButton; + mutable HBITMAP hSmlBmp; + mutable HICON hSmlIco; + int idxLastChar; + WNDPROC wpOrigWndProc; + HANDLE hContact; + bool doSmileyReplace; + bool doSmileyButton; + bool OldButtonPlace; + bool isSplit; + bool isSend; + + MsgWndData() + { + ProtocolName[0] = 0; + REdit = NULL; + QuoteB = NULL; + MEdit = NULL; + MOK = NULL; + LButton = NULL; + hSmlButton = NULL; + hSmlBmp = NULL; + hSmlIco = NULL; + idxLastChar = 0; + hContact = NULL; + doSmileyReplace = false; + doSmileyButton = false; + OldButtonPlace = false; + isSplit = false; + isSend = false; + wpOrigWndProc = NULL; + } + + MsgWndData(const MsgWndData &dsb) + { + *this = dsb; + dsb.hSmlBmp = NULL; + dsb.hSmlIco = NULL; + dsb.hSmlButton = NULL; + } + + + ~MsgWndData() + { + clear(); + } + + void clear(void) + { + if (hSmlBmp != NULL) DeleteObject(hSmlBmp); + if (hSmlIco != NULL) DestroyIcon(hSmlIco); + if (hSmlButton != NULL) DestroyWindow(hSmlButton); + hSmlBmp = NULL; + hSmlIco = NULL; + hSmlButton = NULL; + } + + RECT CalcSmileyButtonPos(void) + { + RECT rect; + POINT pt; + + if (OldButtonPlace) + { + if (isSplit && DBGetContactSettingByte(NULL, "SRMsg", "ShowQuote", FALSE)) + { + GetWindowRect(QuoteB, &rect); + pt.x = rect.right + 12; + } + else + { + GetWindowRect(MEdit, &rect); + pt.x = rect.left; + } + GetWindowRect(MOK, &rect); + pt.y = rect.top; + } + else + { + GetWindowRect(LButton, &rect); + pt.y = rect.top; + + if ((GetWindowLong(LButton, GWL_STYLE) & WS_VISIBLE) != 0) + pt.x = rect.left - 28; + else + pt.x = rect.left; + } + + ScreenToClient(GetParent(LButton), &pt); + rect.bottom += pt.y - rect.top; + rect.right += pt.x - rect.left; + rect.top = pt.y; + rect.left = pt.x; + + return rect; + } + + //helper function + //identifies the message dialog + bool IsMessageSendDialog(HWND hwnd) + { + TCHAR szClassName[32] = _T(""); + + GetClassName(hwnd, szClassName, SIZEOF(szClassName)); + if (_tcscmp(szClassName, _T("#32770"))) return false; + + if ((REdit = GetDlgItem(hwnd, MI_IDC_LOG)) != NULL) + { + GetClassName(REdit, szClassName, SIZEOF(szClassName)); + if (_tcscmp(szClassName, _T("RichEdit20A")) != 0 && + _tcscmp(szClassName, _T("RichEdit20W")) != 0 && + _tcscmp(szClassName, _T("RICHEDIT50W")) != 0) return false; + } + else return false; + + if ((MEdit = GetDlgItem(hwnd, MI_IDC_MESSAGE)) != NULL) + { + GetClassName(MEdit, szClassName, SIZEOF(szClassName)); + if (_tcscmp(szClassName, _T("Edit")) != 0 && + _tcscmp(szClassName, _T("RichEdit20A")) != 0 && + _tcscmp(szClassName, _T("RichEdit20W")) != 0 && + _tcscmp(szClassName, _T("RICHEDIT50W")) != 0) return false; + } + else return false; + + QuoteB = GetDlgItem(hwnd, MI_IDC_QUOTE); + + if ((LButton = GetDlgItem(hwnd, MI_IDC_ADD)) == NULL) + return false; + + if (GetDlgItem(hwnd, MI_IDC_NAME) == NULL) + return false; + if ((MOK = GetDlgItem(hwnd, IDOK)) == NULL) + return false; + + return true; + } + + void CreateSmileyButton(void) + { + doSmileyButton = opt.ButtonStatus != 0; + OldButtonPlace = opt.ButtonStatus == 2; + + SmileyPackType* SmileyPack = GetSmileyPack(ProtocolName, hContact); + doSmileyButton &= SmileyPack != NULL && SmileyPack->VisibleSmileyCount() != 0; + + bool showButtonLine; + if (IsOldSrmm()) + { + isSplit = DBGetContactSettingByte(NULL,"SRMsg","Split", TRUE) != 0; + + doSmileyReplace = (isSplit || !isSend); + doSmileyButton &= isSplit || isSend; + showButtonLine = DBGetContactSettingByte(NULL, "SRMsg", "ShowButtonLine", TRUE) != 0; + } + else + { + doSmileyReplace = true;; + OldButtonPlace = false; + showButtonLine = DBGetContactSettingByte(NULL, "SRMM", "ShowButtonLine", TRUE) != 0; + } + + doSmileyButton &= OldButtonPlace || showButtonLine; + + if (ProtocolName[0] != 0) + { + INT_PTR cap = CallProtoService(ProtocolName, PS_GETCAPS, PFLAGNUM_1, 0); + doSmileyButton &= ((cap & PF1_IMSEND) != 0); + doSmileyReplace &= ((cap & PF1_IMRECV) != 0); + } + + if (doSmileyButton && opt.PluginSupportEnabled) + { + //create smiley button + RECT rect = CalcSmileyButtonPos(); + + hSmlButton = CreateWindowEx( + WS_EX_LEFT | WS_EX_NOPARENTNOTIFY | WS_EX_TOPMOST, + MIRANDABUTTONCLASS, + _T("S"), + WS_CHILD|WS_VISIBLE|WS_TABSTOP, // window style + rect.left, // horizontal position of window + rect.top, // vertical position of window + rect.bottom - rect.top + 1, // window width + rect.bottom - rect.top + 1, // window height + GetParent(LButton), // handle to parent or owner window + (HMENU) IDC_SMLBUTTON, // menu handle or child identifier + NULL, // handle to application instance + NULL); // window-creation data + + // Conversion to bitmap done to prevent Miranda from scaling the image + SmileyType* sml = FindButtonSmiley(SmileyPack); + if (sml != NULL) + { + hSmlBmp = sml->GetBitmap(GetSysColor(COLOR_BTNFACE), 0, 0); + SendMessage(hSmlButton, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hSmlBmp); + } + else + { + hSmlIco = GetDefaultIcon(); + SendMessage(hSmlButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hSmlIco); + } + + SendMessage(hSmlButton, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Show Smiley Selection Window"), 0); + SendMessage(hSmlButton, BUTTONSETASFLATBTN, 0, 0); + } + } +}; + +static int CompareMsgWndData(const MsgWndData* p1, const MsgWndData* p2) +{ + return (int)((INT_PTR)p1->hwnd - (INT_PTR)p2->hwnd); +} +static LIST g_MsgWndList(10, CompareMsgWndData); + + +bool IsOldSrmm(void) +{ + return ServiceExists(MS_MSG_GETWINDOWCLASS) == 0; +} + + +int UpdateSrmmDlg(WPARAM wParam, LPARAM /* lParam */) +{ + WaitForSingleObject(g_hMutex, 2000); + for (int i=0; ihContact == (HANDLE)wParam) + { + SendMessage(g_MsgWndList[i]->hwnd, WM_SETREDRAW, FALSE, 0); + SendMessage(g_MsgWndList[i]->hwnd, DM_OPTIONSAPPLIED, 0, 0); + SendMessage(g_MsgWndList[i]->hwnd, WM_SETREDRAW, TRUE, 0); + } + } + ReleaseMutex(g_hMutex); + + return 0; +} + + +//find the dialog info in the stored list +static MsgWndData* IsMsgWnd(HWND hwnd) +{ + WaitForSingleObject(g_hMutex, 2000); + MsgWndData* res = g_MsgWndList.find((MsgWndData*)&hwnd); + ReleaseMutex(g_hMutex); + + return res; +} + + +static void MsgWndDetect(HWND hwndDlg, HANDLE hContact, msgData* datm) +{ + MsgWndData dat; + + if (dat.IsMessageSendDialog(hwndDlg)) + { + dat.hwnd = hwndDlg; + if (datm != NULL) + { + dat.isSend = datm->isSend != 0; + dat.hContact = datm->hContact; + } + else + dat.hContact = hContact; + + // Get the protocol for this contact to display correct smileys. + char *protonam = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, + (WPARAM)DecodeMetaContact(dat.hContact), 0); + + if (protonam) + { + strncpy(dat.ProtocolName, protonam, sizeof(dat.ProtocolName)); + dat.ProtocolName[sizeof(dat.ProtocolName)-1] = 0; + } + + WaitForSingleObject(g_hMutex, 2000); + + MsgWndData* msgwnd = g_MsgWndList.find((MsgWndData*)&hwndDlg); + if (msgwnd == NULL) + { + msgwnd = new MsgWndData(dat); + g_MsgWndList.insert(msgwnd); + } + else + msgwnd = NULL; + ReleaseMutex(g_hMutex); + + if (msgwnd != NULL) + { + msgwnd->wpOrigWndProc = (WNDPROC)SetWindowLongPtr(hwndDlg, GWLP_WNDPROC, (LONG_PTR)MessageDlgSubclas); + msgwnd->CreateSmileyButton(); + if (hContact == NULL) SetRichCallback(msgwnd->REdit, msgwnd->hContact, true, true); + } + } +} + + +//global subclass function for all dialogs +static LRESULT CALLBACK MessageDlgSubclas(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MsgWndData* dat = IsMsgWnd(hwnd); + if (dat == NULL) return 0; + + switch(uMsg) + { + case DM_OPTIONSAPPLIED: + dat->clear(); + 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->REdit, EM_GETTEXTLENGTHEX, (WPARAM) >l, 0); + } + break; + } + + LRESULT result = CallWindowProc(dat->wpOrigWndProc, hwnd, uMsg, wParam, lParam); + + if (!opt.PluginSupportEnabled) return result; + + switch(uMsg) + { + case WM_DESTROY: + WaitForSingleObject(g_hMutex, 2000); + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)dat->wpOrigWndProc); + { + int ind = g_MsgWndList.getIndex((MsgWndData*)&hwnd); + if ( ind != -1 ) + { + delete g_MsgWndList[ind]; + g_MsgWndList.remove(ind); + } + } + ReleaseMutex(g_hMutex); + break; + + case WM_SIZE: + if (dat->doSmileyButton) + { + RECT rect = dat->CalcSmileyButtonPos(); + SetWindowPos(dat->hSmlButton, NULL, rect.left, rect.top, + 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + } + break; + + case DM_APPENDTOLOG: + if (dat->doSmileyReplace) + { + SmileyPackCType* smcp; + SmileyPackType* SmileyPack = GetSmileyPack(dat->ProtocolName, dat->hContact, &smcp); + if (SmileyPack != NULL) + { + const CHARRANGE sel = { dat->idxLastChar, LONG_MAX }; + ReplaceSmileys(dat->REdit, 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 != NULL) + { + static const CHARRANGE sel = { 0, LONG_MAX }; + ReplaceSmileys(dat->REdit, SmileyPack, smcp, sel, false, false, false); + } + } + break; + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_SMLBUTTON && + HIWORD(wParam) == BN_CLICKED) + { + SmileyToolWindowParam *stwp = new SmileyToolWindowParam; + stwp->pSmileyPack = GetSmileyPack(dat->ProtocolName, dat->hContact); + + stwp->hWndParent = hwnd; + stwp->hWndTarget = dat->MEdit; + stwp->targetMessage = EM_REPLACESEL; + stwp->targetWParam = TRUE; + + RECT rect; + GetWindowRect(dat->hSmlButton, &rect); + + if (dat->OldButtonPlace) + { + stwp->direction = 3; + stwp->xPosition = rect.left; + stwp->yPosition = rect.top + 4; + } + else + { + stwp->direction = 0; + stwp->xPosition = rect.left; + stwp->yPosition = rect.top + 24; + } + + mir_forkthread(SmileyToolThread, stwp); + } + + if (LOWORD(wParam) == MI_IDC_ADD && + HIWORD(wParam) == BN_CLICKED && + dat->doSmileyButton) + { + RECT rect = dat->CalcSmileyButtonPos(); + SetWindowPos(dat->hSmlButton, NULL, rect.left, rect.top, + 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + } + break; + } + + return result; +} + +static int MsgDlgHook(WPARAM, LPARAM lParam) +{ + const MessageWindowEventData *wndEvtData = (MessageWindowEventData*)lParam; + switch(wndEvtData->uType) + { + case MSG_WINDOW_EVT_OPENING: + MsgWndDetect(wndEvtData->hwndWindow, wndEvtData->hContact, NULL); + if (wndEvtData->cbSize >= sizeof(MessageWindowEventData)) + { + 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: + if (wndEvtData->cbSize >= sizeof(MessageWindowEventData)) + { + 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->cbSize >= sizeof(MessageWindowEventData) && wndEvtData->hwndLog) + { + CloseRichCallback(wndEvtData->hwndLog, true); + CloseRichOwnerCallback(wndEvtData->hwndWindow, true); + } + break; + } + return 0; +} + + +//global subclass function for all dialogs +static LRESULT CALLBACK MsgDlgHookProcPre(int code, WPARAM wParam, LPARAM lParam) +{ + const CWPSTRUCT *msg = (CWPSTRUCT*)lParam; + + if (code == HC_ACTION && msg->message == WM_INITDIALOG) + MsgWndDetect(msg->hwnd, NULL, (msgData*)msg->lParam); + + return CallNextHookEx(g_hMessageHookPre, code, wParam, lParam); +} + + +void InstallDialogBoxHook(void) +{ + g_hMutex = CreateMutex(NULL, FALSE, NULL); + + g_hHookMsgWnd = HookEvent(ME_MSG_WINDOWEVENT, MsgDlgHook); + + // Hook message API + if (g_hHookMsgWnd == NULL) + g_hMessageHookPre = SetWindowsHookEx(WH_CALLWNDPROC, MsgDlgHookProcPre, + NULL, GetCurrentThreadId()); +} + + +void RemoveDialogBoxHook(void) +{ + if (g_hHookMsgWnd) UnhookEvent(g_hHookMsgWnd); + if (g_hMessageHookPre) UnhookWindowsHookEx(g_hMessageHookPre); + + WaitForSingleObject(g_hMutex, 2000); + for (int i=0; i