// refactored step 1. /* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-2008 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. */ /************************************************************************/ /* Module responsible for working with contact list control */ /************************************************************************/ #include "hdr/modern_commonheaders.h" #include "m_clc.h" #include "m_skin.h" #include "hdr/modern_commonprototypes.h" #include "hdr/modern_clc.h" #include "hdr/modern_clist.h" #include "hdr/modern_clcpaint.h" #include "m_modernopt.h" int ModernOptInit(WPARAM wParam,LPARAM lParam); int ModernSkinOptInit(WPARAM wParam,LPARAM lParam); /* * Private module variables */ static HANDLE hShowInfoTipEvent; static HANDLE hSettingChanged; static POINT HitPoint; static BOOL fMouseUpped; static BYTE IsDragToScrollMode=0; static int StartDragPos=0; static int StartScrollPos=0; HANDLE hSmileyAddOptionsChangedHook=NULL; HANDLE hIconChangedHook=NULL; HANDLE hAckHook=NULL; HANDLE hAvatarChanged=NULL; static BOOL g_bSortTimerIsSet = FALSE; static struct ClcContact * hitcontact=NULL; static int clcHookSmileyAddOptionsChanged(WPARAM wParam,LPARAM lParam); static int clcHookIconsChanged(WPARAM wParam, LPARAM lParam); static int clcHookBkgndConfigChanged(WPARAM wParam,LPARAM lParam); static int clcProceedDragToScroll(HWND hwnd, int Y); static int clcExitDragToScroll(); static int clcHookModulesLoaded(WPARAM wParam,LPARAM lParam) { int i; if (MirandaExiting()) return 0; ModernHookEvent(ME_MODERNOPT_INITIALIZE,ModernOptInit); ModernHookEvent(ME_MODERNOPT_INITIALIZE,ModernSkinOptInit); if (ServiceExists(MS_MC_DISABLEHIDDENGROUP)) CallService(MS_MC_DISABLEHIDDENGROUP, (WPARAM)TRUE, (LPARAM)0); if (ServiceExists(MS_MC_GETPROTOCOLNAME)) g_szMetaModuleName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0); // Get icons if(ServiceExists(MS_SKIN2_ADDICON)) { SKINICONDESC sid={0}; char szMyPath[MAX_PATH]; int i; GetModuleFileNameA(g_hInst, szMyPath, MAX_PATH); sid.cbSize = sizeof(sid); sid.cx=16; sid.cy=16; sid.pszDefaultFile = szMyPath; sid.pszSection = LPGEN("Contact List"); sid.pszDescription = LPGEN("Listening to"); sid.pszName = "LISTENING_TO_ICON"; sid.iDefaultIndex = - IDI_LISTENING_TO; CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); sid.pszSection = LPGEN("Contact List/Avatar Overlay"); for (i = 0 ; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++) { sid.pszDescription = g_pAvatarOverlayIcons[i].description; sid.pszName = g_pAvatarOverlayIcons[i].name; sid.iDefaultIndex = - g_pAvatarOverlayIcons[i].id; CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); } sid.pszSection = LPGEN("Contact List/Status Overlay"); for (i = 0 ; i < MAX_REGS(g_pStatusOverlayIcons) ; i++) { sid.pszDescription = g_pStatusOverlayIcons[i].description; sid.pszName = g_pStatusOverlayIcons[i].name; sid.iDefaultIndex = - g_pStatusOverlayIcons[i].id; CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); } clcHookIconsChanged(0,0); hIconChangedHook=ModernHookEvent(ME_SKIN2_ICONSCHANGED, clcHookIconsChanged); } else { if (hAvatarOverlays) ImageList_Destroy(hAvatarOverlays); hAvatarOverlays=ImageList_Create(16,16,ILC_MASK|ILC_COLOR32,MAX_REGS(g_pAvatarOverlayIcons)*2,1); for (i = 0 ; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++) { HICON hIcon=LoadSmallIcon(g_hInst, MAKEINTRESOURCE(g_pAvatarOverlayIcons[i].id)); g_pAvatarOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays,hIcon); DestroyIcon_protect(hIcon); hIcon=LoadSmallIcon(g_hInst, MAKEINTRESOURCE(g_pStatusOverlayIcons[i].id)); g_pStatusOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays,hIcon); DestroyIcon_protect(hIcon); } g_hListeningToIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_LISTENING_TO), IMAGE_ICON, 16, 16, 0); } // Register smiley category if (ServiceExists(MS_SMILEYADD_REGISTERCATEGORY)) { SMADD_REGCAT rc; rc.cbSize = sizeof(rc); rc.name = "clist"; rc.dispname = Translate("Contact List smileys"); CallService(MS_SMILEYADD_REGISTERCATEGORY, 0, (LPARAM)&rc); hSmileyAddOptionsChangedHook=ModernHookEvent(ME_SMILEYADD_OPTIONSCHANGED,clcHookSmileyAddOptionsChanged); } CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"List Background/CLC",0); CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Menu Background/Menu",0); CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"StatusBar Background/StatusBar",0); CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Frames TitleBar BackGround/FrameTitleBar",0); ModernHookEvent(ME_BACKGROUNDCONFIG_CHANGED,clcHookBkgndConfigChanged); ModernHookEvent(ME_BACKGROUNDCONFIG_CHANGED,BgStatusBarChange); ModernHookEvent(ME_BACKGROUNDCONFIG_CHANGED,OnFrameTitleBarBackgroundChange); ModernHookEvent(ME_COLOUR_RELOAD, OnFrameTitleBarBackgroundChange); AniAva_UpdateOptions(); return 0; } static int clcHookSmileyAddOptionsChanged(WPARAM wParam,LPARAM lParam) { if (MirandaExiting()) return 0; pcli->pfnClcBroadcast( CLM_AUTOREBUILD,0,0); pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0); return 0; } static int clcHookProtoAck(WPARAM wParam,LPARAM lParam) { return ClcDoProtoAck((HANDLE) wParam,(ACKDATA*) lParam); } static int clcHookIconsChanged(WPARAM wParam, LPARAM lParam) { int i; if (MirandaExiting()) return 0; for (i = 0 ; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++) { g_pAvatarOverlayIcons[i].listID=-1; g_pStatusOverlayIcons[i].listID=-1; } if (hAvatarOverlays) ImageList_Destroy(hAvatarOverlays); hAvatarOverlays=ImageList_Create(16,16,ILC_MASK|ILC_COLOR32,MAX_REGS(g_pAvatarOverlayIcons)*2,1); for (i = 0 ; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++) { HICON hIcon=(HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)g_pAvatarOverlayIcons[i].name); g_pAvatarOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays,hIcon); CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)g_pAvatarOverlayIcons[i].name); hIcon=(HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)g_pStatusOverlayIcons[i].name); g_pStatusOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays,hIcon); CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)g_pStatusOverlayIcons[i].name); } g_hListeningToIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"LISTENING_TO_ICON"); pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0); AniAva_UpdateOptions(); return 0; } static int clcHookSettingChanged(WPARAM wParam,LPARAM lParam) { DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam; if (MirandaExiting()) return 0; if ((HANDLE)wParam==NULL) { if (g_szMetaModuleName && !mir_strcmp(cws->szModule, g_szMetaModuleName)) { if (!mir_strcmp(cws->szSetting, "Enabled")) pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, wParam, lParam); } else if (!mir_strcmp(cws->szModule, "CListGroups")) { pcli->pfnClcBroadcast( INTM_GROUPSCHANGED,wParam,lParam); } else if (!strcmp(cws->szSetting,"XStatusId") || !strcmp(cws->szSetting,"XStatusName") ) { CLUIServices_ProtocolStatusChanged(0,(LPARAM)cws->szModule); } } else // (HANDLE)wParam != NULL { if (!strcmp(cws->szSetting,"TickTS")) { pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0); } else if (g_szMetaModuleName && !strcmp(cws->szModule,g_szMetaModuleName)) { if (!strcmp(cws->szSetting,"Handle")) { pcli->pfnClcBroadcast( INTM_NAMEORDERCHANGED,0,0); } else if (!strcmp(cws->szSetting,"Default")) { pcli->pfnClcBroadcast( INTM_NAMEORDERCHANGED,0,0); } } else if (!strcmp(cws->szModule,"UserInfo")) { if (!strcmp(cws->szSetting,"Timezone")) pcli->pfnClcBroadcast( INTM_TIMEZONECHANGED,wParam,0); } else if (!strcmp(cws->szModule,"CList")) { /* if (!strcmp(cws->szSetting,"MyHandle")) pcli->pfnClcBroadcast( INTM_NAMECHANGED,wParam,lParam); else if (!strcmp(cws->szSetting,"Group")) pcli->pfnClcBroadcast( INTM_GROUPCHANGED,wParam,lParam); else if (!strcmp(cws->szSetting,"Hidden")) pcli->pfnClcBroadcast( INTM_HIDDENCHANGED,wParam,lParam); else if (!strcmp(cws->szSetting,"noOffline")) pcli->pfnClcBroadcast( INTM_NAMEORDERCHANGED,wParam,lParam); else if (!strcmp(cws->szSetting,"NotOnList")) pcli->pfnClcBroadcast( INTM_NOTONLISTCHANGED,wParam,lParam); else if (!strcmp(cws->szSetting,"NameOrder")) pcli->pfnClcBroadcast( INTM_NAMEORDERCHANGED,0,0); else else if (!strcmp(cws->szSetting,"Status")) pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0); else */ if (!strcmp(cws->szSetting,"StatusMsg")) pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0); } else if (!strcmp(cws->szModule,"ContactPhoto")) { if (!strcmp(cws->szSetting,"File")) pcli->pfnClcBroadcast( INTM_AVATARCHANGED,wParam,0); } else //if(0) //turn off { { // if (!strcmp(cws->szSetting,"UIN")) // pcli->pfnClcBroadcast( INTM_NAMECHANGED,wParam,lParam); // else if (!strcmp(cws->szSetting,"Nick") || !strcmp(cws->szSetting,"FirstName") // || !strcmp(cws->szSetting,"e-mail") || !strcmp(cws->szSetting,"LastName") // || !strcmp(cws->szSetting,"JID")) // pcli->pfnClcBroadcast( INTM_NAMECHANGED,wParam,lParam); // else if (!strcmp(cws->szSetting,"ApparentMode")) // pcli->pfnClcBroadcast( INTM_APPARENTMODECHANGED,wParam,lParam); // else if (!strcmp(cws->szSetting,"IdleTS")) // pcli->pfnClcBroadcast( INTM_IDLECHANGED,wParam,lParam); //else if ((!strcmp(cws->szSetting,"XStatusName") || !strcmp(cws->szSetting,"XStatusMsg"))) pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0); else if (!strcmp(cws->szSetting,"XStatusId")) pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0); else if (!strcmp(cws->szSetting,"Timezone")) pcli->pfnClcBroadcast( INTM_TIMEZONECHANGED,wParam,0); else if (!strcmp(cws->szSetting,"ListeningTo")) pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0); else if (!strcmp(cws->szSetting,"Transport") || !strcmp(cws->szSetting,"IsTransported") ) { pcli->pfnInvalidateDisplayNameCacheEntry((HANDLE)wParam); pcli->pfnClcBroadcast( CLM_AUTOREBUILD,wParam,0); } } } } return 0; } static int clcHookDbEventAdded(WPARAM wParam,LPARAM lParam) { DBEVENTINFO dbei = {0}; g_CluiData.t_now = time(NULL); if(wParam && lParam) { dbei.cbSize = sizeof(dbei); dbei.pBlob = 0; dbei.cbBlob = 0; CallService(MS_DB_EVENT_GET, (WPARAM)lParam, (LPARAM)&dbei); if(dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { PDNCE pdnce=(PDNCE)pcli->pfnGetCacheEntry((HANDLE)wParam); ModernWriteSettingDword((HANDLE)wParam, "CList", "mf_lastmsg", dbei.timestamp); if (pdnce) pdnce->dwLastMsgTime=dbei.timestamp; } } return 0; } static int clcHookBkgndConfigChanged(WPARAM wParam,LPARAM lParam) { pcli->pfnClcOptionsChanged(); return 0; } static int clcHookSystemShutdown(WPARAM wParam,LPARAM lParam) { ModernUnhookEvent(hAckHook); ModernUnhookEvent(hSettingChanged); return 0; } static int clcHookAvatarChanged(WPARAM wParam, LPARAM lParam) { if (MirandaExiting()) return 0; pcli->pfnClcBroadcast(INTM_AVATARCHANGED, wParam, lParam); return 0; } static int clcExitDragToScroll() { if (!IsDragToScrollMode) return 0; IsDragToScrollMode=0; ReleaseCapture(); return 1; } static int clcProceedDragToScroll(HWND hwnd, int Y) { int pos,dy; if (!IsDragToScrollMode) return 0; if(GetCapture()!=hwnd) clcExitDragToScroll(); dy=StartDragPos-Y; pos=StartScrollPos+dy; if (pos<0) pos=0; SendMessage(hwnd, WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos),0); return 1; } static int clcSearchNextContact(HWND hwnd, struct ClcData *dat, int index, const TCHAR *text, int prefixOk, BOOL fSearchUp) { struct ClcGroup *group = &dat->list; int testlen = lstrlen(text); BOOL fReturnAsFound=FALSE; int nLastFound=-1; if (index==-1) fReturnAsFound=TRUE; group->scanIndex = 0; for (;;) { if (group->scanIndex == group->cl.count) { group = group->parent; if (group == NULL) break; group->scanIndex++; continue; } if (group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER) { if ((prefixOk && CSTR_EQUAL==CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, text, -1, group->cl.items[group->scanIndex]->szText, testlen)) || (!prefixOk && !lstrcmpi(text, group->cl.items[group->scanIndex]->szText))) { struct ClcGroup *contactGroup = group; int contactScanIndex = group->scanIndex; int foundindex; for (; group; group = group->parent) pcli->pfnSetGroupExpand(hwnd, dat, group, 1); foundindex=pcli->pfnGetRowsPriorTo(&dat->list, contactGroup, contactScanIndex); if (fReturnAsFound) return foundindex; else if (nLastFound!=-1 && fSearchUp && foundindex==index) return nLastFound; else if (!fSearchUp && foundindex==index) fReturnAsFound=TRUE; else nLastFound=foundindex; group=contactGroup; group->scanIndex=contactScanIndex; } if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { if (!(dat->exStyle & CLS_EX_QUICKSEARCHVISONLY) || group->cl.items[group->scanIndex]->group->expanded) { group = group->cl.items[group->scanIndex]->group; group->scanIndex = 0; continue; } } } group->scanIndex++; } return -1; } static BOOL clcItemNotHiddenOffline(struct ClcData * dat, struct ClcGroup* group, struct ClcContact * contact) { PDNCE pdnce; if (!group) return FALSE; if (!contact) return FALSE; if (group->hideOffline) return FALSE; if (g_CluiData.bFilterEffective) return FALSE; if (CLCItems_IsShowOfflineGroup(group)) return TRUE; pdnce=(PDNCE)pcli->pfnGetCacheEntry( contact->hContact); if (!pdnce) return FALSE; if (pdnce->m_cache_nNoHiddenOffline) return TRUE; return FALSE; } static LRESULT clcOnCreate(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { dat=(struct ClcData*)mir_calloc(sizeof(struct ClcData)); SetWindowLongPtr(hwnd,0,(LONG_PTR)dat); dat->hCheckBoxTheme=xpt_AddThemeHandle(hwnd, L"BUTTON"); dat->m_paintCouter=0; dat->hWnd=hwnd; dat->use_avatar_service = ServiceExists(MS_AV_GETAVATARBITMAP); if (dat->use_avatar_service) { if (!hAvatarChanged) hAvatarChanged=ModernHookEvent(ME_AV_AVATARCHANGED, clcHookAvatarChanged); } //else //{ ImageArray_Initialize(&dat->avatar_cache, FALSE, 20); //this array will be used to keep small avatars too //} RowHeights_Initialize(dat); dat->NeedResort=1; dat->MetaIgnoreEmptyExtra=ModernGetSettingByte(NULL,"CLC","MetaIgnoreEmptyExtra",SETTING_METAIGNOREEMPTYEXTRA_DEFAULT); dat->IsMetaContactsEnabled=(!(GetWindowLong(hwnd,GWL_STYLE)&CLS_MANUALUPDATE)) && g_szMetaModuleName && ModernGetSettingByte(NULL,g_szMetaModuleName,"Enabled",1) && ServiceExists(MS_MC_GETDEFAULTCONTACT); dat->expandMeta=ModernGetSettingByte(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT); dat->useMetaIcon=ModernGetSettingByte(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT); dat->drawOverlayedStatus=ModernGetSettingByte(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT); g_CluiData.bSortByOrder[0]=ModernGetSettingByte(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT); g_CluiData.bSortByOrder[1]=ModernGetSettingByte(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT); g_CluiData.bSortByOrder[2]=ModernGetSettingByte(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT); g_CluiData.fSortNoOfflineBottom=ModernGetSettingByte(NULL,"CList","NoOfflineBottom",SETTING_NOOFFLINEBOTTOM_DEFAULT); dat->menuOwnerID=-1; dat->menuOwnerType=CLCIT_INVALID; //InitDisplayNameCache(&dat->lCLCContactsCache); //LoadCLCOptions(hwnd,dat); corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); LoadCLCOptions(hwnd,dat); if ( dat->contact_time_show || dat->second_line_type == TEXT_CONTACT_TIME || dat->third_line_type == TEXT_CONTACT_TIME ) CLUI_SafeSetTimer( hwnd, TIMERID_INVALIDATE, 5000, NULL ); else KillTimer( hwnd, TIMERID_INVALIDATE ); //if (dat->force_in_dialog) // pcli->pfnRebuildEntireList(hwnd,dat); TRACE("Create New ClistControl TO END\r\n"); return 0; } static LRESULT clcOnHitTest(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hwnd,WM_NCHITTEST,wParam,lParam); } static LRESULT clcOnCommand(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { struct ClcContact *contact; int hit = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, NULL); if (hit == -1) return 0; if ( contact->type == CLCIT_CONTACT && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) contact->hContact)) return 0; switch (LOWORD(wParam)) { case POPUP_NEWSUBGROUP: if (contact->type != CLCIT_GROUP) return 0; SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~CLS_HIDEEMPTYGROUPS); CallService(MS_CLIST_GROUPCREATE, contact->groupId, 0); return 0; case POPUP_RENAMEGROUP: pcli->pfnBeginRenameSelection(hwnd, dat); return 0; case POPUP_DELETEGROUP: if (contact->type != CLCIT_GROUP) return 0; CallService(MS_CLIST_GROUPDELETE, contact->groupId, 0); return 0; case POPUP_GROUPSHOWOFFLINE: if (contact->type != CLCIT_GROUP) return 0; CallService(MS_CLIST_GROUPSETFLAGS, contact->groupId, MAKELPARAM(CLCItems_IsShowOfflineGroup(contact->group) ? 0 : GROUPF_SHOWOFFLINE, GROUPF_SHOWOFFLINE)); pcli->pfnClcBroadcast(CLM_AUTOREBUILD,0, 0); return 0; case POPUP_GROUPHIDEOFFLINE: if (contact->type != CLCIT_GROUP) return 0; CallService(MS_CLIST_GROUPSETFLAGS, contact->groupId, MAKELPARAM(contact->group->hideOffline ? 0 : GROUPF_HIDEOFFLINE, GROUPF_HIDEOFFLINE)); return 0; } if (contact->type == CLCIT_GROUP) if (CallService(MO_PROCESSCOMMANDBYMENUIDENT,LOWORD(wParam),(LPARAM)hwnd)) return 0; return 0; } static LRESULT clcOnSize(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { pcli->pfnEndRename(hwnd,dat,1); KillTimer(hwnd,TIMERID_INFOTIP); KillTimer(hwnd,TIMERID_RENAME); cliRecalcScrollBar(hwnd,dat); if ( g_CluiData.fDisableSkinEngine || dat->force_in_dialog ) { HBITMAP hBmp, hBmpMask, hoBmp, hoMaskBmp; HDC hdc,hdcMem; RECT rc={0}; int depth; HBRUSH hBrush; GetClientRect(hwnd, &rc); if (rc.right == 0) return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam);; rc.bottom = max ( dat->row_min_heigh, 1 ); //rc.bottom=8; //rc.right=8; hdc = GetDC(hwnd); depth = GetDeviceCaps(hdc, BITSPIXEL); if (depth < 16) depth = 16; hBmp = CreateBitmap(rc.right, rc.bottom, 1, depth, NULL); hBmpMask = CreateBitmap(rc.right, rc.bottom, 1, 1, NULL); hdcMem = CreateCompatibleDC(hdc); hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp); hBrush = CreateSolidBrush( ( dat->useWindowsColours || dat->force_in_dialog ) ? GetSysColor(COLOR_HIGHLIGHT) : dat->selBkColour); FillRect(hdcMem, &rc, hBrush); DeleteObject(hBrush); hoMaskBmp = (HBITMAP)SelectObject(hdcMem, hBmpMask); FillRect(hdcMem, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); SelectObject(hdcMem, hoMaskBmp); SelectObject(hdcMem, hoBmp); DeleteDC(hdcMem); ReleaseDC(hwnd, hdc); if (dat->himlHighlight) ImageList_Destroy(dat->himlHighlight); dat->himlHighlight = ImageList_Create(rc.right, rc.bottom, (IsWinVerXPPlus()? ILC_COLOR32 : ILC_COLOR16) | ILC_MASK, 1, 1); ImageList_Add(dat->himlHighlight, hBmp, hBmpMask); DeleteObject(hBmpMask); DeleteObject(hBmp); } else if (dat->himlHighlight) { ImageList_Destroy(dat->himlHighlight); dat->himlHighlight = NULL; } return 0; } static LRESULT clcOnChar(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (wParam==27 && dat->szQuickSearch[0] == '\0') //escape and not quick search { // minimize clist CListMod_HideWindow(pcli->hwndContactList, SW_HIDE); } return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam); } static LRESULT clcOnPaint(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; if (IsWindowVisible(hwnd)) { if (!g_CluiData.fLayered || GetParent(hwnd)!=pcli->hwndContactList) { hdc=BeginPaint(hwnd,&ps); g_clcPainter.cliPaintClc(hwnd,dat,hdc,&ps.rcPaint); EndPaint(hwnd,&ps); } else CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0); } return DefWindowProc(hwnd, msg, wParam, lParam); } static LRESULT clcOnEraseBkGround(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return 1; } static LRESULT clcOnKeyDown(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int selMoved=0; int changeGroupExpand=0; int pageSize; if (wParam==VK_CONTROL) return 0; pcli->pfnHideInfoTip(hwnd,dat); KillTimer(hwnd,TIMERID_INFOTIP); KillTimer(hwnd,TIMERID_RENAME); if(CallService(MS_CLIST_MENUPROCESSHOTKEY,wParam,MPCF_CONTACTMENU)) return 0; { RECT clRect; GetClientRect(hwnd,&clRect); if (dat->max_row_height) pageSize=clRect.bottom/dat->max_row_height; else pageSize=0; } switch(wParam) { case VK_DOWN: case VK_UP: { if (dat->szQuickSearch[0]!='\0' && dat->selection!=-1) //get next contact { //get next contact int index=clcSearchNextContact(hwnd,dat,dat->selection,dat->szQuickSearch,1,(wParam==VK_UP)); if (index==-1) { MessageBeep(MB_OK); return 0; } else { dat->selection=index; pcli->pfnInvalidateRect(hwnd, NULL, FALSE); pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0); return 0; } } else { if (wParam==VK_DOWN) dat->selection++; if (wParam==VK_UP) dat->selection--; selMoved=1; break; } } case VK_PRIOR: dat->selection-=pageSize; selMoved=1; break; case VK_NEXT: dat->selection+=pageSize; selMoved=1; break; case VK_HOME: dat->selection=0; selMoved=1; break; case VK_END: dat->selection=pcli->pfnGetGroupContentsCount(&dat->list,1)-1; selMoved=1; break; case VK_LEFT: changeGroupExpand=1; break; case VK_RIGHT: changeGroupExpand=2; break; case VK_RETURN: pcli->pfnDoSelectionDefaultAction(hwnd,dat); SetCapture(hwnd); return 0; case VK_F2: cliBeginRenameSelection(hwnd,dat); /*SetCapture(hwnd);*/ return 0; case VK_DELETE: pcli->pfnDeleteFromContactList(hwnd,dat); SetCapture(hwnd);return 0; case VK_ESCAPE: { if ((dat->dragStage&DRAGSTAGEM_STAGE)==DRAGSTAGE_ACTIVE) { dat->iDragItem=-1; dat->iInsertionMark=-1; dat->dragStage=0; ReleaseCapture(); } return 0; } default: { NMKEY nmkey; nmkey.hdr.hwndFrom=hwnd; nmkey.hdr.idFrom=GetDlgCtrlID(hwnd); nmkey.hdr.code=NM_KEYDOWN; nmkey.nVKey=wParam; nmkey.uFlags=HIWORD(lParam); if(SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nmkey)) { SetCapture(hwnd); return 0; } } } if(changeGroupExpand) { int hit; struct ClcContact *contact; struct ClcGroup *group; dat->szQuickSearch[0]=0; hit=cliGetRowByIndex(dat,dat->selection,&contact,&group); if(hit!=-1) { if (contact->type==CLCIT_CONTACT &&(contact->isSubcontact || contact->SubAllocated>0)) { if (contact->isSubcontact && changeGroupExpand==1) { dat->selection-=contact->isSubcontact; selMoved=1; } else if (!contact->isSubcontact && contact->SubAllocated>0) { if (changeGroupExpand==1 && !contact->SubExpanded) { dat->selection=cliGetRowsPriorTo(&dat->list,group,-1); selMoved=1; } else if (changeGroupExpand==1 && contact->SubExpanded) { //Contract struct ClcContact * ht=NULL; KillTimer(hwnd,TIMERID_SUBEXPAND); contact->SubExpanded=0; ModernWriteSettingByte(contact->hContact,"CList","Expanded",0); ht=contact; dat->NeedResort=1; pcli->pfnSortCLC(hwnd,dat,1); cliRecalcScrollBar(hwnd,dat); hitcontact=NULL; } else if (changeGroupExpand==2 && contact->SubExpanded) { dat->selection++; selMoved=1; } else if (changeGroupExpand==2 && !contact->SubExpanded && dat->expandMeta) { struct ClcContact * ht=NULL; KillTimer(hwnd,TIMERID_SUBEXPAND); contact->SubExpanded=1; ModernWriteSettingByte(contact->hContact,"CList","Expanded",1); ht=contact; dat->NeedResort=1; pcli->pfnSortCLC(hwnd,dat,1); cliRecalcScrollBar(hwnd,dat); if (ht) { int i=0; struct ClcContact *contact2; struct ClcGroup *group2; if(FindItem(hwnd,dat,contact->hContact,&contact2,&group2,NULL,FALSE)) { i=cliGetRowsPriorTo(&dat->list,group2,GetContactIndex(group2,contact2)); pcli->pfnEnsureVisible(hwnd,dat,i+contact->SubAllocated,0); } } hitcontact=NULL; } } } else { if(changeGroupExpand==1 && contact->type==CLCIT_CONTACT) { if(group==&dat->list) {SetCapture(hwnd); return 0;} dat->selection=cliGetRowsPriorTo(&dat->list,group,-1); selMoved=1; } else { if(contact->type==CLCIT_GROUP) { if (changeGroupExpand==1) { if (!contact->group->expanded) { dat->selection--; selMoved=1; } else { pcli->pfnSetGroupExpand(hwnd,dat,contact->group,0); } } else if (changeGroupExpand==2) { pcli->pfnSetGroupExpand(hwnd,dat,contact->group,1); dat->selection++; selMoved=1; } else {SetCapture(hwnd);return 0;} }// // } } } else {SetCapture(hwnd);return 0; } } if(selMoved) { dat->szQuickSearch[0]=0; if(dat->selection>=pcli->pfnGetGroupContentsCount(&dat->list,1)) dat->selection=pcli->pfnGetGroupContentsCount(&dat->list,1)-1; if(dat->selection<0) dat->selection=0; if (dat->bCompactMode) SendMessage(hwnd,WM_SIZE,0,0); CLUI__cliInvalidateRect(hwnd,NULL,FALSE); pcli->pfnEnsureVisible(hwnd,dat,dat->selection,0); UpdateWindow(hwnd); SetCapture(hwnd); return 0; } SetCapture(hwnd); return 0; } void clcSetDelayTimer( UINT_PTR uIDEvent, HWND hwnd, int nDelay) { KillTimer( hwnd, uIDEvent ); int delay = nDelay; if ( delay == -1) { switch ( uIDEvent ) { case TIMERID_DELAYEDRESORTCLC: delay = 10; break; case TIMERID_RECALCSCROLLBAR: delay = 10; break; case TIMERID_REBUILDAFTER: delay = 50; break; default: delay = 100; break; } } CLUI_SafeSetTimer( hwnd, uIDEvent, delay, NULL ); } static LRESULT clcOnTimer(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(wParam) { case TIMERID_INVALIDATE_FULL: { KillTimer(hwnd,TIMERID_INVALIDATE_FULL); pcli->pfnRecalcScrollBar(hwnd,dat); pcli->pfnInvalidateRect(hwnd,NULL,0); return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); } case TIMERID_INVALIDATE: { time_t cur_time=(time(NULL)/60); if (cur_time!=dat->last_tick_time) { CLUI__cliInvalidateRect(hwnd,NULL,FALSE); dat->last_tick_time=cur_time; } return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); } case TIMERID_SUBEXPAND: { struct ClcContact * ht=NULL; KillTimer(hwnd,TIMERID_SUBEXPAND); if (hitcontact && dat->expandMeta) { if (hitcontact->SubExpanded) hitcontact->SubExpanded=0; else hitcontact->SubExpanded=1; ModernWriteSettingByte(hitcontact->hContact,"CList","Expanded",hitcontact->SubExpanded); if (hitcontact->SubExpanded) ht=&(hitcontact->subcontacts[hitcontact->SubAllocated-1]); } dat->NeedResort=1; pcli->pfnSortCLC(hwnd,dat,1); cliRecalcScrollBar(hwnd,dat); if (ht) { int i=0; struct ClcContact *contact; struct ClcGroup *group; if(FindItem(hwnd,dat,hitcontact->hContact,&contact,&group,NULL,FALSE)) { i=cliGetRowsPriorTo(&dat->list,group,GetContactIndex(group,contact)); pcli->pfnEnsureVisible(hwnd,dat,i+hitcontact->SubAllocated,0); } } hitcontact=NULL; return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); } case TIMERID_DELAYEDRESORTCLC: { TRACE("Do sort on Timer\n"); KillTimer(hwnd,TIMERID_DELAYEDRESORTCLC); pcli->pfnSortCLC(hwnd,dat,1); pcli->pfnInvalidateRect(hwnd,NULL,FALSE); return 0; } case TIMERID_RECALCSCROLLBAR: { KillTimer(hwnd,TIMERID_RECALCSCROLLBAR); pcli->pfnRecalcScrollBar(hwnd,dat); return 0; } default: return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); } return 0; } static LRESULT clcOnActivate(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { TRACE ("clcOnActivate\n"); if (dat->bCompactMode) { cliRecalcScrollBar(hwnd,dat); if ( dat->hwndRenameEdit == NULL ) PostMessage( hwnd, WM_SIZE, 0, 0); } dat->dragStage|= DRAGSTAGEF_SKIPRENAME; return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); } static LRESULT clcOnSetCursor(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int lResult; if (!CLUI_IsInMainWindow(hwnd)) return DefWindowProc(hwnd,msg,wParam,lParam); if (g_CluiData.nBehindEdgeState>0) CLUI_ShowFromBehindEdge(); if (g_CluiData.bBehindEdgeSettings) CLUI_UpdateTimer(0); lResult=CLUI_TestCursorOnBorders(); return lResult ? lResult : DefWindowProc(hwnd,msg,wParam,lParam); } static LRESULT clcOnLButtonDown(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { { POINT pt; int k=0; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); ClientToScreen(hwnd,&pt); k=CLUI_SizingOnBorder(pt,0); if (k) { int io=dat->iHotTrack; dat->iHotTrack=0; if(dat->exStyle&CLS_EX_TRACKSELECT) { pcli->pfnInvalidateItem(hwnd,dat,io); } if (k && GetCapture()==hwnd) { SendMessage(GetParent(hwnd),WM_PARENTNOTIFY,WM_LBUTTONDOWN,lParam); } return FALSE; } } { struct ClcContact *contact; struct ClcGroup *group; int hit; DWORD hitFlags; fMouseUpped=FALSE; pcli->pfnHideInfoTip(hwnd,dat); KillTimer(hwnd,TIMERID_INFOTIP); KillTimer(hwnd,TIMERID_RENAME); KillTimer(hwnd,TIMERID_SUBEXPAND); pcli->pfnEndRename(hwnd,dat,1); dat->ptDragStart.x=(short)LOWORD(lParam); dat->ptDragStart.y=(short)HIWORD(lParam); dat->szQuickSearch[0]=0; hit=cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),&contact,&group,&hitFlags); if(GetFocus()!=hwnd) SetFocus(hwnd); if(hit!=-1 && !(hitFlags&CLCHT_NOWHERE)) { if ( hit==dat->selection && hitFlags&CLCHT_ONITEMLABEL && dat->exStyle&CLS_EX_EDITLABELS) { if ( !(dat->dragStage&DRAGSTAGEF_SKIPRENAME) ) { SetCapture(hwnd); dat->iDragItem=dat->selection; dat->dragStage=DRAGSTAGE_NOTMOVED|DRAGSTAGEF_MAYBERENAME; dat->dragAutoScrolling=0; return TRUE; } else { dat->dragStage&= ~DRAGSTAGEF_SKIPRENAME; return TRUE; } } } if(hit!=-1 && !(hitFlags&CLCHT_NOWHERE) && contact->type==CLCIT_CONTACT && contact->SubAllocated && !contact->isSubcontact) if(hitFlags&CLCHT_ONITEMICON && dat->expandMeta) { BYTE doubleClickExpand=ModernGetSettingByte(NULL,"CLC","MetaDoubleClick",SETTING_METAAVOIDDBLCLICK_DEFAULT); hitcontact=contact; HitPoint.x= (short)LOWORD(lParam); HitPoint.y= (short)HIWORD(lParam); fMouseUpped=FALSE; if ((GetKeyState(VK_SHIFT)&0x8000)||(GetKeyState(VK_CONTROL)&0x8000) || (GetKeyState(VK_MENU)&0x8000)) { fMouseUpped=TRUE; hitcontact=contact; KillTimer(hwnd,TIMERID_SUBEXPAND); CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,0,NULL); } } else hitcontact=NULL; if(hit!=-1 && !(hitFlags&CLCHT_NOWHERE) && contact->type==CLCIT_GROUP) if(hitFlags&CLCHT_ONITEMICON) { struct ClcGroup *selgroup; struct ClcContact *selcontact; dat->selection=cliGetRowByIndex(dat,dat->selection,&selcontact,&selgroup); pcli->pfnSetGroupExpand(hwnd,dat,contact->group,-1); if(dat->selection!=-1) { dat->selection=cliGetRowsPriorTo(&dat->list,selgroup,GetContactIndex(selgroup,selcontact)); if(dat->selection==-1) dat->selection=cliGetRowsPriorTo(&dat->list,contact->group,-1); } if (dat->bCompactMode) { SendMessage(hwnd,WM_SIZE,0,0); } else { CLUI__cliInvalidateRect(hwnd,NULL,FALSE); UpdateWindow(hwnd); } return TRUE; } if(hit!=-1 && !(hitFlags&CLCHT_NOWHERE) && hitFlags&CLCHT_ONITEMCHECK) { NMCLISTCONTROL nm; contact->flags^=CONTACTF_CHECKED; if(contact->type==CLCIT_GROUP) pcli->pfnSetGroupChildCheckboxes(contact->group,contact->flags&CONTACTF_CHECKED); pcli->pfnRecalculateGroupCheckboxes(hwnd,dat); CLUI__cliInvalidateRect(hwnd,NULL,FALSE); nm.hdr.code=CLN_CHECKCHANGED; nm.hdr.hwndFrom=hwnd; nm.hdr.idFrom=GetDlgCtrlID(hwnd); nm.flags=0; nm.hItem=ContactToItemHandle(contact,&nm.flags); SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm); } if (!(hitFlags&(CLCHT_ONITEMICON|CLCHT_ONITEMLABEL|CLCHT_ONITEMCHECK))) { NMCLISTCONTROL nm; nm.hdr.code=NM_CLICK; nm.hdr.hwndFrom=hwnd; nm.hdr.idFrom=GetDlgCtrlID(hwnd); nm.flags=0; if(hit==-1 || hitFlags&CLCHT_NOWHERE) nm.hItem=NULL; else nm.hItem=ContactToItemHandle(contact,&nm.flags); nm.iColumn=hitFlags&CLCHT_ONITEMEXTRA?HIBYTE(HIWORD(hitFlags)):-1; nm.pt=dat->ptDragStart; SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm); } if(hitFlags&(CLCHT_ONITEMCHECK|CLCHT_ONITEMEXTRA)) return FALSE; dat->selection=(hitFlags&CLCHT_NOWHERE)?-1:hit; CLUI__cliInvalidateRect(hwnd,NULL,FALSE); UpdateWindow(hwnd); if(dat->selection!=-1 && (contact->type==CLCIT_CONTACT || contact->type==CLCIT_GROUP) && !(hitFlags&(CLCHT_ONITEMEXTRA|CLCHT_ONITEMCHECK|CLCHT_NOWHERE))) { SetCapture(hwnd); dat->iDragItem=dat->selection; dat->dragStage=DRAGSTAGE_NOTMOVED; dat->dragAutoScrolling=0; } if (dat->bCompactMode) { SendMessage(hwnd,WM_SIZE,0,0); } if(dat->selection!=-1) pcli->pfnEnsureVisible(hwnd,dat,hit,0); return TRUE; } } static LRESULT clcOnCaptureChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if ((HWND)lParam!=hwnd) { if (dat->iHotTrack!=-1) { int i; i=dat->iHotTrack; dat->iHotTrack=-1; pcli->pfnInvalidateItem(hwnd,dat,i); pcli->pfnHideInfoTip(hwnd,dat); } } return 0; } static LRESULT clcOnMouseMove(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { BOOL isOutside=FALSE; if (CLUI_IsInMainWindow(hwnd)) { if (g_CluiData.bBehindEdgeSettings) CLUI_UpdateTimer(0); CLUI_TestCursorOnBorders(); } if (clcProceedDragToScroll(hwnd, (short)HIWORD(lParam))) return 0; if ( dat->dragStage&DRAGSTAGEF_MAYBERENAME ) { POINT pt; pt.x= (short)LOWORD(lParam); pt.y= (short)HIWORD(lParam); if ( abs(pt.x-dat->ptDragStart.x)>GetSystemMetrics(SM_CXDOUBLECLK) ||abs(pt.y-dat->ptDragStart.y)>GetSystemMetrics(SM_CYDOUBLECLK) ) { KillTimer( hwnd, TIMERID_RENAME ); dat->dragStage&=(~DRAGSTAGEF_MAYBERENAME); } } if (dat->iDragItem==-1) { POINT pt; HWND window; pt.x= (short)LOWORD(lParam); pt.y= (short)HIWORD(lParam); ClientToScreen(hwnd,&pt); window=WindowFromPoint(pt); if (window!=hwnd) isOutside=TRUE; } if(hitcontact!=NULL) { int x,y,xm,ym; x= (short)LOWORD(lParam); y= (short)HIWORD(lParam); xm=GetSystemMetrics(SM_CXDOUBLECLK); ym=GetSystemMetrics(SM_CYDOUBLECLK); if(abs(HitPoint.x-x)>xm || abs(HitPoint.y-y)>ym) { if (fMouseUpped) { KillTimer(hwnd,TIMERID_SUBEXPAND); CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,0,NULL); fMouseUpped=FALSE; } else { KillTimer(hwnd,TIMERID_SUBEXPAND); hitcontact=NULL; fMouseUpped=FALSE; } } } if(dat->iDragItem==-1) { DWORD flag=0; int iOldHotTrack=dat->iHotTrack; if(dat->hwndRenameEdit!=NULL || GetKeyState(VK_MENU)&0x8000 || GetKeyState(VK_F10)&0x8000) return 0; dat->iHotTrack= isOutside ? -1 : cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),NULL,NULL,&flag); if (flag&CLCHT_NOWHERE) dat->iHotTrack=-1; if(iOldHotTrack!=dat->iHotTrack || isOutside) { if(iOldHotTrack==-1 && !isOutside) SetCapture(hwnd); if (dat->iHotTrack==-1 || isOutside) ReleaseCapture(); if(dat->exStyle&CLS_EX_TRACKSELECT) { pcli->pfnInvalidateItem(hwnd,dat,iOldHotTrack); pcli->pfnInvalidateItem(hwnd,dat,dat->iHotTrack); } pcli->pfnHideInfoTip(hwnd,dat); } KillTimer(hwnd,TIMERID_INFOTIP); if(wParam==0 && dat->hInfoTipItem==NULL) { dat->ptInfoTip.x=(short)LOWORD(lParam); dat->ptInfoTip.y=(short)HIWORD(lParam); CLUI_SafeSetTimer(hwnd,TIMERID_INFOTIP,dat->infoTipTimeout,NULL); } return 0; } if ((dat->dragStage&DRAGSTAGEM_STAGE)==DRAGSTAGE_NOTMOVED && !(dat->exStyle&CLS_EX_DISABLEDRAGDROP)) { if(abs((short)LOWORD(lParam)-dat->ptDragStart.x)>=GetSystemMetrics(SM_CXDRAG) || abs((short)HIWORD(lParam)-dat->ptDragStart.y)>=GetSystemMetrics(SM_CYDRAG)) dat->dragStage=(dat->dragStage&~DRAGSTAGEM_STAGE)|DRAGSTAGE_ACTIVE; } if ((dat->dragStage&DRAGSTAGEM_STAGE)==DRAGSTAGE_ACTIVE) { HCURSOR hNewCursor; RECT clRect; POINT pt; int target; GetClientRect(hwnd,&clRect); pt.x=(short)LOWORD(lParam); pt.y=(short)HIWORD(lParam); hNewCursor=LoadCursor(NULL, IDC_NO); CLUI__cliInvalidateRect(hwnd,NULL,FALSE); if(dat->dragAutoScrolling) {KillTimer(hwnd,TIMERID_DRAGAUTOSCROLL); dat->dragAutoScrolling=0;} target=GetDropTargetInformation(hwnd,dat,pt); if(dat->dragStage&DRAGSTAGEF_OUTSIDE && target!=DROPTARGET_OUTSIDE) { NMCLISTCONTROL nm; struct ClcContact *contact; cliGetRowByIndex(dat,dat->iDragItem,&contact,NULL); nm.hdr.code=CLN_DRAGSTOP; nm.hdr.hwndFrom=hwnd; nm.hdr.idFrom=GetDlgCtrlID(hwnd); nm.flags=0; nm.hItem=ContactToItemHandle(contact,&nm.flags); SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm); dat->dragStage&=~DRAGSTAGEF_OUTSIDE; } switch(target) { case DROPTARGET_ONSELF: break; case DROPTARGET_ONCONTACT: if (ServiceExists(MS_MC_ADDTOMETA)) { struct ClcContact *contSour; cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL); if (contSour->type==CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName)) { if (!contSour->isSubcontact) hNewCursor=LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta else hNewCursor=LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_DROPMETA)); } } break; case DROPTARGET_ONMETACONTACT: if (ServiceExists(MS_MC_ADDTOMETA)) { struct ClcContact *contSour,*contDest; cliGetRowByIndex(dat,dat->selection,&contDest,NULL); cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL); if (contSour->type==CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName)) { if (!contSour->isSubcontact) hNewCursor=LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta else if (contSour->subcontacts==contDest) hNewCursor=LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_DEFAULTSUB)); ///MakeDefault else hNewCursor=LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_REGROUP)); } } break; case DROPTARGET_ONSUBCONTACT: if (ServiceExists(MS_MC_ADDTOMETA)) { struct ClcContact *contSour,*contDest; cliGetRowByIndex(dat,dat->selection,&contDest,NULL); cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL); if (contSour->type==CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName)) { if (!contSour->isSubcontact) hNewCursor=LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta else if (contDest->subcontacts==contSour->subcontacts) break; else hNewCursor=LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_REGROUP)); } } break; case DROPTARGET_ONGROUP: hNewCursor=LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); break; case DROPTARGET_INSERTION: hNewCursor=LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROP)); break; case DROPTARGET_OUTSIDE: { NMCLISTCONTROL nm; struct ClcContact *contact; if(pt.x>=0 && pt.x-dat->dragAutoScrollHeight) || (pt.y>=clRect.bottom && pt.ydragAutoScrollHeight))) { if (!dat->dragAutoScrolling) { if(pt.y<0) dat->dragAutoScrolling=-1; else dat->dragAutoScrolling=1; CLUI_SafeSetTimer(hwnd,TIMERID_DRAGAUTOSCROLL,dat->scrollTime,NULL); } SendMessage(hwnd,WM_TIMER,TIMERID_DRAGAUTOSCROLL,0); } dat->dragStage|=DRAGSTAGEF_OUTSIDE; cliGetRowByIndex(dat,dat->iDragItem,&contact,NULL); nm.hdr.code=CLN_DRAGGING; nm.hdr.hwndFrom=hwnd; nm.hdr.idFrom=GetDlgCtrlID(hwnd); nm.flags=0; nm.hItem=ContactToItemHandle(contact,&nm.flags); nm.pt=pt; if(SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm)) return 0; break; } default: { struct ClcGroup *group=NULL; cliGetRowByIndex(dat,dat->iDragItem,NULL,&group); if(group && group->parent) { struct ClcContact *contSour; cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL); if (!contSour->isSubcontact) hNewCursor=LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); } break; } } SetCursor(hNewCursor); } return 0; } static LRESULT clcOnLButtonUp(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (clcExitDragToScroll()) return 0; fMouseUpped=TRUE; if (hitcontact!=NULL && dat->expandMeta) { BYTE doubleClickExpand=ModernGetSettingByte(NULL,"CLC","MetaDoubleClick",SETTING_METAAVOIDDBLCLICK_DEFAULT); CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,GetDoubleClickTime()*doubleClickExpand,NULL); } else if (dat->iHotTrack==-1 && dat->iDragItem==-1) ReleaseCapture(); if(dat->iDragItem==-1) return 0; SetCursor((HCURSOR)GetClassLongPtr(hwnd,GCLP_HCURSOR)); if(dat->exStyle&CLS_EX_TRACKSELECT) { DWORD flags; dat->iHotTrack=cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),NULL,NULL,&flags); if(dat->iHotTrack==-1) ReleaseCapture(); } else if (hitcontact==NULL) ReleaseCapture(); KillTimer(hwnd,TIMERID_DRAGAUTOSCROLL); if(dat->dragStage==(DRAGSTAGE_NOTMOVED|DRAGSTAGEF_MAYBERENAME)) CLUI_SafeSetTimer(hwnd,TIMERID_RENAME,GetDoubleClickTime(),NULL); else if ((dat->dragStage&DRAGSTAGEM_STAGE)==DRAGSTAGE_ACTIVE) { POINT pt; int target; TCHAR Wording[500]; int res=0; pt.x=(short)LOWORD(lParam); pt.y=(short)HIWORD(lParam); target=GetDropTargetInformation(hwnd,dat,pt); switch(target) { case DROPTARGET_ONSELF: break; case DROPTARGET_ONCONTACT: if (ServiceExists(MS_MC_ADDTOMETA)) { struct ClcContact *contDest, *contSour; int res; HANDLE handle,hcontact; cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL); cliGetRowByIndex(dat,dat->selection,&contDest,NULL); hcontact=contSour->hContact; if (contSour->type==CLCIT_CONTACT) { if (g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName)) { if (!contSour->isSubcontact) { HANDLE hDest=contDest->hContact; mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be converted to MetaContact and '%s' be added to it?"),contDest->szText, contSour->szText); res=MessageBox(hwnd,Wording,TranslateT("Converting to MetaContact"),MB_OKCANCEL|MB_ICONQUESTION); if (res==1) { handle=(HANDLE)CallService(MS_MC_CONVERTTOMETA,(WPARAM)hDest,0); if (!handle) return 0; CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle); } } else { HANDLE handle,hcontact,hfrom,hdest; hcontact=contSour->hContact; hfrom=contSour->subcontacts->hContact; hdest=contDest->hContact; mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be converted to MetaContact and '%s' be added to it (remove it from '%s')?"), contDest->szText,contSour->szText,contSour->subcontacts->szText); res=MessageBox(hwnd,Wording,TranslateT("Converting to MetaContact (Moving)"),MB_OKCANCEL|MB_ICONQUESTION); if (res==1) { handle=(HANDLE)CallService(MS_MC_CONVERTTOMETA,(WPARAM)hdest,0); if (!handle) return 0; CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact); CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle); } } } } } break; case DROPTARGET_ONMETACONTACT: { struct ClcContact *contDest, *contSour; int res; cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL); cliGetRowByIndex(dat,dat->selection,&contDest,NULL); if (contSour->type==CLCIT_CONTACT) { if (g_szMetaModuleName && strcmp(contSour->proto,g_szMetaModuleName)) { if (!contSour->isSubcontact) { HANDLE handle,hcontact; hcontact=contSour->hContact; handle=contDest->hContact; mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do you want to contact '%s' be added to metacontact '%s'?"),contSour->szText, contDest->szText); res=MessageBox(hwnd,Wording,TranslateT("Adding contact to MetaContact"),MB_OKCANCEL|MB_ICONQUESTION); if (res==1) { if (!handle) return 0; CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle); } } else { if (contSour->subcontacts==contDest) { HANDLE hsour; hsour=contSour->hContact; mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be default ?"),contSour->szText); res=MessageBox(hwnd,Wording,TranslateT("Set default contact"),MB_OKCANCEL|MB_ICONQUESTION); if (res==1) { CallService(MS_MC_SETDEFAULTCONTACT,(WPARAM)contDest->hContact,(LPARAM)hsour); } } else { HANDLE handle,hcontact,hfrom; hcontact=contSour->hContact; hfrom=contSour->subcontacts->hContact; handle=contDest->hContact; mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be removed from MetaContact '%s' and added to '%s'?"), contSour->szText,contSour->subcontacts->szText,contDest->szText); res=MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION); if (res==1) { if (!handle) return 0; CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact); CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle); } } } } } } break; case DROPTARGET_ONSUBCONTACT: { struct ClcContact *contDest, *contSour; int res; cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL); cliGetRowByIndex(dat,dat->selection,&contDest,NULL); if (contSour->type==CLCIT_CONTACT) { if (g_szMetaModuleName && strcmp(contSour->proto,g_szMetaModuleName)) { if (!contSour->isSubcontact) { HANDLE handle,hcontact; hcontact=contSour->hContact; handle=contDest->subcontacts->hContact; mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be added to MetaContact '%s'?"), contSour->szText,contDest->subcontacts->szText); res=MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION); if (res==1) { if (!handle) return 0; CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle); } } else { if (contSour->subcontacts!=contDest->subcontacts) { HANDLE handle,hcontact,hfrom; hcontact=contSour->hContact; hfrom=contSour->subcontacts->hContact; handle=contDest->subcontacts->hContact; mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be removed from MetaContact '%s' and added to '%s'?"), contSour->szText,contSour->subcontacts->szText,contDest->subcontacts->szText); res=MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION); if (res==1) { if (!handle) return 0; CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact); CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle); } } } } } } break; case DROPTARGET_ONGROUP: corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); break; case DROPTARGET_INSERTION: { struct ClcContact *contact, *destcontact; struct ClcGroup *group, *destgroup; BOOL NeedRename=FALSE; TCHAR newName[128]={0}; int newIndex,i; pcli->pfnGetRowByIndex(dat, dat->iDragItem, &contact, &group); i=pcli->pfnGetRowByIndex(dat, dat->iInsertionMark, &destcontact, &destgroup); if (i!=-1 && group->groupId!=destgroup->groupId) { TCHAR * groupName=mir_tstrdup(pcli->pfnGetGroupName(contact->groupId,0)); TCHAR * shortGroup=NULL; TCHAR * sourceGrName=mir_tstrdup(pcli->pfnGetGroupName(destgroup->groupId,0)); if (groupName) { int len=(int)_tcslen(groupName); do {len--;}while(len>=0 && groupName[len]!='\\'); if (len>=0) shortGroup=groupName+len+1; else shortGroup=groupName; } if (shortGroup) { NeedRename=TRUE; if (sourceGrName) mir_sntprintf(newName,SIZEOF(newName),_T("%s\\%s"),sourceGrName,shortGroup); else mir_sntprintf(newName,SIZEOF(newName),_T("%s"),shortGroup); } if (groupName) mir_free_and_nill(groupName); if (sourceGrName) mir_free_and_nill(sourceGrName); } newIndex=CallService(MS_CLIST_GROUPMOVEBEFORE, contact->groupId, (destcontact&&i!=-1)?destcontact->groupId:0); newIndex=newIndex?newIndex:contact->groupId; if (NeedRename) pcli->pfnRenameGroup(newIndex,newName); break; } case DROPTARGET_OUTSIDE: corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); break; default: corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); break; } } CLUI__cliInvalidateRect(hwnd,NULL,FALSE); dat->iDragItem=-1; dat->iInsertionMark=-1; return 0; } static LRESULT clcOnLButtonDblClick(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { KillTimer(hwnd,TIMERID_SUBEXPAND); hitcontact=NULL; return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); } static LRESULT clcOnDestroy(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int i=0; for(i=0;i<=FONTID_MODERN_MAX;i++) { if(dat->fontModernInfo[i].hFont) DeleteObject(dat->fontModernInfo[i].hFont); dat->fontModernInfo[i].hFont=NULL; } if (dat->hMenuBackground) { DeleteObject(dat->hMenuBackground); dat->hMenuBackground=NULL; } if (!dat->bkChanged && dat->hBmpBackground) { DeleteObject(dat->hBmpBackground); dat->hBmpBackground=NULL; } ImageArray_Clear(&dat->avatar_cache); mod_DeleteDC(dat->avatar_cache.hdc); ImageArray_Free(&dat->avatar_cache, FALSE); if (dat->himlHighlight) ImageList_Destroy(dat->himlHighlight); RowHeights_Free(dat); corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); xpt_FreeThemeForWindow(hwnd); return 0; } static LRESULT clcOnIntmGroupChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { struct ClcContact *contact; BYTE iExtraImage[MAXEXTRACOLUMNS]; WORD iWideExtraImage[MAXEXTRACOLUMNS]; BYTE flags = 0; if (!pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) { memset(iExtraImage, 0xFF, SIZEOF(iExtraImage)); memset((void*)iWideExtraImage, 0xFF, sizeof(iWideExtraImage)); } else { CopyMemory(iExtraImage, contact->iExtraImage, SIZEOF(iExtraImage)); CopyMemory((void*)iWideExtraImage, (void*)contact->iWideExtraImage, sizeof(iWideExtraImage)); flags = contact->flags; } pcli->pfnDeleteItemFromTree(hwnd, (HANDLE) wParam); if (GetWindowLong(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !ModernGetSettingByte((HANDLE) wParam, "CList", "Hidden", 0)) { NMCLISTCONTROL nm; pcli->pfnAddContactToTree(hwnd, dat, (HANDLE) wParam, 1, 1); if (pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) { CopyMemory(contact->iExtraImage, iExtraImage, SIZEOF(iExtraImage)); CopyMemory((void*)contact->iWideExtraImage, (void*)iWideExtraImage, sizeof(iWideExtraImage)); if(flags & CONTACTF_CHECKED) contact->flags |= CONTACTF_CHECKED; } nm.hdr.code = CLN_CONTACTMOVED; nm.hdr.hwndFrom = hwnd; nm.hdr.idFrom = GetDlgCtrlID(hwnd); nm.flags = 0; nm.hItem = (HANDLE) wParam; SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) & nm); dat->NeedResort = 1; } SetTimer(hwnd,TIMERID_REBUILDAFTER,1,NULL); return 0; } static LRESULT clcOnIntmIconChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { struct ClcContact *contact = NULL; struct ClcGroup *group = NULL; int recalcScrollBar = 0, shouldShow; BOOL needRepaint=FALSE; WORD status; char *szProto; int nHiddenStatus=0; BOOL image_is_special=FALSE; RECT iconRect={0}; int contacticon=CallService(MS_CLIST_GETCONTACTICON, wParam, 1); HANDLE hSelItem = NULL; struct ClcContact *selcontact = NULL; szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); if (szProto == NULL) status = ID_STATUS_OFFLINE; else status=GetContactCachedStatus((HANDLE) wParam); image_is_special=(LOWORD(contacticon) != (LOWORD(lParam))); //check only base icons nHiddenStatus=CLVM_GetContactHiddenStatus((HANDLE)wParam, szProto, dat); DWORD style = GetWindowLong(hwnd, GWL_STYLE); bool isVisiblebyFilter = ( ( ( style & CLS_SHOWHIDDEN ) && nHiddenStatus != -1 ) || !nHiddenStatus ); bool ifVisibleByClui = !pcli->pfnIsHiddenMode( dat, status ); bool isVisible = g_CluiData.bFilterEffective&CLVM_FILTER_STATUS ? TRUE : ifVisibleByClui; bool isIconChanged = CallService(MS_CLIST_GETCONTACTICON, wParam, 0) != LOWORD(lParam); shouldShow = isVisiblebyFilter && ( isVisible || isIconChanged ) ; // XXX CLVM changed - this means an offline msg is flashing, so the contact should be shown if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL)) { if (shouldShow && CallService(MS_DB_CONTACT_IS, wParam, 0)) { if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1) hSelItem = pcli->pfnContactToHItem(selcontact); pcli->pfnAddContactToTree(hwnd, dat, (HANDLE) wParam, (style & CLS_CONTACTLIST) == 0, 0); recalcScrollBar = 1; needRepaint=TRUE; pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL); if (contact) { contact->iImage = lParam; contact->image_is_special=image_is_special; pcli->pfnNotifyNewContact(hwnd, (HANDLE) wParam); dat->NeedResort = 1; } } } else { //item in list already if (contact->iImage == lParam) return 0; if ( !shouldShow && !(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE) && clcItemNotHiddenOffline(dat, group, contact)) { shouldShow=TRUE; } if (!shouldShow && !(style & CLS_NOHIDEOFFLINE) && ((style & CLS_HIDEOFFLINE) || group->hideOffline || g_CluiData.bFilterEffective) ) // CLVM changed { if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1) hSelItem = pcli->pfnContactToHItem(selcontact); pcli->pfnRemoveItemFromGroup(hwnd, group, contact, (style & CLS_CONTACTLIST) == 0); needRepaint=TRUE; recalcScrollBar = 1; dat->NeedResort = 1; } else if (contact) { contact->iImage = lParam; if (!pcli->pfnIsHiddenMode(dat, status)) contact->flags |= CONTACTF_ONLINE; else contact->flags &= ~CONTACTF_ONLINE; contact->image_is_special=image_is_special; if (!image_is_special) //Only if it is status changing { dat->NeedResort = 1; needRepaint=TRUE; } else if (dat->m_paintCouter==contact->lastPaintCounter) //if contacts is visible { needRepaint=TRUE; } } } if (hSelItem) { struct ClcGroup *selgroup; if (pcli->pfnFindItem(hwnd, dat, hSelItem, &selcontact, &selgroup, NULL)) dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, selgroup, li.List_IndexOf(( SortedList* )&selgroup->cl, selcontact)); else dat->selection = -1; } // dat->NeedResort = 1; // SortClcByTimer(hwnd); if (dat->NeedResort) { TRACE("Sort required\n"); clcSetDelayTimer( TIMERID_DELAYEDRESORTCLC, hwnd ); } else if (needRepaint) { if (contact && contact->pos_icon.bottom!=0 && contact->pos_icon.right!=0) CLUI__cliInvalidateRect(hwnd,&(contact->pos_icon),FALSE); else CLUI__cliInvalidateRect(hwnd,NULL,FALSE); //try only needed rectangle } return 0; } static LRESULT clcOnIntmAvatarChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { struct ClcContact *contact; if (FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE)) { Cache_GetAvatar(dat, contact); } else if (dat->use_avatar_service && !wParam) { UpdateAllAvatars(dat); } CLUI__cliInvalidateRect(hwnd, NULL, FALSE); return 0; } static LRESULT clcOnIntmTimeZoneChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { struct ClcContact *contact; if (!FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE)) return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam); if (contact) //!IsBadWritePtr(contact, sizeof(struct ClcContact))) { Cache_GetTimezone(dat,contact->hContact); Cache_GetText(dat, contact,1); cliRecalcScrollBar(hwnd,dat); } return 0; } static LRESULT clcOnIntmNameChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { struct ClcContact *contact; int ret=corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); pcli->pfnInvalidateDisplayNameCacheEntry((HANDLE)wParam); if (!FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE)) return ret; lstrcpyn(contact->szText, pcli->pfnGetContactDisplayName((HANDLE)wParam,0),SIZEOF(contact->szText)); if (contact)//!IsBadWritePtr(contact, sizeof(struct ClcContact))) { Cache_GetText(dat,contact,1); cliRecalcScrollBar(hwnd,dat); } dat->NeedResort=1; pcli->pfnSortContacts(); return ret; } static LRESULT clcOnIntmApparentModeChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int lResult=corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); if (!ServiceExists("ExtraIcon/Register")) ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,(HANDLE)wParam); return lResult; } static LRESULT clcOnIntmStatusMsgChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { struct ClcContact *contact; HANDLE hContact = (HANDLE)wParam; if (hContact == NULL || IsHContactInfo(hContact) || IsHContactGroup(hContact)) return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); if (!FindItem(hwnd,dat,hContact,&contact,NULL,NULL,FALSE)) return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); if (contact)//!IsBadWritePtr(contact, sizeof(struct ClcContact))) { Cache_GetText(dat,contact,1); cliRecalcScrollBar(hwnd,dat); PostMessage(hwnd,INTM_INVALIDATE,0,0); } return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); } static LRESULT clcOnIntmNotOnListChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { DBCONTACTWRITESETTING *dbcws=(DBCONTACTWRITESETTING*)lParam; struct ClcContact *contact; if (!FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,TRUE)) return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); if(contact->type!=CLCIT_CONTACT) return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); if(dbcws->value.type==DBVT_DELETED || dbcws->value.bVal==0) contact->flags&=~CONTACTF_NOTONLIST; else contact->flags|=CONTACTF_NOTONLIST; CLUI__cliInvalidateRect(hwnd,NULL,FALSE); return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); } static LRESULT clcOnIntmScrollBarChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (GetWindowLong(hwnd, GWL_STYLE) & CLS_CONTACTLIST) { if (dat->noVScrollbar) ShowScrollBar(hwnd, SB_VERT, FALSE); else pcli->pfnRecalcScrollBar(hwnd, dat); } return 0; } static LRESULT clcOnIntmStatusChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int ret=corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); if (wParam != 0) { pdisplayNameCacheEntry pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry((HANDLE)wParam); if (pdnce && pdnce->m_cache_cszProto) { struct ClcContact *contact=NULL; pdnce___SetStatus( pdnce, GetStatusForContact(pdnce->m_cache_hContact,pdnce->m_cache_cszProto)); if (!dat->force_in_dialog && ( (dat->second_line_show)// && dat->second_line_type==TEXT_STATUS) || (dat->third_line_show)// && dat->third_line_type==TEXT_STATUS) )) gtaRenewText(pdnce->m_cache_hContact); SendMessage(hwnd,INTM_ICONCHANGED, wParam, (LPARAM) CallService(MS_CLIST_GETCONTACTICON, wParam, 1)); if(FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,TRUE)) { if (contact && contact->type==CLCIT_CONTACT) { if (!contact->image_is_special && pdnce___GetStatus( pdnce )>ID_STATUS_OFFLINE) contact->iImage=CallService(MS_CLIST_GETCONTACTICON, wParam, 1); if (contact->isSubcontact && contact->subcontacts && contact->subcontacts->type==CLCIT_CONTACT) pcli->pfnClcBroadcast( INTM_STATUSCHANGED,(WPARAM)contact->subcontacts->hContact,0); //forward status changing to host meta contact } } } #ifdef _DEBUG else { DebugBreak(); } #endif } if (ModernGetSettingByte(NULL,"CList","PlaceOfflineToRoot",SETTING_PLACEOOFLINETOROOT_DEFAULT) ) { SendMessage(hwnd,CLM_AUTOREBUILD,0,0); } else { pcli->pfnSortContacts(); PostMessage(hwnd,INTM_INVALIDATE,0,0); } return ret; } static LRESULT clcOnIntmReloadOptions(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); pcli->pfnLoadClcOptions(hwnd,dat); LoadCLCOptions(hwnd,dat); pcli->pfnSaveStateAndRebuildList(hwnd,dat); pcli->pfnSortCLC(hwnd,dat,1); if (IsWindowVisible(hwnd)) pcli->pfnInvalidateRect(GetParent(hwnd), NULL, FALSE); return TRUE; } HRESULT ClcLoadModule() { g_himlCListClc=(HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST,0,0); hSettingChanged=ModernHookEvent(ME_DB_CONTACT_SETTINGCHANGED,clcHookSettingChanged); ModernHookEvent(ME_OPT_INITIALISE,ClcOptInit); hAckHook=(HANDLE)ModernHookEvent(ME_PROTO_ACK,clcHookProtoAck); ModernHookEvent(ME_SYSTEM_MODULESLOADED, clcHookModulesLoaded); ModernHookEvent(ME_DB_EVENT_ADDED, clcHookDbEventAdded); ModernHookEvent(ME_SYSTEM_SHUTDOWN,clcHookSystemShutdown); return S_OK; } int ClcUnloadModule() { if(hAvatarChanged!=0) ModernUnhookEvent(hAvatarChanged); if(hSmileyAddOptionsChangedHook!=0) ModernUnhookEvent(hSmileyAddOptionsChangedHook); if(hIconChangedHook!=0) ModernUnhookEvent(hIconChangedHook); if ( g_CluiData.bOldUseGroups != (BYTE)-1 ) ModernWriteSettingByte(NULL,"CList","UseGroups",(BYTE)g_CluiData.bOldUseGroups ); if ( g_CluiData.boldHideOffline != (BYTE)-1 ) ModernWriteSettingByte(NULL,"CList","HideOffline",(BYTE)g_CluiData.boldHideOffline ); return 0; } int ClcDoProtoAck(HANDLE wParam,ACKDATA * ack) { if (MirandaExiting()) return 0; if (ack->type == ACKTYPE_STATUS) { int i; if (ack->result == ACKRESULT_SUCCESS) { for (i = 0; i < pcli->hClcProtoCount; i++) { if (!lstrcmpA(pcli->clcProto[i].szProto, ack->szModule)) { pcli->clcProto[i].dwStatus = (WORD) ack->lParam; if (pcli->clcProto[i].dwStatus>=ID_STATUS_OFFLINE) pcli->pfnTrayIconUpdateBase(pcli->clcProto[i].szProto); if (!ServiceExists("ExtraIcon/Register")) if(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_VISMODE)!=-1) ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,(HANDLE)NULL); return 0; } } } } else if (ack->type==ACKTYPE_AWAYMSG) { if (ack->result==ACKRESULT_SUCCESS && ack->lParam) { {//Do not change DB if it is IRC protocol if (ack->szModule!= NULL) if(ModernGetSettingByte(ack->hContact, ack->szModule, "ChatRoom", 0) != 0) return 0; } { DBVARIANT dbv={0}; BOOL bUnicode = (!ModernGetSetting(ack->hContact, "CList", "StatusMsg", &dbv) && (dbv.type !=DBVT_ASCIIZ) ); ModernDBFreeVariant(&dbv); if (!bUnicode) { char * val= ModernGetStringA(ack->hContact,"CList","StatusMsg"); if (val) { if (!mir_bool_strcmpi(val,(const char *)ack->lParam)) ModernWriteSettingString(ack->hContact,"CList","StatusMsg",(const char *)ack->lParam); else gtaRenewText(ack->hContact); mir_free_and_nill(val); } else ModernWriteSettingString(ack->hContact,"CList","StatusMsg",(const char *)ack->lParam); //pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,(WPARAM)ack->hContact,(LPARAM)ack->lParam); } gtaRenewText(ack->hContact); } } else { //DBDeleteContactSetting(ack->hContact,"CList","StatusMsg"); //char a='\0'; {//Do not change DB if it is IRC protocol if (ack->szModule!= NULL) if(ModernGetSettingByte(ack->hContact, ack->szModule, "ChatRoom", 0) != 0) return 0; } if (ack->hContact) { char * val= ModernGetStringA(ack->hContact,"CList","StatusMsg"); if (val) { if (!mir_bool_strcmpi(val,"")) ModernWriteSettingString(ack->hContact,"CList","StatusMsg",""); else gtaRenewText(ack->hContact); mir_free_and_nill(val); } } //pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,(WPARAM)ack->hContact,&a); } } else if (ack->type==ACKTYPE_AVATAR) { if (ack->result==ACKRESULT_SUCCESS) { PROTO_AVATAR_INFORMATION *pai = (PROTO_AVATAR_INFORMATION *) ack->hProcess; if (pai != NULL && pai->hContact != NULL) { pcli->pfnClcBroadcast( INTM_AVATARCHANGED,(WPARAM)pai->hContact,0); } } } else if (ack->type == ACKTYPE_EMAIL) { CLUIUnreadEmailCountChanged(0,0); } return 0; } int ClcGetShortData(struct ClcData* pData, struct SHORTDATA *pShortData) { if (!pData|| !pShortData) return -1; pShortData->hWnd=pData->hWnd; pShortData->text_replace_smileys=pData->text_replace_smileys; pShortData->text_smiley_height=pData->text_smiley_height; pShortData->text_use_protocol_smileys=pData->text_use_protocol_smileys; pShortData->contact_time_show_only_if_different=pData->contact_time_show_only_if_different; // Second line pShortData->second_line_show=pData->second_line_show; pShortData->second_line_draw_smileys=pData->second_line_draw_smileys; pShortData->second_line_type=pData->second_line_type; _tcsncpy(pShortData->second_line_text,pData->second_line_text,TEXT_TEXT_MAX_LENGTH); pShortData->second_line_xstatus_has_priority=pData->second_line_xstatus_has_priority; pShortData->second_line_show_status_if_no_away=pData->second_line_show_status_if_no_away; pShortData->second_line_show_listening_if_no_away=pData->second_line_show_listening_if_no_away; pShortData->second_line_use_name_and_message_for_xstatus=pData->second_line_use_name_and_message_for_xstatus; pShortData->third_line_show=pData->third_line_show; pShortData->third_line_draw_smileys=pData->third_line_draw_smileys; pShortData->third_line_type=pData->third_line_type; _tcsncpy(pShortData->third_line_text,pData->third_line_text,TEXT_TEXT_MAX_LENGTH); pShortData->third_line_xstatus_has_priority=pData->third_line_xstatus_has_priority; pShortData->third_line_show_status_if_no_away=pData->third_line_show_status_if_no_away; pShortData->third_line_show_listening_if_no_away=pData->third_line_show_listening_if_no_away; pShortData->third_line_use_name_and_message_for_xstatus=pData->third_line_use_name_and_message_for_xstatus; return 0; } int ClcEnterDragToScroll(HWND hwnd, int Y) { struct ClcData * dat; if (IsDragToScrollMode) return 0; dat=(struct ClcData*)GetWindowLongPtr(hwnd,0); if (!dat) return 0; StartDragPos=Y; StartScrollPos=dat->yScroll; IsDragToScrollMode=1; SetCapture(hwnd); return 1; } /* * Contact list control window procedure */ LRESULT CALLBACK cli_ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { #define CASE_MSG_RET(msg, handler) case msg: return handler(dat, hwnd, msg, wParam, lParam); struct ClcData *dat; dat=(struct ClcData*)GetWindowLongPtr(hwnd,0); if(msg>=CLM_FIRST && msg