From 9242a80a84fa5c96dbadec9594177875aeeec1ac Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Tue, 10 Jul 2012 18:37:21 +0000 Subject: only added MyDetails and Skins. not adopted yet git-svn-id: http://svn.miranda-ng.org/main/trunk@892 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MyDetails/frame.cpp | 2428 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2428 insertions(+) create mode 100644 plugins/MyDetails/frame.cpp (limited to 'plugins/MyDetails/frame.cpp') diff --git a/plugins/MyDetails/frame.cpp b/plugins/MyDetails/frame.cpp new file mode 100644 index 0000000000..d5b609a4e9 --- /dev/null +++ b/plugins/MyDetails/frame.cpp @@ -0,0 +1,2428 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#include "commons.h" +#include "frame.h" +#include "wingdi.h" +#include "winuser.h" +#include + + +// Prototypes ///////////////////////////////////////////////////////////////////////////////////// + + +#define WINDOW_NAME_PREFIX "mydetails_window" +#define WINDOW_CLASS_NAME "MyDetailsFrame" +#define CONTAINER_CLASS_NAME "MyDetailsFrameContainer" + +#define ID_FRAME_TIMER 1011 +#define ID_RECALC_TIMER 1012 +#define ID_STATUSMESSAGE_TIMER 1013 + +#define RECALC_TIME 500 + +#define IDC_HAND MAKEINTRESOURCE(32649) + + +// Messages +#define MWM_REFRESH (WM_USER+10) +#define MWM_REFRESH_DATA (WM_USER+18) + + +HWND hwnd_frame = NULL; +HWND hwnd_container = NULL; + +int frame_id = -1; + +HANDLE hMenuShowHideFrame = 0; + +int CreateFrame(); +void FixMainMenu(); +void UpdateFrameData(); +void RedrawFrame(); + + +// used when no multiwindow functionality available +BOOL MyDetailsFrameVisible(); +void SetMyDetailsFrameVisible(BOOL visible); +int ShowHideMenuFunc(WPARAM wParam, LPARAM lParam); +int ShowFrameFunc(WPARAM wParam, LPARAM lParam); +int HideFrameFunc(WPARAM wParam, LPARAM lParam); +int ShowHideFrameFunc(WPARAM wParam, LPARAM lParam); + + + +LRESULT CALLBACK FrameContainerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +void SetCycleTime(); +void SetCycleTime(HWND hwnd); +void SetStatusMessageRefreshTime(); +void SetStatusMessageRefreshTime(HWND hwnd); +int SettingsChangedHook(WPARAM wParam, LPARAM lParam); +int AvatarChangedHook(WPARAM wParam, LPARAM lParam); +int ProtoAckHook(WPARAM wParam, LPARAM lParam); +int SmileyAddOptionsChangedHook(WPARAM wParam,LPARAM lParam); +int ListeningtoEnableStateChangedHook(WPARAM wParam,LPARAM lParam); +int AccListChanged(WPARAM wParam, LPARAM lParam); + + +void ExternalRect(RECT &ret, const RECT r1, const RECT r2); +bool InsideRect(const POINT &p, const RECT &r); + + +int operator==(const RECT& left, const RECT& right) +{ + return left.left == right.left && left.right == right.right + && left.top == right.top && left.bottom == right.bottom; +} + +class ToolTipArea +{ +public: + ToolTipArea() : hwndTT(0), hwndParent(0) { memset(&rc, 0, sizeof(rc)); } + ~ToolTipArea() { removeTooltip(); } + + void createTooltip(HWND hwnd, const RECT &rc, const TCHAR *text) + { + if (text == NULL || text[0] == 0) + { + removeTooltip(); + return; + } + + this->text = text; + + if (this->rc == rc && hwndParent == hwnd && hwndTT != NULL) + return; + + removeTooltip(); + + this->rc = rc; + this->hwndParent = hwnd; + this->hwndTT = CreateTooltip(this->hwndParent, this->rc); + } + + void removeTooltip() + { + if (hwndTT == NULL) + return; + + DestroyWindow(hwndTT); + hwndTT = NULL; + hwndParent = NULL; + } + + const TCHAR * getTextFor(HWND hwndFrom) + { + if (hwndTT == NULL || hwndTT != hwndFrom) + return NULL; + return text.c_str(); + } + + +private: + + HWND hwndTT; + RECT rc; + HWND hwndParent; + std::tstring text; + + HWND CreateTooltip(HWND hwnd, RECT &rect) + { + // struct specifying control classes to register + INITCOMMONCONTROLSEX iccex; + HWND hwndTT; // handle to the ToolTip control + // struct specifying info about tool in ToolTip control + TOOLINFO ti; + unsigned int uid = 0; // for ti initialization + + // Load the ToolTip class from the DLL. + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_BAR_CLASSES; + + if(!InitCommonControlsEx(&iccex)) + return NULL; + + /* CREATE A TOOLTIP WINDOW */ + hwndTT = CreateWindowEx(WS_EX_TOPMOST, + TOOLTIPS_CLASS, + NULL, + WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + hwnd, + NULL, + hInst, + NULL + ); + + /* Gives problem with mToolTip + SetWindowPos(hwndTT, + HWND_TOPMOST, + 0, + 0, + 0, + 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + */ + + /* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */ + ti.cbSize = sizeof(TOOLINFO); + ti.uFlags = TTF_SUBCLASS; + ti.hwnd = hwnd; + ti.hinst = hInst; + ti.uId = uid; + ti.lpszText = LPSTR_TEXTCALLBACK; + // ToolTip control will cover the whole window + ti.rect.left = rect.left; + ti.rect.top = rect.top; + ti.rect.right = rect.right; + ti.rect.bottom = rect.bottom; + + /* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */ + SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); + SendMessage(hwndTT, TTM_SETDELAYTIME, (WPARAM) (DWORD) TTDT_AUTOPOP, (LPARAM) MAKELONG(24 * 60 * 60 * 1000, 0)); + + return hwndTT; + } +}; + + +struct SimpleItem +{ + RECT rc; + bool draw; + bool mouseOver; + ToolTipArea tt; + bool alignRight; + + SimpleItem() : draw(FALSE), mouseOver(FALSE), alignRight(FALSE) + { + memset(&rc, 0, sizeof(rc)); + } + virtual ~SimpleItem() {} + + virtual void hide() + { + draw = false; + mouseOver = false; + tt.removeTooltip(); + } + + virtual void update(HWND hwnd, SkinFieldState *item) + { + draw = item->isVisible(); + alignRight = ( item->getHorizontalAlign() == SKN_HALIGN_RIGHT ); + + if (draw) + { + rc = item->getRect(); + tt.createTooltip(hwnd, rc, item->getToolTip()); + } + else + { + tt.removeTooltip(); + } + } + + virtual bool hitTest(const POINT &p) + { + return draw && InsideRect(p, rc); + } + + virtual const TCHAR * getToolTipFor(HWND hwndFrom) + { + return tt.getTextFor(hwndFrom); + } + + bool setMouseOver(POINT *mousePos) + { + bool over = (mousePos != NULL && hitTest(*mousePos)); + + if (mouseOver == over) + return FALSE; + + mouseOver = over; + return TRUE; + } + +}; + +struct IconAndItem : public SimpleItem +{ + RECT rcIcon; + RECT rcItem; + BOOL drawIcon; + BOOL drawItem; + ToolTipArea ttIcon; + + IconAndItem() : drawIcon(FALSE), drawItem(FALSE) + { + memset(&rcIcon, 0, sizeof(rcIcon)); + memset(&rcItem, 0, sizeof(rcItem)); + } + virtual ~IconAndItem() {} + + virtual void hide() + { + SimpleItem::hide(); + drawIcon = FALSE; + drawItem = FALSE; + } + + virtual void update(HWND hwnd, SkinIconFieldState *icon, SkinTextFieldState *item) + { + drawIcon = icon->isVisible(); + drawItem = item->isVisible(); + alignRight = ( item->getHorizontalAlign() == SKN_HALIGN_RIGHT ); + + draw = drawIcon || drawItem; + if (draw) + { + if (drawIcon) + rcIcon = icon->getRect(); + if (drawItem) + rcItem = item->getRect(); + + if (drawIcon && drawItem) + ExternalRect(rc, rcIcon, rcItem); + else if (drawIcon) + rc = rcIcon; + else // if (drawItem) + rc = rcItem; + } + + if (drawItem) + tt.createTooltip(hwnd, rcItem, item->getToolTip()); + else + tt.removeTooltip(); + + if (drawIcon) + ttIcon.createTooltip(hwnd, rcIcon, icon->getToolTip()); + else + ttIcon.removeTooltip(); + } + + virtual const TCHAR * getToolTipFor(HWND hwndFrom) + { + const TCHAR * ret = tt.getTextFor(hwndFrom); + + if (ret == NULL) + ret = ttIcon.getTextFor(hwndFrom); + + return ret; + } +}; + + +struct MyDetailsFrameData +{ + std::vector items; + SimpleItem proto; + SimpleItem proto_cycle_next; + SimpleItem proto_cycle_prev; + SimpleItem avatar; + SimpleItem nick; + IconAndItem status; + SimpleItem away_msg; + IconAndItem listening_to; + IconAndItem email; + + bool showing_menu; + + bool tracking_exit; + + MyDetailsFrameData() + : showing_menu(false) + , tracking_exit(false) + { + items.push_back(&proto); + items.push_back(&proto_cycle_next); + items.push_back(&proto_cycle_prev); + items.push_back(&avatar); + items.push_back(&nick); + items.push_back(&status); + items.push_back(&away_msg); + items.push_back(&listening_to); + items.push_back(&email); + } +}; + + + +// Functions ////////////////////////////////////////////////////////////////////////////////////// + +void InitFrames() +{ + InitContactListSmileys(); + + CreateFrame(); + + HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingsChangedHook); + HookEvent(ME_AV_MYAVATARCHANGED, AvatarChangedHook); + HookEvent(ME_PROTO_ACK, ProtoAckHook); + HookEvent(ME_SMILEYADD_OPTIONSCHANGED,SmileyAddOptionsChangedHook); + HookEvent(ME_LISTENINGTO_ENABLE_STATE_CHANGED,ListeningtoEnableStateChangedHook); + HookEvent(ME_PROTO_ACCLISTCHANGED, AccListChanged); +} + + +void DeInitFrames() +{ + if(ServiceExists(MS_CLIST_FRAMES_REMOVEFRAME) && frame_id != -1) + { + CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)frame_id, 0); + } + + if (hwnd_frame != NULL) DestroyWindow(hwnd_frame); + if (hwnd_container != NULL) DestroyWindow(hwnd_container); +} + +int SmileyAddOptionsChangedHook(WPARAM wParam,LPARAM lParam) +{ + UpdateFrameData(); + return 0; +} + +int SkinEngineDrawCallback(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData); + +int CreateFrame() +{ + WNDCLASS wndclass; + wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; //CS_PARENTDC | CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = FrameWindowProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = WINDOW_CLASS_NAME; + RegisterClass(&wndclass); + + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + hwnd_frame = CreateWindow(WINDOW_CLASS_NAME, Translate("My Details"), + WS_CHILD | WS_VISIBLE, + 0,0,10,10, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, NULL); + + CLISTFrame Frame = {0}; + + Frame.cbSize = sizeof(Frame); + Frame.name = "My Details"; + Frame.TBname = Translate("My Details"); + Frame.hWnd = hwnd_frame; + Frame.align = alTop; + Frame.Flags = F_VISIBLE | F_SHOWTB | F_SHOWTBTIP | F_NOBORDER | F_NO_SUBCONTAINER; + Frame.height = 100; + + frame_id = CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0); + + if (ServiceExists(MS_SKINENG_REGISTERPAINTSUB)) + { + CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"My Details Background/MyDetails", 0); + CallService(MS_SKINENG_REGISTERPAINTSUB, (WPARAM) Frame.hWnd, (LPARAM) SkinEngineDrawCallback); + } + + if (DBGetContactSettingByte(NULL, "MyDetails", "ForceHideFrame", 0)) + { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if(flags & F_VISIBLE) + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + + DBDeleteContactSetting(NULL, "MyDetails", "ForceHideFrame"); + } + + if (DBGetContactSettingByte(NULL, "MyDetails", "ForceShowFrame", 0)) + { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if(!(flags & F_VISIBLE)) + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + + DBDeleteContactSetting(NULL, "MyDetails", "ForceShowFrame"); + } + } + else + { + wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;//CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = FrameContainerWindowProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = CONTAINER_CLASS_NAME; + RegisterClass(&wndclass); + + hwnd_container = CreateWindowEx(WS_EX_TOOLWINDOW, CONTAINER_CLASS_NAME, Translate("My Details"), + (WS_THICKFRAME | WS_CAPTION | WS_SYSMENU) & ~WS_VISIBLE, + 0,0,200,130, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, NULL); + + hwnd_frame = CreateWindow(WINDOW_CLASS_NAME, Translate("My Details"), + WS_CHILD | WS_VISIBLE, + 0,0,10,10, hwnd_container, NULL, hInst, NULL); + + SetWindowLong(hwnd_container, GWL_USERDATA, (LONG)hwnd_frame); + SendMessage(hwnd_container, WM_SIZE, 0, 0); + + // Create menu item + + CLISTMENUITEM menu = {0}; + + menu.cbSize=sizeof(menu); + menu.flags = CMIM_ALL; + menu.popupPosition = -0x7FFFFFFF; + menu.pszPopupName = Translate("My Details"); + menu.position = 1; // 500010000 + menu.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + menu.pszName = Translate("Show My Details"); + menu.pszService= MODULE_NAME "/ShowHideMyDetails"; + hMenuShowHideFrame = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu); + + if(DBGetContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1) == 1) + { + ShowWindow(hwnd_container, SW_SHOW); + FixMainMenu(); + } + } + + CreateServiceFunction(MS_MYDETAILS_SHOWFRAME, ShowFrameFunc); + CreateServiceFunction(MS_MYDETAILS_HIDEFRAME, HideFrameFunc); + CreateServiceFunction(MS_MYDETAILS_SHOWHIDEFRAME, ShowHideFrameFunc); + + return 0; +} + + +BOOL FrameIsFloating() +{ + if (frame_id == -1) + { + return true; // no frames, always floating + } + + return (CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLOATING, frame_id), 0) != 0); +} + + +LRESULT CALLBACK FrameContainerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch(msg) + { + case WM_SHOWWINDOW: + { + if ((BOOL)wParam) + Utils_RestoreWindowPosition(hwnd, 0, MODULE_NAME, WINDOW_NAME_PREFIX); + else + Utils_SaveWindowPosition(hwnd, 0, MODULE_NAME, WINDOW_NAME_PREFIX); + break; + } + + case WM_ERASEBKGND: + { + HWND child = (HWND)GetWindowLong(hwnd, GWL_USERDATA); + + SendMessage(child, WM_ERASEBKGND, wParam, lParam); + break; + } + + case WM_SIZE: + { + HWND child = (HWND)GetWindowLong(hwnd, GWL_USERDATA); + RECT r; + GetClientRect(hwnd, &r); + + SetWindowPos(child, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); + InvalidateRect(child, NULL, TRUE); + + return TRUE; + } + + case WM_CLOSE: + { + DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 0); + ShowWindow(hwnd, SW_HIDE); + FixMainMenu(); + return TRUE; + } + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + + + +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; +} + + +BOOL MoveWindow(HWND hWnd, const RECT &rect, BOOL bRepaint) +{ + return MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, bRepaint); +} + + +RECT GetInnerRect(const RECT &rc, const RECT &clipping) +{ + RECT rc_ret = rc; + + rc_ret.left = max(rc.left, clipping.left); + rc_ret.top = max(rc.top, clipping.top); + rc_ret.right = min(rc.right, clipping.right); + rc_ret.bottom = min(rc.bottom, clipping.bottom); + + return rc_ret; +} + + + + + +void ExternalRect(RECT &ret, const RECT r1, const RECT r2) +{ + ret.left = min(r1.left, r2.left); + ret.right = max(r1.right, r2.right); + ret.top = min(r1.top, r2.top); + ret.bottom = max(r1.bottom, r2.bottom); +} + + +HBITMAP CreateBitmap32(int cx, int cy) +{ + BITMAPINFO RGB32BitsBITMAPINFO; + UINT * ptPixels; + HBITMAP DirectBitmap; + + ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO)); + RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + RGB32BitsBITMAPINFO.bmiHeader.biWidth=cx;//bm.bmWidth; + RGB32BitsBITMAPINFO.bmiHeader.biHeight=cy;//bm.bmHeight; + RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1; + RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32; + + DirectBitmap = CreateDIBSection(NULL, + (BITMAPINFO *)&RGB32BitsBITMAPINFO, + DIB_RGB_COLORS, + (void **)&ptPixels, + NULL, 0); + return DirectBitmap; +} + + +BOOL UseLayeredMode() +{ + return isLayeredEnabled() && !FrameIsFloating(); +} + + +void EraseBackground(HWND hwnd, HDC hdc) +{ + RECT r; + GetClientRect(hwnd, &r); + + if (isSkinEngineEnabled()) + { + if (FrameIsFloating()) + { + HBRUSH hB = CreateSolidBrush(opts.bkg_color); + FillRect(hdc, &r, hB); + DeleteObject(hB); + } + else + { + SkinDrawWindowBack(hwnd, hdc, &r, "Main,ID=Background"); + } + + SkinDrawGlyph(hdc, &r, &r,"MyDetails,ID=Background"); + } + else + { + HBRUSH hB = CreateSolidBrush(opts.bkg_color); + FillRect(hdc, &r, hB); + DeleteObject(hB); + } +} + +static int Width(const RECT &rc) +{ + return rc.right - rc.left; +} + +static int Height(const RECT &rc) +{ + return rc.bottom - rc.top; +} + +static HICON CreateOverlayedIcon(HICON icon, HICON overlay) +{ + HIMAGELIST il = ImageList_Create( + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + ILC_COLOR32|ILC_MASK, 2, 2); + ImageList_AddIcon(il, icon); + ImageList_AddIcon(il, overlay); + HIMAGELIST newImage = ImageList_Merge(il,0,il,1,0,0); + ImageList_Destroy(il); + HICON hIcon = ImageList_GetIcon(newImage, 0, 0); + ImageList_Destroy(newImage); + return hIcon; // the result should be destroyed by DestroyIcon() +} + +void Draw(HDC hdc, SkinIconFieldState &state) +{ + if (!state.isVisible()) + return; + + RECT rc = state.getInsideRect(); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + rc = state.getInsideRect(true); + + skin_DrawIconEx(hdc, rc.left, rc.top, state.getIcon(), Width(rc), Height(rc), 0, NULL, DI_NORMAL); + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); +} + +void Draw(HDC hdc, SkinTextFieldState &state, BOOL replace_smileys = FALSE, const char *protocol = NULL) +{ + if (!state.isVisible()) + return; + + RECT rc = state.getInsideRect(); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + HGDIOBJ oldFont = SelectObject(hdc, state.getFont()); + COLORREF oldColor = SetTextColor(hdc, state.getFontColor()); + + UINT uFormat = DT_NOPREFIX | DT_END_ELLIPSIS | (opts.draw_text_rtl ? DT_RTLREADING : 0); + + switch(state.getHorizontalAlign()) + { + case SKN_HALIGN_RIGHT: + uFormat |= DT_RIGHT; + break; + case SKN_HALIGN_CENTER: + uFormat |= DT_CENTER; + break; + case SKN_HALIGN_LEFT: + uFormat |= DT_LEFT; + break; + } + + if (replace_smileys && opts.replace_smileys) + { + uFormat |= DT_SINGLELINE; + + // Draw only first line of text + char *tmp = strdup(state.getText()); + char *pos = strchr(tmp, '\r'); + if (pos != NULL) + pos[0] = '\0'; + pos = strchr(tmp, '\n'); + if (pos != NULL) + pos[0] = '\0'; + + Smileys_DrawText(hdc, tmp, -1, &rc, uFormat | (opts.resize_smileys ? DT_RESIZE_SMILEYS : 0), + opts.use_contact_list_smileys ? "clist" : protocol, NULL); + } + else + { + skin_DrawText(hdc, state.getText(), -1, &rc, uFormat); + } + + + SelectObject(hdc, oldFont); + SetTextColor(hdc, oldColor); + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); +} + + +void DrawMouseOver(HDC hdc, RECT *lprc, const char *place) +{ + if (isSkinEngineEnabled()) + { + SkinDrawGlyph(hdc, lprc, lprc, "MyDetails,ID=MouseOver"); + + char glyph[1024]; + mir_snprintf(glyph, MAX_REGS(glyph), "MyDetails,ID=MouseOver%s", place); + SkinDrawGlyph(hdc, lprc, lprc, glyph); + } + else + { + FrameRect(hdc, lprc, (HBRUSH) GetStockObject(GRAY_BRUSH)); + } +} + + +void Draw(HWND hwnd, HDC hdc_orig) +{ + MyDetailsFrameData *data = (MyDetailsFrameData *) GetWindowLong(hwnd, GWL_USERDATA); + + Protocol *proto = GetCurrentProtocol(); + if (proto == NULL) + { + EraseBackground(hwnd, hdc_orig); + return; + } + + if (ServiceExists(MS_CLIST_FRAMES_SETFRAMEOPTIONS) && frame_id != -1) + { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if(flags & F_UNCOLLAPSED) + { + RECT rf; + GetClientRect(hwnd, &rf); + + if (rf.bottom - rf.top != 0) + { + if (FrameIsFloating()) + { + HWND parent = GetParent(hwnd); + + if (parent != NULL) + { + RECT rp_client, rp_window, r_window; + GetClientRect(parent, &rp_client); + GetWindowRect(parent, &rp_window); + GetWindowRect(hwnd, &r_window); + int diff = (rp_window.bottom - rp_window.top) - (rp_client.bottom - rp_client.top); + if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + diff += (r_window.top - rp_window.top); + + SetWindowPos(parent, 0, 0, 0, rp_window.right - rp_window.left, diff, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); + } + } + } + + for (size_t i = 0; i < data->items.size(); ++i) + data->items[i]->hide(); + + return; + } + } + + + RECT r_full; + GetClientRect(hwnd, &r_full); + + HDC hdc; + HBITMAP hBmp; + BOOL useLayeredMode = UseLayeredMode(); + if (useLayeredMode) + { + hdc = hdc_orig; + hBmp = NULL; + } + else + { + hdc = CreateCompatibleDC(hdc_orig); + hBmp = CreateBitmap32(Width(r_full), Height(r_full)); + SelectObject(hdc, hBmp); + } + + int old_bk_mode = SetBkMode(hdc, TRANSPARENT); + HFONT old_font = (HFONT) GetCurrentObject(hdc, OBJ_FONT); + COLORREF old_color = GetTextColor(hdc); + SetStretchBltMode(hdc, HALFTONE); + + + HICON hStatusIcon; + bool freeStatusIcon = false; + if (proto->GetCustomStatus() != 0 && proto->CanCall(PS_ICQ_GETCUSTOMSTATUSICON)) + hStatusIcon = (HICON) proto->Call(PS_ICQ_GETCUSTOMSTATUSICON, proto->GetCustomStatus(), LR_SHARED); + else + hStatusIcon = LoadSkinnedProtoIcon(proto->GetName(), proto->GetStatus()); + + if (proto->IsLocked()) + { + HICON hLockOverlay = LoadSkinnedIcon(SKINICON_OTHER_STATUS_LOCKED); + if (hLockOverlay != NULL) + { + freeStatusIcon = true; + hStatusIcon = CreateOverlayedIcon(hStatusIcon, hLockOverlay); + } + } + + + HICON hListeningIcon = IcoLib_LoadIcon("LISTENING_TO_ICON"); + HICON hEmailIcon = IcoLib_LoadIcon("MYDETAILS_EMAIL"); + HICON hNextIcon = IcoLib_LoadIcon("MYDETAILS_NEXT_PROTOCOL"); + HICON hPrevIcon = IcoLib_LoadIcon("MYDETAILS_PREV_PROTOCOL"); + + { + dialog->setInfoBool("resize_frame", opts.resize_frame); + dialog->setInfoBool("protocol.locked", proto->IsLocked()); + + + if (opts.resize_frame) + dialog->setSize(Width(r_full), 0x1FFFFFFF); + else + dialog->setSize(Width(r_full), Height(r_full)); + + + + SkinImageField avatar = dialog->getImageField("avatar"); + if (proto->CanGetAvatar() && proto->GetAvatarImage() != NULL) + { + avatar.setEnabled(TRUE); + avatar.setImage(proto->GetAvatarImage()); + } + else + { + avatar.setEnabled(FALSE); + avatar.setImage(NULL); + } + + SkinTextField nickname = dialog->getTextField("nickname"); + nickname.setText(proto->GetNick()); + + SkinTextField protocol = dialog->getTextField("protocol"); + protocol.setText(proto->GetDescription()); + + SkinIconField status_icon = dialog->getIconField("status_icon"); + status_icon.setIcon(hStatusIcon); + + SkinTextField status_name = dialog->getTextField("status_name"); + status_name.setText(proto->GetStatusName()); + + SkinTextField status_msg = dialog->getTextField("status_msg"); + if (proto->CanGetStatusMsg()) + { + status_msg.setEnabled(TRUE); + status_msg.setText(proto->GetStatusMsg()); + } + else + { + status_msg.setEnabled(FALSE); + status_msg.setText(_T("")); + } + + SkinIconField listening_icon = dialog->getIconField("listening_icon"); + SkinTextField listening = dialog->getTextField("listening"); + if (proto->ListeningToEnabled() && proto->GetStatus() > ID_STATUS_OFFLINE + && proto->GetListeningTo()[0] != 0) + { + listening_icon.setEnabled(TRUE); + listening.setEnabled(TRUE); + listening_icon.setIcon(hListeningIcon); + listening.setText(proto->GetListeningTo()); + } + else + { + listening_icon.setEnabled(FALSE); + listening.setEnabled(FALSE); + listening_icon.setIcon(NULL); + listening.setText(_T("")); + } + + SkinIconField email_icon = dialog->getIconField("email_icon"); + SkinTextField email = dialog->getTextField("email"); + if (proto->CanGetEmailCount()) + { + email_icon.setEnabled(TRUE); + email.setEnabled(TRUE); + email_icon.setIcon(hEmailIcon); + + TCHAR tmp[64]; + _sntprintf(tmp, MAX_REGS(tmp), _T("%d"), proto->GetEmailCount()); + email.setText(tmp); + } + else + { + email_icon.setEnabled(FALSE); + email.setEnabled(FALSE); + email_icon.setIcon(NULL); + email.setText(_T("")); + } + + SkinIconField next_proto = dialog->getIconField("next_proto"); + SkinIconField prev_proto = dialog->getIconField("prev_proto"); + prev_proto.setIcon(hPrevIcon); + next_proto.setIcon(hNextIcon); + } + + SkinDialogState state = dialog->run(); + SkinImageFieldState avatar = state.getImageField("avatar"); + SkinTextFieldState nickname = state.getTextField("nickname"); + SkinTextFieldState protocol = state.getTextField("protocol"); + SkinIconFieldState status_icon = state.getIconField("status_icon"); + SkinTextFieldState status_name = state.getTextField("status_name"); + SkinTextFieldState status_msg = state.getTextField("status_msg"); + SkinIconFieldState listening_icon = state.getIconField("listening_icon"); + SkinTextFieldState listening = state.getTextField("listening"); + SkinIconFieldState email_icon = state.getIconField("email_icon"); + SkinTextFieldState email = state.getTextField("email"); + SkinIconFieldState next_proto = state.getIconField("next_proto"); + SkinIconFieldState prev_proto = state.getIconField("prev_proto"); + + + { + data->proto.update(hwnd, &protocol); + data->proto_cycle_next.update(hwnd, &next_proto); + data->proto_cycle_prev.update(hwnd, &prev_proto); + data->avatar.update(hwnd, &avatar); + data->nick.update(hwnd, &nickname); + data->status.update(hwnd, &status_icon, &status_name); + data->away_msg.update(hwnd, &status_msg); + data->listening_to.update(hwnd, &listening_icon, &listening); + data->email.update(hwnd, &email_icon, &email); + + + POINT p = {0}; + GetCursorPos(&p); + ScreenToClient(hwnd, &p); + + for(size_t i = 0; i < data->items.size(); ++i) + data->items[i]->setMouseOver(&p); + } + + // Erase + EraseBackground(hwnd, hdc); + + // Draw items + + UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS + | (opts.draw_text_rtl ? DT_RTLREADING : 0); + + // Image + if (avatar.isVisible() && proto->CanGetAvatar() && proto->GetAvatarImage() != NULL) + { + RECT rc = avatar.getInsideRect(); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + rc = avatar.getInsideRect(true); + + int width = Width(rc); + int height = Height(rc); + + int round_radius; + if (opts.draw_avatar_round_corner) + { + if (opts.draw_avatar_use_custom_corner_size) + round_radius = opts.draw_avatar_custom_corner_size; + else + round_radius = min(width, height) / 6; + } + else + { + round_radius = 0; + } + + + AVATARDRAWREQUEST adr = {0}; + + adr.cbSize = sizeof(AVATARDRAWREQUEST); + adr.hTargetDC = hdc; + adr.rcDraw = rc; + + adr.dwFlags = AVDRQ_OWNPIC | AVDRQ_HIDEBORDERONTRANSPARENCY | + (opts.draw_avatar_border ? AVDRQ_DRAWBORDER : 0 ) | + (opts.draw_avatar_round_corner ? AVDRQ_ROUNDEDCORNER : 0 ); + + if (useLayeredMode) + adr.dwFlags |= AVDRQ_AERO; + + adr.clrBorder = opts.draw_avatar_border_color; + adr.radius = round_radius; + adr.alpha = 255; + adr.szProto = (char *) proto->GetName(); + + CallService(MS_AV_DRAWAVATAR, 0, (LPARAM) &adr); + + // Clipping rgn + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + } + + // Nick + if (data->nick.draw && data->nick.mouseOver && proto->CanSetNick()) + DrawMouseOver(hdc, &nickname.getRect(), "Nick"); + + Draw(hdc, nickname, TRUE, proto->GetName()); + + + // Protocol + if (data->proto.draw && data->proto.mouseOver) + DrawMouseOver(hdc, &data->proto.rc, "Proto"); + + Draw(hdc, protocol); + + + // Status + if (data->status.draw && data->status.mouseOver) + DrawMouseOver(hdc, &data->status.rc, "Status"); + + Draw(hdc, status_icon); + Draw(hdc, status_name); + + + // Away message + if (data->away_msg.draw && data->away_msg.mouseOver && proto->CanSetStatusMsg()) + DrawMouseOver(hdc, &data->away_msg.rc, "StatusMsg"); + + Draw(hdc, status_msg, TRUE, proto->GetName()); + + + // Listening to + Draw(hdc, listening_icon); + Draw(hdc, listening); + + if (data->listening_to.draw && data->listening_to.mouseOver && protocols->CanSetListeningTo()) + DrawMouseOver(hdc, &data->listening_to.rc, "Listening"); + + + // Unread email count + Draw(hdc, email_icon); + Draw(hdc, email); + + // Protocol cycle icon + Draw(hdc, next_proto); + Draw(hdc, prev_proto); + + + SelectObject(hdc, old_font); + SetTextColor(hdc, old_color); + SetBkMode(hdc, old_bk_mode); + + if (!useLayeredMode) + { + BitBlt(hdc_orig, r_full.left, r_full.top, r_full.right - r_full.left, + r_full.bottom - r_full.top, hdc, r_full.left, r_full.top, SRCCOPY); + DeleteDC(hdc); + DeleteObject(hBmp); + } + + if (freeStatusIcon) + DestroyIcon(hStatusIcon); + IcoLib_ReleaseIcon(hListeningIcon); + IcoLib_ReleaseIcon(hEmailIcon); + IcoLib_ReleaseIcon(hPrevIcon); + IcoLib_ReleaseIcon(hNextIcon); + + if (opts.resize_frame && ServiceExists(MS_CLIST_FRAMES_SETFRAMEOPTIONS) && frame_id != -1) + { + RECT rf; + GetClientRect(hwnd, &rf); + + int currentSize = Height(r_full); + + int expectedSize = 0; + for(size_t i = 0; i < data->items.size(); ++i) + { + SimpleItem *item = data->items[i]; + if (!item->draw) + continue; + + expectedSize = max(expectedSize, item->rc.bottom); + } + expectedSize += state.getBorders().bottom; + + if (expectedSize != currentSize) + { + if (FrameIsFloating()) + { + HWND parent = GetParent(hwnd); + + if (parent != NULL) + { + RECT rp_client, rp_window, r_window; + GetClientRect(parent, &rp_client); + GetWindowRect(parent, &rp_window); + GetWindowRect(hwnd, &r_window); + int diff = (rp_window.bottom - rp_window.top) - (rp_client.bottom - rp_client.top); + if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + diff += (r_window.top - rp_window.top); + + SetWindowPos(parent, 0, 0, 0, rp_window.right - rp_window.left, expectedSize + diff, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); + } + } + else if (IsWindowVisible(hwnd) && ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if(flags & F_VISIBLE) + { + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_HEIGHT, frame_id), (LPARAM) expectedSize); + CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)(FU_TBREDRAW | FU_FMREDRAW | FU_FMPOS)); + } + } + } + } +} + +int SkinEngineDrawCallback(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData) +{ + Draw(hWnd, hDC); + return 0; +} + +bool InsideRect(const POINT &p, const RECT &r) +{ + return p.x >= r.left && p.x < r.right && p.y >= r.top && p.y < r.bottom; +} + +int ShowPopupMenu(HWND hwnd, HMENU submenu, SimpleItem &item) +{ + POINT p; + if (item.alignRight) + p.x = item.rc.right; + else + p.x = item.rc.left; + p.y = item.rc.bottom+1; + ClientToScreen(hwnd, &p); + + return TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD + | (item.alignRight ? TPM_RIGHTALIGN : TPM_LEFTALIGN), p.x, p.y, 0, hwnd, NULL); +} + + +void ShowGlobalStatusMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p) +{ + HMENU submenu = (HMENU) CallService(MS_CLIST_MENUGETSTATUS,0,0); + + int ret = ShowPopupMenu(hwnd, submenu, data->status); + if(ret) + CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(ret),MPCF_MAINMENU),(LPARAM)NULL); +} + +void ShowProtocolStatusMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p) +{ + HMENU menu = (HMENU) CallService(MS_CLIST_MENUGETSTATUS,0,0); + HMENU submenu = NULL; + + if (menu != NULL) + { + // Find the correct menu item + int count = GetMenuItemCount(menu); + for (int i = 0 ; i < count && submenu == NULL; i++) + { + MENUITEMINFO mii = {0}; + + mii.cbSize = sizeof(mii); + + if(!IsWinVer98Plus()) + { + mii.fMask = MIIM_TYPE; + } + else + { + mii.fMask = MIIM_STRING; + } + + GetMenuItemInfo(menu, i, TRUE, &mii); + + if (mii.cch != 0) + { + mii.cch++; + mii.dwTypeData = (char *)malloc(sizeof(char) * mii.cch); + GetMenuItemInfo(menu, i, TRUE, &mii); + + if (strcmp(mii.dwTypeData, proto->GetDescription()) == 0) + { + submenu = GetSubMenu(menu, i); + } + + free(mii.dwTypeData); + } + } + + if (submenu == NULL && GetNumProtocols() == 1) + { + submenu = menu; + } + } + + if (submenu != NULL) + { + int ret = ShowPopupMenu(hwnd, submenu, data->status); + if(ret) + CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(ret),MPCF_MAINMENU),(LPARAM)NULL); + } + else + { + // Well, lets do it by hand + static int statusModePf2List[]={0xFFFFFFFF,PF2_ONLINE,PF2_SHORTAWAY,PF2_LONGAWAY,PF2_LIGHTDND,PF2_HEAVYDND,PF2_FREECHAT,PF2_INVISIBLE,PF2_ONTHEPHONE,PF2_OUTTOLUNCH}; + + menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + submenu = GetSubMenu(menu, 0); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + DWORD flags = proto->Call(PS_GETCAPS, PFLAGNUM_2); + for ( int i = GetMenuItemCount(submenu) -1 ; i >= 0 ; i-- ) + { + if (!(flags & statusModePf2List[i])) + { + // Hide menu + RemoveMenu(submenu, i, MF_BYPOSITION); + } + } + + int ret = ShowPopupMenu(hwnd, submenu, data->status); + DestroyMenu(menu); + + if(ret) + proto->SetStatus(ret); + } +} + +void ShowListeningToMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p) +{ + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 5); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + // Add this proto to menu + char tmp[128]; + mir_snprintf(tmp, sizeof(tmp), Translate("Enable Listening To for %s"), proto->GetDescription()); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; + mii.fType = MFT_STRING; + mii.fState = proto->ListeningToEnabled() ? MFS_CHECKED : 0; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 1; + + if (!proto->CanSetListeningTo()) + { + mii.fState |= MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = protocols->ListeningToEnabled() ? MFS_CHECKED : 0; + + if (!protocols->CanSetListeningTo()) + { + mii.fState |= MFS_DISABLED; + } + + SetMenuItemInfo(submenu, ID_LISTENINGTOPOPUP_SENDLISTENINGTO, FALSE, &mii); + + int ret = ShowPopupMenu(hwnd, submenu, data->listening_to); + + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_LISTENINGTO_ENABLE, (LPARAM) proto->GetName(), !proto->ListeningToEnabled()); + break; + } + case ID_LISTENINGTOPOPUP_SENDLISTENINGTO: + { + CallService(MS_LISTENINGTO_ENABLE, 0, !protocols->ListeningToEnabled()); + break; + } + } + +} + + +LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_CREATE: + { + MyDetailsFrameData *data = new MyDetailsFrameData(); + SetWindowLong(hwnd, GWL_USERDATA, (LONG) data); + + SetCurrentProtocol(DBGetContactSettingWord(NULL, "MyDetails", "ProtocolNumber", 0)); + + SetCycleTime(hwnd); + + SetStatusMessageRefreshTime(hwnd); + + return TRUE; + } + + + case WM_ERASEBKGND: + { + //EraseBackground(hwnd, (HDC)wParam); + //Draw(hwnd, (HDC)wParam); + return TRUE; + } + + /* + case WM_PRINTCLIENT: + { + Draw(hwnd, (HDC)wParam); + return TRUE; + } + */ + + case WM_PAINT: + { + if (UseLayeredMode()) + { + CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE, (WPARAM) hwnd, 0); + ValidateRect(hwnd, NULL); + } + else + { + RECT r; + if(GetUpdateRect(hwnd, &r, FALSE)) + { + PAINTSTRUCT ps; + + HDC hdc = BeginPaint(hwnd, &ps); + Draw(hwnd, hdc); + EndPaint(hwnd, &ps); + } + } + + return TRUE; + } + + case WM_SIZE: + { + //InvalidateRect(hwnd, NULL, FALSE); + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + RedrawFrame(); + break; + } + + case WM_TIMER: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + + if (wParam == ID_FRAME_TIMER) + { + if (!data->showing_menu) + CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0); + } + else if (wParam == ID_RECALC_TIMER) + { + KillTimer(hwnd, ID_RECALC_TIMER); + + PostMessage(hwnd, MWM_REFRESH_DATA, 0, 0); + } + else if (wParam == ID_STATUSMESSAGE_TIMER) + { + SetStatusMessageRefreshTime(hwnd); + + PostMessage(hwnd, MWM_REFRESH_DATA, 0, 0); + } + + return TRUE; + } + + case WM_LBUTTONUP: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + Protocol *proto = GetCurrentProtocol(); + if (proto == NULL) + break; + + POINT p; + p.x = LOWORD(lParam); + p.y = HIWORD(lParam); + + // In proto cycle button? + if (data->proto_cycle_next.hitTest(p)) + { + CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0); + } + else if (data->proto_cycle_prev.hitTest(p)) + { + CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0); + } + // In image? + else if (data->avatar.hitTest(p) && proto->CanSetAvatar()) + { + if (opts.global_on_avatar) + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0); + else + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->GetName()); + } + // In nick? + else if (data->nick.hitTest(p) && proto->CanSetNick()) + { + if (opts.global_on_nickname) + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0); + else + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->GetName()); + } + // In status message? + else if (data->away_msg.hitTest(p) && proto->CanSetStatusMsg()) + { + if (opts.global_on_status_message) + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0); + else + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->GetName()); + } + // In status? + else if (data->status.hitTest(p)) + { + data->showing_menu = true; + + if (opts.global_on_status) + ShowGlobalStatusMenu(hwnd, data, proto, p); + else + ShowProtocolStatusMenu(hwnd, data, proto, p); + + data->showing_menu = false; + } + // In listening to? + else if (data->listening_to.hitTest(p) && protocols->CanSetListeningTo()) + { + ShowListeningToMenu(hwnd, data, proto, p); + } + // In protocol? + else if (data->proto.hitTest(p)) + { + data->showing_menu = true; + + HMENU menu = CreatePopupMenu(); + + std::vector protos; + GetProtocols(&protos); + + int current = GetCurrentProtocolIndex(); + + int protosSize = (int) protos.size(); + for (int i = protosSize - 1 ; i >= 0 ; i--) + { + Protocol &proto = protos[i]; + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = (char *) proto.GetDescription(); + mii.cch = strlen(mii.dwTypeData); + mii.wID = i + 1; + + if (i == current) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(menu, 0, TRUE, &mii); + } + + int ret = ShowPopupMenu(hwnd, menu, data->proto); + + DestroyMenu(menu); + + if (ret != 0) + PluginCommand_ShowProtocol(NULL, (WPARAM) GetProtocolByIndex(ret - 1).GetName()); + + data->showing_menu = false; + } + + break; + } + + case WM_MEASUREITEM: + { + return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam); + } + case WM_DRAWITEM: + { + return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam); + } + + case WM_CONTEXTMENU: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + Protocol *proto = GetCurrentProtocol(); + if (proto == NULL) + break; + + POINT p; + p.x = LOWORD(lParam); + p.y = HIWORD(lParam); + + ScreenToClient(hwnd, &p); + + data->showing_menu = true; + + // In proto cycle button? + if (data->proto_cycle_next.hitTest(p)) + { + CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0); + } + else if (data->proto_cycle_prev.hitTest(p)) + { + CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0); + } + // In image? + else if (data->avatar.hitTest(p)) + { + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 4); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + // Add this proto to menu + char tmp[128]; + mir_snprintf(tmp, sizeof(tmp), Translate("Set My Avatar for %s..."), proto->GetDescription()); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 1; + + if (!proto->CanSetAvatar()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->GetName()); + break; + } + case ID_AVATARPOPUP_SETMYAVATAR: + { + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0); + break; + } + } + } + // In nick? + else if (data->nick.hitTest(p)) + { + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 2); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + // Add this proto to menu + char tmp[128]; + mir_snprintf(tmp, sizeof(tmp), Translate("Set My Nickname for %s..."), proto->GetDescription()); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 1; + + if (!proto->CanSetNick()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->GetName()); + break; + } + case ID_NICKPOPUP_SETMYNICKNAME: + { + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0); + break; + } + } + } + // In status message? + else if (data->away_msg.hitTest(p)) + { + char tmp[128]; + + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 3); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + // Add this proto to menu + mir_snprintf(tmp, sizeof(tmp), Translate("Set My Status Message for %s..."), + proto->GetDescription()); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 1; + + if (!proto->CanSetStatusMsg()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + { + // Add this to menu + mir_snprintf(tmp, sizeof(tmp), Translate("Set My Status Message for %s..."), + CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, proto->GetStatus(), 0)); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 2; + + if (proto->GetStatus() == ID_STATUS_OFFLINE) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + } + + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->GetName()); + break; + } + case 2: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, (WPARAM) proto->GetStatus(), 0); + break; + } + case ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0); + break; + } + } + } + // In status? + else if (data->status.hitTest(p)) + { + if (opts.global_on_status) + ShowProtocolStatusMenu(hwnd, data, proto, p); + else + ShowGlobalStatusMenu(hwnd, data, proto, p); + } + // In listening to? + else if (data->listening_to.hitTest(p) && protocols->CanSetListeningTo()) + { + ShowListeningToMenu(hwnd, data, proto, p); + } + // In protocol? + else if (data->proto.hitTest(p)) + { + } + // Default context menu + else + { + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 1); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + if (opts.cycle_through_protocols) + RemoveMenu(submenu, ID_CYCLE_THROUGH_PROTOS, MF_BYCOMMAND); + else + RemoveMenu(submenu, ID_DONT_CYCLE_THROUGH_PROTOS, MF_BYCOMMAND); + + // Add this proto to menu + char tmp[128]; + MENUITEMINFO mii = {0}; + + mir_snprintf(tmp, sizeof(tmp), Translate("Enable Listening To for %s"), proto->GetDescription()); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; + mii.fType = MFT_STRING; + mii.fState = proto->ListeningToEnabled() ? MFS_CHECKED : 0; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 5; + + if (!proto->CanSetListeningTo()) + { + mii.fState |= MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + // Add this to menu + mir_snprintf(tmp, sizeof(tmp), Translate("Set My Status Message for %s..."), + CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, proto->GetStatus(), 0)); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 4; + + if (proto->GetStatus() == ID_STATUS_OFFLINE) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + // Add this proto to menu + mir_snprintf(tmp, sizeof(tmp), Translate("Set My Status Message for %s..."), proto->GetDescription()); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 3; + + if (!proto->CanSetStatusMsg()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + mir_snprintf(tmp, sizeof(tmp), Translate("Set My Nickname for %s..."), proto->GetDescription()); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 2; + + if (!proto->CanSetNick()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + mir_snprintf(tmp, sizeof(tmp), Translate("Set My Avatar for %s..."), proto->GetDescription()); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = strlen(tmp); + mii.wID = 1; + + if (!proto->CanSetAvatar()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = protocols->ListeningToEnabled() ? MFS_CHECKED : 0; + + if (!protocols->CanSetListeningTo()) + { + mii.fState |= MFS_DISABLED; + } + + SetMenuItemInfo(submenu, ID_CONTEXTPOPUP_ENABLELISTENINGTO, FALSE, &mii); + + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->GetName()); + break; + } + case ID_AVATARPOPUP_SETMYAVATAR: + { + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0); + break; + } + case 2: + { + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->GetName()); + break; + } + case ID_NICKPOPUP_SETMYNICKNAME: + { + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0); + break; + } + case 3: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->GetName()); + break; + } + case 4: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, (WPARAM) proto->GetStatus(), 0); + break; + } + case ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0); + break; + } + case 5: + { + CallService(MS_LISTENINGTO_ENABLE, (LPARAM) proto->GetName(), !proto->ListeningToEnabled()); + break; + } + case ID_CONTEXTPOPUP_ENABLELISTENINGTO: + { + CallService(MS_LISTENINGTO_ENABLE, 0, !protocols->ListeningToEnabled()); + break; + } + case ID_SHOW_NEXT_PROTO: + { + CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0); + break; + } + case ID_SHOW_PREV_PROTO: + { + CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0); + break; + } + case ID_CYCLE_THROUGH_PROTOS: + { + CallService(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS, TRUE, 0); + break; + } + case ID_DONT_CYCLE_THROUGH_PROTOS: + { + CallService(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS, FALSE, 0); + break; + } + } + } + + data->showing_menu = false; + + + break; + } + + case WM_NCMOUSELEAVE: + case WM_MOUSELEAVE: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + data->tracking_exit = false; + } + case WM_NCMOUSEMOVE: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + + bool changed = false; + for(size_t i = 0; i < data->items.size(); ++i) + changed = changed || data->items[i]->setMouseOver(NULL); + + if (changed) + InvalidateRect(hwnd, NULL, FALSE); + + break; + } + + case WM_MOUSEMOVE: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + Protocol *proto = GetCurrentProtocol(); + if (proto == NULL) + break; + + if (!data->tracking_exit) + { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hwnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + + data->tracking_exit = true; + } + + POINT p; + p.x = LOWORD(lParam); + p.y = HIWORD(lParam); + + bool changed = false; + for(size_t i = 0; i < data->items.size(); ++i) + changed = changed || data->items[i]->setMouseOver(&p); + + if (changed) + InvalidateRect(hwnd, NULL, FALSE); + + break; + } + + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR) lParam; + + int i = (int) lpnmhdr->code; + + switch (lpnmhdr->code) { + case TTN_GETDISPINFO: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + + LPNMTTDISPINFO lpttd = (LPNMTTDISPINFO) lpnmhdr; + SendMessage(lpnmhdr->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 300); + + for(int i = 0; i < data->items.size(); i++) + { + lpttd->lpszText = (char *) data->items[i]->getToolTipFor(lpnmhdr->hwndFrom); + if (lpttd->lpszText != NULL) + break; + } + + return 0; + } + } + + break; + } + + case WM_DESTROY: + { + KillTimer(hwnd, ID_FRAME_TIMER); + + MyDetailsFrameData *tmp = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA); + if (tmp != NULL) delete tmp; + + break; + } + + // Custom Messages ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + case MWM_REFRESH: + { + KillTimer(hwnd, ID_RECALC_TIMER); + SetTimer(hwnd, ID_RECALC_TIMER, RECALC_TIME, NULL); + break; + } + + case MWM_REFRESH_DATA: + { + Protocol *proto = GetCurrentProtocol(false); + if (proto) + { + proto->UpdateAll(); + RedrawFrame(); + } + break; + } + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + + +int ShowHideFrameFunc(WPARAM wParam, LPARAM lParam) +{ + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + } + else + { + if (MyDetailsFrameVisible()) + { + SendMessage(hwnd_container, WM_CLOSE, 0, 0); + } + else + { + ShowWindow(hwnd_container, SW_SHOW); + DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1); + } + + FixMainMenu(); + } + return 0; +} + + +int ShowFrameFunc(WPARAM wParam, LPARAM lParam) +{ + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if(!(flags & F_VISIBLE)) + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + } + else + { + if (!MyDetailsFrameVisible()) + { + ShowWindow(hwnd_container, SW_SHOW); + DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1); + + FixMainMenu(); + } + + } + return 0; +} + + +int HideFrameFunc(WPARAM wParam, LPARAM lParam) +{ + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if (flags & F_VISIBLE) + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + } + else + { + if (MyDetailsFrameVisible()) + { + SendMessage(hwnd_container, WM_CLOSE, 0, 0); + + FixMainMenu(); + } + } + return 0; +} + + +void FixMainMenu() +{ + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(CLISTMENUITEM); + mi.flags = CMIM_NAME; + + if(MyDetailsFrameVisible()) + mi.pszName = Translate("Hide My Details"); + else + mi.pszName = Translate("Show My Details"); + + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuShowHideFrame, (LPARAM)&mi); +} + +#include + +void RedrawFrame() +{ + if (frame_id == -1) + { + InvalidateRect(hwnd_container, NULL, TRUE); + } + else + { + CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)FU_TBREDRAW | FU_FMREDRAW); + } +} + +void UpdateFrameData() +{ + if (hwnd_frame != NULL) + PostMessage(hwnd_frame, MWM_REFRESH, 0, 0); +} + +// only used when no multiwindow functionality is available +BOOL MyDetailsFrameVisible() +{ + return IsWindowVisible(hwnd_container) ? true : false; +} + +void SetMyDetailsFrameVisible(BOOL visible) +{ + if (frame_id == -1 && hwnd_container != 0) + { + ShowWindow(hwnd_container, visible ? SW_SHOW : SW_HIDE); + } +} + +void SetCycleTime() +{ + if (hwnd_frame != NULL) + SetCycleTime(hwnd_frame); +} + +void SetCycleTime(HWND hwnd) +{ + KillTimer(hwnd, ID_FRAME_TIMER); + + if (opts.cycle_through_protocols) + SetTimer(hwnd, ID_FRAME_TIMER, opts.seconds_to_show_protocol * 1000, 0); +} + +void SetStatusMessageRefreshTime() +{ + if (hwnd_frame != NULL) + SetStatusMessageRefreshTime(hwnd_frame); +} + +void SetStatusMessageRefreshTime(HWND hwnd) +{ + KillTimer(hwnd, ID_STATUSMESSAGE_TIMER); + + opts.refresh_status_message_timer = DBGetContactSettingWord(NULL, "MyDetails", "RefreshStatusMessageTimer",5); + if (opts.refresh_status_message_timer > 0) + { + SetTimer(hwnd, ID_STATUSMESSAGE_TIMER, opts.refresh_status_message_timer * 1000, NULL); + } +} + +int PluginCommand_ShowNextProtocol(WPARAM wParam,LPARAM lParam) +{ + if (hwnd_frame == NULL) + return -1; + + SetCurrentProtocol(GetCurrentProtocolIndex() + 1); + + SetCycleTime(); + + RedrawFrame(); + + return 0; +} + +int PluginCommand_ShowPreviousProtocol(WPARAM wParam,LPARAM lParam) +{ + if (hwnd_frame == NULL) + return -1; + + SetCurrentProtocol(GetCurrentProtocolIndex() - 1); + + SetCycleTime(); + + RedrawFrame(); + + return 0; +} + +int PluginCommand_ShowProtocol(WPARAM wParam,LPARAM lParam) +{ + char * proto = (char *)lParam; + + if (proto == NULL) + return -1; + + int proto_num = GetProtocolIndexByName(proto); + if (proto_num == -1) + return -2; + + if (hwnd_frame == NULL) + return -3; + + SetCurrentProtocol(proto_num); + + SetCycleTime(); + + RedrawFrame(); + + return 0; +} + +int SettingsChangedHook(WPARAM wParam, LPARAM lParam) +{ + if (hwnd_frame == NULL) + return 0; + + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; + + if (wParam != NULL) + return 0; + + if (strstr(cws->szModule,"Away")) + { + // Status message changed + UpdateFrameData(); + return 0; + } + + Protocol *proto = GetCurrentProtocol(false); + if (proto == NULL || strcmp(proto->GetName(), cws->szModule) != 0) + return 0; + + if (!strcmp(cws->szSetting,"Status") + || !strcmp(cws->szSetting,"StatusMood") + || !strcmp(cws->szSetting,"XStatusName") + || !strcmp(cws->szSetting,"XStatusMsg") + || !strcmp(cws->szSetting,"XStatusId") + || ( proto->GetCustomStatus() != 0 && !strcmp(cws->szSetting, proto->GetCustomStatusNameKey()) ) + || ( proto->GetCustomStatus() != 0 && !strcmp(cws->szSetting, proto->GetCustomStatusMessageKey()) )) + { + // Status changed + UpdateFrameData(); + } + else if(!strcmp(cws->szSetting,"MyHandle") + || !strcmp(cws->szSetting,"UIN") + || !strcmp(cws->szSetting,"Nick") + || !strcmp(cws->szSetting,"FirstName") + || !strcmp(cws->szSetting,"e-mail") + || !strcmp(cws->szSetting,"LastName") + || !strcmp(cws->szSetting,"JID")) + { + // Name changed + UpdateFrameData(); + } + else if (strcmp(cws->szSetting,"ListeningTo") == 0) + { + UpdateFrameData(); + } + else if (strcmp(cws->szSetting,"LockMainStatus") == 0) + { + UpdateFrameData(); + } + + return 0; +} + +int AvatarChangedHook(WPARAM wParam, LPARAM lParam) +{ + if (hwnd_frame == NULL) + return 0; + + Protocol *proto = GetCurrentProtocol(false); + if (proto == NULL || strcmp(proto->GetName(), (const char *) wParam) != 0) + return 0; + + UpdateFrameData(); + + return 0; +} + +int ProtoAckHook(WPARAM wParam, LPARAM lParam) +{ + if (hwnd_frame == NULL) + return 0; + + ACKDATA *ack = (ACKDATA*) lParam; + if (ack->hContact != NULL) + return 0; + + Protocol *proto = GetCurrentProtocol(false); + if (proto == NULL || strcmp(proto->GetName(), ack->szModule) != 0) + return 0; + + if (ack->type == ACKTYPE_STATUS) + { + UpdateFrameData(); + } + else if (ack->type == ACKTYPE_AWAYMSG) + { + UpdateFrameData(); + } + else if (ack->type == ACKTYPE_EMAIL) + { + UpdateFrameData(); + } + + return 0; +} + +int ListeningtoEnableStateChangedHook(WPARAM wParam,LPARAM lParam) +{ + if (hwnd_frame == NULL) + return 0; + + Protocol *proto = GetCurrentProtocol(false); + if (proto == NULL || strcmp(proto->GetName(), (const char *) wParam) != 0) + return 0; + + UpdateFrameData(); + + return 0; +} + +int AccListChanged(WPARAM wParam, LPARAM lParam) +{ + SetCurrentProtocol(0); + + RedrawFrame(); + + return 0; +} -- cgit v1.2.3