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/Avs/acc.cpp | 908 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 908 insertions(+) create mode 100644 plugins/Avs/acc.cpp (limited to 'plugins/Avs/acc.cpp') diff --git a/plugins/Avs/acc.cpp b/plugins/Avs/acc.cpp new file mode 100644 index 0000000000..f62009b43d --- /dev/null +++ b/plugins/Avs/acc.cpp @@ -0,0 +1,908 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2004 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" + +extern FI_INTERFACE *fei; + +int GetImageFormat(TCHAR *filename); +INT_PTR DrawAvatarPicture(WPARAM wParam, LPARAM lParam); +INT_PTR GetAvatarBitmap(WPARAM wParam, LPARAM lParam); +INT_PTR GetMyAvatar(WPARAM wParam, LPARAM lParam); +void InternalDrawAvatar(AVATARDRAWREQUEST *r, HBITMAP hbm, LONG bmWidth, LONG bmHeight, DWORD dwFlags); + + +#define DM_AVATARCHANGED (WM_USER + 20) +#define DM_MYAVATARCHANGED (WM_USER + 21) + +#define GIF_DISPOSAL_UNSPECIFIED 0 +#define GIF_DISPOSAL_LEAVE 1 +#define GIF_DISPOSAL_BACKGROUND 2 +#define GIF_DISPOSAL_PREVIOUS 3 + +typedef struct +{ + HANDLE hContact; + char proto[64]; + HANDLE hHook; + HANDLE hHookMy; + HFONT hFont; // font + COLORREF borderColor; + COLORREF bkgColor; + COLORREF avatarBorderColor; + int avatarRoundCornerRadius; + TCHAR noAvatarText[128]; + BOOL respectHidden; + BOOL showingFlash; + BOOL resizeIfSmaller; + BOOL fAero; + BOOL showingAnimatedGif; + + struct { + HBITMAP *hbms; + int *times; + + FIMULTIBITMAP *multi; + FIBITMAP *dib; + int frameCount; + int logicalWidth; + int logicalHeight; + BOOL loop; + RGBQUAD background; + BOOL started; + + struct { + int num; + int top; + int left; + int width; + int height; + int disposal_method; + } frame; + } ag; + +} ACCData; + + +void ResizeFlash(HWND hwnd, ACCData* data) +{ + if ((data->hContact != NULL || data->proto[0] != '\0') + && ServiceExists(MS_FAVATAR_RESIZE)) + { + RECT rc; + GetClientRect(hwnd, &rc); + + if (data->borderColor != -1 || data->avatarBorderColor != -1) + { + rc.left ++; + rc.right -= 2; + rc.top ++; + rc.bottom -= 2; + } + + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + CallService(MS_FAVATAR_RESIZE, (WPARAM)&fa, (LPARAM)&rc); + CallService(MS_FAVATAR_SETPOS, (WPARAM)&fa, (LPARAM)&rc); + } +} + +void SetBkgFlash(HWND hwnd, ACCData* data) +{ + if ((data->hContact != NULL || data->proto[0] != '\0') + && ServiceExists(MS_FAVATAR_SETBKCOLOR)) + { + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + + if (data->bkgColor != -1) + CallService(MS_FAVATAR_SETBKCOLOR, (WPARAM)&fa, (LPARAM)data->bkgColor); + else + CallService(MS_FAVATAR_SETBKCOLOR, (WPARAM)&fa, (LPARAM)RGB(255,255,255)); + } +} + +void DestroyFlash(HWND hwnd, ACCData* data) +{ + if (!data->showingFlash) + return; + + if ((data->hContact != NULL || data->proto[0] != '\0') + && ServiceExists(MS_FAVATAR_DESTROY)) + { + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + CallService(MS_FAVATAR_DESTROY, (WPARAM)&fa, 0); + } + + data->showingFlash = FALSE; +} + +void StartFlash(HWND hwnd, ACCData* data) +{ + if (!ServiceExists(MS_FAVATAR_MAKE)) + return; + + int format; + if (data->hContact != NULL) + { + format = DBGetContactSettingWord(data->hContact, "ContactPhoto", "Format", 0); + } + else if (data->proto[0] != '\0') + { + protoPicCacheEntry *ace = NULL; + for(int i = 0; i < g_MyAvatars.getCount(); i++) + { + if (!lstrcmpA(data->proto, g_MyAvatars[i].szProtoname)) + { + ace = &g_MyAvatars[i]; + break; + } + } + + if (ace != NULL && ace->szFilename != NULL) + format = GetImageFormat(ace->szFilename); + else + format = 0; + } + else + return; + + if (format != PA_FORMAT_XML && format != PA_FORMAT_SWF) + return; + + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + CallService(MS_FAVATAR_MAKE, (WPARAM)&fa, 0); + + if (fa.hWindow == NULL) + return; + + data->showingFlash = TRUE; + ResizeFlash(hwnd, data); + SetBkgFlash(hwnd, data); +} + +BOOL AnimatedGifGetData(ACCData* data) +{ + FIBITMAP *page = fei->FI_LockPage(data->ag.multi, 0); + if (page == NULL) + return FALSE; + + // Get info + FITAG *tag = NULL; + if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "LogicalWidth", &tag)) + goto ERR; + data->ag.logicalWidth = *(WORD *)fei->FI_GetTagValue(tag); + + if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "LogicalHeight", &tag)) + goto ERR; + data->ag.logicalHeight = *(WORD *)fei->FI_GetTagValue(tag); + + if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "Loop", &tag)) + goto ERR; + data->ag.loop = (*(LONG *)fei->FI_GetTagValue(tag) > 0); + + if (fei->FI_HasBackgroundColor(page)) + fei->FI_GetBackgroundColor(page, &data->ag.background); + + fei->FI_UnlockPage(data->ag.multi, page, FALSE); + return TRUE; + +ERR: + fei->FI_UnlockPage(data->ag.multi, page, FALSE); + return FALSE; +} + +void AnimatedGifDispodeFrame(ACCData* data) +{ + if (data->ag.frame.disposal_method == GIF_DISPOSAL_PREVIOUS) + { + // TODO + } + else if (data->ag.frame.disposal_method == GIF_DISPOSAL_BACKGROUND) + { + for (int y = 0; y < data->ag.frame.height; y++) + { + RGBQUAD *scanline = (RGBQUAD *) fei->FI_GetScanLine(data->ag.dib, + data->ag.logicalHeight - (y + data->ag.frame.top) - 1) + data->ag.frame.left; + for (int x = 0; x < data->ag.frame.width; x++) + *scanline++ = data->ag.background; + } + } +} + +void AnimatedGifMountFrame(ACCData* data, int page) +{ + data->ag.frame.num = page; + + if (data->ag.hbms[page] != NULL) + { + data->ag.frame.disposal_method = GIF_DISPOSAL_LEAVE; + return; + } + + FIBITMAP *dib = fei->FI_LockPage(data->ag.multi, data->ag.frame.num); + if (dib == NULL) + return; + + FITAG *tag = NULL; + if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameLeft", &tag)) + data->ag.frame.left = *(WORD *)fei->FI_GetTagValue(tag); + else + data->ag.frame.left = 0; + + if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameTop", &tag)) + data->ag.frame.top = *(WORD *)fei->FI_GetTagValue(tag); + else + data->ag.frame.top = 0; + + if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameTime", &tag)) + data->ag.times[page] = *(LONG *)fei->FI_GetTagValue(tag); + else + data->ag.times[page] = 0; + + if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "DisposalMethod", &tag)) + data->ag.frame.disposal_method = *(BYTE *)fei->FI_GetTagValue(tag); + else + data->ag.frame.disposal_method = 0; + + data->ag.frame.width = fei->FI_GetWidth(dib); + data->ag.frame.height = fei->FI_GetHeight(dib); + + + //decode page + int palSize = fei->FI_GetColorsUsed(dib); + RGBQUAD *pal = fei->FI_GetPalette(dib); + bool have_transparent = false; + int transparent_color = -1; + if( fei->FI_IsTransparent(dib) ) { + int count = fei->FI_GetTransparencyCount(dib); + BYTE *table = fei->FI_GetTransparencyTable(dib); + for( int i = 0; i < count; i++ ) { + if( table[i] == 0 ) { + have_transparent = true; + transparent_color = i; + break; + } + } + } + + //copy page data into logical buffer, with full alpha opaqueness + for( int y = 0; y < data->ag.frame.height; y++ ) { + RGBQUAD *scanline = (RGBQUAD *)fei->FI_GetScanLine(data->ag.dib, data->ag.logicalHeight - (y + data->ag.frame.top) - 1) + data->ag.frame.left; + BYTE *pageline = fei->FI_GetScanLine(dib, data->ag.frame.height - y - 1); + for( int x = 0; x < data->ag.frame.width; x++ ) { + if( !have_transparent || *pageline != transparent_color ) { + *scanline = pal[*pageline]; + scanline->rgbReserved = 255; + } + scanline++; + pageline++; + } + } + + data->ag.hbms[page] = fei->FI_CreateHBITMAPFromDIB(data->ag.dib); + + fei->FI_UnlockPage(data->ag.multi, dib, FALSE); +} + +void AnimatedGifDeleteTmpValues(ACCData* data) +{ + if (data->ag.multi != NULL) + { + fei->FI_CloseMultiBitmap(data->ag.multi, 0); + data->ag.multi = NULL; + } + + if (data->ag.dib != NULL) + { + fei->FI_Unload(data->ag.dib); + data->ag.dib = NULL; + } +} + +void DestroyAnimatedGif(HWND hwnd, ACCData* data) +{ + if (!data->showingAnimatedGif) + return; + + AnimatedGifDeleteTmpValues(data); + + if (data->ag.hbms != NULL) + { + for (int i = 0; i < data->ag.frameCount; i++) + if (data->ag.hbms[i] != NULL) + DeleteObject(data->ag.hbms[i]); + + free(data->ag.hbms); + data->ag.hbms = NULL; + } + + if (data->ag.times != NULL) + { + free(data->ag.times); + data->ag.times = NULL; + } + + data->showingAnimatedGif = FALSE; +} + +void StartAnimatedGif(HWND hwnd, ACCData* data) +{ + if (fei == NULL) + return; + + int x, y; + AVATARCACHEENTRY *ace = NULL; + + if (data->hContact != NULL) + ace = (AVATARCACHEENTRY *) GetAvatarBitmap((WPARAM) data->hContact, 0); + else + ace = (AVATARCACHEENTRY *) GetMyAvatar(0, (LPARAM) data->proto); + + if (ace == NULL) + return; + + int format = GetImageFormat(ace->szFilename); + if (format != PA_FORMAT_GIF) + return; + + FREE_IMAGE_FORMAT fif = fei->FI_GetFileTypeT(ace->szFilename, 0); + if(fif == FIF_UNKNOWN) + fif = fei->FI_GetFIFFromFilenameT(ace->szFilename); + + data->ag.multi = fei->FI_OpenMultiBitmapT(fif, ace->szFilename, FALSE, TRUE, FALSE, GIF_LOAD256); + if (data->ag.multi == NULL) + return; + + data->ag.frameCount = fei->FI_GetPageCount(data->ag.multi); + if (data->ag.frameCount <= 1) + goto ERR; + + if (!AnimatedGifGetData(data)) + goto ERR; + + //allocate entire logical area + data->ag.dib = fei->FI_Allocate(data->ag.logicalWidth, data->ag.logicalHeight, 32, 0, 0, 0); + if (data->ag.dib == NULL) + goto ERR; + + //fill with background color to start + for (y = 0; y < data->ag.logicalHeight; y++) + { + RGBQUAD *scanline = (RGBQUAD *) fei->FI_GetScanLine(data->ag.dib, y); + for (x = 0; x < data->ag.logicalWidth; x++) + *scanline++ = data->ag.background; + } + + data->ag.hbms = (HBITMAP *) malloc(sizeof(HBITMAP) * data->ag.frameCount); + memset(data->ag.hbms, 0, sizeof(HBITMAP) * data->ag.frameCount); + + data->ag.times = (int *) malloc(sizeof(int) * data->ag.frameCount); + memset(data->ag.times, 0, sizeof(int) * data->ag.frameCount); + + AnimatedGifMountFrame(data, 0); + + data->showingAnimatedGif = TRUE; + + return; +ERR: + fei->FI_CloseMultiBitmap(data->ag.multi, 0); + data->ag.multi = NULL; +} + +void DestroyAnimation(HWND hwnd, ACCData* data) +{ + DestroyFlash(hwnd, data); + DestroyAnimatedGif(hwnd, data); +} + +void StartAnimation(HWND hwnd, ACCData* data) +{ + StartFlash(hwnd, data); + + if (!data->showingFlash) + StartAnimatedGif(hwnd, data); +} + +BOOL ScreenToClient(HWND hWnd, LPRECT lpRect) +{ + BOOL ret; + + POINT pt; + + pt.x = lpRect->left; + pt.y = lpRect->top; + + ret = ScreenToClient(hWnd, &pt); + + if (!ret) return ret; + + lpRect->left = pt.x; + lpRect->top = pt.y; + + + pt.x = lpRect->right; + pt.y = lpRect->bottom; + + ret = ScreenToClient(hWnd, &pt); + + lpRect->right = pt.x; + lpRect->bottom = pt.y; + + return ret; +} + +static void Invalidate(HWND hwnd) +{ + ACCData* data = (ACCData *) GetWindowLongPtr(hwnd, 0); + if (data->bkgColor == -1) + { + HWND parent = GetParent(hwnd); + RECT rc; + GetWindowRect(hwnd, &rc); + ScreenToClient(parent, &rc); + InvalidateRect(parent, &rc, TRUE); + } + InvalidateRect(hwnd, NULL, TRUE); +} + +static void NotifyAvatarChange(HWND hwnd) +{ + PSHNOTIFY pshn = {0}; + pshn.hdr.idFrom = GetDlgCtrlID(hwnd); + pshn.hdr.hwndFrom = hwnd; + pshn.hdr.code = NM_AVATAR_CHANGED; + pshn.lParam = 0; + SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) &pshn); +} + +static void DrawText(HDC hdc, HFONT hFont, const RECT &rc, const TCHAR *text) +{ + HGDIOBJ oldFont = SelectObject(hdc, hFont); + + // Get text rectangle + RECT tr = rc; + tr.top += 10; + tr.bottom -= 10; + tr.left += 10; + tr.right -= 10; + + // Calc text size + RECT tr_ret = tr; + DrawText(hdc, text, -1, &tr_ret, + DT_WORDBREAK | DT_NOPREFIX | DT_CENTER | DT_CALCRECT); + + // Calc needed size + tr.top += ((tr.bottom - tr.top) - (tr_ret.bottom - tr_ret.top)) / 2; + tr.bottom = tr.top + (tr_ret.bottom - tr_ret.top); + DrawText(hdc, text, -1, &tr, + DT_WORDBREAK | DT_NOPREFIX | DT_CENTER); + + SelectObject(hdc, oldFont); +} + +static LRESULT CALLBACK ACCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + ACCData* data = (ACCData *) GetWindowLongPtr(hwnd, 0); + switch(msg) + { + case WM_NCCREATE: + { + SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | BS_OWNERDRAW); + SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT); + + data = (ACCData*) mir_alloc(sizeof(ACCData)); + if (data == NULL) + return FALSE; + SetWindowLongPtr(hwnd, 0, (LONG_PTR)data); + + ZeroMemory(data, sizeof(ACCData)); + data->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwnd, DM_AVATARCHANGED); + data->hHookMy = HookEventMessage(ME_AV_MYAVATARCHANGED, hwnd, DM_MYAVATARCHANGED); + data->hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); + data->borderColor = -1; + data->bkgColor = -1; + data->avatarBorderColor = -1; + data->respectHidden = TRUE; + data->showingFlash = FALSE; + data->resizeIfSmaller = TRUE; + data->showingAnimatedGif = FALSE; + data->fAero = FALSE; + + return TRUE; + } + case WM_NCDESTROY: + { + DestroyAnimation(hwnd, data); + if (data) + { + UnhookEvent(data->hHook); + UnhookEvent(data->hHookMy); + mir_free(data); + } + SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); + break; + } + case WM_SETFONT: + { + data->hFont = (HFONT)wParam; + Invalidate(hwnd); + break; + } + case AVATAR_SETCONTACT: + { + DestroyAnimation(hwnd, data); + + data->hContact = (HANDLE) lParam; + lstrcpynA(data->proto, (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)data->hContact, 0), sizeof(data->proto)); + + StartAnimation(hwnd, data); + + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETPROTOCOL: + { + DestroyAnimation(hwnd, data); + + data->hContact = NULL; + if (lParam == NULL) + data->proto[0] = '\0'; + else + lstrcpynA(data->proto, (char *) lParam, sizeof(data->proto)); + + StartAnimation(hwnd, data); + + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETBKGCOLOR: + { + data->bkgColor = (COLORREF) lParam; + if (data->showingFlash) + SetBkgFlash(hwnd, data); + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETBORDERCOLOR: + { + data->borderColor = (COLORREF) lParam; + if (data->showingFlash) + ResizeFlash(hwnd, data); + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETAVATARBORDERCOLOR: + { + data->avatarBorderColor = (COLORREF) lParam; + if (data->showingFlash) + ResizeFlash(hwnd, data); + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETAVATARROUNDCORNERRADIUS: + { + data->avatarRoundCornerRadius = (int) lParam; + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETNOAVATARTEXT: + { + lstrcpyn(data->noAvatarText, TranslateTS((TCHAR*) lParam), SIZEOF(data->noAvatarText)); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_RESPECTHIDDEN: + { + data->respectHidden = (BOOL) lParam; + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETRESIZEIFSMALLER: + { + data->resizeIfSmaller = (BOOL) lParam; + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + + case AVATAR_SETAEROCOMPATDRAWING: + data->fAero = lParam; + return(TRUE); + + case AVATAR_GETUSEDSPACE: + { + int *width = (int *)wParam; + int *height = (int *)lParam; + + RECT rc; + GetClientRect(hwnd, &rc); + + // Get avatar + if (data->showingFlash && ServiceExists(MS_FAVATAR_GETINFO)) + { + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0); + if (fa.hWindow != NULL) + { + *width = rc.right - rc.left; + *height = rc.bottom - rc.top; + return TRUE; + } + } + + avatarCacheEntry *ace; + if (data->hContact == NULL) + ace = (avatarCacheEntry *) CallService(MS_AV_GETMYAVATAR, 0, (LPARAM) data->proto); + else + ace = (avatarCacheEntry *) CallService(MS_AV_GETAVATARBITMAP, (WPARAM) data->hContact, 0); + + if (ace == NULL || ace->bmHeight == 0 || ace->bmWidth == 0 + || (data->respectHidden && (ace->dwFlags & AVS_HIDEONCLIST))) + { + *width = 0; + *height = 0; + return TRUE; + } + + // Get its size + int targetWidth = rc.right - rc.left; + int targetHeight = rc.bottom - rc.top; + + if (!data->resizeIfSmaller && ace->bmHeight <= targetHeight && ace->bmWidth <= targetWidth) + { + *height = ace->bmHeight; + *width = ace->bmWidth; + } + else if (ace->bmHeight > ace->bmWidth) + { + float dScale = targetHeight / (float)ace->bmHeight; + *height = targetHeight; + *width = (int) (ace->bmWidth * dScale); + } + else + { + float dScale = targetWidth / (float)ace->bmWidth; + *height = (int) (ace->bmHeight * dScale); + *width = targetWidth; + } + + return TRUE; + } + case DM_AVATARCHANGED: + { + if (data->hContact == (HANDLE) wParam) + { + DestroyAnimation(hwnd, data); + StartAnimation(hwnd, data); + + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + } + break; + } + case DM_MYAVATARCHANGED: + { + if (data->hContact == NULL && strcmp(data->proto, (char*) wParam) == 0) + { + DestroyAnimation(hwnd, data); + StartAnimation(hwnd, data); + + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + } + break; + } + case WM_NCPAINT: + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + if (hdc == NULL) + break; + + int oldBkMode = SetBkMode(hdc, TRANSPARENT); + SetStretchBltMode(hdc, HALFTONE); + + RECT rc; + GetClientRect(hwnd, &rc); + + // Draw background + if (data->bkgColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->bkgColor); + FillRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + + if (data->hContact == NULL && data->proto[0] == '\0' + && DBGetContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) + { + DrawText(hdc, data->hFont, rc, TranslateT("Protocols have different avatars")); + } + + // Has a flash avatar + else if (data->showingFlash) + { + // Don't draw + + // Draw control border if needed + if (data->borderColor == -1 && data->avatarBorderColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->avatarBorderColor); + FrameRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + } + + // Has an animated gif + // Has a "normal" image + else + { + // Draw avatar + AVATARDRAWREQUEST avdrq = {0}; + avdrq.cbSize = sizeof(avdrq); + avdrq.rcDraw = rc; + avdrq.hContact = data->hContact; + avdrq.szProto = data->proto; + avdrq.hTargetDC = hdc; + avdrq.dwFlags = AVDRQ_HIDEBORDERONTRANSPARENCY + | (data->respectHidden ? AVDRQ_RESPECTHIDDEN : 0) + | (data->hContact != NULL ? 0 : AVDRQ_OWNPIC) + | (data->avatarBorderColor == -1 ? 0 : AVDRQ_DRAWBORDER) + | (data->avatarRoundCornerRadius <= 0 ? 0 : AVDRQ_ROUNDEDCORNER) + | (data->fAero ? AVDRQ_AERO : 0) + | (data->resizeIfSmaller ? 0 : AVDRQ_DONTRESIZEIFSMALLER); + avdrq.clrBorder = data->avatarBorderColor; + avdrq.radius = data->avatarRoundCornerRadius; + + INT_PTR ret; + if (data->showingAnimatedGif) + { + InternalDrawAvatar(&avdrq, data->ag.hbms[data->ag.frame.num], data->ag.logicalWidth, data->ag.logicalHeight, 0); + ret = 1; + + if (!data->ag.started) + { + SetTimer(hwnd, 0, data->ag.times[data->ag.frame.num], NULL); + data->ag.started = TRUE; + } + } + else + ret = DrawAvatarPicture(0, (LPARAM)&avdrq); + + if (ret == 0) + DrawText(hdc, data->hFont, rc, data->noAvatarText); + } + + // Draw control border + if (data->borderColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->borderColor); + FrameRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + + SetBkMode(hdc, oldBkMode); + + EndPaint(hwnd, &ps); + return TRUE; + } + case WM_ERASEBKGND: + { + HDC hdc = (HDC) wParam; + RECT rc; + GetClientRect(hwnd, &rc); + + // Draw background + if (data->bkgColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->bkgColor); + FillRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + + // Draw control border + if (data->borderColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->borderColor); + FrameRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + + return TRUE; + } + case WM_SIZE: + { + if (data->showingFlash) + ResizeFlash(hwnd, data); + InvalidateRect(hwnd, NULL, TRUE); + break; + } + case WM_TIMER: + { + if (wParam != 0) + break; + KillTimer(hwnd, 0); + + if (!data->showingAnimatedGif) + break; + + AnimatedGifDispodeFrame(data); + + int frame = data->ag.frame.num + 1; + if (frame >= data->ag.frameCount) + { + // Don't need fi data no more + AnimatedGifDeleteTmpValues(data); + frame = 0; + } + AnimatedGifMountFrame(data, frame); + + data->ag.started = FALSE; + InvalidateRect(hwnd, NULL, FALSE); + + break; + } + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + + +int LoadACC() +{ + WNDCLASSEX wc = {0}; + wc.cbSize = sizeof(wc); + wc.lpszClassName = AVATAR_CONTROL_CLASS; + wc.lpfnWndProc = ACCWndProc; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.cbWndExtra = sizeof(ACCData*); + wc.hbrBackground = 0; + wc.style = CS_GLOBALCLASS; + RegisterClassEx(&wc); + return 0; +} -- cgit v1.2.3