summaryrefslogtreecommitdiff
path: root/plugins/SimpleStatusMsg/src/awaymsg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/SimpleStatusMsg/src/awaymsg.cpp')
-rw-r--r--plugins/SimpleStatusMsg/src/awaymsg.cpp494
1 files changed, 494 insertions, 0 deletions
diff --git a/plugins/SimpleStatusMsg/src/awaymsg.cpp b/plugins/SimpleStatusMsg/src/awaymsg.cpp
new file mode 100644
index 0000000000..705b860cc5
--- /dev/null
+++ b/plugins/SimpleStatusMsg/src/awaymsg.cpp
@@ -0,0 +1,494 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2010 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+Portions of this code modified for Simple Status Message plugin
+Copyright (C) 2006-2011 Bartosz 'Dezeath' Białek, (C) 2005 Harven
+
+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.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "commonheaders.h"
+#include "simplestatusmsg.h"
+
+static HANDLE hAwayMsgMenuItem;
+static HANDLE hCopyMsgMenuItem;
+static HANDLE hGoToURLMenuItem;
+static HANDLE hWindowList;
+static HANDLE hWindowList2;
+
+static char *StrNormNewlineA(char *szStr)
+{
+ if (szStr == NULL) return NULL;
+
+ int nCR = 0;
+ for (int i = 0; szStr[i]; i++)
+ if (szStr[i] != 0x0D && szStr[i + 1] == 0x0A) nCR++;
+
+ if (!nCR) return mir_strdup(szStr);
+
+ char *szNewStr = (char*)mir_alloc(lstrlenA(szStr) + nCR + 1), *pszStr = szNewStr;
+ while (*szStr)
+ {
+ if (*szStr == 0x0A)
+ *pszStr++ = 0x0D;
+ *pszStr++ = *szStr++;
+ }
+ *pszStr++ = 0;
+
+ return szNewStr;
+}
+
+
+static TCHAR *StrNormNewline(TCHAR *tszStr)
+{
+ if (tszStr == NULL) return NULL;
+
+ int nCR = 0;
+ for (int i = 0; tszStr[i]; i++)
+ if (tszStr[i] != 0x0D && tszStr[i + 1] == 0x0A) nCR++;
+
+ if (!nCR) return mir_tstrdup(tszStr);
+
+ TCHAR *tszNewStr = (TCHAR*)mir_alloc((lstrlen(tszStr) + nCR + 1) * sizeof(TCHAR)), *ptszStr = tszNewStr;
+ while (*tszStr)
+ {
+ if (*tszStr == 0x0A)
+ *ptszStr++ = 0x0D;
+ *ptszStr++ = *tszStr++;
+ }
+ *ptszStr++ = 0;
+
+ return tszNewStr;
+}
+
+
+struct AwayMsgDlgData
+{
+ HANDLE hContact;
+ HANDLE hSeq;
+ HANDLE hAwayMsgEvent;
+};
+
+#define HM_AWAYMSG (WM_USER + 10)
+
+static INT_PTR CALLBACK ReadAwayMsgDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ AwayMsgDlgData *dat = (AwayMsgDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ dat = (AwayMsgDlgData*)mir_alloc(sizeof(AwayMsgDlgData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+
+ dat->hContact = (HANDLE)lParam;
+ dat->hSeq = (HANDLE)CallContactService(dat->hContact, PSS_GETAWAYMSG, 0, 0);
+ dat->hAwayMsgEvent = dat->hSeq ? HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_AWAYMSG) : NULL;
+ WindowList_Add(hWindowList, hwndDlg, dat->hContact);
+ {
+ TCHAR str[256], format[128];
+ TCHAR *contactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)dat->hContact, GCDNF_TCHAR);
+ char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0);
+ WORD dwStatus = DBGetContactSettingWord(dat->hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ TCHAR *status = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, dwStatus, GSMDF_TCHAR);
+
+ GetWindowText(hwndDlg, format, SIZEOF(format));
+ mir_sntprintf(str, SIZEOF(str), format, status, contactName);
+ SetWindowText(hwndDlg, str);
+ if (dat->hSeq)
+ {
+ GetDlgItemText(hwndDlg, IDC_RETRIEVING, format, SIZEOF(format));
+ mir_sntprintf(str, SIZEOF(str), format, status);
+ }
+ else
+ {
+ mir_sntprintf(str, SIZEOF(str), TranslateT("Failed to retrieve %s message."), status);
+ SetDlgItemText(hwndDlg, IDOK, TranslateT("&Close"));
+ }
+ SetDlgItemText(hwndDlg, IDC_RETRIEVING, str);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedProtoIcon(szProto, dwStatus));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedProtoIcon(szProto, dwStatus));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COPY), FALSE);
+ }
+ Utils_RestoreWindowPosition(hwndDlg, (HANDLE)lParam, "SRAway", "AwayMsgDlg");
+ return TRUE;
+
+ case HM_AWAYMSG:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+ if (ack->hContact != dat->hContact || ack->type != ACKTYPE_AWAYMSG) break;
+ if (ack->result != ACKRESULT_SUCCESS) break;
+ if (dat->hAwayMsgEvent && ack->hProcess == dat->hSeq) { UnhookEvent(dat->hAwayMsgEvent); dat->hAwayMsgEvent = NULL; }
+
+ TCHAR *tszMsg = StrNormNewline((TCHAR*)ack->lParam);
+ SetDlgItemText(hwndDlg, IDC_MSG, tszMsg);
+ mir_free(tszMsg);
+
+ if (ack->lParam && *((char*)ack->lParam) != '\0')
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COPY), TRUE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_RETRIEVING), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_MSG), SW_SHOW);
+ SetDlgItemText(hwndDlg, IDOK, TranslateT("&Close"));
+ break;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ case IDOK:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_COPY:
+ if (!OpenClipboard(hwndDlg)) break;
+ if (EmptyClipboard())
+ {
+ TCHAR msg[1024];
+ int len = GetDlgItemText(hwndDlg, IDC_MSG, msg, SIZEOF(msg));
+ if (len)
+ {
+ LPTSTR lptstrCopy;
+ HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(TCHAR));
+ if (hglbCopy == NULL)
+ {
+ CloseClipboard();
+ break;
+ }
+ lptstrCopy = (LPTSTR)GlobalLock(hglbCopy);
+ memcpy(lptstrCopy, msg, len * sizeof(TCHAR));
+ lptstrCopy[len] = (TCHAR)0;
+ GlobalUnlock(hglbCopy);
+
+ SetClipboardData(CF_UNICODETEXT, hglbCopy);
+
+ }
+ }
+ CloseClipboard();
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ if (dat->hAwayMsgEvent) UnhookEvent(dat->hAwayMsgEvent);
+ Utils_SaveWindowPosition(hwndDlg, dat->hContact, "SRAway", "AwayMsgDlg");
+ WindowList_Remove(hWindowList, hwndDlg);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)NULL), 0);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)NULL), 0);
+ mir_free(dat);
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR GetMessageCommand(WPARAM wParam, LPARAM)
+{
+ if (HWND hwnd = WindowList_Find(hWindowList, (HANDLE)wParam))
+ {
+ SetForegroundWindow(hwnd);
+ SetFocus(hwnd);
+ }
+ else CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_READAWAYMSG), NULL, ReadAwayMsgDlgProc, wParam);
+ return 0;
+}
+
+static INT_PTR CALLBACK CopyAwayMsgDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ AwayMsgDlgData *dat = (AwayMsgDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ {
+ TCHAR str[256], format[128];
+ TCHAR *contactName;
+
+ TranslateDialogDefault(hwndDlg);
+ dat = (AwayMsgDlgData*)mir_alloc(sizeof(AwayMsgDlgData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+
+ dat->hContact = (HANDLE)lParam;
+ dat->hSeq = (HANDLE)CallContactService(dat->hContact, PSS_GETAWAYMSG, 0, 0);
+ dat->hAwayMsgEvent = dat->hSeq ? HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_AWAYMSG) : NULL;
+ WindowList_Add(hWindowList2, hwndDlg, dat->hContact);
+ contactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)dat->hContact, GCDNF_TCHAR);
+ GetWindowText(hwndDlg, format, SIZEOF(format));
+ mir_sntprintf(str, SIZEOF(str), format, contactName);
+ SetWindowText(hwndDlg, str);
+ if (!dat->hSeq) DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+
+ case HM_AWAYMSG:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+ if (ack->hContact != dat->hContact || ack->type != ACKTYPE_AWAYMSG) { DestroyWindow(hwndDlg); break; }
+ if (ack->result != ACKRESULT_SUCCESS) { DestroyWindow(hwndDlg); break; }
+ if (dat->hAwayMsgEvent && ack->hProcess == dat->hSeq) { UnhookEvent(dat->hAwayMsgEvent); dat->hAwayMsgEvent = NULL; }
+
+ if (!OpenClipboard(hwndDlg)) { DestroyWindow(hwndDlg); break; }
+ if (EmptyClipboard())
+ {
+ TCHAR msg[1024];
+ TCHAR *tszMsg = StrNormNewline((TCHAR*)ack->lParam);
+ mir_sntprintf(msg, SIZEOF(msg), _T("%s"), tszMsg);
+ mir_free(tszMsg);
+ size_t len = lstrlen(msg);
+ if (len)
+ {
+ LPTSTR lptstrCopy;
+ HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(TCHAR));
+ if (hglbCopy == NULL) {
+ CloseClipboard();
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ lptstrCopy = (LPTSTR)GlobalLock(hglbCopy);
+ memcpy(lptstrCopy, msg, len * sizeof(TCHAR));
+ lptstrCopy[len] = (TCHAR)0;
+ GlobalUnlock(hglbCopy);
+
+ SetClipboardData(CF_UNICODETEXT, hglbCopy);
+ }
+ }
+ CloseClipboard();
+ DestroyWindow(hwndDlg);
+ break;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ case IDOK:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ if (dat->hAwayMsgEvent) UnhookEvent(dat->hAwayMsgEvent);
+ WindowList_Remove(hWindowList2, hwndDlg);
+ mir_free(dat);
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CopyAwayMsgCommand(WPARAM wParam, LPARAM)
+{
+ if (HWND hwnd = WindowList_Find(hWindowList2, (HANDLE)wParam))
+ {
+ SetForegroundWindow(hwnd);
+ SetFocus(hwnd);
+ }
+ else CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_COPY), NULL, CopyAwayMsgDlgProc, wParam);
+ return 0;
+}
+
+static char *StrFindURL(char *pszStr)
+{
+ char *pszURL = NULL;
+
+ if (pszStr != NULL && *pszStr != '\0')
+ {
+ pszURL = strstr(pszStr, "www.");
+ if (pszURL == NULL)
+ pszURL = strstr(pszStr, "http://");
+ if (pszURL == NULL)
+ pszURL = strstr(pszStr, "https://");
+ if (pszURL == NULL)
+ pszURL = strstr(pszStr, "ftp://");
+ }
+
+ return pszURL;
+}
+
+static INT_PTR GoToURLMsgCommand(WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ char *szMsg;
+
+
+ int unicode = !DBGetContactSetting((HANDLE)wParam, "CList", "StatusMsg", &dbv) && (dbv.type == DBVT_UTF8 || dbv.type == DBVT_WCHAR);
+ DBFreeVariant(&dbv);
+ if (unicode)
+ {
+ DBGetContactSettingWString((HANDLE)wParam, "CList", "StatusMsg", &dbv);
+ szMsg = mir_u2a(dbv.pwszVal);
+ }
+ else
+
+ {
+ DBGetContactSettingString((HANDLE)wParam, "CList", "StatusMsg", &dbv);
+ szMsg = mir_strdup(dbv.pszVal);
+ }
+ DBFreeVariant(&dbv);
+
+ char *szURL = StrFindURL(szMsg);
+ if (szURL != NULL)
+ {
+ int i;
+ for (i = 0; szURL[i] != ' ' && szURL[i] != '\n' && szURL[i] != '\r' &&
+ szURL[i] != '\t' && szURL[i] != '\0'; i++);
+
+ char *szMsgURL = (char *)mir_alloc(i + 1);
+ if (szMsgURL)
+ {
+ lstrcpynA(szMsgURL, szURL, i + 1);
+ CallService(MS_UTILS_OPENURL, (WPARAM)1, (LPARAM)szMsgURL);
+ mir_free(szMsgURL);
+ }
+ }
+ mir_free(szMsg);
+
+ return 0;
+}
+
+static int AwayMsgPreBuildMenu(WPARAM wParam, LPARAM lParam)
+{
+ CLISTMENUITEM clmi = {0};
+ TCHAR str[128];
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ int iHidden = szProto ? DBGetContactSettingByte((HANDLE)wParam, szProto, "ChatRoom", 0) : 0;
+ char *szMsg;
+ int iStatus;
+
+ clmi.cbSize = sizeof(clmi);
+ clmi.flags = CMIM_FLAGS | CMIF_HIDDEN | CMIF_TCHAR;
+
+ if (!iHidden)
+ {
+ iHidden = 1;
+ iStatus = DBGetContactSettingWord((HANDLE)wParam, szProto, "Status", ID_STATUS_OFFLINE);
+ if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1,0) & PF1_MODEMSGRECV)
+ {
+ if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3,0) & Proto_Status2Flag(iStatus == ID_STATUS_OFFLINE ? ID_STATUS_INVISIBLE : iStatus))
+ {
+ iHidden = 0;
+ clmi.flags = CMIM_FLAGS | CMIM_NAME | CMIM_ICON | CMIF_TCHAR;
+ clmi.hIcon = LoadSkinnedProtoIcon(szProto, iStatus);
+ mir_sntprintf(str, SIZEOF(str), TranslateT("Re&ad %s Message"), (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, GSMDF_TCHAR));
+ clmi.ptszName = str;
+ }
+ }
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hAwayMsgMenuItem, (LPARAM)&clmi);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)clmi.hIcon, (LPARAM)0);
+ clmi.flags = CMIM_FLAGS | CMIF_HIDDEN | CMIF_TCHAR;
+
+ if (!iHidden)
+ {
+ DBVARIANT dbv;
+
+ int unicode = !DBGetContactSetting((HANDLE)wParam, "CList", "StatusMsg", &dbv) && (dbv.type == DBVT_UTF8 || dbv.type == DBVT_WCHAR);
+ DBFreeVariant(&dbv);
+ if (unicode)
+ {
+ DBGetContactSettingWString((HANDLE)wParam, "CList", "StatusMsg", &dbv);
+ szMsg = mir_u2a(dbv.pwszVal);
+ }
+ else
+
+ {
+ DBGetContactSettingString((HANDLE)wParam, "CList", "StatusMsg", &dbv);
+ szMsg = mir_strdup(dbv.pszVal);
+ }
+ DBFreeVariant(&dbv);
+
+ if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ShowCopy", 1) && szMsg && *szMsg != '\0')
+ {
+ clmi.flags = CMIM_FLAGS | CMIM_NAME | CMIF_TCHAR;
+ mir_sntprintf(str, SIZEOF(str), TranslateT("Copy %s Message"), (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, GSMDF_TCHAR));
+ clmi.ptszName = str;
+ }
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hCopyMsgMenuItem, (LPARAM)&clmi);
+ clmi.flags = CMIM_FLAGS | CMIF_HIDDEN | CMIF_TCHAR;
+
+ if (!iHidden)
+ {
+ if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ShowGoToURL", 1) && StrFindURL(szMsg) != NULL)
+ {
+ clmi.flags = CMIM_FLAGS | CMIM_NAME | CMIF_TCHAR;
+ mir_sntprintf(str, SIZEOF(str), TranslateT("&Go to URL in %s Message"), (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, GSMDF_TCHAR));
+ clmi.ptszName = str;
+ }
+ mir_free(szMsg);
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hGoToURLMenuItem, (LPARAM)&clmi);
+
+ return 0;
+}
+
+int AwayMsgPreShutdown(void)
+{
+ if (hWindowList) WindowList_BroadcastAsync(hWindowList, WM_CLOSE, 0, 0);
+ if (hWindowList2) WindowList_BroadcastAsync(hWindowList2, WM_CLOSE, 0, 0);
+
+ return 0;
+}
+
+int LoadAwayMsgModule(void)
+{
+ CLISTMENUITEM mi = {0};
+
+ hWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+ hWindowList2 = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_TCHAR;
+
+ CreateServiceFunctionEx(MS_AWAYMSG_SHOWAWAYMSG, GetMessageCommand);
+ mi.position = -2000005000;
+ mi.ptszName = LPGENT("Re&ad Away Message");
+ mi.pszService = MS_AWAYMSG_SHOWAWAYMSG;
+ hAwayMsgMenuItem = Menu_AddContactMenuItem(&mi);
+
+ mi.flags |= CMIF_ICONFROMICOLIB;
+ CreateServiceFunctionEx(MS_SIMPLESTATUSMSG_COPYMSG, CopyAwayMsgCommand);
+ mi.position = -2000006000;
+ mi.icolibItem = GetIconHandle(IDI_COPY);
+ mi.ptszName = LPGENT("Copy Away Message");
+ mi.pszService = MS_SIMPLESTATUSMSG_COPYMSG;
+ hCopyMsgMenuItem = Menu_AddContactMenuItem(&mi);
+
+ CreateServiceFunctionEx(MS_SIMPLESTATUSMSG_GOTOURLMSG, GoToURLMsgCommand);
+ mi.position = -2000007000;
+ mi.icolibItem = GetIconHandle(IDI_GOTOURL);
+ mi.ptszName = LPGENT("&Go to URL in Away Message");
+ mi.pszService = MS_SIMPLESTATUSMSG_GOTOURLMSG;
+ hGoToURLMenuItem = Menu_AddContactMenuItem(&mi);
+
+ HookEventEx(ME_CLIST_PREBUILDCONTACTMENU, AwayMsgPreBuildMenu);
+
+ // Deprecated SimpleAway services
+ CreateServiceFunctionEx(MS_SA_COPYAWAYMSG, CopyAwayMsgCommand);
+ CreateServiceFunctionEx(MS_SA_GOTOURLMSG, GoToURLMsgCommand);
+
+ return 0;
+}