summaryrefslogtreecommitdiff
path: root/plugins/MenuItemEx/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/MenuItemEx/src/main.cpp')
-rw-r--r--plugins/MenuItemEx/src/main.cpp1386
1 files changed, 1386 insertions, 0 deletions
diff --git a/plugins/MenuItemEx/src/main.cpp b/plugins/MenuItemEx/src/main.cpp
new file mode 100644
index 0000000000..760520ce91
--- /dev/null
+++ b/plugins/MenuItemEx/src/main.cpp
@@ -0,0 +1,1386 @@
+#include "menuex.h"
+#include "images.h"
+#include "version.h"
+
+#define MS_SETINVIS "MenuEx/SetInvis"
+#define MS_SETVIS "MenuEx/SetVis"
+#define MS_HIDE "MenuEx/Hide"
+#define MS_IGNORE "MenuEx/Ignore"
+#define MS_PROTO "MenuEx/ChangeProto"
+#define MS_ADDED "MenuEx/SendAdded"
+#define MS_AUTHREQ "MenuEx/SendAuthReq"
+#define MS_COPYID "MenuEx/CopyID"
+#define MS_RECVFILES "MenuEx/RecvFiles"
+#define MS_STATUSMSG "MenuEx/CopyStatusMsg"
+#define MS_COPYIP "MenuEx/CopyIP"
+#define MS_COPYMIRVER "MenuEx/CopyMirVer"
+
+
+const int vf_default = VF_VS|VF_HFL|VF_IGN|VF_CID|VF_SHOWID|VF_RECV|VF_STAT|VF_SMNAME|VF_CIDN|VF_CIP;
+
+HINSTANCE hinstance;
+HANDLE hmenuVis,hmenuOff,hmenuHide,hmenuIgnore,hmenuProto,hmenuAdded,hmenuAuthReq;
+HANDLE hmenuCopyID,hmenuRecvFiles,hmenuStatusMsg,hmenuCopyIP,hmenuCopyMirVer;
+static HANDLE hIgnoreItem[9], hProtoItem[MAX_PROTOS], hHooks[8], hServices[12];
+HICON hIcon[5];
+BOOL bMetaContacts, bMir_08;
+PROTOACCOUNT **accs;
+OPENOPTIONSDIALOG ood;
+int protoCount;
+int hLangpack;
+static LONG_PTR OldAuthReqEditProc;
+
+struct {
+ char *module;
+ char *name;
+ TCHAR *fullName;
+ char flag;
+}
+static const statusMsg[] = {
+ { "CList", "StatusMsg", LPGENT("Status message"), 1 },
+ { 0, "XStatusName", LPGENT("XStatus title"), 4 },
+ { 0, "XStatusMsg", LPGENT("XStatus message"), 2 },
+ { "AdvStatus", "tune/text", LPGENT("Listening to"), 8 },
+ { "AdvStatus", "activity/title", LPGENT("Activity title"), 8 },
+ { "AdvStatus", "activity/text", LPGENT("Activity text"), 8 }
+};
+
+struct
+{
+ TCHAR* szDescr;
+ char* szName;
+ int defIconID;
+}
+static const iconList[] = {
+ { _T("Hide from list"), "miex_hidefl", IDI_ICON0 },
+ { _T("Show in list"), "miex_showil", IDI_ICON8 },
+ { _T("Always visible"), "miex_vis", IDI_ICON1 },
+ { _T("Never visible"), "miex_invis", IDI_ICON2 },
+ { _T("Send 'You were added'"), "miex_added", IDI_ICON4 },
+ { _T("Request authorization"), "miex_authorization", IDI_ICON5 },
+ { _T("Copy to Account"), "miex_protocol", IDI_ICON6 },
+ { _T("Ignore"), "miex_ignore", IDI_ICON7 },
+ { _T("Browse Received Files"), "miex_recfiles", IDI_ICON12 },
+ { _T("Copy MirVer"), "miex_copymver", IDI_ICON13 }
+};
+
+struct
+{
+ TCHAR* szDescr;
+ char* szName;
+ int defIconID;
+}
+static const overlayIconList[] = {
+ { _T("Copy ID"), "miex_copyid", IDI_ICON3 },
+ { _T("Copy Status Message"), "miex_copysm1", IDI_ICON9 },
+ { _T("Copy xStatus Message"), "miex_copysm2", IDI_ICON10 },
+ { _T("Copy IP"), "miex_copyip", IDI_ICON11 }
+};
+
+struct {
+ TCHAR* name;
+ int type;
+ int icon;
+}
+static const ii[] = {
+ { LPGENT("All"), IGNOREEVENT_ALL, SKINICON_OTHER_FILLEDBLOB },
+ { LPGENT("Messages"), IGNOREEVENT_MESSAGE, SKINICON_EVENT_MESSAGE },
+ { LPGENT("URL"), IGNOREEVENT_URL, SKINICON_EVENT_URL },
+ { LPGENT("Files"), IGNOREEVENT_FILE, SKINICON_EVENT_FILE },
+ { LPGENT("User Online"), IGNOREEVENT_USERONLINE, SKINICON_OTHER_USERONLINE },
+ { LPGENT("Authorization"), IGNOREEVENT_AUTHORIZATION, SKINICON_OTHER_MIRANDA },
+ { LPGENT("You Were Added"), IGNOREEVENT_YOUWEREADDED, SKINICON_OTHER_ADDCONTACT },
+ { LPGENT("Typing Notify"), IGNOREEVENT_TYPINGNOTIFY, SKINICON_OTHER_TYPING }
+};
+
+PLUGININFOEX pluginInfoEx = {
+ sizeof(PLUGININFOEX),
+ MODULENAME,
+ __VERSION_DWORD,
+ __DESC,
+ __AUTHORS,
+ __EMAIL,
+ __COPYRIGHTS,
+ __WEB,
+ UNICODE_AWARE,
+ MIID_MENUEX
+};
+
+struct ModSetLinkLinkItem { // code from dbe++ plugin by Bio
+ char *name;
+ BYTE *next; //struct ModSetLinkLinkItem
+};
+
+typedef struct {
+ struct ModSetLinkLinkItem *first;
+ struct ModSetLinkLinkItem *last;
+} ModuleSettingLL;
+
+int GetSetting(HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
+{
+ DBCONTACTGETSETTING cgs;
+
+ cgs.szModule = szModule;
+ cgs.szSetting = szSetting;
+ cgs.pValue = dbv;
+ dbv->type = 0;
+
+ return CallService(MS_DB_CONTACT_GETSETTING_STR,(WPARAM)hContact,(LPARAM)&cgs);
+}
+
+int enumModulesSettingsProc( const char *szName, LPARAM lParam)
+{
+ ModuleSettingLL *msll = (ModuleSettingLL *)lParam;
+ if (!msll->first)
+ {
+ msll->first = (struct ModSetLinkLinkItem *)malloc(sizeof(struct ModSetLinkLinkItem));
+ if (!msll->first) return 1;
+ msll->first->name = _strdup(szName);
+ msll->first->next = 0;
+ msll->last = msll->first;
+ }
+ else
+ {
+ struct ModSetLinkLinkItem *item = (struct ModSetLinkLinkItem *)malloc(sizeof(struct ModSetLinkLinkItem));
+ if (!item) return 1;
+ msll->last->next = (BYTE*)item;
+ msll->last = (struct ModSetLinkLinkItem *)item;
+ item->name = _strdup(szName);
+ item->next = 0;
+ }
+ return 0;
+}
+
+void FreeModuleSettingLL(ModuleSettingLL* msll)
+{
+ if (msll)
+ {
+ struct ModSetLinkLinkItem *item = msll->first;
+ struct ModSetLinkLinkItem *temp;
+
+ while (item)
+ {
+ if (item->name)
+ {
+ free(item->name);
+ item->name = 0;
+ }
+ temp = item;
+ item = (struct ModSetLinkLinkItem *)item->next;
+ if (temp)
+ {
+ free(temp);
+ temp = 0;
+ }
+ }
+
+ msll->first = 0;
+ msll->last = 0;
+ }
+}
+
+void RenameDbProto(HANDLE hContact, HANDLE hContactNew, char* oldName, char* newName, int delOld)
+{
+ DBVARIANT dbv;
+ ModuleSettingLL settinglist;
+ struct ModSetLinkLinkItem *setting;
+ DBCONTACTENUMSETTINGS dbces;
+
+ // enum all setting the contact has for the module
+ dbces.pfnEnumProc = enumModulesSettingsProc;
+ dbces.szModule = oldName;
+ dbces.lParam = (LPARAM)&settinglist;
+ settinglist.first = 0;
+ settinglist.last = 0;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)hContact,(LPARAM)&dbces);
+
+ setting = settinglist.first;
+ while (setting)
+ {
+ if (!GetSetting(hContact,oldName,setting->name,&dbv))
+ {
+ switch (dbv.type)
+ {
+ case DBVT_BYTE:
+ DBWriteContactSettingByte(hContactNew, newName, setting->name, dbv.bVal);
+ break;
+ case DBVT_WORD:
+ DBWriteContactSettingWord(hContactNew, newName, setting->name, dbv.wVal);
+ break;
+ case DBVT_DWORD:
+ DBWriteContactSettingDword(hContactNew, newName, setting->name, dbv.dVal);
+ break;
+ case DBVT_ASCIIZ:
+ DBWriteContactSettingString(hContactNew, newName, setting->name, dbv.pszVal);
+ break;
+ case DBVT_UTF8:
+ DBWriteContactSettingStringUtf(hContactNew, newName, setting->name, dbv.pszVal);
+ break;
+ case DBVT_BLOB:
+ DBWriteContactSettingBlob(hContactNew, newName, setting->name, dbv.pbVal, dbv.cpbVal);
+ break;
+
+ }
+ if (delOld)
+ DBDeleteContactSetting(hContact, oldName, setting->name);
+ }
+ DBFreeVariant(&dbv);
+ setting = (struct ModSetLinkLinkItem *)setting->next;
+ }
+ FreeModuleSettingLL(&settinglist);
+} // end code from dbe++
+
+static void IconsInit()
+{
+ int i;
+ TCHAR tszFile[MAX_PATH];
+ GetModuleFileName(hinstance, tszFile, MAX_PATH);
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.flags = SIDF_ALL_TCHAR;
+ sid.ptszDefaultFile = tszFile;
+ sid.cx = sid.cy = 16;
+ sid.ptszSection = LPGENT(MODULENAME);
+
+ for ( i = 0; i < SIZEOF(iconList); i++ ) {
+ sid.pszName = iconList[i].szName;
+ sid.ptszDescription = iconList[i].szDescr;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ Skin_AddIcon(&sid);
+ }
+
+ for ( i = 0; i < SIZEOF(overlayIconList); i++ ) {
+ sid.pszName = overlayIconList[i].szName;
+ sid.ptszDescription = overlayIconList[i].szDescr;
+ sid.iDefaultIndex = -overlayIconList[i].defIconID;
+ Skin_AddIcon(&sid);
+ }
+}
+
+void ShowPopup(char* szText, TCHAR* tszText, HANDLE hContact)
+{
+ POPUPDATAT ppd = {0};
+ TCHAR* text = 0;
+
+ if (tszText)
+ text = mir_tstrdup(tszText);
+ else if (szText)
+ text = mir_a2t(szText);
+ if (!text) return;
+
+ ppd.lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ ppd.lchContact = hContact;
+ _tcsncpy(ppd.lptzContactName, (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR), MAX_CONTACTNAME - 1);
+ _tcsncpy(ppd.lptzText, text, MAX_SECONDLINE - 1);
+ ppd.iSeconds = -1;
+
+ PUAddPopUpT(&ppd);
+ mir_free(text);
+}
+
+BOOL DirectoryExists(HANDLE hContact)
+{
+ int attr;
+ char path[MAX_PATH];
+ CallService(MS_FILE_GETRECEIVEDFILESFOLDER, (WPARAM)hContact, (LPARAM)&path);
+ attr = GetFileAttributesA(path);
+ return (attr != -1) && (attr&FILE_ATTRIBUTE_DIRECTORY);
+}
+
+void CopyToClipboard(HWND hwnd,LPSTR pszMsg, LPTSTR ptszMsg)
+{
+ HGLOBAL hglbCopy;
+ LPTSTR lptstrCopy;
+ LPTSTR buf = 0;
+ if (ptszMsg)
+ buf = mir_tstrdup(ptszMsg);
+ else if (pszMsg)
+ buf = mir_a2t(pszMsg);
+
+ if (buf == 0)
+ return;
+
+ hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (lstrlen(buf)+1)*sizeof(TCHAR));
+ lptstrCopy = (LPTSTR)GlobalLock(hglbCopy);
+ lstrcpy(lptstrCopy, buf);
+ mir_free(buf);
+ GlobalUnlock(hglbCopy);
+
+ OpenClipboard(NULL);
+ EmptyClipboard();
+
+ SetClipboardData(CF_UNICODETEXT, hglbCopy);
+
+ CloseClipboard();
+}
+
+BOOL isMetaContact(HANDLE hContact) {
+
+ char *proto;
+ if(bMetaContacts) {
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if ( lstrcmpA(proto,"MetaContacts") == 0 ) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+HANDLE getDefaultContact(HANDLE hContact) {
+
+ if(bMetaContacts) {
+ return (HANDLE)CallService(MS_MC_GETDEFAULTCONTACT,(WPARAM)hContact,0);
+ }
+ return 0;
+}
+
+HANDLE getMostOnline(HANDLE hContact) {
+
+ if(bMetaContacts) {
+ return (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,(WPARAM)hContact,0);
+ }
+ return 0;
+}
+
+void GetID(HANDLE hContact,LPSTR szProto,LPSTR szID)
+{
+ DBVARIANT dbv_uniqueid;
+ LPSTR uID = (LPSTR) CallProtoService(szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+ if ( uID == (LPSTR)CALLSERVICE_NOTFOUND )
+ uID = NULL;
+
+ *szID = '\0';
+
+ if ( uID && DBGetContactSetting(hContact, szProto, uID ,&dbv_uniqueid) == 0 ) {
+ if (dbv_uniqueid.type == DBVT_DWORD)
+ wsprintfA(szID, "%u", dbv_uniqueid.dVal);
+ else if (dbv_uniqueid.type == DBVT_WORD)
+ wsprintfA(szID, "%u", dbv_uniqueid.wVal);
+ else if (dbv_uniqueid.type == DBVT_BLOB)
+ wsprintfA(szID, "%s", dbv_uniqueid.cpbVal);
+ else
+ wsprintfA(szID, "%s", dbv_uniqueid.pszVal);
+
+ DBFreeVariant(&dbv_uniqueid);
+ }
+}
+
+int StatusMsgExists(HANDLE hContact)
+{
+ LPSTR module,msg;
+ char par[32];
+ BOOL ret = 0;
+ int i;
+
+ module = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!module) return 0;
+
+ for(i = 0; i < SIZEOF(statusMsg); i++) {
+ if (statusMsg[i].flag & 8)
+ mir_snprintf(par, SIZEOF(par), "%s/%s", module, statusMsg[i].name);
+ else
+ strcpy(par, statusMsg[i].name);
+
+ msg = DBGetString(hContact, (statusMsg[i].module) ? statusMsg[i].module : module, par);
+ if(msg) {
+ if(strlen(msg))
+ ret |= statusMsg[i].flag;
+ mir_free(msg);
+ }
+ }
+ return ret;
+}
+
+BOOL IPExists(HANDLE hContact)
+{
+ LPSTR szProto;
+ DWORD mIP,rIP;
+
+ szProto = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!szProto) return 0;
+
+ mIP = DBGetContactSettingDword(hContact, szProto, "IP", 0);
+ rIP = DBGetContactSettingDword(hContact, szProto, "RealIP", 0);
+
+ return (mIP != 0 || rIP != 0);
+}
+
+BOOL MirVerExists(HANDLE hContact)
+{
+ LPSTR szProto, msg;
+ BOOL ret = 0;
+
+ szProto = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!szProto) return 0;
+
+ msg = DBGetString(hContact,szProto,"MirVer");
+ if(msg) {
+ if(strlen(msg)) ret = 1;
+ mir_free(msg);
+ }
+
+ return ret;
+}
+
+void getIP(HANDLE hContact,LPSTR szProto,LPSTR szIP)
+{
+ char szmIP[64] = {0};
+ char szrIP[64] = {0};
+ DWORD mIP = DBGetContactSettingDword(hContact, szProto, "IP", 0);
+ DWORD rIP = DBGetContactSettingDword(hContact, szProto, "RealIP", 0);
+ if ( mIP ) wsprintfA(szmIP, "External IP: %d.%d.%d.%d\r\n", mIP>>24,(mIP>>16)&0xFF,(mIP>>8)&0xFF,mIP&0xFF);
+ if ( rIP ) wsprintfA(szrIP, "Internal IP: %d.%d.%d.%d\r\n", rIP>>24,(rIP>>16)&0xFF,(rIP>>8)&0xFF,rIP&0xFF);
+ strcpy(szIP,szrIP);
+ strcat(szIP,szmIP);
+}
+
+LPSTR getMirVer(HANDLE hContact)
+{
+ LPSTR szProto, msg;
+
+ szProto = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!szProto) return NULL;
+
+ msg = DBGetString(hContact,szProto,"MirVer");
+ if(msg) {
+ if(strlen(msg))
+ return msg;
+ mir_free(msg);
+ }
+
+ return NULL;
+}
+
+static LRESULT CALLBACK AuthReqEditSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_CHAR:
+ if(wParam == '\n' && CTRL_IS_PRESSED) { // ctrl + ENTER
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ if(wParam == 1 && CTRL_IS_PRESSED) { // ctrl + a
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return 0;
+ }
+ break;
+ case WM_SETFOCUS:
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ break;
+ }
+ return CallWindowProc((WNDPROC)OldAuthReqEditProc,hwnd,msg,wParam,lParam);
+}
+
+INT_PTR CALLBACK AuthReqWndProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam)
+{
+ static HANDLE hcontact;
+
+ switch(msg){
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hdlg);
+ OldAuthReqEditProc = SetWindowLongPtr(GetDlgItem(hdlg, IDC_REASON), GWLP_WNDPROC, (LONG_PTR)AuthReqEditSubclassProc);
+ SendDlgItemMessage(hdlg, IDC_REASON, EM_LIMITTEXT, (WPARAM)255, 0);
+ SetDlgItemText(hdlg, IDC_REASON, TranslateT("Please authorize me to add you to my contact list."));
+ hcontact = (HANDLE)lparam;
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wparam)) {
+ case IDOK:
+ {
+ char szReason[256] = {0};
+
+ WCHAR wszReason[256] = {0};
+
+ if (CallService(MS_SYSTEM_GETVERSION, 0, 0) < 0x00090007)
+ {
+ GetDlgItemTextA(hdlg,IDC_REASON,szReason,255);
+ CallContactService(hcontact,PSS_AUTHREQUEST,0,(LPARAM)szReason);
+ }
+ else
+ {
+ GetDlgItemText(hdlg,IDC_REASON,wszReason,255);
+ CallContactService(hcontact,PSS_AUTHREQUESTW,0,(LPARAM)wszReason);
+ }
+
+ } // fall through
+ case IDCANCEL:
+ DestroyWindow(hdlg);
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+BOOL isVisSupport(HANDLE hContact)
+{
+ char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+ if(szProto == NULL) return 0;
+ return CallProtoService(szProto,PS_GETCAPS,PFLAGNUM_1,0)&PF1_INVISLIST;
+}
+
+BOOL isInvSupport(HANDLE hContact)
+{
+ char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+ if(szProto == NULL) return 0;
+ return CallProtoService(szProto,PS_GETCAPS,PFLAGNUM_1,0)&PF1_VISLIST;
+}
+
+BOOL isProtoOnline(char *szProto)
+{
+//#ifdef _DEBUG
+// return TRUE;
+//#else
+ DWORD protoStatus;
+ protoStatus = CallProtoService(szProto,PS_GETSTATUS,0,0);
+ return (protoStatus > ID_STATUS_OFFLINE && protoStatus < ID_STATUS_IDLE);
+
+//#endif
+}
+
+INT_PTR onSendAuthRequest(WPARAM wparam,LPARAM lparam)
+{
+ DWORD flags;
+ char *szProto;
+
+ szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,wparam,0);
+
+ flags = CallProtoService(szProto,PS_GETCAPS,PFLAGNUM_4,0);
+ if (flags&PF4_NOCUSTOMAUTH)
+ CallContactService((HANDLE)wparam,PSS_AUTHREQUEST,0, (LPARAM)"");
+ else
+ CreateDialogParam(hinstance,MAKEINTRESOURCE(IDD_AUTHREQ),(HWND)CallService(MS_CLUI_GETHWND,0,0),AuthReqWndProc,(LPARAM)wparam);
+
+ return 0;
+}
+
+INT_PTR onSendAdded(WPARAM wparam,LPARAM lparam)
+{
+ CallContactService((HANDLE)wparam,PSS_ADDED,0,0);
+ return 0;
+}
+
+// set the invisible-flag in db
+INT_PTR onSetInvis(WPARAM wparam,LPARAM lparam)
+{
+ CallContactService((HANDLE)wparam,PSS_SETAPPARENTMODE,(DBGetContactSettingWord((HANDLE)wparam,(const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wparam,0),"ApparentMode",0) == ID_STATUS_OFFLINE)?0:ID_STATUS_OFFLINE,0);
+ return 0;
+}
+
+// set visible-flag in db
+INT_PTR onSetVis(WPARAM wparam,LPARAM lparam)
+{
+ CallContactService((HANDLE)wparam,PSS_SETAPPARENTMODE,(DBGetContactSettingWord((HANDLE)wparam,(const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wparam,0),"ApparentMode",0) == ID_STATUS_ONLINE)?0:ID_STATUS_ONLINE,0);
+ return 0;
+}
+
+INT_PTR onHide(WPARAM wparam,LPARAM lparam)
+{
+ DBWriteContactSettingByte((HANDLE)wparam,"CList","Hidden",(byte)!DBGetContactSettingByte((HANDLE)wparam,"CList","Hidden",0));
+ CallService(MS_CLUI_SORTLIST,0,0);
+ return 0;
+}
+
+void ShowItem(CLISTMENUITEM *cli, HANDLE hmenu)
+{
+ cli->flags = CMIM_FLAGS | CMIF_TCHAR;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hmenu,(LPARAM)cli);
+}
+
+void HideItem(CLISTMENUITEM *cli,HANDLE hmenu)
+{
+ cli->flags|=CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hmenu,(LPARAM)cli);
+}
+
+// following 4 functions should be self-explanatory
+void ModifyVisibleSet(CLISTMENUITEM *cli,int mode,BOOL alpha)
+{
+ cli->flags |= CMIM_ICON;
+ cli->hIcon = (mode) ? hIcon[1] : (alpha?hIcon[3] : LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT));
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hmenuVis, (LPARAM)cli);
+}
+
+void ModifyInvisSet(CLISTMENUITEM *cli,int mode,BOOL alpha)
+{
+ cli->flags |= CMIM_ICON;
+ cli->hIcon = (mode) ? hIcon[2] : (alpha ? hIcon[4] : LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT));
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hmenuOff, (LPARAM)cli);
+}
+
+void ModifyHidden(CLISTMENUITEM *cli,int mode)
+{
+ cli->flags |= CMIM_ICON | CMIM_NAME;
+ cli->hIcon = (mode) ?
+ (HICON)CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_showil") :
+ (HICON)CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_hidefl");
+ cli->ptszName = mode ? LPGENT("Show in list") : LPGENT("Hide from list");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hmenuHide, (LPARAM)cli);
+}
+
+void ModifyCopyID(CLISTMENUITEM *cli, HANDLE hContact, BOOL bShowID, BOOL bTrimID)
+{
+ LPSTR szProto;
+ char szID[256];
+ TCHAR buffer[256];
+ HICON hIconCID;
+ HANDLE hC;
+
+ cli->flags|=CMIM_ICON|CMIM_NAME;
+
+ if(isMetaContact(hContact)) {
+ hC = getMostOnline(hContact);
+ if ( !hContact ) hC = getDefaultContact(hContact);
+ hContact = hC;
+ }
+
+ szProto = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!szProto) {
+ HideItem(cli,hmenuCopyID);
+ return;
+ }
+ hIconCID = (HICON) CallProtoService(szProto, PS_LOADICON, PLI_PROTOCOL|PLIF_SMALL, 0);
+ cli->hIcon = BindOverlayIcon(hIconCID, "miex_copyid");
+ DestroyIcon(hIconCID);
+ hIconCID = cli->hIcon;
+
+ GetID(hContact,szProto,(LPSTR)&szID);
+ if(szID[0])
+ {
+ if (bShowID)
+ {
+ TCHAR* tmp;
+
+ if (bTrimID && (strlen(szID) > MAX_IDLEN))
+ {
+ szID[MAX_IDLEN - 2] = szID[MAX_IDLEN - 1] = szID[MAX_IDLEN] = '.';
+ szID[MAX_IDLEN + 1] = 0;
+ }
+ tmp = mir_a2t(szID);
+ mir_sntprintf(buffer, SIZEOF(buffer), _T("%s [%s]"), TranslateT("Copy ID"), tmp);
+ mir_free(tmp);
+
+ cli->ptszName = (TCHAR*)&buffer;
+ }
+ else
+ cli->ptszName = _T("Copy ID");
+ }
+ else {
+ cli->flags = CMIM_FLAGS|CMIF_HIDDEN;
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hmenuCopyID,(LPARAM)cli);
+ DestroyIcon(hIconCID);
+}
+
+void ModifyStatusMsg(CLISTMENUITEM *cli,HANDLE hContact)
+{
+ LPSTR szProto;
+ HICON hIconSMsg;
+
+ cli->flags|=CMIM_ICON;
+
+ szProto = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!szProto) {
+ HideItem(cli,hmenuStatusMsg);
+ return;
+ }
+
+ hIconSMsg = (HICON) CallProtoService(szProto, PS_LOADICON, PLI_PROTOCOL|PLIF_SMALL, 0);
+ cli->hIcon = BindOverlayIcon(hIconSMsg, (StatusMsgExists(hContact)&2) ? "miex_copysm2" : "miex_copysm1");
+ DestroyIcon(hIconSMsg);
+ hIconSMsg = cli->hIcon;
+
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hmenuStatusMsg,(LPARAM)cli);
+ DestroyIcon(hIconSMsg);
+}
+
+void ModifyCopyIP(CLISTMENUITEM *cli,HANDLE hContact)
+{
+ LPSTR szProto;
+ HICON hIconCIP;
+
+ cli->flags |= CMIM_ICON;
+
+ szProto = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!szProto) {
+ HideItem(cli,hmenuCopyIP);
+ return;
+ }
+
+ hIconCIP = (HICON) CallProtoService(szProto, PS_LOADICON, PLI_PROTOCOL|PLIF_SMALL, 0);
+
+ cli->hIcon = BindOverlayIcon(hIconCIP, "miex_copyip");
+ DestroyIcon(hIconCIP);
+ hIconCIP = cli->hIcon;
+
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hmenuCopyIP,(LPARAM)cli);
+ DestroyIcon(hIconCIP);
+}
+
+void ModifyCopyMirVer(CLISTMENUITEM *cli,HANDLE hContact)
+{
+ LPSTR msg;
+ cli->flags|=CMIM_ICON;
+ cli->hIcon = NULL;
+ if(ServiceExists(MS_FP_GETCLIENTICON)) {
+ msg = getMirVer(hContact);
+ if(msg) {
+ cli->hIcon = (HICON)CallService(MS_FP_GETCLIENTICON,(WPARAM)msg,(LPARAM)1);
+ mir_free(msg);
+ }
+ }
+ if (!cli->hIcon) cli->hIcon = hIcon[0];
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hmenuCopyMirVer,(LPARAM)cli);
+}
+
+INT_PTR onCopyID(WPARAM wparam,LPARAM lparam)
+{
+ LPSTR szProto;
+ char szID[128] = {0}, buffer[256] = {0};
+ HANDLE hContact ,hC;
+ PROTOACCOUNT* pa;
+
+ hContact = (HANDLE)wparam;
+ if(isMetaContact(hContact)) {
+ hC = getMostOnline(hContact);
+ if ( !hContact ) hC = getDefaultContact(hContact);
+ hContact = hC;
+ }
+ if ((szProto = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0)) == NULL)
+ return 0;
+
+ GetID(hContact,szProto,(LPSTR)&szID);
+
+ if(DBGetContactSettingDword(NULL,VISPLG,"flags",vf_default)&VF_CIDN) {
+ if (bMir_08)
+ pa = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)szProto);
+
+ if (bMir_08 && !pa->bOldProto)
+ mir_snprintf(buffer, SIZEOF(buffer), "%s: %s", pa->szProtoName, szID);
+ else
+ mir_snprintf(buffer, SIZEOF(buffer), "%s: %s", szProto, szID);
+ }
+ else
+ strcpy(buffer, szID);
+
+ CopyToClipboard((HWND)lparam, buffer, 0);
+ if(CTRL_IS_PRESSED && ServiceExists(MS_POPUP_ADDPOPUP))
+ ShowPopup(buffer, 0, hContact);
+
+ return 0;
+}
+
+INT_PTR onCopyStatusMsg(WPARAM wparam,LPARAM lparam)
+{
+ LPSTR module;
+ LPTSTR msg;
+ char par[32];
+ TCHAR buffer[2048];
+ int i;
+ DWORD flags = DBGetContactSettingDword(NULL,VISPLG,"flags",vf_default);
+
+ module = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, wparam, 0);
+ if (!module) return 0;
+
+ buffer[0] = 0;
+ for(i = 0; i < SIZEOF(statusMsg); i++) {
+ if (statusMsg[i].flag & 8)
+ mir_snprintf(par, SIZEOF(par), "%s/%s", module, statusMsg[i].name);
+ else
+ strcpy(par, statusMsg[i].name);
+
+ msg = DBGetStringT((HANDLE)wparam, (statusMsg[i].module) ? statusMsg[i].module : module, par);
+ if(msg)
+ {
+ if(_tcsclen(msg))
+ {
+ if (flags&VF_SMNAME)
+ {
+ _tcsncat (buffer, TranslateTS(statusMsg[i].fullName), (SIZEOF(buffer) - _tcsclen(buffer) - 1));
+ _tcsncat (buffer, _T(": "), (SIZEOF(buffer) - _tcsclen(buffer) - 1));
+ }
+ _tcsncat(buffer, msg, (SIZEOF(buffer) - _tcsclen(buffer) - 1));
+ _tcsncat(buffer, _T("\r\n"), (SIZEOF(buffer) - _tcsclen(buffer) - 1));
+ }
+ mir_free(msg);
+ }
+ }
+
+ CopyToClipboard((HWND)lparam, 0, buffer);
+ if(CTRL_IS_PRESSED && ServiceExists(MS_POPUP_ADDPOPUP))
+ ShowPopup(0, buffer, (HANDLE)wparam);
+
+ return 0;
+}
+
+INT_PTR onCopyIP(WPARAM wparam,LPARAM lparam)
+{
+ LPSTR szProto;
+ char szIP[128];
+
+ szProto = (LPSTR) CallService(MS_PROTO_GETCONTACTBASEPROTO, wparam, 0);
+ getIP((HANDLE)wparam,szProto,(LPSTR)&szIP);
+
+ CopyToClipboard((HWND)lparam, szIP, 0);
+ if(CTRL_IS_PRESSED && ServiceExists(MS_POPUP_ADDPOPUP))
+ ShowPopup(szIP, 0, (HANDLE)wparam);
+
+ return 0;
+}
+
+INT_PTR onCopyMirVer(WPARAM wparam,LPARAM lparam)
+{
+ LPSTR msg = getMirVer((HANDLE)wparam);
+ if(msg) {
+ CopyToClipboard((HWND)lparam, msg, 0);
+ if(CTRL_IS_PRESSED && ServiceExists(MS_POPUP_ADDPOPUP))
+ ShowPopup(msg, 0, (HANDLE)wparam);
+
+ mir_free(msg);
+ }
+ return 0;
+}
+
+INT_PTR onRecvFiles(WPARAM wparam,LPARAM lparam)
+{
+ char path[MAX_PATH];
+ CallService(MS_FILE_GETRECEIVEDFILESFOLDER, wparam, (LPARAM)&path);
+ ShellExecuteA(0, "open", path, 0, 0, SW_SHOW);
+ return 0;
+}
+
+INT_PTR onChangeProto(WPARAM wparam,LPARAM lparam)
+{
+ HANDLE hContact, hContactNew;
+
+ hContact = (HANDLE)wparam;
+ if (!strcmp((char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wparam, 0), (char*)lparam))
+ return 0;
+
+ if (CTRL_IS_PRESSED)
+ {
+ hContactNew = hContact;
+ RenameDbProto(hContact, hContactNew, (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0), (char*)lparam, 1);
+ CallService(MS_PROTO_REMOVEFROMCONTACT, (WPARAM)hContact, CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0));
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContactNew, lparam);
+ }
+ else
+ {
+ hContactNew = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ if (hContactNew)
+ {
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContactNew, lparam);
+ RenameDbProto(hContact, hContactNew, (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0), (char*)lparam, 0);
+ RenameDbProto(hContact, hContactNew, "CList", "CList", 0);
+ }
+ else
+ return 0;
+ }
+ if(MessageBox(NULL,(LPCTSTR)TranslateT("Do you want to send authorization request\nto new contact?"),
+ TranslateT("Miranda IM"), MB_OKCANCEL | MB_SETFOREGROUND | MB_TOPMOST) == IDOK)
+
+ onSendAuthRequest((WPARAM)hContactNew, 0);
+
+ return 0;
+}
+
+int isIgnored(HANDLE hContact, int type)
+{
+ int i = 0, all = 0;
+ if (type == IGNOREEVENT_ALL)
+ {
+ for (i = 1; i < SIZEOF(ii); i++)
+ {
+ if (isIgnored(hContact, ii[i].type))
+ all++;
+ }
+ return (all == SIZEOF(ii) - 1) ? 1 : 0; // ignoring all or not
+ }
+ else
+ return CallService(MS_IGNORE_ISIGNORED, (WPARAM)hContact, (LPARAM)type);
+}
+
+INT_PTR onIgnore(WPARAM wparam,LPARAM lparam)
+{
+ if (DBGetContactSettingByte(NULL, VISPLG, "ignorehide", 0) && (lparam == IGNOREEVENT_ALL)) {
+ DBWriteContactSettingByte((HANDLE)wparam, "CList", "Hidden", (isIgnored((HANDLE)wparam, lparam) ? (byte)0 : (byte)1));
+ CallService(MS_CLUI_SORTLIST, 0, 0);
+ }
+
+ CallService(isIgnored((HANDLE)wparam, lparam) ? MS_IGNORE_UNIGNORE : MS_IGNORE_IGNORE, wparam, lparam);
+ return 0;
+}
+
+static HANDLE AddSubmenuItem(HANDLE hRoot, TCHAR* name, HICON icon, DWORD flag, char* service, int pos, int param)
+{
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.hParentMenu = (HGENMENU)hRoot;
+ mi.pszPopupName = (char*)hRoot; // for Miranda 0.7
+ mi.popupPosition = param;
+ mi.position = pos;
+ mi.ptszName = name;
+ mi.hIcon = icon;
+ mi.flags = CMIF_TCHAR | CMIF_CHILDPOPUP;
+ if (flag)
+ mi.flags |= flag;
+ mi.pszService = service;
+ return Menu_AddContactMenuItem(&mi);
+}
+
+static void ModifySubmenuItem(HANDLE hItem, TCHAR* name, int checked, int hidden)
+{
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.ptszName = name;
+ mi.flags = CMIM_FLAGS | CMIF_TCHAR;
+ if ( checked )
+ mi.flags |= CMIF_CHECKED;
+ if ( hidden )
+ mi.flags |= CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hItem, (LPARAM)&mi);
+}
+
+// called when the contact-menu is built
+int BuildMenu(WPARAM wparam,LPARAM lparam)
+{
+ CLISTMENUITEM miAV = {0},miNV,miHFL,miIGN,miPROTO,miADD,miREQ,miCID,miRECV,miSTAT,miCIP,miCMV;
+ DWORD flags = DBGetContactSettingDword(NULL,VISPLG,"flags",vf_default);
+ int i = 0, j = 0, check = 0, all = 0, hide = 0;
+ BOOL bIsOnline = FALSE, bShowAll = CTRL_IS_PRESSED;
+ PROTOACCOUNT* pa;
+ char* pszProto;
+ pszProto = (LPSTR)CallService(MS_PROTO_GETCONTACTBASEPROTO, wparam, 0);
+ if(bMir_08)
+ pa = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)pszProto);
+
+ bIsOnline = isProtoOnline(pszProto);
+
+ miAV.cbSize = sizeof(CLISTMENUITEM);
+ miAV.flags = CMIM_FLAGS | CMIF_TCHAR;
+ miAV.hIcon = NULL;
+ miAV.pszContactOwner = NULL;
+ miNV = miHFL = miIGN = miPROTO = miADD = miREQ = miCID = miRECV = miSTAT = miCIP = miCMV = miAV;
+
+ if(bShowAll || flags&VF_VS) {
+ ShowItem(&miAV,hmenuVis);
+ ShowItem(&miNV,hmenuOff);
+ }
+ else {
+ HideItem(&miAV,hmenuVis);
+ HideItem(&miNV,hmenuOff);
+ }
+
+ if(bShowAll || flags&VF_HFL){
+ ShowItem(&miHFL,hmenuHide);
+ ModifyHidden(&miHFL,DBGetContactSettingByte((HANDLE)wparam,"CList","Hidden",0));
+ }
+ else HideItem(&miHFL,hmenuHide);
+
+ if(bShowAll || flags&VF_IGN)
+ {
+ ShowItem(&miIGN,hmenuIgnore);
+ for (i = 1; i < SIZEOF(ii); i++)
+ {
+ check = isIgnored((HANDLE)wparam, ii[i].type);
+ if (check)
+ all++;
+ ModifySubmenuItem(hIgnoreItem[i], ii[i].name, check, 0);
+
+ if (all == SIZEOF(ii) - 1) // ignor all
+ check = 1;
+ else
+ check = 0;
+ ModifySubmenuItem(hIgnoreItem[0], ii[i].name, check, 0);
+ }
+ }
+
+ else HideItem(&miIGN,hmenuIgnore);
+
+ if(bMir_08 && pa && (bShowAll || flags&VF_PROTO))
+ {
+ for (i = 0; i < protoCount; i++)
+ {
+ if ((!accs[i]->bIsEnabled) || (strcmp(pa->szProtoName, accs[i]->szProtoName)))
+ hide = 1;
+ else
+ {
+ hide = 0;
+ j++;
+ }
+
+ if (CallService(MS_PROTO_ISPROTOONCONTACT, wparam, (LPARAM)accs[i]->szModuleName))
+ check = 1;
+ else
+ check = 0;
+
+ ModifySubmenuItem(hProtoItem[i], accs[i]->tszAccountName, check, hide);
+ }
+ if (j > 1)
+ ShowItem(&miPROTO,hmenuProto);
+ else
+ HideItem(&miPROTO,hmenuProto);
+ }
+ else HideItem(&miPROTO,hmenuProto);
+
+ if ((bShowAll || flags & VF_ADD) && bIsOnline && (bMir_08 ? IsAccountEnabled( pa ) : TRUE))
+ ShowItem(&miADD,hmenuAdded);
+ else
+ HideItem(&miADD,hmenuAdded);
+
+ if ((bShowAll || flags & VF_REQ) && bIsOnline && (bMir_08 ? IsAccountEnabled( pa ) : TRUE))
+ ShowItem(&miREQ,hmenuAuthReq);
+ else
+ HideItem(&miREQ,hmenuAuthReq);
+
+ if(bShowAll || flags&VF_CID){
+ ShowItem(&miCID,hmenuCopyID);
+ ModifyCopyID(&miCID,(HANDLE)wparam, flags&VF_SHOWID, flags&VF_TRIMID);
+ }
+ else HideItem(&miCID,hmenuCopyID);
+
+ if ((bShowAll || flags&VF_RECV) && DirectoryExists((HANDLE)wparam)) ShowItem(&miRECV,hmenuRecvFiles);
+ else HideItem(&miRECV,hmenuRecvFiles);
+
+ if ((bShowAll || flags&VF_STAT) && StatusMsgExists((HANDLE)wparam)) {
+ ShowItem(&miSTAT,hmenuStatusMsg);
+ ModifyStatusMsg(&miSTAT,(HANDLE)wparam);
+ }
+ else HideItem(&miSTAT,hmenuStatusMsg);
+
+ if ((bShowAll || flags&VF_CIP) && IPExists((HANDLE)wparam)) {
+ ShowItem(&miCIP,hmenuCopyIP);
+ ModifyCopyIP(&miCIP,(HANDLE)wparam);
+ }
+ else HideItem(&miCIP,hmenuCopyIP);
+
+ if ((bShowAll || flags&VF_CMV) && MirVerExists((HANDLE)wparam)) {
+ ShowItem(&miCMV,hmenuCopyMirVer);
+ ModifyCopyMirVer(&miCMV,(HANDLE)wparam);
+ }
+ else HideItem(&miCMV,hmenuCopyMirVer);
+
+ if(bShowAll || (flags&VF_VS))
+ {
+ int apparent = DBGetContactSettingWord((HANDLE)wparam,(const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wparam,0),"ApparentMode",0);
+ if(isVisSupport((HANDLE)wparam)) ModifyVisibleSet(&miAV,apparent == ID_STATUS_ONLINE,flags&VF_SAI);
+ else HideItem(&miAV,hmenuVis);
+ if(isInvSupport((HANDLE)wparam)) ModifyInvisSet(&miNV,apparent == ID_STATUS_OFFLINE,flags&VF_SAI);
+ else HideItem(&miAV,hmenuOff);
+ }
+ return 0;
+}
+
+int EnumProtoSubmenu(WPARAM wparam, LPARAM lparam)
+{
+ int i;
+ int pos = 1000;
+ if (protoCount) // remove old items
+ {
+ for (i = 0; i < protoCount; i++)
+ {
+ if (hProtoItem[i])
+ {
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)hProtoItem[i], 0);
+ hProtoItem[i] = 0;
+ }
+ }
+ }
+ CallService( MS_PROTO_ENUMACCOUNTS, (WPARAM)&protoCount, (LPARAM)&accs);
+ if (protoCount > MAX_PROTOS)
+ protoCount = MAX_PROTOS;
+ for (i = 0; i < protoCount; i++)
+ {
+ hProtoItem[i] = AddSubmenuItem((HGENMENU)hmenuProto, accs[i]->tszAccountName,
+ LoadSkinnedProtoIcon(accs[i]->szModuleName, ID_STATUS_ONLINE), CMIF_KEEPUNTRANSLATED,
+ MS_PROTO, pos++, (int)accs[i]->szModuleName);
+ }
+ return 0;
+}
+
+// Tabsrmm toolbar support
+static int TabsrmmButtonPressed(WPARAM wParam, LPARAM lParam)
+{
+ CustomButtonClickData *cbcd = (CustomButtonClickData *)lParam;
+
+ if (!strcmp(cbcd->pszModule, MODULENAME) && cbcd->dwButtonId == 0)
+ onRecvFiles(wParam, 0);
+
+ return 0;
+}
+
+static int TabsrmmButtonsInit(WPARAM wParam, LPARAM lParam)
+{
+ BBButton bbd = {0};
+
+ bbd.cbSize = sizeof(BBButton);
+ bbd.pszModuleName = MODULENAME;
+ bbd.dwButtonID = 0;
+ bbd.dwDefPos = 1000;
+ bbd.ptszTooltip = _T("Browse Received Files");
+ bbd.bbbFlags = BBBF_ISLSIDEBUTTON | BBBF_CANBEHIDDEN;
+ bbd.hIcon = (HANDLE)CallService(MS_SKIN2_GETICONHANDLE, 0, (LPARAM)"miex_recfiles");
+ CallService (MS_BB_ADDBUTTON, 0, (LPARAM)&bbd);
+
+ return 0;
+}
+
+static void TabsrmmButtonsModify(HANDLE hContact)
+{
+ if (!DirectoryExists(hContact))
+ {
+ BBButton bbd = {0};
+ bbd.cbSize = sizeof(BBButton);
+ bbd.dwButtonID = 0;
+ bbd.pszModuleName = MODULENAME;
+ bbd.bbbFlags = BBSF_DISABLED | BBSF_HIDDEN;
+ CallService(MS_BB_SETBUTTONSTATE, (WPARAM)hContact, (LPARAM)&bbd);
+ }
+}
+
+static int ContactWindowOpen(WPARAM wparam,LPARAM lParam)
+{
+ MessageWindowEventData *MWeventdata = (MessageWindowEventData*)lParam;
+
+ if(MWeventdata->uType == MSG_WINDOW_EVT_OPENING && MWeventdata->hContact)
+ {
+ TabsrmmButtonsModify(MWeventdata->hContact);
+ }
+ return 0;
+}
+
+static int ContactSettingChanged( WPARAM wParam, LPARAM lParam )
+{ // NSN
+ DBCONTACTWRITESETTING *cws = ( DBCONTACTWRITESETTING* )lParam;
+ WORD newStatus = 0, oldStatus = 0;
+ DWORD dwStatuses = 0;
+ time_t tCurrentTime;
+ char *lpzProto;
+
+ if ( ( HANDLE )wParam == NULL || lstrcmpA( cws->szSetting, "Status" ))
+ return 0;
+
+ newStatus = cws->value.wVal;
+ oldStatus = DBGetContactSettingWord((HANDLE)wParam,"UserOnline","OldStatus2",ID_STATUS_OFFLINE );
+ if (oldStatus == newStatus)
+ return 0;
+
+ tCurrentTime = time( NULL );
+ lpzProto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )wParam, 0);
+
+ // ignore chat rooms
+ if (DBGetContactSettingByte((HANDLE)wParam, lpzProto, "ChatRoom", 0))
+ return 0;
+
+ if (oldStatus == ID_STATUS_OFFLINE)
+ {
+ // set online timestamp for this contact, only when not set already
+ if (!DBGetContactSettingDword( ( HANDLE )wParam, lpzProto, "LogonTS", FALSE))
+ DBWriteContactSettingDword( ( HANDLE )wParam, lpzProto, "LogonTS", ( DWORD )tCurrentTime);
+
+ // TODO: dont reset logoff timestamp?
+ DBDeleteContactSetting( ( HANDLE )wParam, lpzProto, "LogoffTS");
+
+ // TESTING: updating user's details
+ if (DBGetContactSettingDword(NULL, VISPLG, "flags", vf_default) & VF_REFRESH)
+ {
+ // don't refresh Hidden or NotOnList contact's details
+ if (!DBGetContactSettingByte((HANDLE)wParam, "CList", "Hidden", 0) && !DBGetContactSettingByte((HANDLE)wParam, "CList", "NotOnList", 0))
+ CallContactService( ( HANDLE )wParam, PSS_GETINFO, 0, 0 );
+ }
+ }
+ if (newStatus == ID_STATUS_OFFLINE)
+ {
+ // set offline timestamp for this contact
+ DBWriteContactSettingDword( ( HANDLE )wParam, lpzProto, "LogoffTS", ( DWORD )tCurrentTime);
+ // reset logon timestamp
+ DBDeleteContactSetting( ( HANDLE )wParam, lpzProto, "LogonTS");
+
+ // set last status for this contact
+ DBWriteContactSettingDword( ( HANDLE )wParam, lpzProto, "LastStatus", ( DWORD )oldStatus);
+ }
+ DBWriteContactSettingWord( ( HANDLE )wParam, "UserOnline", "OldStatus2", newStatus);
+
+ return 0;
+}
+
+// called when all modules are loaded
+static int PluginInit(WPARAM wparam,LPARAM lparam)
+{
+ int pos = 1000, i = 0;
+
+ CLISTMENUITEM mi;
+
+ IconsInit();
+
+ bMetaContacts = ServiceExists(MS_MC_GETMETACONTACT) != 0;
+ bMir_08 = ServiceExists(MS_PROTO_GETACCOUNT) != 0;
+
+ hServices[0] = CreateServiceFunction(MS_SETINVIS,onSetInvis);
+ hServices[1] = CreateServiceFunction(MS_SETVIS,onSetVis);
+ hServices[2] = CreateServiceFunction(MS_HIDE,onHide);
+ hServices[3] = CreateServiceFunction(MS_IGNORE,onIgnore);
+ if (bMir_08)
+ hServices[4] = CreateServiceFunction(MS_PROTO,onChangeProto);
+ hServices[5] = CreateServiceFunction(MS_ADDED,onSendAdded);
+ hServices[6] = CreateServiceFunction(MS_AUTHREQ,onSendAuthRequest);
+ hServices[7] = CreateServiceFunction(MS_COPYID,onCopyID);
+ hServices[8] = CreateServiceFunction(MS_RECVFILES,onRecvFiles);
+ hServices[9] = CreateServiceFunction(MS_STATUSMSG,onCopyStatusMsg);
+ hServices[10] = CreateServiceFunction(MS_COPYIP,onCopyIP);
+ hServices[11] = CreateServiceFunction(MS_COPYMIRVER,onCopyMirVer);
+
+ mi.cbSize = sizeof(CLISTMENUITEM);
+ mi.flags = CMIF_TCHAR;
+ mi.hIcon = NULL;
+ mi.pszContactOwner = NULL;
+
+ mi.position = 120000;
+ mi.ptszName = LPGENT("Always visible");
+ mi.pszService = MS_SETVIS;
+ hmenuVis = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.ptszName = LPGENT("Never visible");
+ mi.pszService = MS_SETINVIS;
+ hmenuOff = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.ptszName = NULL;
+ mi.pszService = MS_HIDE;
+ hmenuHide = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.pszPopupName = (char*)-1; // for Miranda 0.7
+ mi.ptszName = LPGENT("Ignore");
+ mi.pszService = 0;
+ mi.flags |= CMIF_ROOTHANDLE;
+ mi.hIcon = (HICON)CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_ignore" );
+ hmenuIgnore = Menu_AddContactMenuItem(&mi);
+
+ hIgnoreItem[0] = AddSubmenuItem(hmenuIgnore, ii[0].name, LoadSkinnedIcon(ii[0].icon), 0, MS_IGNORE, pos, ii[0].type );
+ pos += 100000; // insert separator
+ for (i = 1; i < SIZEOF(ii); i++)
+ hIgnoreItem[i] = AddSubmenuItem(hmenuIgnore, ii[i].name, LoadSkinnedIcon(ii[i].icon), 0, MS_IGNORE, pos++, ii[i].type );
+
+ pos += 100000; // insert separator
+ ood.cbSize = sizeof(ood);
+ ood.pszGroup = "Events";
+ ood.pszPage = "Ignore";
+ AddSubmenuItem(hmenuIgnore, LPGENT("Open ignore settings"), (HICON)CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_ignore"), 0, MS_OPT_OPENOPTIONS, pos, (int)&ood );
+
+ mi.pszPopupName = 0;
+ if (bMir_08) {
+ mi.position++;
+ mi.ptszName = LPGENT("Copy to Account");
+ mi.pszService = MS_PROTO;
+ mi.hIcon = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_protocol");
+ hmenuProto = Menu_AddContactMenuItem(&mi);
+
+ EnumProtoSubmenu(0, 0);
+ }
+
+ mi.flags = CMIF_TCHAR;
+
+ mi.position++;
+ mi.ptszName = LPGENT("Send 'You were added'");
+ mi.pszService = MS_ADDED;
+ mi.hIcon = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_added");
+ hmenuAdded = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.ptszName = LPGENT("Request authorization");
+ mi.pszService = MS_AUTHREQ;
+ mi.hIcon = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_authorization");
+ hmenuAuthReq = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.ptszName = LPGENT("Copy ID");
+ mi.pszService = MS_COPYID;
+ hmenuCopyID = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.ptszName = LPGENT("Browse Received Files");
+ mi.pszService = MS_RECVFILES;
+ mi.hIcon = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_recfiles");
+ hmenuRecvFiles = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.ptszName = LPGENT("Copy Status Message");
+ mi.pszService = MS_STATUSMSG;
+ mi.hIcon = NULL;//LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON5));
+ hmenuStatusMsg = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.ptszName = LPGENT("Copy IP");
+ mi.pszService = MS_COPYIP;
+ hmenuCopyIP = Menu_AddContactMenuItem(&mi);
+
+ mi.position++;
+ mi.ptszName = LPGENT("Copy MirVer");
+ mi.pszService = MS_COPYMIRVER;
+ hmenuCopyMirVer = Menu_AddContactMenuItem(&mi);
+
+ hIcon[0] = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_copymver");
+ hIcon[1] = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_vis");
+ hIcon[2] = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"miex_invis");
+ hIcon[3] = MakeHalfAlphaIcon(hIcon[1]);
+ hIcon[4] = MakeHalfAlphaIcon(hIcon[2]);
+
+ hHooks[0] = HookEvent(ME_CLIST_PREBUILDCONTACTMENU,BuildMenu);
+ hHooks[1] = HookEvent(ME_OPT_INITIALISE,OptionsInit);
+ hHooks[2] = HookEvent(ME_DB_CONTACT_SETTINGCHANGED,ContactSettingChanged);
+ if (bMir_08)
+ hHooks[3] = HookEvent(ME_PROTO_ACCLISTCHANGED, EnumProtoSubmenu);
+ hHooks[4] = HookEvent(ME_MSG_TOOLBARLOADED, TabsrmmButtonsInit);
+ if (hHooks[4])
+ {
+ hHooks[5] = HookEvent(ME_MSG_BUTTONPRESSED, TabsrmmButtonPressed);
+ hHooks[6] = HookEvent(ME_MSG_WINDOWEVENT,ContactWindowOpen);
+ }
+
+ return 0;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_MENUEX, MIID_LAST};
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfoEx;
+}
+
+extern "C" __declspec(dllexport) int Load(void)
+{
+
+ mir_getLP(&pluginInfoEx);
+ hHooks[7] = HookEvent(ME_SYSTEM_MODULESLOADED,PluginInit);
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Unload(void)
+{
+ int i;
+ for (i = 0; i < SIZEOF(hHooks); i++)
+ {
+ if (hHooks[i])
+ UnhookEvent(hHooks[i]);
+ }
+ for (i = 0; i < SIZEOF(hServices); i++)
+ {
+ if (hServices[i])
+ DestroyServiceFunction(hServices[i]);
+ }
+
+ DestroyIcon( hIcon[3] );
+ DestroyIcon( hIcon[4] );
+ return 0;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinst,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hinstance = hinst;
+ return 1;
+} \ No newline at end of file