#include "common.h" #include "api.h" #include "proto.h" #include "core_functions.h" HANDLE hEventDefaultChanged = 0, hEventForceSend = 0, hEventUnforceSend = 0, hSubcontactsChanged = 0; void FireSubcontactsChanged(HANDLE hMeta) { NotifyEventHooks(hSubcontactsChanged, (WPARAM)hMeta, 0); } //get the handle for a contact's parent metacontact //wParam=(HANDLE)hSubContact //lParam=0 //returns a handle to the parent metacontact, or null if this contact is not a subcontact int MetaAPI_GetMeta(WPARAM wParam, LPARAM lParam) { return (int)(HANDLE)DBGetContactSettingDword((HANDLE)wParam, MODULE, "Handle", 0); } //gets the handle for the default contact //wParam=(HANDLE)hMetaContact //lParam=0 //returns a handle to the default contact, or null on failure int MetaAPI_GetDefault(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam; if(metaMap.exists(hMeta) == false || metaMap[hMeta].size() == 0) return 0; int def = DBGetContactSettingByte(hMeta, MODULE, "Default", -1); if(def < 0 || def >= metaMap[hMeta].size()) return 0; return (int)metaMap[hMeta][def].handle(); } //gets the contact number for the default contact //wParam=(HANDLE)hMetaContact //lParam=0 //returns an int contact number, or -1 on failure int MetaAPI_GetDefaultNum(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam; if(metaMap.exists(hMeta) == false || metaMap[hMeta].size() == 0) return -1; int def = DBGetContactSettingByte(hMeta, MODULE, "Default", -1); if(def < 0 || def >= metaMap[hMeta].size()) return -1; return def; } //gets the handle for the 'most online' contact //wParam=(HANDLE)hMetaContact //lParam=0 //returns a handle to the 'most online' contact int MetaAPI_GetMostOnline(WPARAM wParam, LPARAM lParam) { return (int)Meta_GetMostOnline((HANDLE)wParam); } //gets the number of subcontacts for a metacontact //wParam=(HANDLE)hMetaContact //lParam=0 //returns an int representing the number of subcontacts for the given metacontact, or -1 on failure int MetaAPI_GetNumContacts(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam; if(metaMap.exists(hMeta)) return metaMap[hMeta].size(); return -1; } //gets the handle of a subcontact, using the subcontact's number //wParam=(HANDLE)hMetaContact //lParam=(int)contact number //returns a handle to the specified subcontact int MetaAPI_GetContact(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam; if(metaMap.exists(hMeta) && lParam >= 0 && metaMap[hMeta].size() > lParam) return (int)metaMap[hMeta][lParam].handle(); return 0; } //sets the default contact, using the subcontact's contact number //wParam=(HANDLE)hMetaContact //lParam=(int)contact number //returns 0 on success int MetaAPI_SetDefaultContactNum(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam; DWORD num_contacts = metaMap.exists(hMeta) ? metaMap[hMeta].size() : -1; if(num_contacts < 0) return 1; if((DWORD)lParam >= num_contacts || (DWORD)lParam < 0) return 1; if(DBWriteContactSettingByte((HANDLE)wParam, MODULE, "Default", (DWORD)lParam)) return 1; NotifyEventHooks(hEventDefaultChanged, wParam, (LPARAM)metaMap[hMeta][(int)lParam].handle()); return 0; } //sets the default contact, using the subcontact's handle //wParam=(HANDLE)hMetaContact //lParam=(HANDLE)hSubcontact //returns 0 on success int MetaAPI_SetDefaultContact(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam, hSub = (HANDLE)lParam; HANDLE hMetaFromSub = (HANDLE)DBGetContactSettingDword(hSub, MODULE, "Handle", 0); if(hMetaFromSub != hMeta || metaMap.exists(hMeta) == false) return 1; int contact_num = metaMap[hMeta].index_of(hSub); if(contact_num == -1) return 1; if(DBWriteContactSettingByte(hMeta, MODULE, "Default", contact_num)) return 1; NotifyEventHooks(hEventDefaultChanged, wParam, lParam); return 0; } //temporarily forces the metacontact to send using a specific subcontact, using the subcontact's contact number //wParam=(HANDLE)hMetaContact //lParam=(int)contact number //returns 0 on success int MetaAPI_ForceSendContactNum(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam; int contact_num = (int)lParam; if(!hMeta || metaMap.exists(hMeta) == false || contact_num < 0 || contact_num >= metaMap[hMeta].size() || DBGetContactSettingByte(hMeta, MODULE, "ForceDefault", 0)) return 1; HANDLE hSub = metaMap[hMeta][contact_num].handle(); HANDLE hMetaFromSub = (HANDLE)DBGetContactSettingDword(hSub, MODULE, "Handle", 0); if(hMetaFromSub != hMeta) return 1; DBWriteContactSettingDword(hMeta, MODULE, "ForceSend", (DWORD)hSub); NotifyEventHooks(hEventForceSend, wParam, (LPARAM)hSub); return 0; } //temporarily forces the metacontact to send using a specific subcontact, using the subcontact's handle //wParam=(HANDLE)hMetaContact //lParam=(HANDLE)hSubcontact //returns 0 on success (will fail if 'force default' is in effect) int MetaAPI_ForceSendContact(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam, hSub = (HANDLE)lParam; HANDLE hMetaFromSub = (HANDLE)DBGetContactSettingDword(hSub, MODULE, "Handle", 0); if(!hSub || !hMeta || hMetaFromSub != hMeta || !metaMap.exists(hMeta) || metaMap[hMeta].index_of(hSub) == -1 || DBGetContactSettingByte(hMeta, MODULE, "ForceDefault", 0)) return 1; DBWriteContactSettingDword(hMeta, MODULE, "ForceSend", (DWORD)hSub); NotifyEventHooks(hEventForceSend, wParam, lParam); return 0; } //'unforces' the metacontact to send using a specific subcontact //wParam=(HANDLE)hMetaContact //lParam=0 //returns 0 on success (will fail if 'force default' is in effect) int MetaAPI_UnforceSendContact(WPARAM wParam, LPARAM lParam) { if(DBGetContactSettingByte((HANDLE)wParam, MODULE, "ForceDefault", 0) == 0) return 1; DBWriteContactSettingDword((HANDLE)wParam, MODULE, "ForceSend", 0); NotifyEventHooks(hEventUnforceSend, wParam, lParam); return 0; } //'forces' or 'unforces' (i.e. toggles) the metacontact to send using it's default contact // overrides 'force send' above, and will even force use of offline contacts // will send ME_MC_FORCESEND event //wParam=(HANDLE)hMetaContact //lParam=0 //returns 1(true) or 0(false) representing new state of 'force default' int MetaAPI_ForceDefault(WPARAM wParam, LPARAM lParam) { int old_state = DBGetContactSettingByte((HANDLE)wParam, MODULE, "ForceDefault", 0); DBWriteContactSettingByte((HANDLE)wParam, MODULE, "ForceDefault", old_state ? 0 : 1); return old_state ? 0 : 1; } // method to get state of 'force' for a metacontact // wParam=(HANDLE)hMetaContact // lParam= (int)&contact_number or NULL // if lparam supplied, the contact_number of the contatct 'in force' will be copied to the address it points to, // or if none is in force, the value (DWORD)-1 will be copied // (v0.8.0.8+ returns 1 if 'force default' is true with *lParam == default contact number, else returns 0 with *lParam as above) int MetaAPI_GetForceState(WPARAM wParam, LPARAM lParam) { HANDLE hMeta = (HANDLE)wParam; HANDLE hContact; if(!hMeta || !metaMap.exists(hMeta)) return 0; if(DBGetContactSettingByte(hMeta, MODULE, "ForceDefault", 0)) { if(lParam) *(DWORD *)lParam = DBGetContactSettingByte((HANDLE)wParam, MODULE, "Default", -1); return 1; } hContact = (HANDLE)DBGetContactSettingDword(hMeta, MODULE, "ForceSend", 0); if(!hContact) { if(lParam) *(DWORD *)lParam = -1; } else { if(lParam) *(DWORD *)lParam = (DWORD)metaMap[hMeta].index_of(hContact); } return 0; } // method to get protocol name - used to be sure you're dealing with a "real" metacontacts plugin :) // wParam=lParam=0 int MetaAPI_GetProtoName(WPARAM wParam, LPARAM lParam) { return (int)MODULE; } // added 0.9.5.0 (22/3/05) // wParam=(HANDLE)hContact // lParam=0 // convert a given contact into a metacontact int MetaAPI_ConvertToMeta(WPARAM wParam, LPARAM lParam) { return (int)Meta_Convert((HANDLE)wParam); } // added 0.9.5.0 (22/3/05) // wParam=(HANDLE)hContact // lParam=(HANDLE)hMeta // add an existing contact to a metacontact int MetaAPI_AddToMeta(WPARAM wParam, LPARAM lParam) { Meta_Assign((HANDLE)wParam, (HANDLE)lParam); return 0; } // added 0.9.5.0 (22/3/05) // wParam=0 // lParam=(HANDLE)hContact // remove a contact from a metacontact int MetaAPI_RemoveFromMeta(WPARAM wParam, LPARAM lParam) { Meta_Remove((HANDLE)lParam); return 0; } // added 0.9.13.2 (6/10/05) // wParam=(BOOL)disable // lParam=0 // enable/disable the 'hidden group hack' - for clists that support subcontact hiding using 'IsSubcontact' setting // should be called once in your 'onmodulesloaded' event handler bool meta_group_hack_disabled = false; int MetaAPI_DisableHiddenGroup(WPARAM wParam, LPARAM lParam) { meta_group_hack_disabled = (BOOL)wParam; return 0; } int ModulesLoadedAPI(WPARAM wParam, LPARAM lParam) { HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0); char *proto; HANDLE hMeta; while(hContact != NULL) { DWORD id = DBGetContactSettingDword(hContact, MODULE, "ParentMetaID", (DWORD)-1); if(id != (DWORD)-1) { hMeta = GetMetaHandle(id); if(hMeta) { if(id >= next_meta_id) next_meta_id = id + 1; metaMap[hMeta].add(hContact); DBWriteContactSettingDword(hContact, MODULE, "Handle", (DWORD)hMeta); DBWriteContactSettingByte(hContact, MODULE, "IsSubcontact", 1); } else DBDeleteContactSetting(hContact, MODULE, "ParentMetaID"); } else if(IsMetacontact(hContact)) { meta_count++; DBWriteContactSettingWord(hContact, MODULE, "Status", ID_STATUS_OFFLINE); } hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); } return 0; } #define NUM_API_SERVICES 17 HANDLE hServicesAPI[NUM_API_SERVICES] = {0}; HANDLE hEventModulesLoadedAPI = 0; void InitAPI() { int i = 0; hServicesAPI[i++] = CreateServiceFunction(MS_MC_GETMETACONTACT, MetaAPI_GetMeta); hServicesAPI[i++] = CreateServiceFunction(MS_MC_GETDEFAULTCONTACT, MetaAPI_GetDefault); hServicesAPI[i++] = CreateServiceFunction(MS_MC_GETDEFAULTCONTACTNUM, MetaAPI_GetDefaultNum); hServicesAPI[i++] = CreateServiceFunction(MS_MC_GETMOSTONLINECONTACT, MetaAPI_GetMostOnline); hServicesAPI[i++] = CreateServiceFunction(MS_MC_GETNUMCONTACTS, MetaAPI_GetNumContacts); hServicesAPI[i++] = CreateServiceFunction(MS_MC_GETSUBCONTACT, MetaAPI_GetContact); hServicesAPI[i++] = CreateServiceFunction(MS_MC_SETDEFAULTCONTACTNUM, MetaAPI_SetDefaultContactNum); hServicesAPI[i++] = CreateServiceFunction(MS_MC_SETDEFAULTCONTACT, MetaAPI_SetDefaultContact); hServicesAPI[i++] = CreateServiceFunction(MS_MC_FORCESENDCONTACTNUM, MetaAPI_ForceSendContactNum); hServicesAPI[i++] = CreateServiceFunction(MS_MC_FORCESENDCONTACT, MetaAPI_ForceSendContact); hServicesAPI[i++] = CreateServiceFunction(MS_MC_UNFORCESENDCONTACT, MetaAPI_UnforceSendContact); hServicesAPI[i++] = CreateServiceFunction(MS_MC_GETPROTOCOLNAME, MetaAPI_GetProtoName); hServicesAPI[i++] = CreateServiceFunction(MS_MC_GETFORCESTATE, MetaAPI_GetForceState); hServicesAPI[i++] = CreateServiceFunction(MS_MC_CONVERTTOMETA, MetaAPI_ConvertToMeta); hServicesAPI[i++] = CreateServiceFunction(MS_MC_ADDTOMETA, MetaAPI_AddToMeta); hServicesAPI[i++] = CreateServiceFunction(MS_MC_REMOVEFROMMETA, MetaAPI_RemoveFromMeta); hServicesAPI[i++] = CreateServiceFunction(MS_MC_DISABLEHIDDENGROUP, MetaAPI_DisableHiddenGroup); hEventDefaultChanged = CreateHookableEvent(ME_MC_DEFAULTTCHANGED); hEventForceSend = CreateHookableEvent(ME_MC_FORCESEND); hEventUnforceSend = CreateHookableEvent(ME_MC_UNFORCESEND); hSubcontactsChanged = CreateHookableEvent(ME_MC_SUBCONTACTSCHANGED); //hEventModulesLoadedAPI = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoadedAPI); ModulesLoadedAPI(0, 0); } void DeinitAPI() { if(hEventModulesLoadedAPI) UnhookEvent(hEventModulesLoadedAPI); DestroyHookableEvent(hSubcontactsChanged); DestroyHookableEvent(hEventUnforceSend); DestroyHookableEvent(hEventForceSend); DestroyHookableEvent(hEventDefaultChanged); for(int i = 0; i < NUM_API_SERVICES; i++) DestroyServiceFunction(hServicesAPI[i]); }