#include "common.h" #include "services.h" #include "popwin.h" #include "message_pump.h" #include "resource.h" #include "popup_history.h" #include #include "str_utils.h" #define NUM_SERVICES 16 HANDLE hService[NUM_SERVICES]; HANDLE hMenuShowHistory, hMenuToggleOnOff; void StripBBCodesInPlace(wchar_t *text) { if(!DBGetContactSettingByte(0, MODULE, "StripBBCodes", 1)) return; int read = 0, write = 0; int len = wcslen(text); while(read <= len) { // copy terminating null too while(read <= len && text[read] != L'[') { if(text[read] != text[write]) text[write] = text[read]; read++; write++; } if(read > len) break; if(len - read >= 3 && (wcsnicmp(text + read, L"[b]", 3) == 0 || wcsnicmp(text + read, L"[i]", 3) == 0)) read += 3; else if(len - read >= 4 && (wcsnicmp(text + read, L"[/b]", 4) == 0 || wcsnicmp(text + read, L"[/i]", 4) == 0)) read += 4; else if(len - read >= 6 && (wcsnicmp(text + read, L"[color", 6) == 0)) { while(read < len && text[read] != L']') read++; read++;// skip the ']' } else if(len - read >= 8 && (wcsnicmp(text + read, L"[/color]", 8) == 0)) read += 8; else { if(text[read] != text[write]) text[write] = text[read]; read++; write++; } } } int CreatePopupA(WPARAM wParam, LPARAM lParam) { if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) return 0; POPUPDATA *pd_in = (POPUPDATA *)wParam; POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW)); MultiByteToWideChar(code_page, 0, pd_in->lpzContactName, -1, pd_out->lpwzContactName, MAX_CONTACTNAME); MultiByteToWideChar(code_page, 0, pd_in->lpzText, -1, pd_out->lpwzText, MAX_SECONDLINE); pd_out->lpwzContactName[MAX_CONTACTNAME - 1] = 0; pd_out->lpwzText[MAX_SECONDLINE - 1] = 0; StripBBCodesInPlace(pd_out->lpwzContactName); StripBBCodesInPlace(pd_out->lpwzText); pd_out->lchContact = pd_in->lchContact; pd_out->lchIcon = pd_in->lchIcon; if(pd_in->colorBack == 0xffffffff) // that's the old #define for 'skinned bg' pd_out->colorBack = pd_out->colorText = 0; else { pd_out->colorBack = pd_in->colorBack & 0xFFFFFF; pd_out->colorText = pd_in->colorText & 0xFFFFFF; } pd_out->PluginWindowProc = pd_in->PluginWindowProc; pd_out->PluginData = pd_in->PluginData; pd_out->iSeconds = 0; lstPopupHistory.Add(pd_out->lpwzContactName, pd_out->lpwzText, time(0)); if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) { free(pd_out); return 0; } //MessageBox(0, pd_out->lpwzContactName, _T("CreatePopupA"), MB_OK); PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)pd_out); return 0; } int CreatePopupExA(WPARAM wParam, LPARAM lParam) { POPUPDATAEX *pd_in = (POPUPDATAEX *)wParam; POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW)); MultiByteToWideChar(code_page, 0, pd_in->lpzContactName, -1, pd_out->lpwzContactName, MAX_CONTACTNAME); MultiByteToWideChar(code_page, 0, pd_in->lpzText, -1, pd_out->lpwzText, MAX_SECONDLINE); pd_out->lpwzContactName[MAX_CONTACTNAME - 1] = 0; pd_out->lpwzText[MAX_SECONDLINE - 1] = 0; StripBBCodesInPlace(pd_out->lpwzContactName); StripBBCodesInPlace(pd_out->lpwzText); pd_out->lchContact = pd_in->lchContact; pd_out->lchIcon = pd_in->lchIcon; if(pd_in->colorBack == 0xffffffff) // that's the old #define for 'skinned bg' pd_out->colorBack = pd_out->colorText = 0; else { pd_out->colorBack = pd_in->colorBack & 0xFFFFFF; pd_out->colorText = pd_in->colorText & 0xFFFFFF; } pd_out->PluginWindowProc = pd_in->PluginWindowProc; pd_out->PluginData = pd_in->PluginData; pd_out->iSeconds = pd_in->iSeconds; lstPopupHistory.Add(pd_out->lpwzContactName, pd_out->lpwzText, time(0)); if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) { free(pd_out); return 0; } //MessageBox(0, pd_out->lpwzContactName, _T("CreatePopupExA"), MB_OK); PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)pd_out); return 0; } int CreatePopupW(WPARAM wParam, LPARAM lParam) { POPUPDATAW *pd_in = (POPUPDATAW *)wParam; POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW)); memcpy(pd_out, pd_in, sizeof(POPUPDATAW)); pd_out->lpwzContactName[MAX_CONTACTNAME - 1] = 0; pd_out->lpwzText[MAX_SECONDLINE - 1] = 0; StripBBCodesInPlace(pd_out->lpwzContactName); StripBBCodesInPlace(pd_out->lpwzText); if(pd_in->colorBack == 0xffffffff) // that's the old #define for 'skinned bg' pd_out->colorBack = pd_out->colorText = 0; else { pd_out->colorBack &= 0xFFFFFF; pd_out->colorText &= 0xFFFFFF; } lstPopupHistory.Add(pd_out->lpwzContactName, pd_out->lpwzText, time(0)); if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) { free(pd_out); return 0; } //MessageBox(0, pd_out->lpwzContactName, _T("CreatePopupW"), MB_OK); PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)pd_out); return 0; } int ChangeTextW(WPARAM wParam, LPARAM lParam) { HWND hwndPop = (HWND)wParam; wchar_t *newText = wcsdup((wchar_t *)lParam); StripBBCodesInPlace(newText); if(IsWindow(hwndPop)) PostMessage(hwndPop, PUM_SETTEXT, 0, (LPARAM)newText); return 0; } int ChangeTextA(WPARAM wParam, LPARAM lParam) { HWND hwndPop = (HWND)wParam; char *newText = (char *)lParam; wchar_t buff[MAX_SECONDLINE]; MultiByteToWideChar(code_page, 0, newText, -1, buff, MAX_SECONDLINE); buff[MAX_SECONDLINE - 1] = 0; StripBBCodesInPlace(buff); if(IsWindow(hwndPop)) PostMessage(hwndPop, PUM_SETTEXT, 0, (LPARAM)wcsdup(buff)); return 0; } int GetContact(WPARAM wParam, LPARAM lParam) { HWND hwndPop = (HWND)wParam; HANDLE hContact; if(GetCurrentThreadId() == message_pump_thread_id) { SendMessage(hwndPop, PUM_GETCONTACT, (WPARAM)&hContact, 0); } else { HANDLE hEvent = CreateEvent(0, 0, 0, 0); PostMessage(hwndPop, PUM_GETCONTACT, (WPARAM)&hContact, (LPARAM)hEvent); //WaitForSingleObject(hEvent, INFINITE); MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, 0, 0); CloseHandle(hEvent); } return (int)hContact; } int GetPluginData(WPARAM wParam, LPARAM lParam) { HWND hwndPop = (HWND)wParam; void *data = 0; if(GetCurrentThreadId() == message_pump_thread_id) { SendMessage(hwndPop, PUM_GETPLUGINDATA, (WPARAM)&data, 0); } else { HANDLE hEvent = CreateEvent(0, 0, 0, 0); PostMessage(hwndPop, PUM_GETPLUGINDATA, (WPARAM)&data, (LPARAM)hEvent); //WaitForSingleObject(hEvent, INFINITE); MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, 0, 0); CloseHandle(hEvent); } if(lParam && !ignore_gpd_passed_addy) { void **pData = (void **)lParam; *pData = data; } return (int)data; } int IsSecondLineShown(WPARAM wParam, LPARAM lParam) { return TRUE; } void UpdateMenu() { CLISTMENUITEM menu = {0}; menu.cbSize = sizeof(CLISTMENUITEM); menu.pszName = (DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 1 ? Translate("Disable Popups") : Translate("Enable Popups")); menu.flags = CMIM_NAME;// | CMIM_ICON; CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuToggleOnOff, (LPARAM)&menu); } int PopupQuery(WPARAM wParam, LPARAM lParam) { switch(wParam) { case PUQS_ENABLEPOPUPS: { bool enabled = (DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 1); if(!enabled) DBWriteContactSettingByte(0, MODULE, "Enabled", 1); return enabled ? 0: 1; } break; case PUQS_DISABLEPOPUPS: { bool enabled = (DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 1); if(enabled) DBWriteContactSettingByte(0, MODULE, "Enabled", 0); DBWriteContactSettingByte(0, MODULE, "Enabled", 0); return enabled ? 1 : 0; } break; case PUQS_GETSTATUS: return DBGetContactSettingByte(0, MODULE, "Enabled", 1); default: return 1; } UpdateMenu(); return 0; } int TogglePopups(WPARAM wParam, LPARAM lParam) { if(DBGetContactSettingByte(0, MODULE, "Enabled", 1)) { DBWriteContactSettingByte(0, MODULE, "Enabled", 0); } else { DBWriteContactSettingByte(0, MODULE, "Enabled", 1); } UpdateMenu(); return 0; } int PopupChange(WPARAM wParam, LPARAM lParam) { HWND hwndPop = (HWND)wParam; POPUPDATAEX *pd_in = (POPUPDATAEX *)lParam; if(IsWindow(hwndPop)) { POPUPDATAW *pd_out = (POPUPDATAW *)malloc(sizeof(POPUPDATAW)); MultiByteToWideChar(code_page, 0, pd_in->lpzContactName, -1, pd_out->lpwzContactName, MAX_CONTACTNAME); MultiByteToWideChar(code_page, 0, pd_in->lpzText, -1, pd_out->lpwzText, MAX_SECONDLINE); pd_out->lchContact = pd_in->lchContact; pd_out->lchIcon = pd_in->lchIcon; if(pd_in->colorBack == 0xffffffff) // that's the old #define for 'skinned bg' pd_out->colorBack = pd_out->colorText = 0; else { pd_out->colorBack = pd_in->colorBack & 0xFFFFFF; pd_out->colorText = pd_in->colorText & 0xFFFFFF; } pd_out->colorBack = pd_in->colorBack; pd_out->colorText = pd_in->colorText; pd_out->PluginWindowProc = pd_in->PluginWindowProc; pd_out->PluginData = pd_in->PluginData; pd_out->iSeconds = pd_in->iSeconds; lstPopupHistory.Add(pd_out->lpwzContactName, pd_out->lpwzText, time(0)); PostMessage(hwndPop, PUM_CHANGE, 0, (LPARAM)pd_out); } return 0; } int ShowMessage(WPARAM wParam, LPARAM lParam) { if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) return 0; POPUPDATAT pd = {0}; _tcscpy(pd.lptzContactName, lParam == SM_WARNING ? _T("Warning") : _T("Notification")); pd.lchIcon = LoadIcon(0, lParam == SM_WARNING ? IDI_WARNING : IDI_INFORMATION); TCHAR buff[MAX_SECONDLINE]; a2t((char *)wParam, buff, MAX_SECONDLINE); _tcscpy(pd.lptzText, buff); CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&pd, 0); return 0; } int ShowMessageW(WPARAM wParam, LPARAM lParam) { if(!DBGetContactSettingByte(0, MODULE, "Enabled", 1)) return 0; POPUPDATAW pd = {0}; wcscpy(pd.lpwzContactName, lParam == SM_WARNING ? L"Warning" : L"Notification"); pd.lchIcon = LoadIcon(0, lParam == SM_WARNING ? IDI_WARNING : IDI_INFORMATION); wcsncpy(pd.lpwzText, (wchar_t *)wParam, MAX_SECONDLINE); CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&pd, 0); return 0; } //=====PopUp/ShowHistory //extern BOOL CALLBACK DlgProcHistLstOpts(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); int PopUp_ShowHistory(WPARAM wParam, LPARAM lParam) { if (!hHistoryWindow) { hHistoryWindow = CreateDialog(hInst, MAKEINTRESOURCE(IDD_LST_HISTORY), NULL, DlgProcHistLst); } ShowWindow(hHistoryWindow, SW_SHOW); return 0; } int num_classes = 0; POPUPCLASS *classes = 0; int RegisterPopupClass(WPARAM wParam, LPARAM lParam) { POPUPCLASS *pc = (POPUPCLASS *)lParam; pc->pszName = strdup(pc->pszName); if(pc->flags & PCF_UNICODE) pc->pwszDescription = wcsdup(pc->pwszDescription); else pc->pszDescription = strdup(pc->pszDescription); char setting[256]; mir_snprintf(setting, 256, "%s/Timeout", pc->pszName); pc->iSeconds = DBGetContactSettingWord(0, MODULE, setting, pc->iSeconds); if(pc->iSeconds == (WORD)-1) pc->iSeconds = -1; mir_snprintf(setting, 256, "%s/TextCol", pc->pszName); pc->colorText = (COLORREF)DBGetContactSettingDword(0, MODULE, setting, (DWORD)pc->colorText); mir_snprintf(setting, 256, "%s/BgCol", pc->pszName); pc->colorBack = (COLORREF)DBGetContactSettingDword(0, MODULE, setting, (DWORD)pc->colorBack); classes = (POPUPCLASS *)realloc(classes, sizeof(POPUPCLASS) * (num_classes + 1)); memcpy(classes + num_classes, pc, sizeof(POPUPCLASS)); num_classes++; return 0; } int CreateClassPopup(WPARAM wParam, LPARAM lParam) { POPUPDATACLASS *pdc = (POPUPDATACLASS *)lParam; if(pdc->cbSize != sizeof(POPUPDATACLASS)) return 1; POPUPCLASS *pc = 0; if(wParam) pc = (POPUPCLASS *)wParam; else { for(int i = 0; i < num_classes; i++) { if(strcmp(classes[i].pszName, pdc->pszClassName) == 0) { pc = &classes[i]; break; } } } if(pc) { if(pc->flags & PCF_UNICODE) { POPUPDATAW pdw = {0}; pdw.colorBack = pc->colorBack; pdw.colorText = pc->colorText; pdw.lchIcon = pc->hIcon; pdw.iSeconds = pc->iSeconds; pdw.PluginWindowProc = pc->PluginWindowProc; pdw.lchContact = pdc->hContact; pdw.PluginData = pdc->PluginData; wcsncpy(pdw.lpwzContactName, pdc->pwszTitle, MAX_CONTACTNAME); wcsncpy(pdw.lpwzText, pdc->pwszText, MAX_SECONDLINE); CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&pdw, 0); } else { POPUPDATAEX pd = {0}; pd.colorBack = pc->colorBack; pd.colorText = pc->colorText; pd.lchIcon = pc->hIcon; pd.iSeconds = pc->iSeconds; pd.PluginWindowProc = pc->PluginWindowProc; pd.lchContact = pdc->hContact; pd.PluginData = pdc->PluginData; strncpy(pd.lpzContactName, pdc->pszTitle, MAX_CONTACTNAME); strncpy(pd.lpzText, pdc->pszText, MAX_SECONDLINE); CallService(MS_POPUP_ADDPOPUP, (WPARAM)&pd, 0); } } return 0; } int PrebuildMenu(WPARAM wParam, LPARAM lParam) { return 0; } HANDLE hEventBuildMenu; void InitServices() { int i = 0; hService[i++] = CreateServiceFunction(MS_POPUP_ADDPOPUP, CreatePopupA); hService[i++] = CreateServiceFunction(MS_POPUP_ADDPOPUPEX, CreatePopupExA); hService[i++] = CreateServiceFunction(MS_POPUP_ADDPOPUPW, CreatePopupW); hService[i++] = CreateServiceFunction(MS_POPUP_CHANGETEXTW, ChangeTextW); hService[i++] = CreateServiceFunction(MS_POPUP_CHANGETEXT, ChangeTextA); hService[i++] = CreateServiceFunction(MS_POPUP_CHANGE, PopupChange); hService[i++] = CreateServiceFunction(MS_POPUP_GETCONTACT, GetContact); hService[i++] = CreateServiceFunction(MS_POPUP_GETPLUGINDATA, GetPluginData); hService[i++] = CreateServiceFunction(MS_POPUP_ISSECONDLINESHOWN, IsSecondLineShown); hService[i++] = CreateServiceFunction(MS_POPUP_QUERY, PopupQuery); hService[i++] = CreateServiceFunction(MS_POPUP_SHOWMESSAGE, ShowMessage); hService[i++] = CreateServiceFunction(MS_POPUP_SHOWMESSAGE"W", ShowMessageW); hService[i++] = CreateServiceFunction(MS_POPUP_SHOWHISTORY, PopUp_ShowHistory); hService[i++] = CreateServiceFunction("PopUp/ToggleEnabled", TogglePopups); hService[i++] = CreateServiceFunction(MS_POPUP_REGISTERCLASS, RegisterPopupClass); hService[i++] = CreateServiceFunction(MS_POPUP_ADDPOPUPCLASS, CreateClassPopup); CLISTMENUITEM menu = {0}; menu.cbSize=sizeof(menu); menu.flags = CMIM_ALL; menu.hIcon=0; menu.position = 500010000; menu.pszPopupName = Translate("PopUps"); hiPopupHistory = LoadIcon(hInst, MAKEINTRESOURCE(IDI_POPUP_HISTORY)); menu.hIcon = hiPopupHistory; menu.pszService= MS_POPUP_SHOWHISTORY; menu.pszName = Translate("Popup History"); hMenuShowHistory = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu); menu.hIcon = 0; menu.pszService= "PopUp/ToggleEnabled"; menu.pszName = (DBGetContactSettingByte(0, MODULE, "Enabled", 1) == 1 ? Translate("Disable Popups") : Translate("Enable Popups")); hMenuToggleOnOff = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu); hEventBuildMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildMenu); if(ServiceExists(MS_LANGPACK_GETCODEPAGE)) code_page = CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); } void DeinitServices() { for(int i = 0; i < num_classes; i++) { free(classes[i].pszName); free(classes[i].pszDescription); } free(classes); num_classes = 0; UnhookEvent(hEventBuildMenu); for(int i = 0; i < NUM_SERVICES; i++) if(hService[i]) DestroyServiceFunction(hService[i]); }