diff options
44 files changed, 4539 insertions, 0 deletions
diff --git a/meta2/api.cpp b/meta2/api.cpp new file mode 100644 index 0000000..03e3c71 --- /dev/null +++ b/meta2/api.cpp @@ -0,0 +1,317 @@ +#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]);
+}
\ No newline at end of file diff --git a/meta2/api.h b/meta2/api.h new file mode 100644 index 0000000..e1aa8f5 --- /dev/null +++ b/meta2/api.h @@ -0,0 +1,28 @@ +#include <m_metacontacts.h>
+
+int MetaAPI_GetMeta(WPARAM wParam, LPARAM lParam);
+int MetaAPI_GetDefault(WPARAM wParam, LPARAM lParam);
+int MetaAPI_GetDefaultNum(WPARAM wParam, LPARAM lParam);
+int MetaAPI_GetMostOnline(WPARAM wParam, LPARAM lParam);
+int MetaAPI_GetNumContacts(WPARAM wParam, LPARAM lParam);
+int MetaAPI_GetContact(WPARAM wParam, LPARAM lParam);
+int MetaAPI_SetDefaultContactNum(WPARAM wParam, LPARAM lParam);
+int MetaAPI_SetDefaultContact(WPARAM wParam, LPARAM lParam);
+int MetaAPI_ForceSendContactNum(WPARAM wParam, LPARAM lParam);
+int MetaAPI_ForceSendContact(WPARAM wParam, LPARAM lParam);
+int MetaAPI_UnforceSendContact(WPARAM wParam, LPARAM lParam);
+int MetaAPI_ForceDefault(WPARAM wParam, LPARAM lParam);
+int MetaAPI_GetForceState(WPARAM wParam, LPARAM lParam);
+int MetaAPI_GetProtoName(WPARAM wParam, LPARAM lParam);
+int MetaAPI_ConvertToMeta(WPARAM wParam, LPARAM lParam);
+int MetaAPI_AddToMeta(WPARAM wParam, LPARAM lParam);
+int MetaAPI_RemoveFromMeta(WPARAM wParam, LPARAM lParam);
+int MetaAPI_DisableHiddenGroup(WPARAM wParam, LPARAM lParam);
+
+
+void FireSubcontactsChanged(HANDLE hMeta);
+
+extern bool meta_group_hack_disabled;
+void InitAPI();
+void DeinitAPI();
+
diff --git a/meta2/collection.h b/meta2/collection.h new file mode 100644 index 0000000..725bb1d --- /dev/null +++ b/meta2/collection.h @@ -0,0 +1,588 @@ +#include <malloc.h>
+
+template<class T> class Collection {
+protected:
+ unsigned long count;
+public:
+ Collection(): count(0) {}
+
+ virtual void clear() = 0;
+ virtual void add(T &val) = 0;
+ virtual const bool remove(T &val) = 0;
+
+ const unsigned long size() const {return count;}
+};
+
+template<class T> class Node {
+public:
+ T val;
+
+ Node(T &v): val(v) {}
+ virtual ~Node() {}
+};
+
+template<class T> class ListNode: public Node<T> {
+public:
+ ListNode<T> *next, *prev;
+
+ ListNode(T &v): Node<T>(v), next(0), prev(0) {}
+ virtual ~ListNode() {
+ if(next) next->prev = prev;
+ if(prev) prev->next = next;
+ }
+};
+
+template<class T> class LinkedList: public Collection<T> {
+protected:
+ ListNode<T> *head, *tail;
+
+public:
+ class Iterator {
+ friend class LinkedList<T>;
+ protected:
+ ListNode<T> *n;
+ Iterator(ListNode<T> *start): n(start) {}
+ public:
+ Iterator(const Iterator &other): n(other.n) {}
+
+ virtual T &val() {return n->val;}
+ virtual void next() {if(n) n = n->next;}
+ virtual void prev() {if(n) n = n->prev;}
+ virtual const bool has_val() {return (n ? true : false); }
+ };
+
+ LinkedList(): Collection<T>(), head(0), tail(0) {};
+ LinkedList(const LinkedList<T> &other): Collection<T>(), head(0), tail(0) {
+ for(Iterator i = other.start(); i.has_val(); i.next())
+ add(i.val());
+ }
+ virtual ~LinkedList() {clear();}
+
+ LinkedList<T> &operator=(const LinkedList<T> &other) {
+ clear();
+ for(Iterator i = other.start(); i.has_val(); i.next())
+ add(i.val());
+ return *this;
+ }
+
+ virtual void clear() {
+ ListNode<T> *n;
+ while(head) {
+ n = head;
+ head = head->next;
+ delete n;
+ }
+ tail = 0;
+ Collection<T>::count = 0;
+ }
+
+ virtual Iterator start() const {return Iterator(head);}
+
+ virtual void add_front(T &val) {
+ ListNode<T> *n = new ListNode<T>(val);
+ n->next = head;
+ if(head) head->prev = n;
+ head = n;
+ if(!tail) tail = n;
+ Collection<T>::count++;
+ }
+
+ virtual void add(T &val) {
+ ListNode<T> *n = new ListNode<T>(val);
+ n->prev = tail;
+ if(tail) tail->next = n;
+ tail = n;
+ if(!head) head = n;
+ Collection<T>::count++;
+ }
+
+ virtual const bool remove(T &val) {
+ ListNode<T> *n = head;
+ while(n) {
+ if(n->val == val) {
+ if(n == head) head = head->next;
+ if(n == tail) tail = tail->prev;
+
+ delete n;
+ Collection<T>::count--;
+ return true;
+ } else
+ n = n->next;
+ }
+
+ return false;
+ }
+
+ virtual const bool contains(T &val) const {
+ ListNode<T> *n = head;
+ while(n) {
+ if(n->val == val) {
+ return true;
+ } else
+ n = n->next;
+ }
+
+ return false;
+ }
+
+ // queue/stack functions
+ // stack - use push/pop
+ // queue - use push_back/pop
+ virtual void push(T val) {
+ add_front(val);
+ }
+
+ virtual void push_back(T &val) {
+ add(val);
+ }
+
+ virtual const bool pop(T &val) {
+ if(!head) return false;
+
+ ListNode<T> *n = head;
+ if(head) {
+ head = head->next;
+ if(n == tail) tail = 0;
+ val = n->val;
+ delete n;
+ Collection<T>::count--;
+ return true;
+ } else
+ return false;
+ }
+};
+
+template<class T> class DynamicArray: public Collection<T> {
+protected:
+ T *ar;
+
+ unsigned long initial, limit, increment;
+
+public:
+ class Iterator {
+ friend class DynamicArray<T>;
+ protected:
+ T *ar;
+ unsigned long count;
+ unsigned long pos;
+ Iterator(T *a, const int c, unsigned long p): ar(a), count(c), pos(p) {}
+ public:
+ Iterator(const Iterator &other): ar(other.ar), count(other.count), pos(other.pos) {}
+
+ virtual T &val() {return ar[pos];}
+ virtual void next() {pos++;}
+ virtual void prev() {pos--;}
+ virtual const bool has_val() {return pos < count; }
+ };
+
+ DynamicArray(unsigned long init = 0, unsigned long inc = 1): Collection<T>(), ar(0), initial(init), limit(init), increment(inc) {
+ if(limit) ar = (T *)malloc(limit * sizeof(T));
+ }
+ virtual ~DynamicArray() {if(ar) free(ar);}
+
+ virtual void clear() {
+ Collection<T>::count = 0;
+ limit = initial;
+ if(limit) ar = (T *)realloc(ar, limit * sizeof(T));
+ else {
+ free(ar);
+ ar = 0;
+ }
+ }
+
+ virtual Iterator start() const {return Iterator(ar, Collection<T>::count, 0);}
+
+ virtual void add(T &val) {
+ if(Collection<T>::count == limit) {
+ limit += increment;
+ ar = (T *)realloc(ar, limit * sizeof(T));
+ ar[Collection<T>::count++] = val;
+ } else
+ ar[Collection<T>::count++] = val;
+ }
+
+ virtual void add_all(DynamicArray<T> &other) {
+ for(DynamicArray<T>::Iterator i = other.start(); i.has_val(); i.next()) {
+ add(i.val());
+ }
+ }
+
+ virtual const bool remove(T &val) {
+ for(unsigned long i = 0; i < Collection<T>::count; i++) {
+ if(ar[i] == val) {
+ memmove(ar + i, ar + i + 1, (Collection<T>::count - i) * sizeof(T));
+ Collection<T>::count--;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual const bool remove(const unsigned long index) {
+ if(index >= Collection<T>::count) return false;
+
+ memmove(ar + index, ar + index + 1, (Collection<T>::count - index) * sizeof(T));
+ Collection<T>::count--;
+ return true;
+ }
+
+ virtual const bool insert(T &val, const unsigned long index) {
+ if(index > Collection<T>::count) return false;
+
+ if(Collection<T>::count == limit) {
+ limit += increment;
+ ar = (T *)realloc(ar, limit * sizeof(T));
+ }
+
+ if(index < Collection<T>::count)
+ memmove(ar + index + 1, ar + index, (Collection<T>::count - index) * sizeof(T));
+
+ ar[index] = val;
+ Collection<T>::count++;
+ return true;
+ }
+
+ virtual T &operator[](const int index) {
+ return ar[index];
+ }
+
+ const bool index_of(const T &val, unsigned long &index) const {
+ for(int i = 0; i < Collection<T>::count; i++) {
+ if(ar[index] == val) {
+ index = i;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ const int index_of(const T &val) const {
+ for(int i = 0; i < Collection<T>::count; i++) {
+ if(ar[i] == val) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // stack functions
+ virtual const bool pop(T &val) {
+ if(Collection<T>::count) {
+ val = ar[Collection<T>::count -1];
+ remove(Collection<T>::count -1);
+ return true;
+ }
+ return false;
+ }
+
+ virtual void push(T &val) {
+ add(val);
+ }
+};
+
+template<class T> class SortedDynamicArray: public DynamicArray<T> {
+public:
+ SortedDynamicArray(unsigned long init = 0, unsigned long inc = 1): DynamicArray<T>(init, inc) {}
+ virtual ~SortedDynamicArray() {}
+
+ const bool get_index(T &val, unsigned long &index) {
+ unsigned long low = 0;
+ unsigned long high = Collection<T>::count-1;
+
+ while( high < Collection<T>::count && low <= high )
+ {
+ unsigned long i = ( low+high )/2;
+ if ( DynamicArray<T>::ar[i] == val )
+ { index = i;
+ return true;
+ } else
+ if (DynamicArray<T>::ar[i] < val)
+ low = i+1;
+ else
+ high = i-1;
+ }
+
+ index = low;
+ return false;
+ }
+
+ virtual void add(T &val) {
+ unsigned long index;
+ get_index(val, index);
+ insert(val, index);
+ }
+};
+
+template<class T> class TreeNode: public Node<T> {
+public:
+ TreeNode<T> *parent, *left, *right;
+
+ TreeNode(T &v, TreeNode<T> *par): Node<T>(v), parent(par), left(0), right(0) {}
+ virtual ~TreeNode() {
+ if(parent) {
+ if(parent->left == this) parent->left = 0;
+ else parent->right = 0;
+ }
+ }
+};
+
+template<class T> class BinaryTree: public Collection<T> {
+protected:
+
+ TreeNode<T> *root;
+
+ TreeNode<T> *delete_node(TreeNode<T> *n) {
+ if(n->left && n->right) {
+ //if(rand() & 1) { // ?
+ TreeNode<T> *minmax = n->left;
+ while(minmax->right) minmax = minmax->right;
+ //} else {
+ // Node *minmax = current->right;
+ // while(minmax->left) minmax = minmax->left;
+ //}
+ n->val = minmax->val;
+ delete_node(minmax);
+ Collection<T>::count--;
+ return n;
+ } else if(n->right) {
+ if(n->parent) {
+ if(n->parent->left = n) n->parent->left = n->right;
+ else n->parent->right = n->right;
+ } else
+ root = n->right;
+ n->right->parent = n->parent;
+ } else if(n->left) {
+ if(n->parent) {
+ if(n->parent->left = n) n->parent->left = n->left;
+ else n->parent->right = n->left;
+ } else
+ root = n->left;
+ n->left->parent = n->parent;
+ } else {
+ if(n == root) root = 0;
+ }
+ delete n;
+ Collection<T>::count--;
+ return 0;
+ }
+
+ void insert_node(TreeNode<T> *n) {
+ TreeNode<T> *current = root, *parent = 0;
+ while(current) {
+ parent = current;
+ if(n->val < current->val)
+ current = current->left;
+ else
+ current = current->right;
+ }
+
+ if(parent) {
+ if(n->val < parent->val) {
+ parent->left = n;
+ n->parent = parent;
+ } else {
+ parent->right = n;
+ n->parent = parent;
+ }
+ } else
+ root = n;
+
+ }
+
+public:
+ class Iterator {
+ friend class BinaryTree<T>;
+ protected:
+
+ class EvalNode {
+ public:
+ bool evaluate;
+ TreeNode<T> *node;
+
+ EvalNode(): evaluate(false), node(0) {}
+ EvalNode(const bool eval, TreeNode<T> *n): evaluate(eval), node(n) {}
+ const bool operator==(const EvalNode &other) const {return node == other.node;}
+ EvalNode &operator=(const EvalNode &other) {evaluate = other.evaluate; node = other.node; return *this;}
+
+ };
+
+ TreeNode<T> *n;
+ LinkedList<EvalNode> stack;
+
+
+ Iterator(TreeNode<T> *start): n(0) {
+ if(start) {
+ stack.push(EvalNode(true, start));
+ next();
+ }
+ }
+
+ public:
+ Iterator(const Iterator &other):n(other.n), stack(other.stack) {}
+ virtual ~Iterator() {}
+
+ virtual T &val() {return n->val;}
+ virtual void next() {
+ EvalNode en;
+ bool popped = false;
+ while((popped = stack.pop(en)) && en.evaluate) {
+ if(en.node->right) stack.push(EvalNode(true, en.node->right));
+ stack.push(EvalNode(false, en.node));
+ if(en.node->left) stack.push(EvalNode(true, en.node->left));
+ }
+
+ n = (popped ? en.node : 0);
+ }
+ virtual const bool has_val() {return (n ? true : false);}
+ };
+
+ BinaryTree(): Collection<T>(), root(0) {};
+ BinaryTree(BinaryTree<T> &other): Collection<T>(), root(0) {
+ for(Iterator i = other.start(); i.has_val(); i.next())
+ add(i.val());
+ }
+ virtual ~BinaryTree() {clear();}
+
+ BinaryTree &operator=(BinaryTree<T> &other) {
+ clear();
+ for(Iterator i = other.start(); i.has_val(); i.next())
+ add(i.val());
+ return *this;
+ }
+
+ virtual void clear() {
+ TreeNode<T> *current = root, *parent = 0;
+ while(current) {
+ if(current->left) current = current->left;
+ else if(current->right) current = current->right;
+ else {
+ parent = current->parent;
+ delete current;
+ current = parent;
+ }
+ }
+
+ root = 0;
+ Collection<T>::count = 0;
+ }
+
+ void add(T &val) {
+ TreeNode<T> *n = new TreeNode<T>(val, 0);
+ insert_node(n);
+ Collection<T>::count++;
+ }
+
+ const bool remove(T &val) {
+ TreeNode<T> *current = root;
+ while(current) {
+ if(current->val == val)
+ break;
+ else if(val < current->val)
+ current = current->left;
+ else
+ current = current->right;
+ }
+
+ if(current) {
+ delete_node(current);
+ return true;
+ }
+
+ return false;
+ }
+
+ const bool contains(T &val) const {
+ TreeNode<T> *current = root;
+ while(current) {
+ if(current->val == val)
+ break;
+ else if(val < current->val)
+ current = current->left;
+ else
+ current = current->right;
+ }
+
+ return current != 0;
+ }
+
+ Iterator start() const {return Iterator(root);}
+};
+
+template<class A, class B> class Pair {
+public:
+ A first;
+ B second;
+
+ Pair(const A &f): first(f) {}
+ Pair(const A &f, const B &s): first(f), second(s) {}
+ Pair(Pair<A,B> &other): first(other.first), second(other.second) {}
+ virtual ~Pair() {}
+
+ const bool operator<(const Pair<A,B> &other) const {return first < other.first;}
+ const bool operator==(const Pair<A,B> &other) const {return first == other.first;}
+ Pair<A,B> &operator=(const Pair<A,B> &other) {first = other.first; second = other.second; return *this;}
+};
+
+template<class A, class B> class Map: public BinaryTree< Pair< A, B > > {
+protected:
+
+ TreeNode<Pair< A, B > > *find(A &val) const {
+ TreeNode<Pair< A, B > > *n = BinaryTree< Pair< A, B > >::root;
+ while(n) {
+ if(n->val.first == val)
+ return n;
+ else if(val < n->val.first)
+ n = n->left;
+ else
+ n = n->right;
+
+ }
+ return 0;
+ }
+public:
+ Map(): BinaryTree< Pair<A,B> >() {}
+ virtual ~Map() {}
+
+ void put(A &key, B &value) {
+ add(Pair<A,B>(key, value));
+ }
+
+ const bool get(A &key, B &val) const {
+ const TreeNode<Pair< A, B > > *n = find(key);
+ if(n) {
+ val = n->val.second;
+ return true;
+ } else
+ return false;
+ }
+
+ B &operator[](A &key) {
+ TreeNode<Pair< A, B > > *n = find(key);
+ if(n)
+ return n->val.second;
+ else {
+ Pair< A, B > p(key);
+ TreeNode<Pair< A, B > > *n = new TreeNode<Pair< A, B > >(p, 0);
+ insert_node(n);
+ Collection< Pair< A, B > >::count++;
+ return n->val.second;
+ }
+ }
+
+ virtual const bool exists(A &key) const {
+ const TreeNode<Pair< A, B > > *n = find(key);
+ if(n) {
+ return true;
+ } else
+ return false;
+ }
+
+ virtual const bool remove(A &key) {
+ TreeNode<Pair< A, B > > *n = find(key);
+ if(n) {
+ delete_node(n);
+ return true;
+ } else
+ return false;
+ }
+};
diff --git a/meta2/common.cpp b/meta2/common.cpp new file mode 100644 index 0000000..fe22092 --- /dev/null +++ b/meta2/common.cpp @@ -0,0 +1,11 @@ +#include "common.h"
+
+bool ContactHandle::operator==(const ContactHandle &other) const {
+ return hContact == other.handle();
+}
+
+bool ContactHandle::operator<(const ContactHandle &other) const {
+ //return CallService(MS_CLIST_CONTACTSCOMPARE, (WPARAM)hContact, (LPARAM)other.handle()) < 0;
+ return hContact < other.handle();
+}
+
diff --git a/meta2/common.h b/meta2/common.h new file mode 100644 index 0000000..c613ef5 --- /dev/null +++ b/meta2/common.h @@ -0,0 +1,134 @@ +#ifndef _COMMON_INC
+#define _COMMON_INC
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Allow use of features specific to Windows XP or later.
+#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+#endif
+
+#if defined( UNICODE ) && !defined( _UNICODE )
+#define _UNICODE
+#endif
+
+#include <tchar.h>
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+#include <windows.h>
+#include <commctrl.h>
+
+#define MIRANDA_VER 0x0700
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_options.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_clist.h>
+#include <m_clc.h>
+#include <m_clui.h>
+#include <m_message.h>
+#include <m_icolib.h>
+#include <m_skin.h>
+#include <m_utils.h>
+
+#include <m_metacontacts.h>
+#include <m_yapp.h>
+
+#include "collection.h"
+
+////////////
+// included for backward compatibility
+#ifndef CMIF_UNICODE
+#define CMIF_UNICODE 512 //will return TCHAR* instead of char*
+#if defined( _UNICODE )
+ #define CMIF_TCHAR CMIF_UNICODE //will return TCHAR* instead of char*
+#else
+ #define CMIF_TCHAR 0 //will return char*, as usual
+#endif
+#endif
+////////////
+
+#define MODULE "meta2"
+
+extern HINSTANCE hInst;
+extern PLUGINLINK *pluginLink;
+extern MM_INTERFACE mmi;
+extern UTF8_INTERFACE utfi;
+extern HANDLE metaMainThread;
+extern DWORD next_meta_id;
+
+extern int meta_count;
+
+#ifndef MIID_META2
+#define MIID_META2 { 0x4415A85D, 0xD6DA, 0x4551, { 0xB2, 0xB8, 0x9B, 0xDD, 0x82, 0xE2, 0x4B, 0x50 } }
+#endif
+
+#define MAX_SUBCONTACTS 20
+
+inline bool MetaEnabled() {
+ return DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 1;
+}
+
+inline bool IsMetacontact(HANDLE hContact) {
+ return DBGetContactSettingDword(hContact, MODULE, "MetaID", (DWORD)-1) != (DWORD)-1;
+}
+
+inline bool IsSubcontact(HANDLE hContact) {
+ return DBGetContactSettingByte(hContact, MODULE, "IsSubcontact", 0) == 1;
+}
+
+inline char *ContactProto(HANDLE hContact) {
+ return (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+}
+
+inline WORD ContactStatus(HANDLE hContact, char *proto) {
+ if(!proto) return ID_STATUS_OFFLINE;
+ return DBGetContactSettingWord(hContact, proto, "Status", ID_STATUS_OFFLINE);
+}
+
+class ContactHandle {
+public:
+ ContactHandle(const HANDLE &hCon): hContact(hCon) {}
+ virtual ~ContactHandle() {}
+
+ HANDLE handle() const {return hContact;}
+ //operator HANDLE () const {return hContact;}
+
+ bool operator==(const ContactHandle &other) const;
+ bool operator<(const ContactHandle &other) const;
+ const ContactHandle &operator=(HANDLE h) {hContact = h;}
+protected:
+ HANDLE hContact;
+};
+
+class SubcontactList: public SortedDynamicArray<ContactHandle> {
+public:
+
+ void add(HANDLE h) {
+ SortedDynamicArray<ContactHandle>::add(ContactHandle(h));
+ }
+
+ void remove(HANDLE h) {
+ SortedDynamicArray<ContactHandle>::remove(ContactHandle(h));
+ }
+
+};
+
+
+#endif
diff --git a/meta2/core_functions.cpp b/meta2/core_functions.cpp new file mode 100644 index 0000000..aba22c0 --- /dev/null +++ b/meta2/core_functions.cpp @@ -0,0 +1,138 @@ +#include "common.h"
+#include "core_functions.h"
+#include "proto.h"
+#include "api.h"
+#include "priorities.h"
+
+MetaMap metaMap;
+
+HANDLE GetMetaHandle(DWORD id) {
+ HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0);
+ char *proto;
+ while(hContact) {
+ proto = ContactProto(hContact);
+ if(proto && !strcmp(proto, MODULE)) {
+ DWORD mid = DBGetContactSettingDword(hContact, MODULE, META_ID, (DWORD)-1);
+ if(mid == id) return hContact;
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ return 0;
+}
+
+void Meta_Hide(bool hide) {
+ HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0);
+ char *proto;
+ HANDLE hMeta;
+ while(hContact != NULL) {
+ if(IsMetacontact(hContact)) {
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", hide ? 1 : 0);
+ } else if(IsSubcontact(hContact) && !meta_group_hack_disabled) {
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", hide ? 0 : 1);
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+}
+
+HANDLE Meta_GetMostOnline(HANDLE hMeta) {
+ return Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_1, PF1_IM);
+}
+
+HANDLE Meta_GetMostOnlineSupporting(HANDLE hMeta, int flag, int cap) {
+ if(!metaMap.exists(hMeta)) return 0;
+
+ HANDLE most_online = (HANDLE)MetaAPI_GetDefault((WPARAM)hMeta, 0);
+ char *most_online_proto = ContactProto(most_online);
+ int most_online_status = ContactStatus(most_online, most_online_proto);
+ int most_online_prio = GetRealPriority(most_online_proto, most_online_status);
+
+ char *proto;
+ int status, prio;
+ SubcontactList::Iterator i = metaMap[hMeta].start();
+ while(i.has_val()) {
+ proto = ContactProto(i.val().handle());
+ if(proto && (CallContactService(i.val().handle(), PS_GETCAPS, flag, 0) & cap)) {
+ status = ContactStatus(i.val().handle(), proto);
+ if((prio = GetRealPriority(proto, status)) < most_online_prio) {
+ most_online_status = status;
+ most_online = i.val().handle();
+ most_online_proto = proto;
+ most_online_prio = prio;
+ }
+ }
+ i.next();
+ }
+
+ return most_online;
+}
+
+void Meta_CalcStatus(HANDLE hMeta) {
+ HANDLE hSub = Meta_GetMostOnline(hMeta);
+ char *proto = ContactProto(hSub);
+ DBWriteContactSettingWord(hMeta, MODULE, "Status", ContactStatus(hSub, proto));
+}
+
+HANDLE Meta_Convert(HANDLE hSub) {
+ HANDLE hMeta = NewMetaContact();
+
+ DBWriteContactSettingByte(hMeta, MODULE, "Default", 0);
+ Meta_Assign(hSub, hMeta);
+
+ DBVARIANT dbv;
+ if(!DBGetContactSettingUTF8String(hSub, "CList", "Group", &dbv)) {
+ DBWriteContactSettingUTF8String(hMeta, "CList", "Group", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ if(!DBGetContactSettingUTF8String(hSub, "CList", "MyHandle", &dbv)) {
+ DBWriteContactSettingUTF8String(hMeta, "CList", "MyHandle", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ char *subProto = ContactProto(hSub);
+ if(subProto) {
+ if(!DBGetContactSettingUTF8String(hSub, subProto, "Nick", &dbv)) {
+ DBWriteContactSettingUTF8String(hMeta, MODULE, "Nick", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ Meta_CalcStatus(hMeta);
+ return hMeta;
+}
+
+void Meta_Assign(HANDLE hSub, HANDLE hMeta) {
+ metaMap[hMeta].add(hSub);
+ DBWriteContactSettingDword(hSub, MODULE, "ParentMetaID", DBGetContactSettingDword(hMeta, MODULE, META_ID, -1));
+ DBWriteContactSettingDword(hSub, MODULE, "Handle", (DWORD)hMeta);
+ DBWriteContactSettingByte(hSub, MODULE, "IsSubcontact", 1);
+ if(MetaEnabled()) {
+ if(!meta_group_hack_disabled)
+ DBWriteContactSettingByte(hSub, "CList", "Hidden", 1);
+ } else // shouldn't happen, as the menu option is hidden when metas are disabled...
+ DBWriteContactSettingByte(hMeta, "CList", "Hidden", 1);
+
+ FireSubcontactsChanged(hMeta);
+}
+
+void Meta_Remove(HANDLE hSub) {
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword(hSub, MODULE, "Handle", 0);
+ if(hMeta) {
+ DBDeleteContactSetting(hSub, MODULE, "ParentMetaID");
+ // deleting these (resident) settings doesn't work :( [25/9/07]
+ DBWriteContactSettingDword(hSub, MODULE, "Handle", 0);
+ DBWriteContactSettingByte(hSub, MODULE, "IsSubcontact", 0);
+ if(!meta_group_hack_disabled) DBWriteContactSettingByte(hSub, "CList", "Hidden", 0);
+
+ metaMap[hMeta].remove(hSub);
+ if(metaMap[hMeta].size() == 0) {
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hMeta, 0);
+ } else {
+ int def = DBGetContactSettingByte(hMeta, MODULE, "Default", -1);
+ if(def < 0 || def >= metaMap[hMeta].size())
+ DBWriteContactSettingByte(hMeta, MODULE, "Default", 0);
+ }
+ FireSubcontactsChanged(hMeta);
+ }
+}
\ No newline at end of file diff --git a/meta2/core_functions.h b/meta2/core_functions.h new file mode 100644 index 0000000..8f6a6ee --- /dev/null +++ b/meta2/core_functions.h @@ -0,0 +1,25 @@ +class MetaMap: public Map<ContactHandle, SubcontactList> {
+public:
+ SubcontactList &operator[](HANDLE h) {
+ return Map<ContactHandle, SubcontactList>::operator[](ContactHandle(h));
+ }
+
+ const bool exists(HANDLE h) const {
+ return Map<ContactHandle, SubcontactList>::exists(ContactHandle(h));
+ }
+
+ const bool remove(HANDLE h) {
+ return Map<ContactHandle, SubcontactList>::remove(ContactHandle(h));
+ }
+};
+
+extern MetaMap metaMap;
+
+HANDLE GetMetaHandle(DWORD id);
+void Meta_Hide(bool hide);
+HANDLE Meta_GetMostOnline(HANDLE hMeta);
+HANDLE Meta_GetMostOnlineSupporting(HANDLE hMeta, int flag, int cap);
+HANDLE Meta_Convert(HANDLE hSub);
+void Meta_CalcStatus(HANDLE hMeta);
+void Meta_Assign(HANDLE hSub, HANDLE hMeta);
+void Meta_Remove(HANDLE hSub);
\ No newline at end of file diff --git a/meta2/edit_meta.cpp b/meta2/edit_meta.cpp new file mode 100644 index 0000000..a43bec1 --- /dev/null +++ b/meta2/edit_meta.cpp @@ -0,0 +1,243 @@ +#include "common.h"
+#include "edit_meta.h"
+#include "resource.h"
+#include "core_functions.h"
+#include "icons.h"
+#include "api.h"
+
+TCHAR *GetIdString(HANDLE hContact, char *proto) {
+ if(proto) {
+ char *field = (char *)CallProtoService(proto,PS_GETCAPS,PFLAG_UNIQUEIDSETTING,0);
+ DBVARIANT dbv;
+
+ if(!DBGetContactSetting(hContact,proto,field,&dbv)) {
+ TCHAR *buff = 0;
+ switch(dbv.type)
+ {
+ case DBVT_ASCIIZ:
+ return mir_a2t(dbv.pszVal);
+ case DBVT_UTF8:
+#ifdef _UNICODE
+ return mir_utf8decodeW(dbv.pszVal);
+#else
+ return mir_utf8decode(dbv.pszVal, 0);
+#endif
+ case DBVT_WCHAR:
+ return mir_u2t(dbv.pwszVal);
+ case DBVT_BYTE:
+ buff = (TCHAR *)mir_alloc(4 * sizeof(TCHAR));
+ mir_sntprintf(buff, 4, _T("%d"),dbv.bVal);
+ return buff;
+ case DBVT_WORD:
+ buff = (TCHAR *)mir_alloc(16 * sizeof(TCHAR));
+ mir_sntprintf(buff, 16, _T("%d"),dbv.wVal);
+ return buff;
+ case DBVT_DWORD:
+ buff = (TCHAR *)mir_alloc(32 * sizeof(TCHAR));
+ mir_sntprintf(buff, 32, _T("%d"),dbv.dVal);
+ return buff;
+ default:
+ return 0;
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ return 0;
+}
+
+HANDLE hMeta;
+int def;
+SubcontactList subs;
+bool changed;
+
+void FillList(HWND hwndLst) {
+ LVITEM LvItem = {0};
+ LvItem.mask=LVIF_TEXT; // Text Style
+ LvItem.cchTextMax = 256; // Max size of test
+
+ int row = 0;
+ char *proto;
+ TCHAR *proto_t;
+
+ SendMessage(hwndLst, LVM_DELETEALLITEMS, 0, 0);
+
+ for(SubcontactList::Iterator i = subs.start(); i.has_val(); i.next()) {
+ LvItem.iItem = row;
+
+ LvItem.iSubItem = 0; // clist display name
+ LvItem.pszText = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)i.val().handle(), GCDNF_TCHAR);
+ SendMessage(hwndLst, LVM_INSERTITEM, (WPARAM)0, (LPARAM)&LvItem);
+
+ proto = ContactProto(i.val().handle());
+
+ LvItem.iSubItem = 1; // id
+ LvItem.pszText = GetIdString(i.val().handle(), proto);
+ SendMessage(hwndLst, LVM_SETITEM, (WPARAM)0, (LPARAM)&LvItem);
+ mir_free(LvItem.pszText);
+
+#ifdef _UNICODE
+ proto_t = mir_a2u(proto);
+#else
+ proto_t = proto;
+#endif
+ LvItem.iSubItem = 2; // protocol
+ LvItem.pszText = proto_t;
+ SendMessage(hwndLst, LVM_SETITEM, (WPARAM)0, (LPARAM)&LvItem);
+#ifdef _UNICODE
+ mir_free(proto_t);
+#endif;
+
+ LvItem.iSubItem = 3; // default
+ LvItem.pszText = (row == def ? TranslateT("TRUE") : TranslateT("FALSE"));
+ SendMessage(hwndLst, LVM_SETITEM, (WPARAM)0, (LPARAM)&LvItem);
+
+ row++;
+ }
+}
+
+void SetListSelection(HWND hList, int sel) {
+ LVITEM LvItem;
+
+ ZeroMemory(&LvItem, sizeof(LvItem));
+ LvItem.iItem = sel;
+ LvItem.mask = LVIF_STATE;
+ LvItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
+ LvItem.state = LVIS_SELECTED|LVIS_FOCUSED;
+
+ SendMessage(hList, LVM_SETITEMSTATE, (WPARAM)sel, (LPARAM)&LvItem);
+
+}
+
+void ApplyChanges() {
+ if(def >= 0 && def < metaMap[hMeta].size())
+ MetaAPI_SetDefaultContactNum((WPARAM)hMeta, (LPARAM)def);
+ else
+ MetaAPI_SetDefaultContactNum((WPARAM)hMeta, (LPARAM)0);
+
+ unsigned long index;
+ for(SubcontactList::Iterator i = metaMap[hMeta].start(); i.has_val(); i.next()) {
+ if(!subs.get_index(i.val(), index)) {
+ Meta_Remove(i.val().handle());
+ }
+ }
+}
+
+#define WMU_SET_BUTTONS (WM_USER + 0x100)
+BOOL CALLBACK Meta_EditDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx(I_EDIT));
+
+ SetDlgItemText(hwndDlg, IDC_ED_NAME, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hMeta, GCDNF_TCHAR));
+
+ {
+ HWND hwndLst = GetDlgItem(hwndDlg, IDC_LST_CONTACTS);
+ SendMessage(hwndLst,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT); // Set style
+
+ LVCOLUMN LvCol = {0};
+ LvCol.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
+
+ LvCol.pszText=TranslateT("Contact");
+ LvCol.cx=100;
+ SendMessage(hwndLst,LVM_INSERTCOLUMN,0,(LPARAM)&LvCol);
+
+ LvCol.pszText=TranslateT("Id");
+ LvCol.cx=130;
+ SendMessage(hwndLst,LVM_INSERTCOLUMN,1,(LPARAM)&LvCol);
+ LvCol.pszText=TranslateT("Protocol");
+ LvCol.cx=100;
+ SendMessage(hwndLst,LVM_INSERTCOLUMN,2,(LPARAM)&LvCol);
+ LvCol.pszText=TranslateT("Default");
+ LvCol.cx=60;
+ SendMessage(hwndLst,LVM_INSERTCOLUMN,3,(LPARAM)&LvCol);
+
+ FillList(hwndLst);
+ SendMessage(hwndDlg, WMU_SET_BUTTONS, 0, 0);
+ }
+
+ break;
+ case WMU_SET_BUTTONS:
+ {
+ HWND hwnd = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hwnd, changed);
+ hwnd = GetDlgItem(hwndDlg, IDC_VALIDATE);
+ EnableWindow(hwnd, changed);
+
+ int index = SendDlgItemMessage(hwndDlg, IDC_LST_CONTACTS, LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_SETDEFAULT);
+ EnableWindow(hwnd, index != -1 && index != def);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_REM);
+ EnableWindow(hwnd, index != -1);
+
+ }
+ return TRUE;
+ case WM_COMMAND:
+ if(HIWORD(wParam) == BN_CLICKED) {
+ switch(LOWORD(wParam))
+ {
+ case IDC_BTN_SETDEFAULT:
+ {
+ int index = SendDlgItemMessage(hwndDlg, IDC_LST_CONTACTS, LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+ def = index;
+ changed = true;
+ FillList(GetDlgItem(hwndDlg, IDC_LST_CONTACTS));
+ SetListSelection(GetDlgItem(hwndDlg, IDC_LST_CONTACTS), index);
+ SendMessage(hwndDlg, WMU_SET_BUTTONS, 0, 0);
+ }
+ break;
+ case IDC_BTN_REM:
+ {
+ int index = SendDlgItemMessage(hwndDlg, IDC_LST_CONTACTS, LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+ if(index >= 0 && index < subs.size()) {
+ subs.remove(subs[index].handle());
+ if(def >= index && def > 0) def--;
+ changed = true;
+ FillList(GetDlgItem(hwndDlg, IDC_LST_CONTACTS));
+ SendMessage(hwndDlg, WMU_SET_BUTTONS, 0, 0);
+ }
+ }
+ break;
+ case IDOK:
+ EndDialog(hwndDlg, IDOK);
+ break;
+ case IDCANCEL:
+ EndDialog(hwndDlg, IDCANCEL);
+ break;
+ case IDC_VALIDATE:
+ ApplyChanges();
+ break;
+ }
+ return TRUE;
+ }
+ break;
+ case WM_NOTIFY: // the message that is being sent always
+ switch(LOWORD(wParam)) // hit control
+ {
+ case IDC_LST_CONTACTS: // did we hit our ListView contorl?
+ if(((LPNMHDR)lParam)->code == NM_CLICK) {
+ SendMessage(hwndDlg, WMU_SET_BUTTONS, 0, 0);
+ }
+ break;
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+void EditMeta(HANDLE hM) {
+ hMeta = hM;
+ subs.add_all(metaMap[hMeta]);
+ def = (int)DBGetContactSettingByte(hMeta, MODULE, "Default", -1);
+ changed = false;
+
+ HWND clui = (HWND)CallService(MS_CLUI_GETHWND,0,0);
+ if(DialogBox(hInst, MAKEINTRESOURCE(IDD_METAEDIT), clui, Meta_EditDialogProc) == IDOK) {
+
+ // apply changes
+
+ ApplyChanges();
+ }
+ subs.clear();
+}
\ No newline at end of file diff --git a/meta2/edit_meta.h b/meta2/edit_meta.h new file mode 100644 index 0000000..f102bd1 --- /dev/null +++ b/meta2/edit_meta.h @@ -0,0 +1,2 @@ +
+void EditMeta(HANDLE hMeta);
\ No newline at end of file diff --git a/meta2/icons.cpp b/meta2/icons.cpp new file mode 100644 index 0000000..bf28b8c --- /dev/null +++ b/meta2/icons.cpp @@ -0,0 +1,102 @@ +#include "common.h"
+#include "icons.h"
+#include "resource.h"
+#include "menu.h"
+
+HANDLE hIcoLibIconsChanged = NULL;
+
+
+typedef struct {
+ char* szDescr;
+ char* szName;
+ int defIconID;
+ HANDLE hIcolib;
+} IconStruct;
+
+static IconStruct iconList[] = {
+ { "Toggle Off", "mc_off", IDI_MCMENUOFF, 0},
+ { "Toggle On", "mc_on", IDI_MCMENU, 0},
+ { "Convert to MetaContact", "mc_convert", IDI_MCCONVERT, 0},
+ { "Add to Existing", "mc_add", IDI_MCADD, 0},
+ { "Edit", "mc_edit", IDI_MCEDIT, 0},
+ { "Set to Default", "mc_default", IDI_MCSETDEFAULT, 0},
+ { "Remove", "mc_remove", IDI_MCREMOVE, 0},
+};
+
+
+HICON LoadIconEx(IconIndex i) {
+ HICON hIcon;
+
+ hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)iconList[(int)i].szName);
+
+ return hIcon;
+}
+
+HANDLE GetIcolibHandle(IconIndex i) {
+ return iconList[i].hIcolib;
+}
+
+void ReleaseIconEx(HICON hIcon) {
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+}
+
+int ReloadIcons(WPARAM wParam, LPARAM lParam) {
+ // fix menu icons
+ CLISTMENUITEM menu = {0};
+
+ menu.cbSize = sizeof(menu);
+ menu.flags = CMIM_ICON;
+
+ menu.hIcon = LoadIconEx(MetaEnabled() ? I_MENUOFF : I_MENU);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuOnOff, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_CONVERT);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_ADD);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_EDIT);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuEdit, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_SETDEFAULT);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_REMOVE);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuRemove, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ return 0;
+}
+
+void InitIcons() {
+ SKINICONDESC sid = {0};
+ char path[MAX_PATH];
+ int i;
+
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.pszSection = MODULE;
+ sid.pszDefaultFile = path;
+ GetModuleFileNameA(hInst, path, sizeof(path));
+
+ for (i = 0; i < sizeof(iconList) / sizeof(IconStruct); ++i)
+ {
+ sid.pszDescription = Translate(iconList[i].szDescr);
+ sid.pszName = iconList[i].szName;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ iconList[i].hIcolib = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+
+ //hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, ReloadIcons);
+
+ //ReloadIcons(0, 0);
+}
+
+void DeinitIcons() {
+ UnhookEvent(hIcoLibIconsChanged);
+}
diff --git a/meta2/icons.h b/meta2/icons.h new file mode 100644 index 0000000..630e6e9 --- /dev/null +++ b/meta2/icons.h @@ -0,0 +1,12 @@ +#ifndef _ICONS_INC
+#define _ICONS_INC
+
+typedef enum {I_MENUOFF, I_MENU, I_CONVERT, I_ADD, I_EDIT, I_SETDEFAULT, I_REMOVE} IconIndex;
+HICON LoadIconEx(IconIndex i);
+HANDLE GetIcolibHandle(IconIndex i);
+void ReleaseIconEx(HICON hIcon);
+
+void InitIcons(void);
+void DeinitIcons(void);
+
+#endif
diff --git a/meta2/icons/mcmenu.ico b/meta2/icons/mcmenu.ico Binary files differnew file mode 100644 index 0000000..66a521a --- /dev/null +++ b/meta2/icons/mcmenu.ico diff --git a/meta2/icons/mcmenuof.ico b/meta2/icons/mcmenuof.ico Binary files differnew file mode 100644 index 0000000..37443ec --- /dev/null +++ b/meta2/icons/mcmenuof.ico diff --git a/meta2/icons/mcmenuoff2.ico b/meta2/icons/mcmenuoff2.ico Binary files differnew file mode 100644 index 0000000..c9cda8b --- /dev/null +++ b/meta2/icons/mcmenuoff2.ico diff --git a/meta2/icons/meta_add.ico b/meta2/icons/meta_add.ico Binary files differnew file mode 100644 index 0000000..32bc5a9 --- /dev/null +++ b/meta2/icons/meta_add.ico diff --git a/meta2/icons/meta_convert.ico b/meta2/icons/meta_convert.ico Binary files differnew file mode 100644 index 0000000..da56997 --- /dev/null +++ b/meta2/icons/meta_convert.ico diff --git a/meta2/icons/meta_edit.ico b/meta2/icons/meta_edit.ico Binary files differnew file mode 100644 index 0000000..87e8b19 --- /dev/null +++ b/meta2/icons/meta_edit.ico diff --git a/meta2/icons/meta_remove2.ico b/meta2/icons/meta_remove2.ico Binary files differnew file mode 100644 index 0000000..9bf7265 --- /dev/null +++ b/meta2/icons/meta_remove2.ico diff --git a/meta2/icons/meta_set_as_default.ico b/meta2/icons/meta_set_as_default.ico Binary files differnew file mode 100644 index 0000000..c608232 --- /dev/null +++ b/meta2/icons/meta_set_as_default.ico diff --git a/meta2/import.cpp b/meta2/import.cpp new file mode 100644 index 0000000..abdab20 --- /dev/null +++ b/meta2/import.cpp @@ -0,0 +1,46 @@ +#include "common.h"
+#include "import.h"
+#include "core_functions.h"
+#include "proto.h"
+
+void ImportOldMetas() {
+ HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0);
+ char *proto;
+ HANDLE hMeta;
+ while(hContact != NULL) {
+ DWORD id = DBGetContactSettingDword(hContact, "MetaContacts", "MetaLink", (DWORD)-1);
+ if(id != (DWORD)-1) {
+ if(id > next_meta_id) next_meta_id = id + 1;
+ hMeta = GetMetaHandle(id);
+ if(hMeta) {
+ Meta_Assign(hContact, hMeta);
+ } else {
+ hMeta = NewMetaContact();
+ DBWriteContactSettingDword(hMeta, MODULE, META_ID, id);
+
+ DBWriteContactSettingByte(hMeta, MODULE, "Default", 0);
+ Meta_Assign(hContact, hMeta);
+
+ DBVARIANT dbv;
+ if(!DBGetContactSettingUTF8String(hContact, "CList", "Group", &dbv)) {
+ DBWriteContactSettingUTF8String(hMeta, "CList", "Group", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ if(!DBGetContactSettingUTF8String(hContact, "CList", "MyHandle", &dbv)) {
+ DBWriteContactSettingUTF8String(hMeta, "CList", "MyHandle", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ char *subProto = ContactProto(hContact);
+ if(subProto) {
+ if(!DBGetContactSettingUTF8String(hContact, subProto, "Nick", &dbv)) {
+ DBWriteContactSettingUTF8String(hMeta, MODULE, "Nick", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+}
\ No newline at end of file diff --git a/meta2/import.h b/meta2/import.h new file mode 100644 index 0000000..c18996c --- /dev/null +++ b/meta2/import.h @@ -0,0 +1,2 @@ +
+void ImportOldMetas();
\ No newline at end of file diff --git a/meta2/m_metacontacts.h b/meta2/m_metacontacts.h new file mode 100644 index 0000000..9f348bd --- /dev/null +++ b/meta2/m_metacontacts.h @@ -0,0 +1,166 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+Copyright © 2004 Scott Ellis (www.scottellis.com.au mail@scottellis.com.au)
+
+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.
+*/
+
+#ifndef M_METACONTACTS_H__
+#define M_METACONTACTS_H__ 1
+
+#ifndef MIID_METACONTACTS
+#define MIID_METACONTACTS {0xc0325019, 0xc1a7, 0x40f5, { 0x83, 0x65, 0x4f, 0x46, 0xbe, 0x21, 0x86, 0x3e}}
+#endif
+
+//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
+#define MS_MC_GETMETACONTACT "MetaContacts/GetMeta"
+
+//gets the handle for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the default contact, or null on failure
+#define MS_MC_GETDEFAULTCONTACT "MetaContacts/GetDefault"
+
+//gets the contact number for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD contact number, or -1 on failure
+#define MS_MC_GETDEFAULTCONTACTNUM "MetaContacts/GetDefaultNum"
+
+//gets the handle for the 'most online' contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the 'most online' contact
+#define MS_MC_GETMOSTONLINECONTACT "MetaContacts/GetMostOnline"
+
+//gets the number of subcontacts for a metacontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD representing the number of subcontacts for the given metacontact
+#define MS_MC_GETNUMCONTACTS "MetaContacts/GetNumContacts"
+
+//gets the handle of a subcontact, using the subcontact's number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns a handle to the specified subcontact
+#define MS_MC_GETSUBCONTACT "MetaContacts/GetSubContact"
+
+//sets the default contact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+#define MS_MC_SETDEFAULTCONTACTNUM "MetaContacts/SetDefault"
+
+//sets the default contact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success
+#define MS_MC_SETDEFAULTCONTACT "MetaContacts/SetDefaultByHandle"
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+#define MS_MC_FORCESENDCONTACTNUM "MetaContacts/ForceSendContact"
+
+//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)
+#define MS_MC_FORCESENDCONTACT "MetaContacts/ForceSendContactByHandle"
+
+//'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)
+#define MS_MC_UNFORCESENDCONTACT "MetaContacts/UnforceSendContact"
+
+//'forces' or 'unforces' (i.e. toggles) the metacontact to send using it's default contact
+// overrides (and clears) 'force send' above, and will even force use of offline contacts
+// will send ME_MC_FORCESEND or ME_MC_UNFORCESEND event
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 1(true) or 0(false) representing new state of 'force default'
+#define MS_MC_FORCEDEFAULT "MetaContacts/ForceSendDefault"
+
+// method to get state of 'force' for a metacontact
+// wParam=(HANDLE)hMetaContact
+// lParam= (DWORD)&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)
+#define MS_MC_GETFORCESTATE "MetaContacts/GetForceState"
+
+// fired when a metacontact's default contact changes (fired upon creation of metacontact also, when default is initially set)
+// wParam=(HANDLE)hMetaContact
+// lParam=(HANDLE)hDefaultContact
+#define ME_MC_DEFAULTTCHANGED "MetaContacts/DefaultChanged"
+
+// fired when a metacontact's subcontacts change (fired upon creation of metacontact, when contacts are added or removed, and when
+// contacts are reordered) - a signal to re-read metacontact data
+// wParam=(HANDLE)hMetaContact
+// lParam=0
+#define ME_MC_SUBCONTACTSCHANGED "MetaContacts/SubcontactsChanged"
+
+// fired when a metacontact is forced to send using a specific subcontact
+// wParam=(HANDLE)hMetaContact
+// lParam=(HANDLE)hForceContact
+#define ME_MC_FORCESEND "MetaContacts/ForceSend"
+
+// fired when a metacontact is 'unforced' to send using a specific subcontact
+// wParam=(HANDLE)hMetaContact
+// lParam=0
+#define ME_MC_UNFORCESEND "MetaContacts/UnforceSend"
+
+// method to get protocol name - used to be sure you're dealing with a "real" metacontacts plugin :)
+// wParam=lParam=0
+#define MS_MC_GETPROTOCOLNAME "MetaContacts/GetProtoName"
+
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=0
+// convert a given contact into a metacontact
+#define MS_MC_CONVERTTOMETA "MetaContacts/ConvertToMetacontact"
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=(HANDLE)hMeta
+// add an existing contact to a metacontact
+#define MS_MC_ADDTOMETA "MetaContacts/AddToMetacontact"
+
+// added 0.9.5.0 (22/3/05)
+// wParam=0
+// lParam=(HANDLE)hContact
+// remove a contact from a metacontact
+#define MS_MC_REMOVEFROMMETA "MetaContacts/RemoveFromMetacontact"
+
+
+// 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 the clist 'onmodulesloaded' event handler (which, since it's loaded after the db, will be called
+// before the metacontact onmodulesloaded handler where the subcontact hiding is usually done)
+#define MS_MC_DISABLEHIDDENGROUP "MetaContacts/DisableHiddenGroup"
+
+#endif
diff --git a/meta2/menu.cpp b/meta2/menu.cpp new file mode 100644 index 0000000..68c3674 --- /dev/null +++ b/meta2/menu.cpp @@ -0,0 +1,265 @@ +#include "common.h"
+#include "menu.h"
+#include "resource.h"
+#include "icons.h"
+#include "core_functions.h"
+#include "api.h"
+#include "select_meta.h"
+#include "edit_meta.h"
+
+HANDLE hServiceMenuOnOff = 0, hServiceMenuConvert = 0, hServiceMenuAdd = 0, hServiceMenuEdit = 0,
+ hServiceMenuDefault = 0, hServiceMenuRemove = 0, hServiceToggle = 0;
+HANDLE hMenuOnOff = 0, hMenuConvert = 0, hMenuAdd = 0, hMenuEdit = 0, hMenuDefault = 0, hMenuRemove = 0;
+POINT menuMousePoint;
+
+int ServiceMenuOnOff(WPARAM wParam, LPARAM lParam) {
+ DBWriteContactSettingByte(0, MODULE, "Enabled", MetaEnabled() ? 0 : 1);
+ Meta_Hide(!MetaEnabled());
+
+ CLISTMENUITEM menu = {0};
+ menu.cbSize=sizeof(menu);
+ menu.flags = CMIM_NAME | CMIM_ICON | CMIF_TCHAR | CMIF_ICONFROMICOLIB;
+ menu.ptszName = MetaEnabled() ? _T("Disable MetaContacts") : _T("Enable MetaContacts");
+ menu.icolibItem = GetIcolibHandle(MetaEnabled() ? I_MENUOFF : I_MENU);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuOnOff, (LPARAM)&menu);
+
+ return 0;
+}
+
+HANDLE hEventMenuBuild = 0;
+
+int ContactMenuConvert(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+ Meta_Convert(hContact);
+ return 0;
+}
+
+int ContactMenuAdd(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+ TCHAR buff[256];
+ mir_sntprintf(buff, 256, TranslateT("Adding %s..."), (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+ HANDLE hMeta = SelectMeta(buff);
+ if(hMeta)
+ Meta_Assign(hContact, hMeta);
+ return 0;
+}
+
+int ContactMenuRemove(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+
+ Meta_Remove(hContact);
+ return 0;
+}
+
+int ContactMenuEdit(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+
+ EditMeta(hContact);
+ return 0;
+}
+
+int ContactMenuDefault(WPARAM wParam, LPARAM lParam) {
+ HANDLE hSub = (HANDLE)wParam,
+ hMeta = (HANDLE)DBGetContactSettingDword(hSub, MODULE, "Handle", 0);
+
+ MetaAPI_SetDefaultContact((WPARAM)hMeta, (LPARAM)hSub);
+ return 0;
+}
+
+// show contact's context menu
+DWORD CALLBACK sttMenuFunc( LPVOID param )
+{
+ HMENU hMenu;
+ TPMPARAMS tpmp = {0};
+ BOOL menuRet;
+ HANDLE hSub = (HANDLE)param;
+
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)hSub, 0);
+
+ tpmp.cbSize = sizeof(tpmp);
+
+ menuRet = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, menuMousePoint.x, menuMousePoint.y, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), &tpmp);
+
+ CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(menuRet), MPCF_CONTACTMENU), (LPARAM)hSub);
+
+ DestroyMenu(hMenu);
+
+ return 0;
+}
+
+int Meta_ContactMenuFunc(WPARAM wParam, LPARAM lParam) {
+ char buff[1024];
+ HANDLE hMeta = (HANDLE)wParam;
+ int contact_num = (int)lParam;
+ if(metaMap.exists(hMeta) && contact_num >= 0 && contact_num < metaMap[hMeta].size()) {
+ QueueUserAPC((PAPCFUNC)sttMenuFunc, metaMainThread, (ULONG)metaMap[hMeta][contact_num].handle());
+ }
+
+ return 0;
+}
+
+HANDLE hMenuContact[MAX_SUBCONTACTS], hServiceContactMenu = 0;
+
+int PrebuildContactMenu(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(CLISTMENUITEM);
+
+ if(MetaEnabled()) {
+ if(IsSubcontact(hContact)) {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuRemove, (LPARAM)&mi);
+ } else if(IsMetacontact(hContact)) {
+ GetCursorPos(&menuMousePoint);
+
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuRemove, (LPARAM)&mi);
+
+ if(!metaMap.exists(hContact)) {
+ PUShowMessage("No such meta!", SM_WARNING);
+ return 0;
+ }
+
+ // show subcontact menu items
+ mi.flags = CMIM_FLAGS | CMIM_NAME | CMIM_ICON | CMIF_TCHAR;
+ HIMAGELIST il = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0);
+ SubcontactList::Iterator i = metaMap[hContact].start();
+ int count = 0;
+ while(i.has_val()) {
+ mi.ptszName = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)i.val().handle(), GCDNF_TCHAR);
+ mi.hIcon = ImageList_GetIcon(il, (int)CallService(MS_CLIST_GETCONTACTICON, (WPARAM)i.val().handle(), 0), 0);
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuContact[count], (LPARAM)&mi);
+
+ i.next();
+ count++;
+ }
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ for(;count < MAX_SUBCONTACTS; count++)
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuContact[count], (LPARAM)&mi);
+
+ // show hide nudge menu item
+// wParam = char *szProto
+// lParam = BOOL show
+#define MS_NUDGE_SHOWMENU "NudgeShowMenu"
+ {
+ char serviceFunc[256];
+ hContact = Meta_GetMostOnline((HANDLE)wParam);
+ mir_snprintf(serviceFunc, 256, "%s/SendNudge", ContactProto(hContact));
+ CallService(MS_NUDGE_SHOWMENU, (WPARAM)MODULE, (LPARAM)ServiceExists(serviceFunc));
+ }
+
+ } else {
+ mi.flags = CMIM_FLAGS;
+ if(meta_count) CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ if(!meta_count) CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuRemove, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&mi);
+ }
+ } else {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuRemove, (LPARAM)&mi);
+ }
+
+ return 0;
+}
+
+void InitMenu() {
+ CLISTMENUITEM menu = {0};
+ menu.cbSize=sizeof(menu);
+
+ menu.flags = CMIM_ALL | CMIF_TCHAR | CMIF_ICONFROMICOLIB;
+
+ // main menu item
+ hServiceMenuOnOff = CreateServiceFunction(MODULE "/MenuOnOff", ServiceMenuOnOff);
+ menu.ptszName = MetaEnabled() ? _T("Disable MetaContacts") : _T("Enable MetaContacts");
+ menu.pszService = MODULE "/MenuOnOff";
+ menu.icolibItem = GetIcolibHandle(MetaEnabled() ? I_MENUOFF : I_MENU);
+ hMenuOnOff = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&menu);
+
+ // normal and subcontact menu items
+ hServiceMenuConvert = CreateServiceFunction(MODULE "/ContactMenuConvert", ContactMenuConvert);
+ menu.ptszName = _T("Convert to MetaContact");
+ menu.pszService = MODULE "/ContactMenuConvert";
+ menu.icolibItem = GetIcolibHandle(I_CONVERT);
+ hMenuConvert = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+
+ hServiceMenuAdd = CreateServiceFunction(MODULE "/ContactMenuAdd", ContactMenuAdd);
+ menu.ptszName = _T("Add to existing MetaContact...");
+ menu.pszService = MODULE "/ContactMenuAdd";
+ menu.icolibItem = GetIcolibHandle(I_ADD);
+ hMenuAdd = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+
+ hServiceMenuRemove = CreateServiceFunction(MODULE "/ContactMenuRemove", ContactMenuRemove);
+ menu.ptszName = _T("Remove from MetaContact");
+ menu.pszService = MODULE "/ContactMenuRemove";
+ menu.icolibItem = GetIcolibHandle(I_REMOVE);
+ hMenuRemove = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+
+ hServiceMenuDefault = CreateServiceFunction(MODULE "/ContactMenuDefault", ContactMenuDefault);
+ menu.ptszName = _T("Set as MetaContact default");
+ menu.pszService = MODULE "/ContactMenuDefault";
+ menu.icolibItem = GetIcolibHandle(I_SETDEFAULT);
+ hMenuDefault = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+
+ // hidden contact menu items...ho hum
+ hServiceContactMenu = CreateServiceFunction("MetaContacts/MenuFunc",Meta_ContactMenuFunc);
+
+ menu.flags = CMIM_ALL | CMIF_TCHAR | CMIF_HIDDEN;
+ menu.pszContactOwner = MODULE;
+ menu.hIcon = 0;
+ menu.position = -99000;
+ menu.hIcon = 0;
+
+ TCHAR buff[256];
+ menu.ptszName = buff;
+ for(int i = 0; i < MAX_SUBCONTACTS; i++) {
+ menu.position--;
+ menu.popupPosition = i;
+ mir_sntprintf(buff, 256, _T("Context%d"), i);
+
+ menu.pszService= "MetaContacts/MenuFunc";
+
+ hMenuContact[i] = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+ }
+
+
+ // metacontact items
+ menu.flags = CMIM_ALL | CMIF_TCHAR | CMIF_ICONFROMICOLIB;
+ hServiceMenuEdit = CreateServiceFunction(MODULE "/ContactMenuEdit", ContactMenuEdit);
+ menu.ptszName = _T("Edit MetaContact");
+ menu.pszService = MODULE "/ContactMenuEdit";
+ menu.icolibItem = GetIcolibHandle(I_EDIT);
+ menu.pszContactOwner = MODULE;
+ hMenuEdit = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+
+ hEventMenuBuild = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu);
+
+ // for toptoolbar buttons (backward compatible)
+ hServiceToggle = CreateServiceFunction("MetaContacts/OnOff", ServiceMenuOnOff);
+
+}
+
+void DeinitMenu() {
+ UnhookEvent(hEventMenuBuild);
+ DestroyServiceFunction(hServiceMenuRemove);
+ DestroyServiceFunction(hServiceMenuDefault);
+ DestroyServiceFunction(hServiceMenuEdit);
+ DestroyServiceFunction(hServiceMenuAdd);
+ DestroyServiceFunction(hServiceMenuConvert);
+ DestroyServiceFunction(hServiceMenuOnOff);
+ DestroyServiceFunction(hServiceContactMenu);
+ DestroyServiceFunction(hServiceToggle);
+}
\ No newline at end of file diff --git a/meta2/menu.h b/meta2/menu.h new file mode 100644 index 0000000..2e77e6f --- /dev/null +++ b/meta2/menu.h @@ -0,0 +1,9 @@ +#ifndef _MENU_INC
+#define _MENU_INC
+
+extern HANDLE hMenuOnOff, hMenuConvert, hMenuAdd, hMenuEdit, hMenuDefault, hMenuRemove;
+
+void InitMenu();
+void DeinitMenu();
+
+#endif
diff --git a/meta2/menu.ico b/meta2/menu.ico Binary files differnew file mode 100644 index 0000000..94f62a2 --- /dev/null +++ b/meta2/menu.ico diff --git a/meta2/meta2.cpp b/meta2/meta2.cpp new file mode 100644 index 0000000..eba4262 --- /dev/null +++ b/meta2/meta2.cpp @@ -0,0 +1,107 @@ +/* Replace "dll.h" with the name of your header */
+#include "common.h"
+#include "version.h"
+#include "resource.h"
+#include "options.h"
+#include "proto.h"
+#include "menu.h"
+#include "icons.h"
+#include "api.h"
+#include "priorities.h"
+#include "m_metacontacts.h"
+#include "settings.h"
+#include "import.h"
+
+///////////////////////////////////////////////
+// Common Plugin Stuff
+///////////////////////////////////////////////
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+MM_INTERFACE mmi;
+UTF8_INTERFACE utfi;
+HANDLE metaMainThread;
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ 0,
+ { 0x5F9B2B98, 0x3412, 0x4671, { 0x89, 0xAD, 0x5B, 0xA9, 0x53, 0x74, 0xC6, 0xA8 } }
+};
+
+
+extern "C" BOOL APIENTRY DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) {
+ hInst=hinstDLL;
+ return TRUE;
+}
+
+extern "C" __declspec (dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) {
+ return &pluginInfo;
+}
+
+
+// TODO: add any interfaces you implement to this list
+static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_METACONTACTS, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ InitIcons();
+ InitMenu();
+
+ if(DBGetContactSettingByte(0, MODULE, "FirstRun", 1) == 1) {
+ ImportOldMetas();
+ DBWriteContactSettingByte(0, MODULE, "FirstRun", 0);
+ }
+ return 0;
+}
+
+HANDLE hModulesLoaded;
+extern "C" __declspec (dllexport) int Load(PLUGINLINK *link) {
+
+ pluginLink=link;
+ DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &metaMainThread, THREAD_SET_CONTEXT, FALSE, 0 );
+
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+
+ InitOptions();
+ InitPriorities();
+
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/Status"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/IdleTS"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/Handle"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/WindowOpen"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/IsSubcontact"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/ForceSend"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/TempDefault"));
+
+ InitProto();
+ InitAPI();
+ InitSettings(link);
+
+ // hook modules loaded
+ hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+ return 0;
+}
+
+extern "C" __declspec (dllexport) int Unload(void) {
+ DeinitSettings();
+ UnhookEvent(hModulesLoaded);
+ DeinitMenu();
+ DeinitIcons();
+ DeinitAPI();
+ DeinitProto();
+ DeinitPriorities();
+ DeinitOptions();
+
+ return 0;
+}
diff --git a/meta2/meta2.rc b/meta2/meta2.rc new file mode 100644 index 0000000..289c49f --- /dev/null +++ b/meta2/meta2.rc @@ -0,0 +1,170 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral (Default) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPT1 DIALOGEX 0, 0, 246, 179
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+END
+
+IDD_PRIORITIES DIALOGEX 0, 0, 266, 157
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Subcontact Priorities",IDC_STATIC,7,7,252,143
+ EDITTEXT IDC_ED_PRIORITY,157,78,40,14,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_SP_PRIORITY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,195,78,11,14
+ RTEXT "Rank:",IDC_STATIC,42,81,49,8
+ RTEXT "Status:",IDC_STATIC,30,57,61,8
+ COMBOBOX IDC_CMB_STATUS,98,53,112,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ RTEXT "Protocol:",IDC_STATIC,30,31,61,8
+ COMBOBOX IDC_CMB_PROTOCOL,98,28,112,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Reset All",IDC_BTN_RESET,87,119,91,14
+ CONTROL "Default",IDC_CHK_DEFAULT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,97,81,58,10
+ CTEXT "(Lower ranks are preferred)",IDC_STATIC,51,99,162,8
+END
+
+IDD_METASELECT DIALOGEX 0, 0, 256, 259
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Select MetaContact"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CTEXT "Please select a MetaContact:",IDC_STATIC,27,11,201,14
+ DEFPUSHBUTTON "&Ok",IDOK,73,238,48,14,WS_DISABLED
+ PUSHBUTTON "&Cancel",IDCANCEL,133,238,48,14
+ LISTBOX IDC_METALIST,44,28,168,168,LBS_NOINTEGRALHEIGHT | WS_VSCROLL
+ CONTROL "Sort Alphabetically",IDC_CHK_SRT,"Button",BS_AUTOCHECKBOX | BS_VCENTER | WS_TABSTOP,78,210,124,13
+END
+
+IDD_METAEDIT DIALOGEX 0, 0, 311, 260
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION
+EXSTYLE WS_EX_STATICEDGE
+CAPTION "Edit MetaContact"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "&OK",IDOK,70,241,50,14,WS_DISABLED
+ PUSHBUTTON "&Cancel",IDCANCEL,130,241,50,14
+ LTEXT "Name:",IDC_STATIC,55,26,42,8
+ GROUPBOX "Information",IDC_STATIC,5,4,299,45
+ GROUPBOX "Contacts",IDC_STATIC,5,54,299,180
+ DEFPUSHBUTTON "&Apply",IDC_VALIDATE,190,241,50,14,WS_DISABLED
+ PUSHBUTTON "&Remove",IDC_BTN_REM,103,214,50,14,WS_DISABLED
+ PUSHBUTTON "&Set as Default",IDC_BTN_SETDEFAULT,157,214,50,14,WS_DISABLED
+ EDITTEXT IDC_ED_NAME,96,24,160,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP
+ CONTROL "List1",IDC_LST_CONTACTS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,13,66,283,142,WS_EX_CLIENTEDGE
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include <windows.h>\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_METASELECT, DIALOG
+ BEGIN
+ LEFTMARGIN, 8
+ RIGHTMARGIN, 247
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 252
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // Neutral (Default) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Australia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MCSETDEFAULT ICON "icons\\meta_set_as_default.ico"
+IDI_MCMENU ICON "icons\\mcmenu.ico"
+IDI_MCMENUOFF ICON "icons\\mcmenuof.ico"
+IDI_MCMENUOFF2 ICON "icons\\mcmenuoff2.ico"
+IDI_MCADD ICON "icons\\meta_add.ico"
+IDI_MCCONVERT ICON "icons\\meta_convert.ico"
+IDI_MCEDIT ICON "icons\\meta_edit.ico"
+IDI_MCREMOVE ICON "icons\\meta_remove2.ico"
+#endif // English (Australia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/meta2/meta2.sln b/meta2/meta2.sln new file mode 100644 index 0000000..70e7972 --- /dev/null +++ b/meta2/meta2.sln @@ -0,0 +1,26 @@ +
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "meta2", "meta2.vcproj", "{C7542E4E-BCC9-4620-8C72-77DBD8119186}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug (Unicode)|Win32 = Debug (Unicode)|Win32
+ Debug|Win32 = Debug|Win32
+ Release (Unicode)|Win32 = Release (Unicode)|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C7542E4E-BCC9-4620-8C72-77DBD8119186}.Debug (Unicode)|Win32.ActiveCfg = Debug (Unicode)|Win32
+ {C7542E4E-BCC9-4620-8C72-77DBD8119186}.Debug (Unicode)|Win32.Build.0 = Debug (Unicode)|Win32
+ {C7542E4E-BCC9-4620-8C72-77DBD8119186}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C7542E4E-BCC9-4620-8C72-77DBD8119186}.Debug|Win32.Build.0 = Debug|Win32
+ {C7542E4E-BCC9-4620-8C72-77DBD8119186}.Release (Unicode)|Win32.ActiveCfg = Release (Unicode)|Win32
+ {C7542E4E-BCC9-4620-8C72-77DBD8119186}.Release (Unicode)|Win32.Build.0 = Release (Unicode)|Win32
+ {C7542E4E-BCC9-4620-8C72-77DBD8119186}.Release|Win32.ActiveCfg = Release|Win32
+ {C7542E4E-BCC9-4620-8C72-77DBD8119186}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/meta2/meta2.vcproj b/meta2/meta2.vcproj new file mode 100644 index 0000000..c99ae3a --- /dev/null +++ b/meta2/meta2.vcproj @@ -0,0 +1,584 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="meta2"
+ ProjectGUID="{C7542E4E-BCC9-4620-8C72-77DBD8119186}"
+ RootNamespace="meta2"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;_USERDLL"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="common.h"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="comctl32.lib"
+ SubSystem="2"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="NDEBUG;_WINDOWS;_USERDLL"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="common.h"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="comctl32.lib"
+ SubSystem="2"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug (Unicode)|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;_USERDLL;UNICODE;_UNICODE"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="common.h"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="comctl32.lib"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release (Unicode)|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="NDEBUG;_WINDOWS;_USERDLL;UNICODE;_UNICODE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="common.h"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="comctl32.lib"
+ SubSystem="2"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\api.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\common.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug (Unicode)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (Unicode)|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\core_functions.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\edit_meta.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\icons.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\import.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\menu.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\meta2.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\options.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\priorities.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\proto.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\select_meta.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\settings.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\api.h"
+ >
+ </File>
+ <File
+ RelativePath=".\collection.h"
+ >
+ </File>
+ <File
+ RelativePath=".\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\core_functions.h"
+ >
+ </File>
+ <File
+ RelativePath=".\edit_meta.h"
+ >
+ </File>
+ <File
+ RelativePath=".\icons.h"
+ >
+ </File>
+ <File
+ RelativePath=".\import.h"
+ >
+ </File>
+ <File
+ RelativePath=".\menu.h"
+ >
+ </File>
+ <File
+ RelativePath=".\options.h"
+ >
+ </File>
+ <File
+ RelativePath=".\priorities.h"
+ >
+ </File>
+ <File
+ RelativePath=".\proto.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\select_meta.h"
+ >
+ </File>
+ <File
+ RelativePath=".\settings.h"
+ >
+ </File>
+ <File
+ RelativePath=".\version.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\icons\mcmenu.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icons\mcmenuof.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icons\mcmenuoff2.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\menu.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\meta2.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug (Unicode)|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (Unicode)|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icons\meta_add.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icons\meta_convert.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icons\meta_edit.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icons\meta_remove2.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\icons\meta_set_as_default.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\version.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug (Unicode)|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release (Unicode)|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\readme.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/meta2/meta_api.c b/meta2/meta_api.c new file mode 100644 index 0000000..d84e469 --- /dev/null +++ b/meta2/meta_api.c @@ -0,0 +1,245 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+Copyright © 2004 Scott Ellis (www.scottellis.com.au mail@scottellis.com.au)
+
+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.
+*/
+
+/** @file meta_api.c
+*
+* API functions needed to handle MetaContacts.
+* Centralizes functions called by other plugins.
+*/
+
+#include "metacontacts.h"
+
+//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, META_PROTO, "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) {
+ DWORD default_contact_number = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Default", -1);
+ if(default_contact_number != -1) {
+ return (int)Meta_GetContactHandle((HANDLE)wParam, default_contact_number);
+ }
+ return 0;
+}
+
+//gets the contact number for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD contact number, or -1 on failure
+int MetaAPI_GetDefaultNum(WPARAM wParam, LPARAM lParam) {
+ return DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Default", -1);
+}
+
+//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 a DWORD representing the number of subcontacts for the given metacontact
+int MetaAPI_GetNumContacts(WPARAM wParam, LPARAM lParam) {
+ DWORD num_contacts = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "NumContacts", -1);
+ return num_contacts;
+}
+
+//gets the handle of a subcontact, using the subcontact's number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns a handle to the specified subcontact
+int MetaAPI_GetContact(WPARAM wParam, LPARAM lParam) {
+ return (int)Meta_GetContactHandle((HANDLE)wParam, (DWORD)lParam);
+}
+
+//sets the default contact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+int MetaAPI_SetDefaultContactNum(WPARAM wParam, LPARAM lParam) {
+ DWORD num_contacts = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "NumContacts", -1);
+ if(num_contacts == -1)
+ return 1;
+ if((DWORD)lParam >= num_contacts || (DWORD)lParam < 0)
+ return 1;
+ if(DBWriteContactSettingDword((HANDLE)wParam, META_PROTO, "Default", (DWORD)lParam))
+ return 1;
+
+ NotifyEventHooks(hEventDefaultChanged, wParam, (LPARAM)Meta_GetContactHandle((HANDLE)wParam, (int)lParam));
+ 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)DBGetContactSettingDword((HANDLE)lParam, META_PROTO, "Handle", 0);
+ DWORD contact_number = Meta_GetContactNumber((HANDLE)lParam);
+ if(contact_number == -1 || !hMeta || hMeta != (HANDLE)wParam)
+ return 1;
+ if(DBWriteContactSettingDword(hMeta, META_PROTO, "Default", contact_number))
+ return 1;
+
+ NotifyEventHooks(hEventDefaultChanged, wParam, lParam);
+ return 0;
+}
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+int MetaAPI_ForceSendContactNum(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = Meta_GetContactHandle((HANDLE)wParam, (int)lParam);
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword(hContact, META_PROTO, "Handle", 0);
+ if(!hContact || !hMeta || hMeta != (HANDLE)wParam || DBGetContactSettingByte(hMeta, META_PROTO, "ForceDefault", 0))
+ return 1;
+
+ DBWriteContactSettingDword(hMeta, META_PROTO, "ForceSend", (DWORD)hContact);
+
+ NotifyEventHooks(hEventForceSend, wParam, (LPARAM)hContact);
+ return 0;
+}
+
+//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 hContact = (HANDLE)lParam;
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword(hContact, META_PROTO, "Handle", 0);
+ if(!hContact || !hMeta || hMeta != (HANDLE)wParam || DBGetContactSettingByte(hMeta, META_PROTO, "ForceDefault", 0))
+ return 1;
+
+ DBWriteContactSettingDword(hMeta, META_PROTO, "ForceSend", (DWORD)hContact);
+
+ 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, META_PROTO, "ForceDefault", 0))
+ return 1;
+
+ DBWriteContactSettingDword((HANDLE)wParam, META_PROTO, "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) {
+ // forward to menu function
+ Meta_ForceDefault(wParam, lParam);
+ return DBGetContactSettingByte((HANDLE)wParam, META_PROTO, "ForceDefault", 0);
+}
+
+// method to get state of 'force' for a metacontact
+// wParam=(HANDLE)hMetaContact
+// lParam= (DWORD)&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) return 0;
+
+ if(DBGetContactSettingByte(hMeta, META_PROTO, "ForceDefault", 0)) {
+ if(lParam) *(DWORD *)lParam = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Default", -1);
+ return 1;
+ }
+
+ hContact = (HANDLE)DBGetContactSettingDword(hMeta, META_PROTO, "ForceSend", 0);
+
+ if(!hContact) {
+ if(lParam) *(DWORD *)lParam = -1;
+ } else {
+ if(lParam) *(DWORD *)lParam = (DWORD)Meta_GetContactNumber(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)META_PROTO;
+}
+
+// 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 Meta_Convert(wParam, lParam);
+}
+
+// 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) {
+ return Meta_Assign((HANDLE)wParam, (HANDLE)lParam, FALSE);
+}
+
+// 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) {
+ // notice we switch args - to keep the API function consistent with the others
+ return Meta_Delete((WPARAM)lParam, (LPARAM)wParam);
+}
+
+// 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; // this global flag is used in utils 'SetGroup' function
+
+int MetaAPI_DisableHiddenGroup(WPARAM wParam, LPARAM lParam) {
+ meta_group_hack_disabled = (BOOL)wParam;
+ return 0;
+}
diff --git a/meta2/options.cpp b/meta2/options.cpp new file mode 100644 index 0000000..7c96cba --- /dev/null +++ b/meta2/options.cpp @@ -0,0 +1,71 @@ +#include "common.h"
+#include "options.h"
+#include "resource.h"
+
+Options options;
+
+void LoadOptions() {
+ //options.dummy = DBGetContactSettingDword(0, MODULE, "Dummy", 0);
+}
+
+void SaveOptions() {
+ //DBWriteContactSettingDword(0, MODULE, "Dummy", options.dummy);
+}
+
+BOOL CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+ static HANDLE hItemAll;
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+ // TODO: read options variable into control states
+ return FALSE;
+ case WM_COMMAND:
+ // enable the 'apply' button
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ // TODO: read control states into options variable
+ SaveOptions();
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+int OptInit(WPARAM wParam, LPARAM lParam) {
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.flags |= ODPF_TCHAR;
+ odp.position = -790000000;
+ odp.hInstance = hInst;
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT1);
+ odp.ptszTitle = TranslateT("MetaContacts");
+ odp.ptszGroup = TranslateT("Contact List");
+ odp.ptszTab = TranslateT("General");
+ odp.nIDBottomSimpleControl = 0;
+ odp.pfnDlgProc = DlgProcOpts;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ return 0;
+}
+
+HANDLE hEventOptInit;
+void InitOptions() {
+ hEventOptInit = HookEvent(ME_OPT_INITIALISE, OptInit);
+ LoadOptions();
+}
+
+void DeinitOptions() {
+ UnhookEvent(hEventOptInit);
+}
diff --git a/meta2/options.h b/meta2/options.h new file mode 100644 index 0000000..82c90c7 --- /dev/null +++ b/meta2/options.h @@ -0,0 +1,13 @@ +#ifndef _OPTIONS_INC
+#define _OPTIONS_INC
+
+typedef struct {
+ int dummy;
+} Options;
+
+extern Options options;
+
+void InitOptions();
+void DeinitOptions();
+
+#endif
diff --git a/meta2/priorities.cpp b/meta2/priorities.cpp new file mode 100644 index 0000000..7b35223 --- /dev/null +++ b/meta2/priorities.cpp @@ -0,0 +1,354 @@ +#include "common.h"
+#include "priorities.h"
+#include "resource.h"
+#include <malloc.h>
+
+/*
+#define ID_STATUS_OFFLINE 40071 ->8
+#define ID_STATUS_ONLINE 40072 ->0
+#define ID_STATUS_AWAY 40073 ->4
+#define ID_STATUS_DND 40074 ->7
+#define ID_STATUS_NA 40075 ->6
+#define ID_STATUS_OCCUPIED 40076 ->5
+#define ID_STATUS_FREECHAT 40077 ->1
+#define ID_STATUS_INVISIBLE 40078 ->0
+#define ID_STATUS_ONTHEPHONE 40079 ->2
+#define ID_STATUS_OUTTOLUNCH 40080 ->3
+*/
+
+int status_order[10] = {8, 0, 4, 7, 6, 5, 1, 0, 2, 3};
+
+int GetDefaultPrio(int status) {
+ return status_order[status - ID_STATUS_OFFLINE];
+}
+
+typedef struct {
+ int prio[10]; // priority for each status
+ BOOL def[10]; // use default for this one?
+} ProtoStatusPrio;
+
+ProtoStatusPrio *priorities = 0;
+
+int GetRealPriority(char *proto, int status) {
+ char szSetting[256];
+ if(!proto) {
+ mir_snprintf(szSetting, 256, "DefaultPrio_%d", status);
+ return DBGetContactSettingWord(0, MODULE, szSetting, GetDefaultPrio(status));
+ } else {
+ int prio;
+ mir_snprintf(szSetting, 256, "ProtoPrio_%s%d", proto, status);
+ prio = DBGetContactSettingWord(0, MODULE, szSetting, 0xFFFF);
+ if(prio == 0xFFFF) {
+ mir_snprintf(szSetting, 256, "DefaultPrio_%d", status);
+ return DBGetContactSettingWord(0, MODULE, szSetting, GetDefaultPrio(status));
+ } else
+ return prio;
+ }
+ return 0xFFFF;
+}
+
+void ReadPriorities() {
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ char szSetting[256];
+ ProtoStatusPrio * current;
+ int i, j;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+
+ current = priorities = (ProtoStatusPrio *)malloc((num_protocols + 1) * sizeof(ProtoStatusPrio));
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ mir_snprintf(szSetting, 256, "DefaultPrio_%d", i);
+ current->def[i - ID_STATUS_OFFLINE] = TRUE;
+ current->prio[i - ID_STATUS_OFFLINE] = DBGetContactSettingWord(0, MODULE, szSetting, GetDefaultPrio(i));
+ }
+ for(i = 0; i < num_protocols; i++) {
+ current = priorities + (i + 1);
+ for(j = ID_STATUS_OFFLINE; j <= ID_STATUS_OUTTOLUNCH; j++) {
+ mir_snprintf(szSetting, 256, "ProtoPrio_%s%d", pppDesc[i]->szName, j);
+ current->prio[j - ID_STATUS_OFFLINE] = DBGetContactSettingWord(0, MODULE, szSetting, 0xFFFF);
+ current->def[j - ID_STATUS_OFFLINE] = (current->prio[j - ID_STATUS_OFFLINE] == 0xFFFF);
+ }
+ }
+}
+
+void WritePriorities() {
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ char szSetting[256];
+ ProtoStatusPrio * current = priorities;
+ int i, j;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ mir_snprintf(szSetting, 256, "DefaultPrio_%d", i);
+ if(current->prio[i - ID_STATUS_OFFLINE] != GetDefaultPrio(i))
+ DBWriteContactSettingWord(0, MODULE, szSetting, current->prio[i - ID_STATUS_OFFLINE]);
+ else
+ DBDeleteContactSetting(0, MODULE, szSetting);
+ }
+ for(i = 0; i < num_protocols; i++) {
+ current = priorities + (i + 1);
+ for(j = ID_STATUS_OFFLINE; j <= ID_STATUS_OUTTOLUNCH; j++) {
+ mir_snprintf(szSetting, 256, "ProtoPrio_%s%d", pppDesc[i]->szName, j);
+ if(!current->def[j - ID_STATUS_OFFLINE])
+ DBWriteContactSettingWord(0, MODULE, szSetting, current->prio[j - ID_STATUS_OFFLINE]);
+ else
+ DBDeleteContactSetting(0, MODULE, szSetting);
+ }
+ }
+}
+
+int GetIsDefault(int proto_index, int status) {
+ return (priorities + (proto_index + 1))->def[status - ID_STATUS_OFFLINE];
+}
+
+BOOL GetPriority(int proto_index, int status) {
+ ProtoStatusPrio * current;
+ if(proto_index == -1) {
+ current = priorities;
+ return current->prio[status - ID_STATUS_OFFLINE];
+ } else {
+ current = priorities + (proto_index + 1);
+ if(current->def[status - ID_STATUS_OFFLINE]) {
+ current = priorities;
+ }
+ return current->prio[status - ID_STATUS_OFFLINE];
+ }
+ return 0xFFFF;
+}
+
+void SetPriority(int proto_index, int status, BOOL def, int prio) {
+ ProtoStatusPrio * current;
+ if(prio < 0) prio = 0;
+ if(prio > 500) prio = 500;
+ if(proto_index == -1) {
+ current = priorities;
+ current->prio[status - ID_STATUS_OFFLINE] = prio;
+ } else {
+ current = priorities + (proto_index + 1);
+ current->def[status - ID_STATUS_OFFLINE] = def;
+ if(!def) {
+ current->prio[status - ID_STATUS_OFFLINE] = prio;
+ }
+ }
+}
+
+void ResetPriorities() {
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ ProtoStatusPrio * current;
+ int i, j;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+
+ current = priorities;
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ current->def[i - ID_STATUS_OFFLINE] = TRUE;
+ current->prio[i - ID_STATUS_OFFLINE] = GetDefaultPrio(i);
+ }
+ for(i = 0; i < num_protocols; i++) {
+ current = priorities + (i + 1);
+ for(j = ID_STATUS_OFFLINE; j <= ID_STATUS_OUTTOLUNCH; j++) {
+ current->def[j - ID_STATUS_OFFLINE] = TRUE;
+ }
+ }
+}
+
+#define WMU_FILLSTATUSCMB (WM_USER + 0x100)
+#define WMU_FILLPRIODATA (WM_USER + 0x101)
+
+BOOL CALLBACK DlgProcOptsPriorities(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hw;
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+ SendMessage(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), UDM_SETRANGE, 0, (LPARAM)MAKELONG(500, 0));
+ ReadPriorities();
+ {
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ int i, index;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+ hw = GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL);
+ index = SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TranslateT("<default>"));
+ SendMessage(hw, CB_SETITEMDATA, (WPARAM)index, -1);
+ for(i = 0; i < num_protocols; i++) {
+ if(pppDesc[i]->type == PROTOTYPE_PROTOCOL) {
+ if(strcmp(pppDesc[i]->szName, MODULE) != 0) {
+ index = SendMessageA(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)pppDesc[i]->szName);
+ SendMessage(hw, CB_SETITEMDATA, (WPARAM)index, i);
+ }
+ }
+ }
+
+ SendMessage(hw, CB_SETCURSEL, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLSTATUSCMB, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLPRIODATA, 0, 0);
+ }
+ return FALSE;
+ case WMU_FILLPRIODATA:
+ {
+ int sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETITEMDATA, (WPARAM)sel, 0);
+ sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int status = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETITEMDATA, (WPARAM)sel, 0);
+ SetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, GetPriority(index, status), FALSE);
+ if(index == -1) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PRIORITY), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), TRUE);
+ CheckDlgButton(hwndDlg, IDC_CHK_DEFAULT, TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_DEFAULT), FALSE);
+ } else {
+ if(GetIsDefault(index, status)) {
+ CheckDlgButton(hwndDlg, IDC_CHK_DEFAULT, TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PRIORITY), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), FALSE);
+ } else {
+ CheckDlgButton(hwndDlg, IDC_CHK_DEFAULT, FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PRIORITY), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), TRUE);
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_DEFAULT), TRUE);
+ }
+ }
+ }
+ }
+ return TRUE;
+ case WMU_FILLSTATUSCMB:
+ {
+ int sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETITEMDATA, (WPARAM)sel, 0);
+ HWND hw = GetDlgItem(hwndDlg, IDC_CMB_STATUS);
+ SendMessage(hw, CB_RESETCONTENT, 0, 0);
+ if(index == -1) {
+ int i;
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ index = SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)(TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, i, GCMDF_TCHAR));
+ SendMessage(hw, CB_SETITEMDATA, (WPARAM)index, i);
+ }
+ } else {
+ int num_protocols, caps, i;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+
+ caps = CallProtoService(pppDesc[index]->szName, PS_GETCAPS, PFLAGNUM_2, 0);
+
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ if(caps & Proto_Status2Flag(i)) {
+ index = SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)(TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, i, GCMDF_TCHAR));
+ SendMessage(hw, CB_SETITEMDATA, (WPARAM)index, i);
+ }
+ }
+ }
+ SendMessage(hw, CB_SETCURSEL, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLPRIODATA, 0, 0);
+ }
+ }
+ return TRUE;
+ case WM_COMMAND:
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDC_CHK_DEFAULT:
+ {
+ int sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETITEMDATA, (WPARAM)sel, 0);
+ sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ BOOL checked = IsDlgButtonChecked(hwndDlg, IDC_CHK_DEFAULT);
+ int status = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETITEMDATA, (WPARAM)sel, 0);
+ if(checked) {
+ SetPriority(index, status, TRUE, 0);
+ SetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, GetPriority(index, status), FALSE);
+ } else {
+ SetPriority(index, status, FALSE, GetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, 0, FALSE));
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PRIORITY), !checked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), !checked);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+ }
+ break;
+ case IDC_BTN_RESET:
+ ResetPriorities();
+ SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_SETCURSEL, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLSTATUSCMB, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLPRIODATA, 0, 0);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ }
+ }
+ if ( HIWORD( wParam ) == EN_CHANGE && LOWORD(wParam) == IDC_ED_PRIORITY && ( HWND )lParam == GetFocus()) {
+ int sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETITEMDATA, (WPARAM)sel, 0);
+ sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int status = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETITEMDATA, (WPARAM)sel, 0);
+ int prio = GetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, 0, FALSE);
+ SetPriority(index, status, FALSE, prio);
+ if(prio != GetPriority(index, status))
+ SetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, GetPriority(index, status), FALSE);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+ }
+ if ( HIWORD( wParam ) == CBN_SELCHANGE) {
+ switch( LOWORD( wParam )) {
+ case IDC_CMB_STATUS:
+ SendMessage(hwndDlg, WMU_FILLPRIODATA, 0, 0);
+ break;
+ case IDC_CMB_PROTOCOL:
+ SendMessage(hwndDlg, WMU_FILLSTATUSCMB, 0, 0);
+ break;
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == PSN_APPLY ) {
+ WritePriorities();
+ return TRUE;
+ }
+ break;
+ case WM_DESTROY:
+ free(priorities);
+ priorities = 0;
+ break;
+ }
+
+ return FALSE;
+}
+
+int PrioOptInit(WPARAM wParam, LPARAM lParam) {
+ OPTIONSDIALOGPAGE odp = {0};
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.flags = ODPF_BOLDGROUPS;
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_PRIORITIES);
+ odp.pszTitle = Translate("MetaContacts");
+ odp.pszGroup = Translate("Contact List");
+ odp.pszTab = Translate("Priorities");
+ odp.pfnDlgProc = DlgProcOptsPriorities;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ return 0;
+}
+
+void InitPriorities() {
+ HookEvent(ME_OPT_INITIALISE, PrioOptInit);
+}
+
+void DeinitPriorities() {
+}
diff --git a/meta2/priorities.h b/meta2/priorities.h new file mode 100644 index 0000000..3036360 --- /dev/null +++ b/meta2/priorities.h @@ -0,0 +1,6 @@ +
+
+int GetRealPriority(char *proto, int status);
+
+void InitPriorities();
+void DeinitPriorities();
diff --git a/meta2/proto.cpp b/meta2/proto.cpp new file mode 100644 index 0000000..61ff69d --- /dev/null +++ b/meta2/proto.cpp @@ -0,0 +1,547 @@ +#include "common.h"
+#include "proto.h"
+#include "resource.h"
+#include "core_functions.h"
+#include "api.h"
+#include "priorities.h"
+
+bool firstSetOnline = true;
+DWORD status = ID_STATUS_OFFLINE;
+DWORD setStatusTimerId = 0;
+
+DWORD next_meta_id = 1;
+int meta_count = 0;
+
+// a 'fake' module name for copied subcontact events - used to prevent infinite recursion when creating event copies
+#define META_COPY_MODULE "MetaCopy"
+
+HANDLE NewMetaContact() {
+ HANDLE hMeta = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
+ DBWriteContactSettingDword(hMeta, MODULE, META_ID, next_meta_id++);
+ CallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hMeta, ( LPARAM )MODULE);
+ meta_count++;
+ return hMeta;
+}
+
+
+int GetCaps(WPARAM wParam,LPARAM lParam) {
+ int ret = 0;
+ switch (wParam) {
+ case PFLAGNUM_1:
+ ret = PF1_NUMERICUSERID | PF1_IM | PF1_MODEMSGRECV | PF1_FILESEND;
+ break;
+ case PFLAGNUM_2:
+ ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND
+ | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE;
+ break;
+ case PFLAGNUM_3:
+ ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND
+ | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE;
+ break;
+ case PFLAGNUM_4:
+ ret = PF4_SUPPORTTYPING | PF4_AVATARS | PF4_SUPPORTIDLE | PF4_IMSENDUTF | PF4_IMSENDOFFLINE;
+ break;
+ case PFLAGNUM_5:
+ ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND
+ | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE;
+ break;
+ case PFLAG_UNIQUEIDTEXT:
+ ret = (int) Translate("Meta ID");
+ break;
+ case PFLAG_MAXLENOFMESSAGE:
+ ret = 2048;
+ break;
+ case PFLAG_UNIQUEIDSETTING:
+ ret = (int) META_ID;
+ break;
+ }
+ return ret;
+}
+
+int GetName(WPARAM wParam,LPARAM lParam) {
+ char *name = (char *)Translate(MODULE);
+ size_t size = min(strlen(name),wParam-1); // copy only the first size bytes.
+ if(strncpy((char *)lParam,name,size)==NULL)
+ return 1;
+ ((char *)lParam)[size]='\0';
+ return 0;
+}
+
+int LoadIcon(WPARAM wParam,LPARAM lParam) {
+
+ UINT id;
+ switch (wParam & 0xFFFF)
+ {
+ case PLI_PROTOCOL:
+ id = IDI_MCMENU;
+ break;
+ case PLI_ONLINE:
+ id = IDI_MCMENU;
+ break;
+ case PLI_OFFLINE:
+ id = IDI_MCMENUOFF;
+ break;
+ default:
+ return (int) (HICON) NULL;
+ }
+
+ return (int) LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON,
+ GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON),
+ GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0);
+ return 0;
+}
+
+int ProtoGetInfo(WPARAM wParam,LPARAM lParam) {
+ CCSDATA *ccs = ( CCSDATA* )lParam;
+
+ ccs->hContact = Meta_GetMostOnline(ccs->hContact);
+ char *proto = ContactProto(ccs->hContact);
+ if(!proto)
+ return 1;
+
+ char szServiceName[256];
+ mir_snprintf(szServiceName, 256, "%s%s", proto, PSS_GETINFO);
+ if (ServiceExists(szServiceName)) {
+ return CallContactService(ccs->hContact, PSS_GETINFO, ccs->wParam, ccs->lParam);
+ }
+ return 1;
+}
+
+int ProtoGetAwayMsg(WPARAM wParam, LPARAM lParam) {
+ CCSDATA *ccs = ( CCSDATA* )lParam;
+
+ ccs->hContact = Meta_GetMostOnline(ccs->hContact);
+ char *proto = ContactProto(ccs->hContact);
+ if(!proto)
+ return 0;
+
+ char szServiceName[256];
+ mir_snprintf(szServiceName, 256, "%s%s", proto, PSS_GETAWAYMSG);
+ if (ServiceExists(szServiceName)) {
+ return CallContactService(ccs->hContact, PSS_GETAWAYMSG, ccs->wParam, ccs->lParam);
+ }
+ return 0;
+}
+
+void CALLBACK SetStatusProc(HWND hWnd, UINT msg, UINT_PTR id, DWORD dw)
+{
+ int previousMode = status;
+ status = (int)ID_STATUS_ONLINE;
+ ProtoBroadcastAck(MODULE, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)previousMode, status);
+
+ KillTimer(0, setStatusTimerId);
+}
+
+int SetStatus(WPARAM wParam,LPARAM lParam)
+{
+ // firstSetOnline starts out true - used to delay metacontact's 'onlineness' to prevent double status notifications on startup
+ if(status == ID_STATUS_OFFLINE && firstSetOnline) {
+ // causes crash on exit if miranda is closed in under options.set_status_from_offline milliseconds!
+ //CloseHandle( CreateThread( NULL, 0, SetStatusThread, (void *)wParam, 0, 0 ));
+ setStatusTimerId = SetTimer(0, 0, 10000, SetStatusProc);
+ firstSetOnline = FALSE;
+ } else {
+ int previousMode = status;
+ status = (int)wParam;
+ ProtoBroadcastAck(MODULE, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)previousMode, status);
+ }
+ return 0;
+}
+
+int GetStatus(WPARAM wParam,LPARAM lParam) {
+ return status;
+}
+
+int ProtoSendMessage(WPARAM wParam, LPARAM lParam) {
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *message = (char *)ccs->lParam;
+ int flags = ccs->wParam;
+ char *buff = 0;
+
+ HANDLE most_online = Meta_GetMostOnline(ccs->hContact);
+ char *proto = ContactProto(most_online);
+ if(ContactStatus(most_online, proto) == ID_STATUS_OFFLINE) {
+ most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_4, PF4_IMSENDOFFLINE);
+ proto = ContactProto(most_online);
+ }
+
+ char szServiceName[256];
+ mir_snprintf(szServiceName, 256, "%s", PSS_MESSAGE);
+ if((flags & PREF_UNICODE) && proto != 0) {
+ char szTemp[256];
+ mir_snprintf(szTemp, 256, "%s%sW", proto, PSS_MESSAGE);
+ if (ServiceExists(szTemp))
+ strncpy(szServiceName, PSS_MESSAGE "W", sizeof(szServiceName));
+ }
+ if((flags & PREF_UTF) && !(CallContactService(most_online, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF)) {
+ ccs->wParam &= ~PREF_UTF;
+ ccs->wParam |= PREF_UNICODE;
+ wchar_t *unicode = mir_utf8decodeW(message);
+ char *ascii = mir_u2a(unicode);
+
+ char *buff = new char[strlen(ascii) + 1 + (wcslen(unicode) + 1) * sizeof(wchar_t)];
+ strcpy(buff, ascii);
+ wcscpy((wchar_t *)(buff + strlen(ascii) + 1), unicode);
+ mir_free(unicode);
+ mir_free(ascii);
+ ccs->lParam = (LPARAM)buff;
+ }
+
+ int ret = (int)CallContactService(most_online, szServiceName, ccs->wParam, ccs->lParam);
+ if(buff) {
+ ccs->lParam = (LPARAM)message;
+ delete[] buff;
+ }
+ return ret;
+}
+
+int ProtoSendMessageW(WPARAM wParam, LPARAM lParam) {
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ if(!(ccs->wParam & PREF_UTF))
+ ccs->wParam |= PREF_UNICODE;
+
+ return ProtoSendMessage(wParam, lParam);
+}
+
+int ProtoRecvMessage(WPARAM wParam, LPARAM lParam) {
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam;
+
+ // use the subcontact's protocol to add to the db (AIMOSCAR removes HTML here!)
+ HANDLE most_online = Meta_GetMostOnline(ccs->hContact);
+ char *proto = ContactProto(most_online);
+ if(proto) {
+ char service[256];
+ mir_snprintf(service, 256, "%s%s", proto, PSR_MESSAGE);
+ if(ServiceExists(service))
+ return CallService(service, wParam, lParam);
+ }
+
+ return 0;
+}
+
+int RedirectACKs(WPARAM wParam, LPARAM lParam)
+{
+ ACKDATA *ack = (ACKDATA*) lParam;
+ HANDLE hMeta;
+
+ if(ack->hContact == 0 || (hMeta = (HANDLE)DBGetContactSettingDword(ack->hContact, MODULE, "Handle", 0)) == 0)
+ return 0; // Can't find the MetaID, let through the protocol chain
+
+ if(!strcmp(ack->szModule, MODULE)) {
+ return 0; // don't rebroadcast our own acks
+ }
+
+ // if it's for something we don't support, ignore
+ if(ack->type != ACKTYPE_MESSAGE && ack->type != ACKTYPE_CHAT && ack->type != ACKTYPE_FILE && ack->type != ACKTYPE_AWAYMSG
+ && ack->type != ACKTYPE_AVATAR && ack->type != ACKTYPE_GETINFO)
+ {
+ return 0;
+ }
+
+ // change the hContact in the avatar info struct, if it's the avatar we're using - else drop it
+ if(ack->type == ACKTYPE_AVATAR) {
+ if(ack->result == ACKRESULT_SUCCESS || ack->result == ACKRESULT_FAILED || ack->result == ACKRESULT_STATUS) {
+ if(ack->hContact == 0) {
+ return 0;
+ }
+
+ if(ack->hProcess) {
+ PROTO_AVATAR_INFORMATION AI;
+ memcpy(&AI, (PROTO_AVATAR_INFORMATION *)ack->hProcess, sizeof(PROTO_AVATAR_INFORMATION));
+ if(AI.hContact)
+ AI.hContact = hMeta;
+
+ return ProtoBroadcastAck(MODULE,hMeta,ack->type,ack->result, (HANDLE)&AI, ack->lParam);
+ } else
+ return ProtoBroadcastAck(MODULE,hMeta,ack->type,ack->result, 0, ack->lParam);
+ }
+ }
+
+ return ProtoBroadcastAck(MODULE, hMeta, ack->type, ack->result, ack->hProcess, ack->lParam);
+}
+
+int ProtoGetAvatarInfo(WPARAM wParam, LPARAM lParam) {
+ PROTO_AVATAR_INFORMATION *AI = (PROTO_AVATAR_INFORMATION *) lParam;
+
+ HANDLE hMeta = AI->hContact;
+
+ // find the most online contact supporting avatars, according to priorities
+ HANDLE most_online = (HANDLE)Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_4, PF4_AVATARS);
+ char *most_online_proto = ContactProto(most_online);
+
+ AI->hContact = most_online;
+ char szServiceName[100];
+ mir_snprintf(szServiceName, sizeof(szServiceName), "%s%s", most_online_proto, PS_GETAVATARINFO);
+ int result = CallService(szServiceName, wParam, lParam);
+ AI->hContact = hMeta;
+ if (result != CALLSERVICE_NOTFOUND) return result;
+
+ return GAIR_NOAVATAR; // fail
+}
+
+int ProtoFileSend(WPARAM wParam, LPARAM lParam) {
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ HANDLE hMeta = ccs->hContact;
+
+ // find the most online contact supporting file send, according to priorities
+ HANDLE most_online = (HANDLE)Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_1, PF1_FILESEND);
+ char *most_online_proto = ContactProto(most_online);
+
+ ccs->hContact = most_online;
+ char szServiceName[100];
+ mir_snprintf(szServiceName, sizeof(szServiceName), "%s%s", most_online_proto, PSS_FILE);
+ int result = CallService(szServiceName, wParam, lParam);
+ ccs->hContact = hMeta;
+ if(result != CALLSERVICE_NOTFOUND) return result;
+
+ return 0; // fail
+}
+
+int ProtoUserIsTyping(WPARAM wParam, LPARAM lParam) {
+ HANDLE hMeta = (HANDLE)wParam;
+ // find the most online contact supporting file send, according to priorities
+ HANDLE most_online = (HANDLE)Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_4, PF4_SUPPORTTYPING);
+ char *most_online_proto = ContactProto(most_online);
+
+ CallContactService(most_online, PSS_USERISTYPING, (WPARAM)most_online, lParam);
+ return 0;
+}
+
+int EventContactIsTyping(WPARAM wParam, LPARAM lParam) {
+ HANDLE hMeta;
+
+ if((hMeta = (HANDLE)DBGetContactSettingDword((HANDLE)wParam, MODULE, "Handle", 0)) != 0 && MetaEnabled()) {
+ // try to remove any clist events added for subcontact
+ CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1);
+
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hMeta, lParam);
+
+ // stop processing of event
+ return 1;
+ }
+
+ return 0;
+}
+
+int SendNudge(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hMeta = (HANDLE)wParam,
+ hSubContact = Meta_GetMostOnline(hMeta);
+
+ char servicefunction[256];
+ char *protoName = ContactProto(hSubContact);
+ mir_snprintf(servicefunction, 256, "%s/SendNudge", protoName);
+
+ return CallService(servicefunction, (WPARAM)hSubContact, lParam);
+}
+
+int ContactDeleted(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+ if(IsSubcontact(hContact))
+ Meta_Remove(hContact);
+ else if(IsMetacontact(hContact)) {
+ SubcontactList::Iterator i = metaMap[hContact].start();
+ HANDLE hSub;
+ while(i.has_val()) {
+ // same functionality as Meta_Remove - except the meta is not deleted when all subcontacts are removed here since it's already happening,
+ // and the 'subcontacts changed' event isn't fired
+ hSub = i.val().handle();
+ DBDeleteContactSetting(hSub, MODULE, "ParentMetaID");
+ // deleting these (resident) settings doesn't work :( [25/9/07]
+ DBWriteContactSettingDword(hSub, MODULE, "Handle", 0);
+ DBWriteContactSettingByte(hSub, MODULE, "IsSubcontact", 0);
+ if(!meta_group_hack_disabled) DBWriteContactSettingByte(hSub, "CList", "Hidden", 0);
+
+ i.next();
+ }
+ metaMap.remove(hContact);
+ meta_count--;
+ }
+ return 0;
+}
+
+int SettingChanged(WPARAM wParam, LPARAM lParam) {
+ if(wParam == 0 || !IsSubcontact((HANDLE)wParam)) return 0;
+
+ DBCONTACTWRITESETTING *dcws = (DBCONTACTWRITESETTING *)lParam;
+ if(strcmp(dcws->szSetting, "Status") == 0) {
+ // subcontact status has changed
+ Meta_CalcStatus((HANDLE)DBGetContactSettingDword((HANDLE)wParam, MODULE, "Handle", 0));
+ }
+
+ // keep subcontacts hidden if the clist doesn't do it for us
+ if(strcmp(dcws->szSetting, "Hidden") == 0 && strcmp(dcws->szModule, "CList") == 0 && MetaEnabled() && !meta_group_hack_disabled) {
+ if(dcws->value.type == DBVT_DELETED || dcws->value.bVal == 0) {
+ DBWriteContactSettingByte((HANDLE)wParam, "CList", "Hidden", 1);
+ }
+ }
+
+ return 0;
+}
+
+int MetaChanged(WPARAM wParam, LPARAM lParam) {
+ Meta_CalcStatus((HANDLE)wParam);
+ return 0;
+}
+
+int WindowEvent(WPARAM wParam, LPARAM lParam) {
+ MessageWindowEventData *mwed = (MessageWindowEventData *)lParam;
+ if(IsMetacontact(mwed->hContact) || IsSubcontact(mwed->hContact)) {
+ if(mwed->uType == MSG_WINDOW_EVT_OPEN || mwed->uType == MSG_WINDOW_EVT_OPENING) {
+ DBWriteContactSettingByte(mwed->hContact, MODULE, "WindowOpen", 1);
+ if(IsMetacontact(mwed->hContact))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)mwed->hContact, (LPARAM)EVENTTYPE_MESSAGE);
+ } else if(mwed->uType == MSG_WINDOW_EVT_CLOSE || mwed->uType == MSG_WINDOW_EVT_CLOSING)
+ DBWriteContactSettingByte(mwed->hContact, MODULE, "WindowOpen", 0);
+
+ }
+ return 0;
+}
+
+void RegisterProto() {
+ PROTOCOLDESCRIPTOR pd = {0};
+ pd.cbSize = sizeof(pd);
+ pd.szName = MODULE;
+ pd.type = PROTOTYPE_PROTOCOL;
+ CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);
+}
+
+// redirect events to subcontact (except the ones we add in the EventAdded handler below - i.e. dbei->szModule == META_COPY_MODULE)
+int EventFilterAdd(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+ DBEVENTINFO *dbei = (DBEVENTINFO *)lParam;
+
+ if(IsMetacontact(hContact) && strcmp(dbei->szModule, MODULE) == 0) {
+ // add the event to the subcontact instead
+ HANDLE most_online = Meta_GetMostOnline(hContact);
+ dbei->szModule = ContactProto(most_online);
+ CallService(MS_DB_EVENT_ADD, (WPARAM)most_online, (LPARAM)dbei);
+ return 1; // don't add original event
+ }
+ if(IsSubcontact(hContact)) {
+ if(dbei->eventType == EVENTTYPE_MESSAGE && !(dbei->flags & DBEF_SENT) && DBGetContactSettingByte(hContact, MODULE, "WindowOpen", 0) == 0) {
+ dbei->flags |= DBEF_READ;
+ }
+ }
+
+ return 0;
+}
+
+// add subcontact events to metacontacts
+int EventAdded(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam,
+ hDbEvent = (HANDLE)lParam,
+ hMeta;
+
+ if(MetaEnabled() && (hMeta = (HANDLE)DBGetContactSettingDword(hContact, MODULE, "Handle", 0)) != 0) {
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = (int)CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0);
+ dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob);
+ if(CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei) == 0) {
+ if(dbei.eventType < EVENTTYPE_ADDED) {
+ DBEVENTINFO dbeiMeta = {0};
+ dbeiMeta.cbSize = sizeof(dbeiMeta);
+ dbeiMeta.eventType = dbei.eventType;
+ dbeiMeta.flags = dbei.flags & ~DBEF_READ;
+ dbeiMeta.cbBlob = dbei.cbBlob;
+ dbeiMeta.pBlob = dbei.pBlob;
+ dbeiMeta.szModule = dbei.szModule;
+ dbeiMeta.timestamp = dbei.timestamp;
+
+ if(dbei.eventType == EVENTTYPE_MESSAGE) {
+ if(!(dbeiMeta.flags & DBEF_SENT)
+ && DBGetContactSettingByte(hContact, MODULE, "WindowOpen", 0) == 1
+ && DBGetContactSettingByte(hMeta, MODULE, "WindowOpen", 0) == 0)
+ {
+ dbeiMeta.flags |= DBEF_READ;
+ }
+
+ // set default
+ int num = metaMap[hMeta].index_of(hContact);
+ if(num != -1 && num != DBGetContactSettingByte(hMeta, MODULE, "Default", -1))
+ MetaAPI_SetDefaultContactNum((WPARAM)hMeta, (LPARAM)num);
+
+ // set meta nick
+ char *proto = ContactProto(hContact);
+ DBVARIANT dbv;
+ if(proto && !DBGetContactSettingUTF8String(0, proto, "Nick", &dbv)) {
+ DBWriteContactSettingUTF8String(0, MODULE, "Nick", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ CallService(MS_DB_EVENT_ADD, (WPARAM)hMeta, (LPARAM)&dbeiMeta);
+ }
+ }
+ mir_free(dbei.pBlob);
+ }
+
+ return 0;
+}
+
+HANDLE hEventMessageWindow = 0;
+int ModulesLoadedProto(WPARAM wParam, LPARAM lParam) {
+ hEventMessageWindow = (HANDLE)HookEvent(ME_MSG_WINDOWEVENT, WindowEvent);
+
+ Meta_Hide(DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 0);
+ return 0;
+}
+
+#define NUM_SERVICES 14
+HANDLE hServices[NUM_SERVICES] = {0}, hEventContactDeleted = 0, hEventSettingChanged = 0;
+#define NUM_HOOKS_INTERNAL 8
+HANDLE hHooksInternal[NUM_HOOKS_INTERNAL] = {0};
+
+void InitProto() {
+ RegisterProto();
+
+ // create our services
+ int i = 0;
+
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETCAPS, GetCaps);
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETNAME, GetName);
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PS_LOADICON, LoadIcon);
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PS_SETSTATUS, SetStatus);
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETSTATUS, GetStatus);
+
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_GETINFO, ProtoGetInfo);
+
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_MESSAGE, ProtoSendMessage);
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_MESSAGE"W", ProtoSendMessageW);
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PSR_MESSAGE, ProtoRecvMessage);
+
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_GETAWAYMSG, ProtoGetAwayMsg);
+
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETAVATARINFO, ProtoGetAvatarInfo);
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_FILE, ProtoFileSend);
+ hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_USERISTYPING, ProtoUserIsTyping);
+
+ // REMEMBER to modify the NUM_SERVICES #define above if you add more services!
+
+ hServices[i++] = CreateProtoServiceFunction(MODULE, "/SendNudge", SendNudge);
+
+ hEventContactDeleted = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted);
+ hEventSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingChanged);
+
+ i = 0;
+ hHooksInternal[i++] = (HANDLE)HookEvent(ME_MC_DEFAULTTCHANGED, MetaChanged );
+ hHooksInternal[i++] = (HANDLE)HookEvent(ME_MC_FORCESEND, MetaChanged );
+ hHooksInternal[i++] = (HANDLE)HookEvent(ME_MC_UNFORCESEND, MetaChanged );
+ hHooksInternal[i++] = (HANDLE)HookEvent(ME_PROTO_ACK, RedirectACKs);
+ hHooksInternal[i++] = (HANDLE)HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoadedProto);
+ hHooksInternal[i++] = (HANDLE)HookEvent(ME_DB_EVENT_ADDED, EventAdded);
+ hHooksInternal[i++] = (HANDLE)HookEvent(ME_DB_EVENT_FILTER_ADD, EventFilterAdd);
+ hHooksInternal[i++] = (HANDLE)HookEvent(ME_PROTO_CONTACTISTYPING, EventContactIsTyping);
+}
+
+void DeinitProto() {
+ UnhookEvent(hEventMessageWindow);
+ UnhookEvent(hEventSettingChanged);
+ UnhookEvent(hEventContactDeleted);
+ for(int i = 0; i < NUM_SERVICES; i++)
+ DestroyServiceFunction(hServices[i]);
+ for(int i = 0; i < NUM_HOOKS_INTERNAL; i++)
+ UnhookEvent(hHooksInternal[i]);
+
+}
\ No newline at end of file diff --git a/meta2/proto.h b/meta2/proto.h new file mode 100644 index 0000000..176791e --- /dev/null +++ b/meta2/proto.h @@ -0,0 +1,11 @@ +#ifndef _FILTER_INC
+#define _FILTER_INC
+
+void InitProto();
+void DeinitProto();
+
+HANDLE NewMetaContact();
+
+#define META_ID "MetaID"
+
+#endif
diff --git a/meta2/resource.h b/meta2/resource.h new file mode 100644 index 0000000..7462749 --- /dev/null +++ b/meta2/resource.h @@ -0,0 +1,45 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by meta2.rc
+//
+#define IDD_OPT1 109
+#define IDI_MCSETDEFAULT 120
+#define IDI_MCMENU 121
+#define IDI_MCMENUOFF 122
+#define IDI_MCMENUOFF2 123
+#define IDI_MCADD 124
+#define IDI_MCCONVERT 125
+#define IDI_MCEDIT 126
+#define IDI_MCREMOVE 127
+
+#define IDD_PRIORITIES 128
+#define IDC_ED_PRIORITY 1001
+#define IDC_SP_PRIORITY 1002
+#define IDC_CMB_STATUS 1003
+#define IDC_CMB_PROTOCOL 1004
+#define IDC_BTN_RESET 1005
+#define IDC_CHK_DEFAULT 1006
+
+#define IDD_METASELECT 129
+#define IDC_METALIST 1007
+#define IDC_CHK_SRT 1008
+
+#define IDD_METAEDIT 130
+#define IDC_VALIDATE 1009
+#define IDC_BTN_REM 1010
+#define IDC_BTN_SETDEFAULT 1011
+#define IDC_ED_NAME 1012
+#define IDC_LST_CONTACTS 1013
+
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 131
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1014
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/meta2/resource.rc b/meta2/resource.rc new file mode 100644 index 0000000..f8cad6f --- /dev/null +++ b/meta2/resource.rc @@ -0,0 +1,2 @@ +#include "version.rc"
+#include "meta2.rc"
diff --git a/meta2/select_meta.cpp b/meta2/select_meta.cpp new file mode 100644 index 0000000..74df9c5 --- /dev/null +++ b/meta2/select_meta.cpp @@ -0,0 +1,95 @@ +#include "common.h"
+#include "select_meta.h"
+#include "resource.h"
+#include "icons.h"
+
+
+void FillList(HWND list, bool sort)
+{
+ SendMessage(list, LB_RESETCONTENT, 0, 0);
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ int count = 0;
+ while(hContact) {
+ if(!IsMetacontact(hContact)) {
+ // This isn't a MetaContact, go to the next
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ continue;
+ }
+
+ // get contact display name from clist
+ TCHAR *szCDN = (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+ int index;
+ if(sort) {
+ int j;
+ TCHAR buff[1024];
+ for(j = 0; j < count; j++) {
+ SendMessageW(list, LB_GETTEXT, j, (LPARAM)buff);
+ if(_tcscmp(buff, szCDN) > 0) break;
+ }
+ index = SendMessageW(list, LB_INSERTSTRING, (WPARAM)j, (LPARAM)szCDN);
+ } else
+ index = SendMessage(list, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szCDN);
+ SendMessage(list, LB_SETITEMDATA, (WPARAM)index, (LPARAM)hContact);
+ count++;
+
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+}
+
+BOOL CALLBACK Meta_SelectDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault( hwndDlg );
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx(I_ADD));
+ SetWindowText(hwndDlg, (TCHAR *)lParam);
+ FillList(GetDlgItem(hwndDlg, IDC_METALIST), false);
+ }
+ case WM_COMMAND:
+ if(HIWORD(wParam) == BN_CLICKED) {
+ switch(LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ HANDLE hContact = (HANDLE)GetWindowLong(hwndDlg, GWL_USERDATA);
+ int item = SendMessage(GetDlgItem(hwndDlg, IDC_METALIST),LB_GETCURSEL, 0, 0);
+ HANDLE hMeta = (HANDLE)SendMessage(GetDlgItem(hwndDlg, IDC_METALIST), LB_GETITEMDATA, (WPARAM)item, 0);
+
+ EndDialog(hwndDlg, (INT_PTR)hMeta);
+ break;
+ }
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ break;
+
+ case IDC_CHK_SRT:
+ FillList(GetDlgItem(hwndDlg,IDC_METALIST), IsDlgButtonChecked(hwndDlg, IDC_CHK_SRT));
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
+ break;
+ }
+ return TRUE;
+ }
+ if(LOWORD(wParam) == IDC_METALIST && HIWORD(wParam) == LBN_SELCHANGE) {
+ int item = SendMessage(GetDlgItem(hwndDlg, IDC_METALIST),LB_GETCURSEL, 0, 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), item != -1);
+ }
+ break;
+ case WM_DESTROY:
+ { // Free all allocated memory and return the focus to the CList
+ HWND clist = GetParent(hwndDlg);
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
+ EndDialog(hwndDlg,TRUE);
+ SetFocus(clist);
+ return TRUE;
+ }
+ }
+ return FALSE; // All other Message are not handled
+}
+
+
+HANDLE SelectMeta(TCHAR *msg) {
+ HWND clui = (HWND)CallService(MS_CLUI_GETHWND,0,0);
+ return (HANDLE)DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_METASELECT), clui, Meta_SelectDialogProc, (WPARAM)msg);
+}
\ No newline at end of file diff --git a/meta2/select_meta.h b/meta2/select_meta.h new file mode 100644 index 0000000..0547cad --- /dev/null +++ b/meta2/select_meta.h @@ -0,0 +1,2 @@ +
+HANDLE SelectMeta(TCHAR *msg);
\ No newline at end of file diff --git a/meta2/settings.cpp b/meta2/settings.cpp new file mode 100644 index 0000000..06c9b9f --- /dev/null +++ b/meta2/settings.cpp @@ -0,0 +1,110 @@ +#include "common.h"
+#include "settings.h"
+#include "core_functions.h"
+
+PLUGINLINK *core_link = 0;
+typedef int (*ServiceFunc)(const char *,WPARAM,LPARAM);
+ServiceFunc coreCallService, coreCallServiceSync;
+
+int ServiceFuncRedirect(const char *service,WPARAM wParam, LPARAM lParam, ServiceFunc coreServiceFunc) {
+ if(wParam ==0
+ || strncmp(service, "DB/Contact/", 11) != 0
+ || (strcmp(MS_DB_CONTACT_GETSETTING, service) != 0
+ && strcmp(MS_DB_CONTACT_GETSETTING_STR, service) != 0
+ && strcmp(MS_DB_CONTACT_GETSETTINGSTATIC, service) != 0
+ && strcmp(MS_DB_CONTACT_WRITESETTING, service) != 0
+ && strcmp(MS_DB_CONTACT_DELETESETTING, service) != 0
+ && strcmp(MS_DB_CONTACT_ENUMSETTINGS, service) != 0))
+ {
+ return coreServiceFunc(service, wParam, lParam);
+ }
+
+ HANDLE hContact = (HANDLE)wParam;
+ if(strcmp(MS_DB_CONTACT_ENUMSETTINGS, service) == 0) {
+ DBCONTACTENUMSETTINGS *ces = (DBCONTACTENUMSETTINGS *)lParam;
+ if(IsMetacontact(hContact) && strcmp(ces->szModule, MODULE) != 0) {
+ HANDLE hSub = Meta_GetMostOnline(hContact);
+ return coreServiceFunc(service, (WPARAM)hSub, lParam);
+ } else
+ return coreServiceFunc(service, wParam, lParam);
+ }
+
+ const char *szSetting = 0, *szModule = 0;
+ bool read; // true for get setting, false for write setting
+ if(strcmp(MS_DB_CONTACT_WRITESETTING, service) == 0 || strcmp(MS_DB_CONTACT_DELETESETTING, service)) {
+ read = false;
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *)lParam;
+ szSetting = cws->szSetting;
+ szModule = cws->szModule;
+ } else { // get setting
+ read = true;
+ DBCONTACTGETSETTING *cgs = (DBCONTACTGETSETTING *)lParam;
+ szSetting = cgs->szSetting;
+ szModule = cgs->szModule;
+ }
+
+ if(szModule == 0 || szSetting == 0
+ || strcmp(szModule, "Protocol") == 0
+ || strcmp(szModule, "_Filter") == 0
+ || (strcmp(szModule, MODULE) == 0
+ && (strcmp(szSetting, "MetaID") == 0
+ || strcmp(szSetting, "IsSubcontact") == 0
+ || strcmp(szSetting, "Default") == 0
+ || strcmp(szSetting, "Handle") == 0
+ || strcmp(szSetting, "WindowOpen") == 0
+ || strcmp(szSetting, "ParentMetaID") == 0
+ || strcmp(szSetting, "Status") == 0))
+ || !IsMetacontact(hContact))
+ {
+ return coreServiceFunc(service, wParam, lParam);
+ }
+
+ HANDLE hMeta = hContact;
+ int ret;
+ if((ret = coreServiceFunc(service, (WPARAM)hMeta, lParam)) != 0) {
+ // if the setting does not exist in the metacontact, get it from the most online subcontact
+ HANDLE hSub = Meta_GetMostOnline(hMeta);
+ if(!hSub) return ret; // no most online - fail
+ if((ret = coreServiceFunc(service, (WPARAM)hSub, lParam)) != 0) {
+ // if it does not exist in the subcontact and we're using the meta proto module, try changing the module to the subcontact proto module
+ if(strcmp(szModule, MODULE) == 0) {
+ char *subProto = ContactProto(hSub);
+ if(subProto) {
+ if(read) {
+ DBCONTACTGETSETTING *cgs = (DBCONTACTGETSETTING *)lParam;
+ cgs->szModule = MODULE;
+ } else {
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *)lParam;
+ cws->szModule = MODULE;
+ }
+ return coreServiceFunc(service, (WPARAM)hSub, lParam);
+ } else
+ return ret; // no subcontact proto - fail
+ } else
+ return ret; // not reading from meta proto module - fail
+ } else
+ return 0; // got from subcontact
+ } else
+ return 0; // got from metacontact
+}
+
+int CallServiceRedirect(const char *service,WPARAM wParam, LPARAM lParam) {
+ return ServiceFuncRedirect(service, wParam, lParam, coreCallService);
+}
+
+int CallServiceSyncRedirect(const char *service,WPARAM wParam, LPARAM lParam) {
+ return ServiceFuncRedirect(service, wParam, lParam, coreCallServiceSync);
+}
+
+void InitSettings(PLUGINLINK *link) {
+ core_link = link;
+ coreCallService = core_link->CallService;
+ coreCallServiceSync = core_link->CallServiceSync;
+ core_link->CallService = CallServiceRedirect;
+ core_link->CallServiceSync = CallServiceSyncRedirect;
+}
+
+void DeinitSettings() {
+ core_link->CallService = coreCallService;
+ core_link->CallServiceSync = coreCallServiceSync;
+}
\ No newline at end of file diff --git a/meta2/settings.h b/meta2/settings.h new file mode 100644 index 0000000..f8b0f31 --- /dev/null +++ b/meta2/settings.h @@ -0,0 +1,4 @@ +#include <newpluginapi.h>
+
+void InitSettings(PLUGINLINK *link);
+void DeinitSettings();
\ No newline at end of file diff --git a/meta2/version.h b/meta2/version.h new file mode 100644 index 0000000..81ba1a8 --- /dev/null +++ b/meta2/version.h @@ -0,0 +1,26 @@ +// Set the version number here - it will affect the version resource and the version field of the pluginInfo structure
+// (Be careful that you don't have the resource file open when you change this and rebuild, otherwise the changes may not
+// take effect within the version resource)
+
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 0
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 1
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+#define __FILEVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
+#define __STRINGIFY(x) #x
+#define __VERSION_STRING __STRINGIFY(__FILEVERSION_STRING_DOTS)
+
+#ifdef _UNICODE
+#define __PLUGIN_NAME "meta2 (Unicode)"
+#else
+#define __PLUGIN_NAME "meta2"
+#endif
+#define __FILENAME "meta2.dll"
+
+#define __DESC "Merges multiple contacts into one"
+#define __AUTHOR "Scott Ellis"
+#define __AUTHOREMAIL "mail@scottellis.com.au"
+#define __AUTHORWEB "http://www.scottellis.com.au"
+#define __COPYRIGHT "© 2007 Scott Ellis"
diff --git a/meta2/version.rc b/meta2/version.rc new file mode 100644 index 0000000..0bb7a49 --- /dev/null +++ b/meta2/version.rc @@ -0,0 +1,33 @@ +
+#include <windows.h>
+#include "version.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __FILEVERSION_STRING
+ PRODUCTVERSION __FILEVERSION_STRING
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Author", __AUTHOR
+ VALUE "FileDescription", __DESC
+ VALUE "InternalName", __PLUGIN_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ VALUE "OriginalFilename", __FILENAME
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
|