/* Show Contact Gender plugin for Miranda-IM (www.miranda-im.org) (c) 2006-2011 by Thief 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 name : $URL: http://svn.miranda.im/mainrepo/gender/trunk/main.cpp $ Revision : $Rev: 1688 $ Last change on : $Date: 2011-01-22 19:44:43 +0200 (Сб, 22 янв 2011) $ Last change by : $Author: Thief $ */ #include "commonheaders.h" HINSTANCE g_hInst; static HANDLE hHookModulesLoaded = NULL, hSystemOKToExit = NULL, hOptInitialise = NULL, hIcoLibIconsChanged = NULL; static HANDLE hHookExtraIconsRebuild = NULL, hHookExtraIconsApply = NULL, hContactMenu = NULL; static HANDLE hContactMenuMale = NULL, hContactMenuFemale = NULL, hContactMenuNotDef = NULL, hHookPrebuildContactMenu = NULL; static HANDLE hSetMale = NULL, hSetFemale = NULL, hSetUndef = NULL, hGenderGetIcon = NULL; HANDLE g_hExtraIcon = NULL; HANDLE g_hIconMale, g_hIconFemale, g_hIconMenu; IconExtraColumn g_IECMale = {0}; IconExtraColumn g_IECFemale = {0}; IconExtraColumn g_IECUndef = {0}; IconExtraColumn g_IECClear = {0}; int clistIcon = 0; // Icon slot to use byte bEnableClistIcon = 1; // do we need clist icon? byte bDrawNoGenderIcon = 0; // enable icon when no info? byte bContactMenuItems = 1; // do we need a contact menu items? byte bMetaAvail = 0; // metacontacts installed? int hLangpack; extern int onOptInitialise(WPARAM wParam, LPARAM lParam); PLUGININFOEX pluginInfo={ sizeof(PLUGININFOEX), "Show Contact Gender", PLUGIN_MAKE_VERSION(0,0,2,1), "Shows contacts gender as an icon in contact list", "Thief, idea by nile, icons by a0x", "thief@miranda.im", "2006-2011 Alexander Turyak", "http://thief.miranda.im/", UNICODE_AWARE, //doesn't replace anything built-in {0xfb1c17e0, 0x77fc, 0x45a7, {0x9c, 0x8b, 0xe2, 0xbe, 0xf4, 0xf5, 0x6b, 0x28}} /* FB1C17E0-77FC-45A7-9C8B-E2BEF4F56B28 */ }; extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { g_hInst = hinstDLL; return TRUE; } /* 0FF3991A-5505-479D-A2E0-53DD31C6DFA7 */ #define MIID_GENDER {0x0ff3991a, 0x5505, 0x479d, {0xa2, 0xe0, 0x53, 0xdd, 0x31, 0xc6, 0xdf, 0xa7}} extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_GENDER, MIID_LAST}; extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) { return &pluginInfo; } void setIcon(HANDLE hContact, unsigned int gender) { if (g_hExtraIcon != NULL) { char *ico; switch (gender) { case 77: ico = "male_icon"; break; case 70: ico = "female_icon"; break; default: ico = (bDrawNoGenderIcon ? "menu_icon" : NULL); break; } ExtraIcon_SetIcon(g_hExtraIcon, hContact, ico); } else { IconExtraColumn *col; switch (gender) { case 77: col = &g_IECMale; break; case 70: col = &g_IECFemale; break; default: col = (bDrawNoGenderIcon ? &g_IECUndef : &g_IECClear); break; } CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)col); } } int onExtraImageApplying(WPARAM wParam, LPARAM lParam) { if (g_hExtraIcon == NULL && !bEnableClistIcon) return 0; HANDLE hContact = (HANDLE)wParam; if (bMetaAvail) { HANDLE hMetacontact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, wParam, 0); if (hMetacontact != NULL) hContact = hMetacontact; } char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); if (!proto) return 0; if (DBGetContactSettingByte((HANDLE)wParam, proto, "ChatRoom", 0)) return 0; unsigned int gender = DBGetContactSettingByte(hContact, "UserInfo", "Gender", DBGetContactSettingByte(hContact, proto, "Gender", 0)); setIcon(hContact, gender); if ((HANDLE)wParam != hContact) setIcon((HANDLE)wParam, gender); return 0; } int onExtraImageListRebuild(WPARAM wParam, LPARAM lParam) { g_IECMale.cbSize = sizeof(IconExtraColumn); g_IECMale.ColumnType = clistIcon; g_IECFemale.cbSize = sizeof(IconExtraColumn); g_IECFemale.ColumnType = clistIcon; g_IECUndef.cbSize = sizeof(IconExtraColumn); g_IECUndef.ColumnType = clistIcon; if (ServiceExists(MS_CLIST_EXTRA_ADD_ICON)) { if(hIcoLibIconsChanged) { g_IECMale.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconMale), (LPARAM)0); g_IECFemale.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconFemale), (LPARAM)0); g_IECUndef.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconMenu), (LPARAM)0); } } return 0; } // Returns gender icon for specific contact INT_PTR GetIcon(WPARAM wParam, LPARAM lParam) { char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); unsigned short gender = DBGetContactSettingByte((HANDLE)wParam, "UserInfo", "Gender", DBGetContactSettingByte((HANDLE)wParam, proto, "Gender", 0)); if (gender > 0) { if (gender == 77) return CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconMale); else if (gender == 70) return CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconFemale); } return 0; } int onPrebuildContactMenu(WPARAM wParam, LPARAM lParam) { char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); if (!proto) return 0; CLISTMENUITEM mi = {0}; mi.cbSize = sizeof(CLISTMENUITEM); if (DBGetContactSettingByte((HANDLE)wParam, proto, "ChatRoom", 0) || !(CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND)) mi.flags = CMIM_FLAGS | CMIF_HIDDEN; else mi.flags = CMIM_FLAGS; CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenu, (LPARAM)&mi); unsigned short gender = DBGetContactSettingByte((HANDLE)wParam, proto, "Gender", DBGetContactSettingByte((HANDLE)wParam, "UserInfo", "Gender", 0)); CLISTMENUITEM mitem = {0}; mitem.cbSize = sizeof(CLISTMENUITEM); mitem.flags = CMIM_FLAGS; CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuMale, (LPARAM)&mitem); CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuFemale, (LPARAM)&mitem); CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuNotDef, (LPARAM)&mitem); mitem.flags = CMIM_FLAGS | CMIF_CHECKED; switch (gender) { case 77: CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuMale, (LPARAM)&mitem); break; case 70: CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuFemale, (LPARAM)&mitem); break; case 0: CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuNotDef, (LPARAM)&mitem); break; } return 0; } void setGender(HANDLE hContact, unsigned int gender) { DBWriteContactSettingByte(hContact, "UserInfo", "Gender", gender); setIcon(hContact, gender); int metasnum = (bMetaAvail ? CallService(MS_MC_GETNUMCONTACTS,(WPARAM)hContact,0) : 0); for(int i=0; i<metasnum; i++) { HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETSUBCONTACT, (WPARAM)hContact, i); DBWriteContactSettingByte(hSubContact, "UserInfo", "Gender", gender); setIcon(hSubContact, gender); } } INT_PTR onSetMale(WPARAM wParam,LPARAM lParam) { setGender((HANDLE)wParam, 77); return 0; } INT_PTR onSetFemale(WPARAM wParam,LPARAM lParam) { setGender((HANDLE)wParam, 70); return 0; } INT_PTR onSetUndef(WPARAM wParam,LPARAM lParam) { DBDeleteContactSetting((HANDLE)wParam, "UserInfo", "Gender"); onExtraImageApplying(wParam, 0); int metasnum = (bMetaAvail ? CallService(MS_MC_GETNUMCONTACTS,wParam,0) : 0); for(int i=0; i<metasnum; i++) { HANDLE hContact = (HANDLE)CallService(MS_MC_GETSUBCONTACT, wParam, i); DBDeleteContactSetting(hContact, "UserInfo", "Gender"); onExtraImageApplying((WPARAM)hContact, 0); } return 0; } int onModulesLoaded(WPARAM wParam,LPARAM lParam) { hOptInitialise = HookEvent(ME_OPT_INITIALISE, onOptInitialise); if (bContactMenuItems) hHookPrebuildContactMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, onPrebuildContactMenu); bMetaAvail = (ServiceExists(MS_MC_GETMETACONTACT) != 0); //IcoLib support SKINICONDESC sid = {0}; sid.cbSize = sizeof(sid); sid.flags = SIDF_ALL_TCHAR; sid.ptszSection = LPGENT("Gender"); TCHAR szFile[MAX_PATH]; GetModuleFileName(g_hInst, szFile, MAX_PATH); sid.ptszDefaultFile = szFile; sid.ptszDescription = LPGENT("Male"); sid.pszName = "male_icon"; sid.iDefaultIndex = -IDI_MALE; g_hIconMale = Skin_AddIcon(&sid); sid.ptszDescription = LPGENT("Female"); sid.pszName = "female_icon"; sid.iDefaultIndex = -IDI_FEMALE; g_hIconFemale = Skin_AddIcon(&sid); sid.ptszDescription = LPGENT("No info"); sid.pszName = "menu_icon"; sid.iDefaultIndex = -IDI_UNDEF; g_hIconMenu = Skin_AddIcon(&sid); hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, onExtraImageListRebuild); g_hExtraIcon = ExtraIcon_Register("gender", "Gender", "menu_icon"); if (g_hExtraIcon != NULL) { HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); while (hContact != NULL) { onExtraImageApplying((WPARAM) hContact, 0); hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); } } else { hHookExtraIconsRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, onExtraImageListRebuild); hHookExtraIconsApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, onExtraImageApplying); onExtraImageListRebuild(0,0); } // Adding menu items, submenu even if clist supports that if (bContactMenuItems) { if(ServiceExists(MS_CLIST_MENUBUILDSUBGROUP)) { CLISTMENUITEM mi = {0}; mi.cbSize = sizeof(CLISTMENUITEM); mi.flags = CMIF_ROOTPOPUP | CMIF_ICONFROMICOLIB | CMIF_TCHAR; mi.icolibItem = g_hIconMenu; mi.pszPopupName = (char*)-1; mi.position = 203; mi.ptszName = LPGENT("Set Gender"); mi.pszService = NULL; hContactMenu = Menu_AddContactMenuItem(&mi); mi.flags = CMIF_CHILDPOPUP | CMIF_ICONFROMICOLIB | CMIF_TCHAR; mi.position = 1001; mi.pszPopupName = (char*)hContactMenu; mi.ptszName = LPGENT("Male"); mi.icolibItem = g_hIconMale; mi.pszService = "Gender/MenuItemSetMale"; hContactMenuMale = Menu_AddContactMenuItem(&mi); mi.ptszName = LPGENT("Female"); mi.icolibItem = g_hIconFemale; mi.pszService = "Gender/MenuItemSetFemale"; hContactMenuFemale = Menu_AddContactMenuItem(&mi); mi.ptszName = LPGENT("Undefined"); mi.hIcon = NULL; mi.pszService = "Gender/MenuItemSetUndef"; hContactMenuNotDef = Menu_AddContactMenuItem(&mi); } else { CLISTMENUITEM mi = {0}; mi.cbSize = sizeof(CLISTMENUITEM); mi.flags = CMIF_ICONFROMICOLIB | CMIF_TCHAR; mi.position = 1001; mi.ptszName = LPGENT("Set Male"); mi.icolibItem = g_hIconMale; mi.pszService = "Gender/MenuItemSetMale"; hContactMenuMale = Menu_AddContactMenuItem(&mi); mi.flags = CMIF_ICONFROMICOLIB | CMIF_TCHAR; mi.position = 1002; mi.ptszName = LPGENT("Set Female"); mi.icolibItem = g_hIconFemale; mi.pszService = "Gender/MenuItemSetFemale"; hContactMenuFemale = Menu_AddContactMenuItem(&mi); mi.flags = CMIF_TCHAR; mi.position = 1003; mi.ptszName = LPGENT("Set Undefined"); mi.pszService = "Gender/MenuItemSetUndef"; mi.hIcon = NULL; hContactMenuNotDef = Menu_AddContactMenuItem(&mi); } } return 0; } int onSystemOKToExit(WPARAM wParam,LPARAM lParam) { UnhookEvent(hHookModulesLoaded); UnhookEvent(hHookExtraIconsRebuild); UnhookEvent(hHookExtraIconsApply); UnhookEvent(hHookPrebuildContactMenu); UnhookEvent(hOptInitialise); UnhookEvent(hSystemOKToExit); if (hIcoLibIconsChanged) UnhookEvent(hIcoLibIconsChanged); DestroyServiceFunction(hSetMale); DestroyServiceFunction(hSetFemale); DestroyServiceFunction(hSetUndef); DestroyServiceFunction(hGenderGetIcon); if (hIcoLibIconsChanged) { CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)"menu_icon"); CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)"male_icon"); CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)"female_icon"); } return 0; } extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, onModulesLoaded); hSystemOKToExit = HookEvent(ME_SYSTEM_OKTOEXIT,onSystemOKToExit); bEnableClistIcon = DBGetContactSettingByte(NULL, MODULENAME, "ClistIcon", 1); bContactMenuItems = DBGetContactSettingByte(NULL, MODULENAME, "MenuItems", 1); bDrawNoGenderIcon = DBGetContactSettingByte(NULL, MODULENAME, "NoGenderIcon", 0); hSetMale = CreateServiceFunction("Gender/MenuItemSetMale", onSetMale); hSetFemale = CreateServiceFunction("Gender/MenuItemSetFemale", onSetFemale); hSetUndef = CreateServiceFunction("Gender/MenuItemSetUndef", onSetUndef); clistIcon = DBGetContactSettingByte(NULL, MODULENAME, "AdvancedIcon", DefaultSlot); g_IECClear.cbSize = sizeof(IconExtraColumn); g_IECClear.ColumnType = clistIcon; g_IECClear.hImage = (HANDLE) -1; hGenderGetIcon = CreateServiceFunction(MS_GENDER_GETICON, GetIcon); return 0; } extern "C" int __declspec(dllexport) Unload(void) { return 0; }