summaryrefslogtreecommitdiff
path: root/miranda-wine/plugins/srmm/msgdialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'miranda-wine/plugins/srmm/msgdialog.c')
-rw-r--r--miranda-wine/plugins/srmm/msgdialog.c1859
1 files changed, 1859 insertions, 0 deletions
diff --git a/miranda-wine/plugins/srmm/msgdialog.c b/miranda-wine/plugins/srmm/msgdialog.c
new file mode 100644
index 0000000..0d8085e
--- /dev/null
+++ b/miranda-wine/plugins/srmm/msgdialog.c
@@ -0,0 +1,1859 @@
+/*
+SRMM
+
+Copyright 2000-2005 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+
+#define _USE_32BIT_TIME_T
+
+#include "commonheaders.h"
+#pragma hdrstop
+
+#include <malloc.h>
+
+#define TIMERID_MSGSEND 0
+#define TIMERID_FLASHWND 1
+#define TIMERID_TYPE 2
+#define TIMEOUT_FLASHWND 900
+#define TIMEOUT_TYPEOFF 10000 //send type off after 10 seconds of inactivity
+#define SB_CHAR_WIDTH 45;
+#define VALID_AVATAR(x) (x==PA_FORMAT_PNG||x==PA_FORMAT_JPEG||x==PA_FORMAT_ICON||x==PA_FORMAT_BMP||x==PA_FORMAT_GIF)
+
+#if defined(_UNICODE)
+ #define SEND_FLAGS PREF_UNICODE
+#else
+ #define SEND_FLAGS 0
+#endif
+
+extern HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand;
+extern HANDLE hHookWinEvt;
+extern struct CREOleCallback reOleCallback;
+extern HINSTANCE g_hInst;
+
+static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus);
+
+static WNDPROC OldMessageEditProc, OldSplitterProc;
+static const UINT infoLineControls[] = { IDC_PROTOCOL, IDC_NAME };
+static const UINT buttonLineControls[] = { IDC_ADD, IDC_USERMENU, IDC_DETAILS, IDC_HISTORY };
+static const UINT sendControls[] = { IDC_MESSAGE };
+
+static void NotifyLocalWinEvent(HANDLE hContact, HWND hwnd, unsigned int type) {
+ MessageWindowEventData mwe = { 0 };
+
+ if (hContact==NULL || hwnd==NULL) return;
+ mwe.cbSize = sizeof(mwe);
+ mwe.hContact = hContact;
+ mwe.hwndWindow = hwnd;
+ mwe.szModule = SRMMMOD;
+ mwe.uType = type;
+ mwe.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
+ NotifyEventHooks(hHookWinEvt, 0, (LPARAM)&mwe);
+}
+
+static char *MsgServiceName(HANDLE hContact)
+{
+#ifdef _UNICODE
+ char szServiceName[100];
+ char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto == NULL)
+ return PSS_MESSAGE;
+
+ mir_snprintf(szServiceName, SIZEOF(szServiceName), "%s%sW", szProto, PSS_MESSAGE);
+ if (ServiceExists(szServiceName))
+ return PSS_MESSAGE "W";
+#endif
+ return PSS_MESSAGE;
+}
+
+#if defined(_UNICODE)
+static int RTL_Detect(WCHAR *pszwText)
+{
+ WORD *infoTypeC2;
+ int i;
+ int iLen = lstrlenW(pszwText);
+
+ infoTypeC2 = (WORD *)malloc(sizeof(WORD) * (iLen + 2));
+
+ if(infoTypeC2) {
+ ZeroMemory(infoTypeC2, sizeof(WORD) * (iLen + 2));
+
+ GetStringTypeW(CT_CTYPE2, pszwText, iLen, infoTypeC2);
+
+ for(i = 0; i < iLen; i++) {
+ if(infoTypeC2[i] == C2_RIGHTTOLEFT) {
+ free(infoTypeC2);
+ //_DebugTraceA("RTL text found");
+ return 1;
+ }
+ }
+ free(infoTypeC2);
+ //_DebugTraceA("NO RTL text detected");
+ }
+ return 0;
+}
+#endif
+
+// mod from tabsrmm
+static void AddToFileList(char ***pppFiles,int *totalCount,const char *szFilename) {
+ *pppFiles=(char**)realloc(*pppFiles,(++*totalCount+1)*sizeof(char*));
+ (*pppFiles)[*totalCount]=NULL;
+ (*pppFiles)[*totalCount-1]=_strdup(szFilename);
+ if(GetFileAttributesA(szFilename)&FILE_ATTRIBUTE_DIRECTORY) {
+ WIN32_FIND_DATAA fd;
+ HANDLE hFind;
+ char szPath[MAX_PATH];
+ lstrcpyA(szPath,szFilename);
+ lstrcatA(szPath,"\\*");
+ if(hFind=FindFirstFileA(szPath,&fd)) {
+ do {
+ if(!lstrcmpA(fd.cFileName,".") || !lstrcmpA(fd.cFileName,"..")) continue;
+ lstrcpyA(szPath,szFilename);
+ lstrcatA(szPath,"\\");
+ lstrcatA(szPath,fd.cFileName);
+ AddToFileList(pppFiles,totalCount,szPath);
+ } while(FindNextFileA(hFind,&fd));
+ FindClose(hFind);
+ }
+ }
+}
+
+static void ShowMultipleControls(HWND hwndDlg, const UINT * controls, int cControls, int state)
+{
+ int i;
+ for (i = 0; i < cControls; i++)
+ ShowWindow(GetDlgItem(hwndDlg, controls[i]), state);
+}
+
+static void SetDialogToType(HWND hwndDlg)
+{
+ struct MessageWindowData *dat;
+ WINDOWPLACEMENT pl = { 0 };
+
+ dat = (struct MessageWindowData *) GetWindowLong(hwndDlg, GWL_USERDATA);
+ if (dat->hContact) {
+ ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), (g_dat->flags&SMF_SHOWINFO) ? SW_SHOW : SW_HIDE);
+ }
+ else
+ ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), SW_HIDE);
+ if (dat->hContact) {
+ ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), (g_dat->flags&SMF_SHOWBTNS) ? SW_SHOW : SW_HIDE);
+ if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE);
+ }
+ else {
+ ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), SW_HIDE);
+ }
+ ShowMultipleControls(hwndDlg, sendControls, SIZEOF(sendControls), SW_SHOW);
+ if (!dat->hwndStatus) {
+ dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL);
+ SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0);
+ }
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT)) {
+ RECT rc;
+ int statwidths[2];
+
+ GetWindowRect(dat->hwndStatus, &rc);
+ statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH;
+ statwidths[1] = -1;
+ SendMessage(dat->hwndStatus, SB_SETPARTS, 2, (LPARAM) statwidths);
+ }
+ else {
+ int statwidths[] = { -1 };
+
+ SendMessage(dat->hwndStatus, SB_SETPARTS, 1, (LPARAM) statwidths);
+ }
+ UpdateReadChars(hwndDlg, dat->hwndStatus);
+ ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_SPLITTER), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDOK), (g_dat->flags&SMF_SENDBTN) ? SW_SHOW : SW_HIDE);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE))?TRUE:FALSE);
+ if (dat->avatarPic==0||!(g_dat->flags&SMF_AVATAR))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE);
+ SendMessage(hwndDlg, DM_UPDATETITLE, 0, 0);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ pl.length = sizeof(pl);
+ GetWindowPlacement(hwndDlg, &pl);
+ if (!IsWindowVisible(hwndDlg))
+ pl.showCmd = SW_HIDE;
+ SetWindowPlacement(hwndDlg, &pl); //in case size is smaller than new minimum
+}
+
+struct SavedMessageData
+{
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+ DWORD keyStates; //use MOD_ defines from RegisterHotKey()
+};
+
+struct MsgEditSubclassData
+{
+ DWORD lastEnterTime;
+ struct SavedMessageData *keyboardMsgQueue;
+ int msgQueueCount;
+};
+
+static void SaveKeyboardMessage(struct MsgEditSubclassData *dat, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ dat->keyboardMsgQueue = (struct SavedMessageData *) realloc(dat->keyboardMsgQueue, sizeof(struct SavedMessageData) * (dat->msgQueueCount + 1));
+ dat->keyboardMsgQueue[dat->msgQueueCount].message = message;
+ dat->keyboardMsgQueue[dat->msgQueueCount].wParam = wParam;
+ dat->keyboardMsgQueue[dat->msgQueueCount].lParam = lParam;
+ dat->keyboardMsgQueue[dat->msgQueueCount].keyStates = (GetKeyState(VK_SHIFT) & 0x8000 ? MOD_SHIFT : 0) | (GetKeyState(VK_CONTROL) & 0x8000 ? MOD_CONTROL : 0) | (GetKeyState(VK_MENU) & 0x8000 ? MOD_ALT : 0);
+ dat->msgQueueCount++;
+}
+
+#define EM_REPLAYSAVEDKEYSTROKES (WM_USER+0x100)
+#define EM_SUBCLASSED (WM_USER+0x101)
+#define EM_UNSUBCLASSED (WM_USER+0x102)
+#define ENTERCLICKTIME 1000 //max time in ms during which a double-tap on enter will cause a send
+#define EDITMSGQUEUE_PASSTHRUCLIPBOARD //if set the typing queue won't capture ctrl-C etc because people might want to use them on the read only text
+ //todo: decide if this should be set or not
+static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct MsgEditSubclassData *dat;
+ struct MessageWindowData *pdat;
+
+ pdat=(struct MessageWindowData *)GetWindowLong(GetParent(hwnd),GWL_USERDATA);
+ dat = (struct MsgEditSubclassData *) GetWindowLong(hwnd, GWL_USERDATA);
+ switch (msg) {
+ case WM_DROPFILES:
+ SendMessage(GetParent(hwnd), WM_DROPFILES, (WPARAM)wParam, (LPARAM)lParam);
+ break;
+ case EM_SUBCLASSED:
+ dat = (struct MsgEditSubclassData *) malloc(sizeof(struct MsgEditSubclassData));
+ SetWindowLong(hwnd, GWL_USERDATA, (LONG) dat);
+ dat->lastEnterTime = 0;
+ dat->keyboardMsgQueue = NULL;
+ dat->msgQueueCount = 0;
+ return 0;
+ case EM_SETREADONLY:
+ if (wParam) {
+ if (dat->keyboardMsgQueue)
+ free(dat->keyboardMsgQueue);
+ dat->keyboardMsgQueue = NULL;
+ dat->msgQueueCount = 0;
+ }
+ break;
+ case EM_REPLAYSAVEDKEYSTROKES:
+ {
+ int i;
+ BYTE keyStateArray[256], originalKeyStateArray[256];
+ MSG msg;
+
+ while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ GetKeyboardState(originalKeyStateArray);
+ GetKeyboardState(keyStateArray);
+ for (i = 0; i < dat->msgQueueCount; i++) {
+ keyStateArray[VK_SHIFT] = dat->keyboardMsgQueue[i].keyStates & MOD_SHIFT ? 0x80 : 0;
+ keyStateArray[VK_CONTROL] = dat->keyboardMsgQueue[i].keyStates & MOD_CONTROL ? 0x80 : 0;
+ keyStateArray[VK_MENU] = dat->keyboardMsgQueue[i].keyStates & MOD_ALT ? 0x80 : 0;
+ SetKeyboardState(keyStateArray);
+ PostMessage(hwnd, dat->keyboardMsgQueue[i].message, dat->keyboardMsgQueue[i].wParam, dat->keyboardMsgQueue[i].lParam);
+ while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ if (dat->keyboardMsgQueue)
+ free(dat->keyboardMsgQueue);
+ dat->keyboardMsgQueue = NULL;
+ dat->msgQueueCount = 0;
+ SetKeyboardState(originalKeyStateArray);
+ return 0;
+ }
+ case WM_CHAR:
+ if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY)
+ break;
+ //for saved msg queue the keyup/keydowns generate wm_chars themselves
+ if (wParam == '\n' || wParam == '\r') {
+ if (((GetKeyState(VK_CONTROL) & 0x8000) != 0) ^ (0 != DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER))) {
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)) {
+ if (dat->lastEnterTime + ENTERCLICKTIME < GetTickCount())
+ dat->lastEnterTime = GetTickCount();
+ else {
+ SendMessage(hwnd, WM_CHAR, '\b', 0);
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ }
+ }
+ else
+ dat->lastEnterTime = 0;
+ if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-a
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return 0;
+ }
+ if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w
+ SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
+ return 0;
+ }
+ if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-backspace
+ DWORD start, end;
+ TCHAR *text;
+ int textLen;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM) & end, (LPARAM) (PDWORD) NULL);
+ SendMessage(hwnd, WM_KEYDOWN, VK_LEFT, 0);
+ SendMessage(hwnd, EM_GETSEL, (WPARAM) & start, (LPARAM) (PDWORD) NULL);
+ textLen = GetWindowTextLength(hwnd);
+ text = (TCHAR *) malloc(sizeof(TCHAR) * (textLen + 1));
+ GetWindowText(hwnd, text, textLen + 1);
+ MoveMemory(text + start, text + end, sizeof(TCHAR) * (textLen + 1 - end));
+ SetWindowText(hwnd, text);
+ free(text);
+ SendMessage(hwnd, EM_SETSEL, start, start);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd);
+ return 0;
+ }
+ break;
+ case WM_KEYUP:
+ if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY) {
+ int i;
+ //mustn't allow keyups for which there is no keydown
+ for (i = 0; i < dat->msgQueueCount; i++)
+ if (dat->keyboardMsgQueue[i].message == WM_KEYDOWN && dat->keyboardMsgQueue[i].wParam == wParam)
+ break;
+ if (i == dat->msgQueueCount)
+ break;
+ #ifdef EDITMSGQUEUE_PASSTHRUCLIPBOARD
+ if (GetKeyState(VK_CONTROL) & 0x8000) {
+ if (wParam == 'X' || wParam == 'C' || wParam == 'V' || wParam == VK_INSERT)
+ break;
+ }
+ if (GetKeyState(VK_SHIFT) & 0x8000) {
+ if (wParam == VK_INSERT || wParam == VK_DELETE)
+ break;
+ }
+ #endif
+ SaveKeyboardMessage(dat, msg, wParam, lParam);
+ return 0;
+ }
+ break;
+ case WM_KEYDOWN:
+ if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY) {
+ #ifdef EDITMSGQUEUE_PASSTHRUCLIPBOARD
+ if (GetKeyState(VK_CONTROL) & 0x8000) {
+ if (wParam == 'X' || wParam == 'C' || wParam == 'V' || wParam == VK_INSERT)
+ break;
+ }
+ if (GetKeyState(VK_SHIFT) & 0x8000) {
+ if (wParam == VK_INSERT || wParam == VK_DELETE)
+ break;
+ }
+ #endif
+ SaveKeyboardMessage(dat, msg, wParam, lParam);
+ return 0;
+ }
+ if (wParam == VK_UP && (GetKeyState(VK_CONTROL) & 0x8000) && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT) && !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)) {
+ if (pdat->cmdList) {
+ if (!pdat->cmdListCurrent) {
+ pdat->cmdListCurrent = tcmdlist_last(pdat->cmdList);
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+ SetWindowText(hwnd, pdat->cmdListCurrent->szCmd);
+ SendMessage(hwnd, EM_SCROLLCARET, 0,0);
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ }
+ else if (pdat->cmdListCurrent->prev) {
+ pdat->cmdListCurrent = pdat->cmdListCurrent->prev;
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+ SetWindowText(hwnd, pdat->cmdListCurrent->szCmd);
+ SendMessage(hwnd, EM_SCROLLCARET, 0,0);
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ }
+ }
+ EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(GetDlgItem(GetParent(hwnd), IDC_MESSAGE)) != 0);
+ UpdateReadChars(GetParent(hwnd), pdat->hwndStatus);
+ }
+ else if (wParam == VK_DOWN && (GetKeyState(VK_CONTROL) & 0x8000) && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT) && !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)) {
+ if (pdat->cmdList) {
+ if (!pdat->cmdListCurrent)
+ pdat->cmdListCurrent = tcmdlist_last(pdat->cmdList);
+ if (pdat->cmdListCurrent->next) {
+ pdat->cmdListCurrent = pdat->cmdListCurrent->next;
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+ SetWindowText(hwnd, pdat->cmdListCurrent->szCmd);
+ SendMessage(hwnd, EM_SCROLLCARET, 0,0);
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ }
+ else {
+ pdat->cmdListCurrent = 0;
+ SetWindowTextA(hwnd, "");
+ }
+ }
+ EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(GetDlgItem(GetParent(hwnd), IDC_MESSAGE)) != 0);
+ UpdateReadChars(GetParent(hwnd), pdat->hwndStatus);
+ }
+ if (wParam == VK_RETURN)
+ break;
+ //fall through
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_MOUSEWHEEL:
+ case WM_KILLFOCUS:
+ dat->lastEnterTime = 0;
+ break;
+ case WM_SYSCHAR:
+ dat->lastEnterTime = 0;
+ if ((wParam == 's' || wParam == 'S') && GetKeyState(VK_MENU) & 0x8000) {
+ if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY)
+ SaveKeyboardMessage(dat, msg, wParam, lParam);
+ else
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ break;
+ case EM_UNSUBCLASSED:
+ if (dat->keyboardMsgQueue)
+ free(dat->keyboardMsgQueue);
+ free(dat);
+ return 0;
+ }
+ return CallWindowProc(OldMessageEditProc, hwnd, msg, wParam, lParam);
+}
+
+static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_NCHITTEST:
+ return HTCLIENT;
+ case WM_SETCURSOR:
+ {
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ SetCursor(rc.right > rc.bottom ? hCurSplitNS : hCurSplitWE);
+ return TRUE;
+ }
+ case WM_LBUTTONDOWN:
+ SetCapture(hwnd);
+ return 0;
+ case WM_MOUSEMOVE:
+ if (GetCapture() == hwnd) {
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ SendMessage(GetParent(hwnd), DM_SPLITTERMOVED, rc.right > rc.bottom ? (short) HIWORD(GetMessagePos()) + rc.bottom / 2 : (short) LOWORD(GetMessagePos()) + rc.right / 2, (LPARAM) hwnd);
+ }
+ return 0;
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ return 0;
+ }
+ return CallWindowProc(OldSplitterProc, hwnd, msg, wParam, lParam);
+}
+
+static int MessageDialogResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL * urc)
+{
+ struct MessageWindowData *dat = (struct MessageWindowData *) lParam;
+
+ if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS)) {
+ int i;
+ for (i = 0; i < SIZEOF(buttonLineControls); i++)
+ if (buttonLineControls[i] == urc->wId)
+ OffsetRect(&urc->rcItem, 0, -dat->lineHeight);
+ }
+ switch (urc->wId) {
+ case IDC_NAME:
+ {
+ int len;
+ HWND h;
+
+ h = GetDlgItem(hwndDlg, IDC_NAME);
+ len = GetWindowTextLength(h);
+ if (len > 0) {
+ HDC hdc;
+ SIZE textSize;
+ TCHAR buf[256];
+ HFONT hFont;
+
+ GetWindowText(h, buf, SIZEOF(buf));
+
+ hdc = GetDC(h);
+ hFont = SelectObject(hdc, (HFONT) SendMessage(GetDlgItem(hwndDlg, IDOK), WM_GETFONT, 0, 0));
+ GetTextExtentPoint32(hdc, buf, lstrlen(buf), &textSize);
+ urc->rcItem.right = urc->rcItem.left + textSize.cx + 10;
+ if ((g_dat->flags&SMF_SHOWBTNS) && urc->rcItem.right > urc->dlgNewSize.cx - dat->nLabelRight)
+ urc->rcItem.right = urc->dlgNewSize.cx - dat->nLabelRight;
+ SelectObject(hdc, hFont);
+ ReleaseDC(h, hdc);
+ }
+ }
+ case IDC_PROTOCOL:
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+ case IDC_ADD:
+ case IDC_USERMENU:
+ case IDC_DETAILS:
+ case IDC_HISTORY:
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP;
+ case IDC_LOG:
+ if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS))
+ urc->rcItem.top -= dat->lineHeight;
+ urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+ case IDC_SPLITTER:
+ urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos;
+ urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
+ case IDC_MESSAGE:
+ {
+ if (!(g_dat->flags&SMF_SENDBTN))
+ urc->rcItem.right = urc->dlgNewSize.cx - urc->rcItem.left;
+ if ((g_dat->flags&SMF_AVATAR)&&dat->avatarPic) {
+ urc->rcItem.left = dat->avatarWidth+4;
+ }
+ urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos;
+ if (!(g_dat->flags&SMF_SENDBTN))
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
+ }
+ case IDCANCEL:
+ case IDOK:
+ urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos;
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
+ case IDC_AVATAR:
+ urc->rcItem.top=urc->rcItem.bottom-(dat->avatarHeight + 2);
+ urc->rcItem.right=urc->rcItem.left+(dat->avatarWidth + 2);
+ return RD_ANCHORX_LEFT|RD_ANCHORY_BOTTOM;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+}
+
+static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus)
+{
+ if (hwndStatus && SendMessage(hwndStatus, SB_GETPARTS, 0, 0) == 2) {
+ TCHAR buf[128];
+ int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+
+ mir_sntprintf(buf, SIZEOF(buf), _T("%d"), len);
+ SendMessage(hwndStatus, SB_SETTEXT, 1, (LPARAM) buf);
+ }
+}
+
+void ShowAvatar(HWND hwndDlg, struct MessageWindowData *dat) {
+ DBVARIANT dbv;
+
+ if (dat->avatarPic) {
+ DeleteObject(dat->avatarPic);
+ dat->avatarPic=0;
+ }
+ if (!DBGetContactSetting(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, &dbv)) {
+ if(dbv.pszVal) {
+ HANDLE hFile;
+
+ hFile = CreateFileA(dbv.pszVal, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile!=INVALID_HANDLE_VALUE) {
+ dat->avatarPic=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ CloseHandle(hFile);
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0);
+ SendMessage(hwndDlg, DM_AVATARSIZECHANGE, 0, 0);
+}
+
+static void NotifyTyping(struct MessageWindowData *dat, int mode)
+{
+ DWORD protoStatus;
+ DWORD protoCaps;
+ DWORD typeCaps;
+
+ if (!dat->hContact)
+ return;
+ // Don't send to protocols who don't support typing
+ // Don't send to users who are unchecked in the typing notification options
+ // Don't send to protocols that are offline
+ // Don't send to users who are not visible and
+ // Don't send to users who are not on the visible list when you are in invisible mode.
+ if (!DBGetContactSettingByte(dat->hContact, SRMMMOD, SRMSGSET_TYPING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)))
+ return;
+ if (!dat->szProto)
+ return;
+ protoStatus = CallProtoService(dat->szProto, PS_GETSTATUS, 0, 0);
+ protoCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1, 0);
+ typeCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0);
+
+ if (!(typeCaps & PF4_SUPPORTTYPING))
+ return;
+ if (protoStatus < ID_STATUS_ONLINE)
+ return;
+ if (protoCaps & PF1_VISLIST && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ return;
+ if (protoCaps & PF1_INVISLIST && protoStatus == ID_STATUS_INVISIBLE && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) != ID_STATUS_ONLINE)
+ return;
+ if (DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)
+ && !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN))
+ return;
+ // End user check
+ dat->nTypeMode = mode;
+ CallService(MS_PROTO_SELFISTYPING, (WPARAM) dat->hContact, dat->nTypeMode);
+}
+
+BOOL CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct MessageWindowData *dat;
+
+ dat = (struct MessageWindowData *) GetWindowLong(hwndDlg, GWL_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ struct NewMessageWindowLParam *newData = (struct NewMessageWindowLParam *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ dat = (struct MessageWindowData *) calloc(sizeof(struct MessageWindowData),1);
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) dat);
+ {
+ dat->hContact = newData->hContact;
+ NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING);
+ if (newData->szInitialText) {
+ int len;
+#if defined(_UNICODE)
+ if(newData->isWchar)
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, (TCHAR *)newData->szInitialText);
+ else
+ SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText);
+#else
+ SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText);
+#endif
+ len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, len, len);
+ }
+ }
+ dat->szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->hContact, 0);
+ RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_LOG));
+ { // avatar stuff
+ dat->avatarPic = 0;
+ dat->avatarWidth = 0;
+ dat->avatarHeight = 0;
+ dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)?DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT):0;
+ }
+ if (dat->hContact && dat->szProto != NULL)
+ dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ else
+ dat->wStatus = ID_STATUS_OFFLINE;
+ dat->wOldStatus = dat->wStatus;
+ dat->hSendId = NULL;
+ dat->hBkgBrush = NULL;
+ dat->hDbEventFirst = NULL;
+ dat->sendBuffer = NULL;
+ dat->splitterPos = (int) DBGetContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", (DWORD) - 1);
+ dat->windowWasCascaded = 0;
+ dat->nFlash = 0;
+ dat->nTypeSecs = 0;
+ dat->nLastTyping = 0;
+ dat->showTyping = 0;
+ dat->cmdList = 0;
+ dat->cmdListCurrent = 0;
+ dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF;
+ SetTimer(hwndDlg, TIMERID_TYPE, 1000, NULL);
+ dat->lastMessage = 0;
+ dat->lastEventType = -1;
+ dat->nFlashMax = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT);
+ {
+ RECT rc, rc2;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_USERMENU), &rc);
+ GetWindowRect(hwndDlg, &rc2);
+ dat->nLabelRight = rc2.right - rc.left;
+ }
+ {
+ RECT rc;
+ POINT pt;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_SPLITTER), &rc);
+ pt.y = (rc.top + rc.bottom) / 2;
+ pt.x = 0;
+ ScreenToClient(hwndDlg, &pt);
+ dat->originalSplitterPos = pt.y;
+ if (dat->splitterPos == -1)
+ dat->splitterPos = dat->originalSplitterPos;// + 60;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_ADD), &rc);
+ dat->lineHeight = rc.bottom - rc.top + 3;
+ }
+ WindowList_Add(g_dat->hMessageWindowList, hwndDlg, dat->hContact);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &dat->minEditInit);
+ SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0);
+ dat->hwndStatus = NULL;
+ SendDlgItemMessage(hwndDlg, IDC_ADD, BM_SETIMAGE, IMAGE_ICON, (LPARAM) g_dat->hIcons[SMF_ICON_ADD]);
+ SendDlgItemMessage(hwndDlg, IDC_DETAILS, BM_SETIMAGE, IMAGE_ICON, (LPARAM) g_dat->hIcons[SMF_ICON_USERDETAIL]);
+ SendDlgItemMessage(hwndDlg, IDC_HISTORY, BM_SETIMAGE, IMAGE_ICON, (LPARAM) g_dat->hIcons[SMF_ICON_HISTORY]);
+ SendDlgItemMessage(hwndDlg, IDC_USERMENU, BM_SETIMAGE, IMAGE_ICON, (LPARAM) g_dat->hIcons[SMF_ICON_ARROW]);
+ // Make them flat buttons
+ {
+ int i;
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_NAME), BUTTONSETASFLATBTN, 0, 0);
+ for (i = 0; i < SIZEOF(buttonLineControls); i++)
+ SendMessage(GetDlgItem(hwndDlg, buttonLineControls[i]), BUTTONSETASFLATBTN, 0, 0);
+ }
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADD), BUTTONADDTOOLTIP, (WPARAM) Translate("Add Contact Permanently to List"), 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_USERMENU), BUTTONADDTOOLTIP, (WPARAM) Translate("User Menu"), 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_DETAILS), BUTTONADDTOOLTIP, (WPARAM) Translate("View User's Details"), 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_HISTORY), BUTTONADDTOOLTIP, (WPARAM) Translate("View User's History"), 0);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOL), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AVATAR), FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK);
+ /* duh, how come we didnt use this from the start? */
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, (WPARAM) TRUE, 0);
+ if (dat->hContact) {
+ if (dat->szProto) {
+ int nMax;
+ nMax = CallProtoService(dat->szProto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM) dat->hContact);
+ if (nMax)
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_LIMITTEXT, (WPARAM) nMax, 0);
+ /* get around a lame bug in the Windows template resource code where richedits are limited to 0x7FFF */
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_LIMITTEXT, (WPARAM) sizeof(TCHAR) * 0x7FFFFFFF, 0);
+ }
+ }
+ OldMessageEditProc = (WNDPROC) SetWindowLong(GetDlgItem(hwndDlg, IDC_MESSAGE), GWL_WNDPROC, (LONG) MessageEditSubclassProc);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SUBCLASSED, 0, 0);
+ OldSplitterProc = (WNDPROC) SetWindowLong(GetDlgItem(hwndDlg, IDC_SPLITTER), GWL_WNDPROC, (LONG) SplitterSubclassProc);
+ if (dat->hContact) {
+ int historyMode = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY);
+ // This finds the first message to display, it works like shit
+ dat->hDbEventFirst = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) dat->hContact, 0);
+ switch (historyMode) {
+ case LOADHISTORY_COUNT:
+ {
+ int i;
+ HANDLE hPrevEvent;
+ DBEVENTINFO dbei = { 0 };
+ dbei.cbSize = sizeof(dbei);
+ for (i = DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT); i > 0; i--) {
+ if (dat->hDbEventFirst == NULL)
+ hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0);
+ else
+ hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0);
+ if (hPrevEvent == NULL)
+ break;
+ dbei.cbBlob = 0;
+ dat->hDbEventFirst = hPrevEvent;
+ CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei);
+ if (!DbEventIsShown(&dbei, dat))
+ i++;
+ }
+ break;
+ }
+ case LOADHISTORY_TIME:
+ {
+ HANDLE hPrevEvent;
+ DBEVENTINFO dbei = { 0 };
+ DWORD firstTime;
+
+ dbei.cbSize = sizeof(dbei);
+ if (dat->hDbEventFirst == NULL)
+ dbei.timestamp = time(NULL);
+ else
+ CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei);
+ firstTime = dbei.timestamp - 60 * DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME);
+ for (;;) {
+ if (dat->hDbEventFirst == NULL)
+ hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0);
+ else
+ hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0);
+ if (hPrevEvent == NULL)
+ break;
+ dbei.cbBlob = 0;
+ CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) & dbei);
+ if (dbei.timestamp < firstTime)
+ break;
+ dat->hDbEventFirst = hPrevEvent;
+ }
+ break;
+ }
+ }
+ }
+ SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 1, 0);
+ {
+ int savePerContact = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT);
+ if (Utils_RestoreWindowPosition(hwndDlg, savePerContact ? dat->hContact : NULL, SRMMMOD, "")) {
+ if (savePerContact) {
+ if (Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, SRMMMOD, ""))
+ SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE);
+ }
+ else
+ SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE);
+ }
+ if (!savePerContact && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE))
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_CASCADENEWWINDOW, (WPARAM) hwndDlg, (LPARAM) & dat->windowWasCascaded);
+ }
+ {
+ DBEVENTINFO dbei = { 0 };
+ HANDLE hdbEvent;
+
+ dbei.cbSize = sizeof(dbei);
+ hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0);
+ if (hdbEvent) {
+ do {
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ CallService(MS_DB_EVENT_GET, (WPARAM) hdbEvent, (LPARAM) & dbei);
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) {
+ dat->lastMessage = dbei.timestamp;
+ SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0);
+ break;
+ }
+ }
+ while (hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) hdbEvent, 0));
+ }
+
+ }
+ SendMessage(hwndDlg, DM_GETAVATAR, 0, 0);
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN);
+ return TRUE;
+ }
+ case WM_CONTEXTMENU:
+ {
+ if (dat->hwndStatus && dat->hwndStatus == (HWND) wParam) {
+ POINT pt;
+ HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0);
+
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ }
+ break;
+ }
+ // Mod from tabsrmm
+ case WM_DROPFILES:
+ {
+ if (dat->szProto==NULL) break;
+ if (!(CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1,0)&PF1_FILESEND)) break;
+ if (dat->wStatus==ID_STATUS_OFFLINE) break;
+ if (dat->hContact!=NULL) {
+ HDROP hDrop;
+ char **ppFiles=NULL;
+ char szFilename[MAX_PATH];
+ int fileCount,totalCount=0,i;
+
+ hDrop=(HDROP)wParam;
+ fileCount=DragQueryFile(hDrop,-1,NULL,0);
+ ppFiles=NULL;
+ for(i=0;i<fileCount;i++) {
+ DragQueryFileA(hDrop, i, szFilename, SIZEOF(szFilename));
+ AddToFileList(&ppFiles, &totalCount, szFilename);
+ }
+ CallServiceSync(MS_FILE_SENDSPECIFICFILES, (WPARAM)dat->hContact, (LPARAM)ppFiles);
+ for(i=0;ppFiles[i];i++) free(ppFiles[i]);
+ free(ppFiles);
+ }
+ break;
+ }
+ case HM_AVATARACK:
+ {
+ ACKDATA *pAck = (ACKDATA *)lParam;
+ PROTO_AVATAR_INFORMATION *pai = (PROTO_AVATAR_INFORMATION *)pAck->hProcess;
+ HWND hwnd = 0;
+
+ if (pAck->hContact!=dat->hContact)
+ return 0;
+ if (pAck->type != ACKTYPE_AVATAR)
+ return 0;
+ if (pAck->result == ACKRESULT_STATUS) {
+ SendMessage(hwndDlg, DM_GETAVATAR, 0, 0);
+ break;
+ }
+ if (pai==NULL)
+ return 0;
+ if (pAck->result == ACKRESULT_SUCCESS) {
+ if (pai->filename&&strlen(pai->filename)&&VALID_AVATAR(pai->format)) {
+ DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, pai->filename);
+ ShowAvatar(hwndDlg, dat);
+ }
+ }
+ else if (pAck->result == ACKRESULT_FAILED) {
+ DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, "");
+ ShowAvatar(hwndDlg, dat);
+ }
+ break;
+ }
+ case DM_AVATARCALCSIZE:
+ {
+ BITMAP bminfo;
+
+ if (dat->avatarPic==0||!(g_dat->flags&SMF_AVATAR)) {
+ dat->avatarWidth=50;
+ dat->avatarHeight=50;
+ ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE);
+ return 0;
+ }
+ GetObject(dat->avatarPic, sizeof(bminfo), &bminfo);
+ dat->avatarWidth=bminfo.bmWidth+2;
+ dat->avatarHeight=bminfo.bmHeight+2;
+ if (dat->limitAvatarH&&dat->avatarHeight>dat->limitAvatarH) {
+ double aspect = 0;
+
+ aspect = (double)dat->limitAvatarH / (double)bminfo.bmHeight;
+ dat->avatarWidth = (int)(bminfo.bmWidth * aspect + 2);
+ dat->avatarHeight = dat->limitAvatarH + 2;
+ }
+ ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_SHOW);
+ break;
+ }
+ case DM_UPDATESIZEBAR:
+ {
+ dat->minEditBoxSize.cx = dat->minEditInit.right - dat->minEditInit.left;
+ dat->minEditBoxSize.cy = dat->minEditInit.bottom - dat->minEditInit.top;
+ if (g_dat->flags&SMF_AVATAR) {
+ SendMessage(hwndDlg, DM_AVATARCALCSIZE, 0, 0);
+ if(dat->avatarPic) {
+ if (dat->minEditBoxSize.cy<=dat->avatarHeight)
+ dat->minEditBoxSize.cy = dat->avatarHeight;
+ }
+ }
+ break;
+ }
+ case DM_AVATARSIZECHANGE:
+ {
+ RECT rc;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc);
+ if (rc.bottom-rc.top<dat->minEditBoxSize.cy) {
+ SendMessage(hwndDlg, DM_SPLITTERMOVED, rc.top-(rc.bottom-rc.top-dat->minEditBoxSize.cy-4), (LPARAM) GetDlgItem(hwndDlg, IDC_SPLITTER));
+ }
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SendMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0);
+ break;
+ }
+ case DM_GETAVATAR:
+ {
+ PROTO_AVATAR_INFORMATION pai;
+ int caps = 0, result;
+
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, 0);
+ if (!(g_dat->flags&SMF_AVATAR)||!(CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0)&PF4_AVATARS)) {
+ SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0);
+ SendMessage(hwndDlg, DM_AVATARSIZECHANGE, 0, 0);
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, 1);
+ return 0;
+ }
+ if(DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) {
+ ShowAvatar(hwndDlg, dat);
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, 1);
+ return 0;
+ }
+ ZeroMemory((void *)&pai, sizeof(pai));
+ pai.cbSize = sizeof(pai);
+ pai.hContact = dat->hContact;
+ pai.format = PA_FORMAT_UNKNOWN;
+ strcpy(pai.filename, "");
+ result = CallProtoService(dat->szProto, PS_GETAVATARINFO, GAIF_FORCE, (LPARAM)&pai);
+ if (result==GAIR_SUCCESS) {
+ if (VALID_AVATAR(pai.format))
+ DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, pai.filename);
+ else DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, "");
+ ShowAvatar(hwndDlg, dat);
+ } else if (result == GAIR_NOAVATAR) {
+ DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, "");
+ ShowAvatar(hwndDlg, dat);
+ }
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, 1);
+ break;
+ }
+ case DM_TYPING:
+ {
+ dat->nTypeSecs = (int) lParam > 0 ? (int) lParam : 0;
+ break;
+ }
+ case DM_UPDATEWINICON:
+ {
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)) {
+ WORD wStatus;
+
+ if (dat->szProto) {
+ wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedProtoIcon(dat->szProto, wStatus));
+ break;
+ }
+ }
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+ break;
+ }
+ case DM_USERNAMETOCLIP:
+ {
+ CONTACTINFO ci;
+ char buf[128];
+ HGLOBAL hData;
+
+ buf[0] = 0;
+ if(dat->hContact) {
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = dat->hContact;
+ ci.szProto = dat->szProto;
+ ci.dwFlag = CNF_UNIQUEID;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
+ switch (ci.type) {
+ case CNFT_ASCIIZ:
+ mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal);
+ miranda_sys_free(ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ mir_snprintf(buf, SIZEOF(buf), "%u", ci.dVal);
+ break;
+ }
+ }
+ if (!OpenClipboard(hwndDlg) || !lstrlenA(buf)) break;
+ EmptyClipboard();
+ hData = GlobalAlloc(GMEM_MOVEABLE, lstrlenA(buf) + 1);
+ lstrcpyA(GlobalLock(hData), buf);
+ GlobalUnlock(hData);
+ SetClipboardData(CF_TEXT, hData);
+ CloseClipboard();
+ }
+ break;
+ }
+ case DM_UPDATELASTMESSAGE:
+ {
+ if (!dat->hwndStatus || dat->nTypeSecs)
+ break;
+ if (dat->lastMessage) {
+ DBTIMETOSTRINGT dbtts;
+ TCHAR date[64], time[64], fmt[128];
+
+ dbtts.szFormat = _T("d");
+ dbtts.cbDest = SIZEOF(date);
+ dbtts.szDest = date;
+ CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT, dat->lastMessage, (LPARAM) & dbtts);
+ dbtts.szFormat = _T("t");
+ dbtts.cbDest = SIZEOF(time);
+ dbtts.szDest = time;
+ CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT, dat->lastMessage, (LPARAM) & dbtts);
+ mir_sntprintf(fmt, SIZEOF(fmt), TranslateT("Last message received on %s at %s."), date, time);
+ SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) fmt);
+ SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) NULL);
+ }
+ else {
+ SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) _T(""));
+ SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) NULL);
+ }
+ break;
+ }
+ case DM_OPTIONSAPPLIED:
+ SetDialogToType(hwndDlg);
+ if (dat->hBkgBrush)
+ DeleteObject(dat->hBkgBrush);
+ {
+ COLORREF colour = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR);
+ dat->hBkgBrush = CreateSolidBrush(colour);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETBKGNDCOLOR, 0, colour);
+ }
+ { // avatar stuff
+ dat->avatarPic = 0;
+ dat->limitAvatarH = 0;
+ if (CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0)&PF4_AVATARS) {
+ dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)?DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT):0;
+ }
+ if (!wParam) SendMessage(hwndDlg, DM_GETAVATAR, 0, 0);
+ }
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, FALSE);
+ {
+ HFONT hFont;
+ LOGFONT lf;
+ hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0);
+ if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0))
+ DeleteObject(hFont);
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, &lf, NULL);
+ hFont = CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0));
+ }
+
+ /*
+ * configure message history for proper RTL formatting
+ */
+
+ {
+ PARAFORMAT2 pf2;
+ ZeroMemory((void *)&pf2, sizeof(pf2));
+ pf2.cbSize = sizeof(pf2);
+
+ pf2.wEffects = PFE_RTLPARA;
+ pf2.dwMask = PFM_RTLPARA;
+ SetDlgItemText(hwndDlg, IDC_LOG, _T(""));
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ pf2.wEffects = 0;
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
+ }
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ break;
+ case DM_UPDATETITLE:
+ {
+ TCHAR newtitle[256], oldtitle[256], *szStatus;
+ TCHAR *contactName, *pszNewTitleEnd;
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) wParam;
+
+ pszNewTitleEnd = _T("Message Session");
+ if (dat->hContact) {
+ if (dat->szProto) {
+ CONTACTINFO ci;
+ char buf[128];
+ int statusIcon = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON);
+
+ buf[0] = 0;
+ dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ contactName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR);
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = dat->hContact;
+ ci.szProto = dat->szProto;
+ ci.dwFlag = CNF_UNIQUEID;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
+ switch (ci.type) {
+ case CNFT_ASCIIZ:
+ mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal);
+ miranda_sys_free(ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ mir_snprintf(buf, SIZEOF(buf), "%u", ci.dVal);
+ break;
+ }
+ }
+ if ( buf[0] )
+ SetDlgItemTextA(hwndDlg, IDC_NAME, buf );
+ else
+ SetDlgItemText(hwndDlg, IDC_NAME, contactName);
+
+ szStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, dat->szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE), GCMDF_TCHAR);
+ if (statusIcon)
+ mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s - %s"), contactName, TranslateTS(pszNewTitleEnd));
+ else
+ mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s (%s): %s"), contactName, szStatus, TranslateTS(pszNewTitleEnd));
+ if (!cws || (!strcmp(cws->szModule, dat->szProto) && !strcmp(cws->szSetting, "Status"))) {
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOCOL), NULL, TRUE);
+ if (statusIcon) {
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ }
+ }
+
+ // log
+ if ((dat->wStatus != dat->wOldStatus || lParam != 0)
+ && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)) {
+ DBEVENTINFO dbei;
+ TCHAR buffer[200];
+ HANDLE hNewEvent;
+ int iLen;
+
+ TCHAR *szOldStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wOldStatus, GCMDF_TCHAR);
+ TCHAR *szNewStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wStatus, GCMDF_TCHAR);
+
+ if (dat->wStatus == ID_STATUS_OFFLINE) {
+ iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed off (was %s)"), szOldStatus);
+ SendMessage(hwndDlg, DM_TYPING, 0, 0);
+ }
+ else if (dat->wOldStatus == ID_STATUS_OFFLINE)
+ iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed on (%s)"), szNewStatus);
+ else
+ iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("is now %s (was %s)"), szNewStatus, szOldStatus);
+
+ {
+ char* blob = ( char* )alloca( 1000 );
+ #if defined( _UNICODE )
+ int ansiLen = WideCharToMultiByte(CP_ACP, 0, buffer, -1, blob, 1000, 0, 0);
+ memcpy( blob+ansiLen, buffer, sizeof(TCHAR)*(iLen+1));
+ dbei.cbBlob = ansiLen + sizeof(TCHAR)*(iLen+1);
+ #else
+ int wLen = MultiByteToWideChar(CP_ACP, 0, buffer, -1, NULL, 0 );
+ memcpy( blob, buffer, iLen+1 );
+ MultiByteToWideChar(CP_ACP, 0, buffer, -1, (WCHAR*)&blob[iLen+1], wLen+1 );
+ dbei.cbBlob = iLen+1 + sizeof(WCHAR)*wLen;
+ #endif
+
+ dbei.cbSize = sizeof(dbei);
+ dbei.pBlob = (PBYTE) blob;
+ dbei.eventType = EVENTTYPE_STATUSCHANGE;
+ dbei.flags = 0;
+ dbei.timestamp = time(NULL);
+ dbei.szModule = dat->szProto;
+ hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) dat->hContact, (LPARAM) & dbei);
+ if (dat->hDbEventFirst == NULL) {
+ dat->hDbEventFirst = hNewEvent;
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ }
+ }
+ }
+ dat->wOldStatus = dat->wStatus;
+ }
+ }
+ else lstrcpyn(newtitle, pszNewTitleEnd, SIZEOF(newtitle));
+
+ GetWindowText(hwndDlg, oldtitle, SIZEOF(oldtitle));
+ if ( lstrcmp(newtitle, oldtitle )) { //swt() flickers even if the title hasn't actually changed
+ SetWindowText(hwndDlg, newtitle);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ }
+ break;
+ }
+ case DM_GETWINDOWSTATE:
+ {
+ UINT state = 0;
+
+ state |= MSG_WINDOW_STATE_EXISTS;
+ if (IsWindowVisible(hwndDlg))
+ state |= MSG_WINDOW_STATE_VISIBLE;
+ if (GetForegroundWindow()==hwndDlg)
+ state |= MSG_WINDOW_STATE_FOCUS;
+ if (IsIconic(hwndDlg))
+ state |= MSG_WINDOW_STATE_ICONIC;
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, state);
+ return TRUE;
+
+ }
+ case DM_CASCADENEWWINDOW:
+ if ((HWND) wParam == hwndDlg)
+ break;
+ {
+ RECT rcThis, rcNew;
+ GetWindowRect(hwndDlg, &rcThis);
+ GetWindowRect((HWND) wParam, &rcNew);
+ if (abs(rcThis.left - rcNew.left) < 3 && abs(rcThis.top - rcNew.top) < 3) {
+ int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
+ SetWindowPos((HWND) wParam, 0, rcNew.left + offset, rcNew.top + offset, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+ *(int *) lParam = 1;
+ }
+ }
+ break;
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_ACTIVE)
+ break;
+ //fall through
+ case WM_MOUSEACTIVATE:
+ if (KillTimer(hwndDlg, TIMERID_FLASHWND))
+ FlashWindow(hwndDlg, FALSE);
+ break;
+ case WM_SETFOCUS:
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ break;
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO *mmi = (MINMAXINFO *) lParam;
+ RECT rcWindow, rcLog;
+ GetWindowRect(hwndDlg, &rcWindow);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog);
+ mmi->ptMinTrackSize.x = rcWindow.right - rcWindow.left - ((rcLog.right - rcLog.left) - dat->minEditBoxSize.cx);
+ mmi->ptMinTrackSize.y = rcWindow.bottom - rcWindow.top - ((rcLog.bottom - rcLog.top) - dat->minEditBoxSize.cy);
+ return 0;
+ }
+ case WM_SIZE:
+ {
+ UTILRESIZEDIALOG urd;
+ if (IsIconic(hwndDlg))
+ break;
+ if (dat->hwndStatus) {
+ SendMessage(dat->hwndStatus, WM_SIZE, 0, 0);
+ if (SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) == 2) {
+ int statwidths[2];
+ RECT rc;
+
+ GetWindowRect(dat->hwndStatus, &rc);
+ statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH;
+ statwidths[1] = -1;
+ SendMessage(dat->hwndStatus, SB_SETPARTS, 2, (LPARAM) statwidths);
+ }
+ }
+ ZeroMemory(&urd, sizeof(urd));
+ urd.cbSize = sizeof(urd);
+ urd.hInstance = g_hInst;
+ urd.hwndDlg = hwndDlg;
+ urd.lParam = (LPARAM) dat;
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_MSG);
+ urd.pfnResizer = MessageDialogResize;
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) & urd);
+ // The statusbar sometimes draws over these 2 controls so
+ // redraw them
+ if (dat->hwndStatus) {
+ RedrawWindow(GetDlgItem(hwndDlg, IDOK), NULL, NULL, RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE);
+ }
+ if ((g_dat->flags&SMF_AVATAR)&&dat->avatarPic)
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE);
+ break;
+ }
+ case DM_SPLITTERMOVED:
+ {
+ POINT pt;
+ RECT rc;
+ RECT rcLog;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog);
+ if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SPLITTER)) {
+ int oldSplitterY;
+ GetClientRect(hwndDlg, &rc);
+ pt.x = 0;
+ pt.y = wParam;
+ ScreenToClient(hwndDlg, &pt);
+
+ oldSplitterY = dat->splitterPos;
+ dat->splitterPos = rc.bottom - pt.y + 23;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc);
+ if (rc.bottom - rc.top + (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy)
+ dat->splitterPos = oldSplitterY + dat->minEditBoxSize.cy - (rc.bottom - rc.top);
+ if (rcLog.bottom - rcLog.top - (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy)
+ dat->splitterPos = oldSplitterY - dat->minEditBoxSize.cy + (rcLog.bottom - rcLog.top);
+ }
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+ }
+ case DM_REMAKELOG:
+ dat->lastEventType = -1;
+ StreamInEvents(hwndDlg, dat->hDbEventFirst, -1, 0);
+ break;
+ case DM_APPENDTOLOG: //takes wParam=hDbEvent
+ StreamInEvents(hwndDlg, (HANDLE) wParam, 1, 1);
+ break;
+ case DM_SCROLLLOGTOBOTTOM:
+ {
+ SCROLLINFO si = { 0 };
+ if ((GetWindowLong(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL) == 0)
+ break;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_PAGE | SIF_RANGE;
+ GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si);
+ si.fMask = SIF_POS;
+ si.nPos = si.nMax - si.nPage + 1;
+ SetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si, TRUE);
+ PostMessage(GetDlgItem(hwndDlg, IDC_LOG), WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0);
+ break;
+ }
+ case HM_DBEVENTADDED:
+ if ((HANDLE) wParam != dat->hContact)
+ break;
+ {
+ DBEVENTINFO dbei = { 0 };
+
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = 0;
+ CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei);
+ if (dat->hDbEventFirst == NULL)
+ dat->hDbEventFirst = (HANDLE) lParam;
+ if (dbei.eventType == EVENTTYPE_MESSAGE && (dbei.flags & DBEF_READ))
+ break;
+ if (DbEventIsShown(&dbei, dat)) {
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & (DBEF_SENT))) {
+ if (GetForegroundWindow()==hwndDlg)
+ SkinPlaySound("RecvMsgActive");
+ else SkinPlaySound("RecvMsgInactive");
+ }
+ if (dbei.eventType == EVENTTYPE_MESSAGE && dat->hwndStatus && !(dbei.flags & (DBEF_SENT))) {
+ dat->lastMessage = dbei.timestamp;
+ SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0);
+ }
+ if ((HANDLE) lParam != dat->hDbEventFirst && (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, lParam, 0) == NULL)
+ SendMessage(hwndDlg, DM_APPENDTOLOG, lParam, 0);
+ else
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ if ((GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg) && !(dbei.flags & DBEF_SENT)
+ && dbei.eventType != EVENTTYPE_STATUSCHANGE) {
+ SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ }
+ }
+ break;
+ }
+ case WM_TIMER:
+ if (wParam == TIMERID_MSGSEND) {
+ KillTimer(hwndDlg, wParam);
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ EnableWindow(hwndDlg, FALSE);
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGSENDERROR), hwndDlg, ErrorDlgProc, (LPARAM) strdup( Translate("The message send timed out.")));
+ }
+ else if (wParam == TIMERID_FLASHWND) {
+ FlashWindow(hwndDlg, TRUE);
+ if (dat->nFlash > dat->nFlashMax) {
+ KillTimer(hwndDlg, TIMERID_FLASHWND);
+ FlashWindow(hwndDlg, FALSE);
+ dat->nFlash = 0;
+ }
+ dat->nFlash++;
+ }
+ else if (wParam == TIMERID_TYPE) {
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON && GetTickCount() - dat->nLastTyping > TIMEOUT_TYPEOFF) {
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+ }
+ if (dat->showTyping) {
+ if (dat->nTypeSecs) {
+ dat->nTypeSecs--;
+ if (GetForegroundWindow() == hwndDlg)
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ }
+ else {
+ SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0);
+ if (g_dat->flags&SMF_SHOWTYPINGWIN)
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ dat->showTyping = 0;
+ }
+ }
+ else {
+ if (dat->nTypeSecs) {
+ TCHAR szBuf[256];
+ TCHAR *szContactName = ( TCHAR* ) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR);
+
+ mir_sntprintf(szBuf, SIZEOF(szBuf), TranslateT("%s is typing a message..."), szContactName);
+ dat->nTypeSecs--;
+ SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) szBuf);
+ SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) g_dat->hIcons[SMF_ICON_TYPING]);
+ if ((g_dat->flags&SMF_SHOWTYPINGWIN) && GetForegroundWindow() != hwndDlg)
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) g_dat->hIcons[SMF_ICON_TYPING]);
+ dat->showTyping = 1;
+ }
+ }
+ }
+ break;
+ case DM_ERRORDECIDED:
+ EnableWindow(hwndDlg, TRUE);
+ switch (wParam) {
+ case MSGERROR_CANCEL:
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETREADONLY, FALSE, 0);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ break;
+ case MSGERROR_RETRY:
+ {
+ if (dat->hSendId == NULL && dat->hContact == NULL)
+ return 0;
+ dat->hSendId = (HANDLE) CallContactService(dat->hContact, MsgServiceName(dat->hContact), SEND_FLAGS, (LPARAM) dat->sendBuffer);
+ }
+ SetTimer(hwndDlg, TIMERID_MSGSEND, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT), NULL);
+ break;
+ }
+ break;
+ case WM_CTLCOLOREDIT:
+ {
+ COLORREF colour;
+ if ((HWND) lParam != GetDlgItem(hwndDlg, IDC_MESSAGE))
+ break;
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, NULL, &colour);
+ SetTextColor((HDC) wParam, colour);
+ SetBkColor((HDC) wParam, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR));
+ return (BOOL) dat->hBkgBrush;
+ }
+ case WM_MEASUREITEM:
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
+ if (dis->hwndItem == GetDlgItem(hwndDlg, IDC_PROTOCOL)) {
+ if (dat->szProto) {
+ HICON hIcon;
+ int dwStatus;
+
+ dwStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ hIcon = LoadSkinnedProtoIcon(dat->szProto, dwStatus);
+ if (hIcon) {
+ if (DBGetContactSettingDword(dat->hContact, dat->szProto, "IdleTS", 0)) {
+ HIMAGELIST hImageList;
+
+ hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, 1, 0);
+ ImageList_AddIcon(hImageList, hIcon);
+ ImageList_DrawEx(hImageList, 0, dis->hDC, dis->rcItem.left, dis->rcItem.top, 0, 0, CLR_NONE, CLR_NONE, ILD_SELECTED);
+ ImageList_RemoveAll(hImageList);
+ ImageList_Destroy(hImageList);
+ }
+ else DrawIconEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
+ }
+ }
+ }
+ else if (dis->hwndItem == GetDlgItem(hwndDlg, IDC_AVATAR) && dat->avatarPic && (g_dat->flags&SMF_AVATAR)) {
+ BITMAP bminfo;
+ HPEN hPen, hOldPen;
+
+ hPen = CreatePen(PS_SOLID, 1, RGB(0,0,0));
+ hOldPen = SelectObject(dis->hDC, hPen);
+ Rectangle(dis->hDC, 0, 0, dat->avatarWidth, dat->avatarHeight);
+ SelectObject(dis->hDC,hOldPen);
+ DeleteObject(hPen);
+ GetObject(dat->avatarPic, sizeof(bminfo), &bminfo);
+ {
+ HDC hdcMem = CreateCompatibleDC(dis->hDC);
+ HBITMAP hbmMem = (HBITMAP)SelectObject(hdcMem, dat->avatarPic);
+ {
+ double aspect = 0, w = 0;
+
+ aspect = (double)dat->limitAvatarH / (double)bminfo.bmHeight;
+ w = (double)bminfo.bmWidth * aspect;
+ SetStretchBltMode(dis->hDC, HALFTONE);
+ StretchBlt(dis->hDC, 1, 1, dat->avatarWidth-2, dat->avatarHeight-2, hdcMem, 0, 0, bminfo.bmWidth, bminfo.bmHeight, SRCCOPY);
+ }
+ SelectObject(hdcMem,hbmMem);
+ DeleteDC(hdcMem);
+ }
+ }
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+ }
+ case WM_COMMAND:
+ if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) dat->hContact))
+ break;
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDOK)))
+ break;
+ {
+ int flags = SEND_FLAGS;
+ //this is a 'send' button
+ int bufSize = GetWindowTextLengthA(GetDlgItem(hwndDlg, IDC_MESSAGE)) + 1;
+ dat->sendBuffer = (char *) realloc(dat->sendBuffer, bufSize * (sizeof(TCHAR) + 1));
+ dat->bIsRtl = 0;
+ GetDlgItemTextA(hwndDlg, IDC_MESSAGE, dat->sendBuffer, bufSize);
+ #if defined( _UNICODE )
+ // all that crap with temporary buffers is related to the bug #0001466 (empty messages
+ // on x64 machines). GetDlgItemTextW should use the 2-byte aligned buffer
+ { WCHAR* temp = ( WCHAR* )alloca( bufSize * sizeof( TCHAR ));
+ GetDlgItemTextW(hwndDlg, IDC_MESSAGE, temp, bufSize);
+ memcpy(( TCHAR*)&dat->sendBuffer[bufSize], temp, bufSize * sizeof( TCHAR ));
+ if ( RTL_Detect( temp )) {
+ flags |= PREF_RTL;
+ dat->bIsRtl = 1;
+ }
+ }
+ #endif
+ if (dat->sendBuffer[0] == 0)
+ break;
+ #if defined( _UNICODE )
+ dat->cmdList = tcmdlist_append(dat->cmdList, (TCHAR *) & dat->sendBuffer[bufSize]);
+ #else
+ dat->cmdList = tcmdlist_append(dat->cmdList, dat->sendBuffer);
+ #endif
+ dat->cmdListCurrent = 0;
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) {
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+ }
+
+ if (dat->hContact == NULL)
+ break; //never happens
+ dat->sendCount = 1;
+ dat->hSendId = (HANDLE) CallContactService(dat->hContact, MsgServiceName(dat->hContact), flags, (LPARAM) dat->sendBuffer);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETREADONLY, TRUE, 0);
+
+ //create a timeout timer
+ SetTimer(hwndDlg, TIMERID_MSGSEND, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT), NULL);
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN))
+ ShowWindow(hwndDlg, SW_MINIMIZE);
+ }
+ return TRUE;
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ case IDC_USERMENU:
+ case IDC_NAME:
+ {
+ if(GetKeyState(VK_SHIFT) & 0x8000) { // copy user name
+ SendMessage(hwndDlg, DM_USERNAMETOCLIP, 0, 0);
+ }
+ else {
+ RECT rc;
+ HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0);
+ GetWindowRect(GetDlgItem(hwndDlg, LOWORD(wParam)), &rc);
+ TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ }
+ }
+ break;
+ case IDC_HISTORY:
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM) dat->hContact, 0);
+ break;
+ case IDC_DETAILS:
+ CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) dat->hContact, 0);
+ break;
+ case IDC_ADD:
+ {
+ ADDCONTACTSTRUCT acs = { 0 };
+
+ acs.handle = dat->hContact;
+ acs.handleType = HANDLE_CONTACT;
+ acs.szProto = 0;
+ CallService(MS_ADDCONTACT_SHOW, (WPARAM) hwndDlg, (LPARAM) & acs);
+ }
+ if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) {
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE);
+ }
+ break;
+ case IDC_MESSAGE:
+ if (HIWORD(wParam) == EN_CHANGE) {
+ int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ UpdateReadChars(hwndDlg, dat->hwndStatus);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), len != 0);
+ if (!(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000)) {
+ dat->nLastTyping = GetTickCount();
+ if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE))) {
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_OFF) {
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_ON);
+ }
+ }
+ else {
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) {
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+ }
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((NMHDR *) lParam)->idFrom) {
+ case IDC_LOG:
+ switch (((NMHDR *) lParam)->code) {
+ case EN_MSGFILTER:
+ switch (((MSGFILTER *) lParam)->msg) {
+ case WM_LBUTTONDOWN:
+ {
+ HCURSOR hCur = GetCursor();
+ if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE)
+ || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) {
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+ case WM_MOUSEMOVE:
+ {
+ HCURSOR hCur = GetCursor();
+ if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE)
+ || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE))
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ break;
+ }
+ case WM_RBUTTONUP:
+ {
+ HMENU hMenu, hSubMenu;
+ POINT pt;
+ CHARRANGE sel, all = { 0, -1 };
+
+ hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ hSubMenu = GetSubMenu(hMenu, 0);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hSubMenu, 0);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin == sel.cpMax)
+ EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) {
+ case IDM_COPY:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0);
+ break;
+ case IDM_COPYALL:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel);
+ break;
+ case IDM_SELECTALL:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all);
+ break;
+ case IDM_CLEAR:
+ SetDlgItemText(hwndDlg, IDC_LOG, _T(""));
+ dat->hDbEventFirst = NULL;
+ break;
+ }
+ DestroyMenu(hMenu);
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ }
+ break;
+ case EN_LINK:
+ switch (((ENLINK *) lParam)->msg) {
+ case WM_SETCURSOR:
+ SetCursor(hCurHyperlinkHand);
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE);
+ return TRUE;
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ {
+ TEXTRANGEA tr;
+ CHARRANGE sel;
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin != sel.cpMax)
+ break;
+ tr.chrg = ((ENLINK *) lParam)->chrg;
+ tr.lpstrText = malloc(tr.chrg.cpMax - tr.chrg.cpMin + 8);
+ SendDlgItemMessageA(hwndDlg, IDC_LOG, EM_GETTEXTRANGE, 0, (LPARAM) & tr);
+ if (strchr(tr.lpstrText, '@') != NULL && strchr(tr.lpstrText, ':') == NULL && strchr(tr.lpstrText, '/') == NULL) {
+ MoveMemory(tr.lpstrText + 7, tr.lpstrText, tr.chrg.cpMax - tr.chrg.cpMin + 1);
+ CopyMemory(tr.lpstrText, "mailto:", 7);
+ }
+ if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN) {
+ HMENU hMenu, hSubMenu;
+ POINT pt;
+
+ hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ hSubMenu = GetSubMenu(hMenu, 1);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hSubMenu, 0);
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) {
+ case IDM_OPENNEW:
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) tr.lpstrText);
+ break;
+ case IDM_OPENEXISTING:
+ CallService(MS_UTILS_OPENURL, 0, (LPARAM) tr.lpstrText);
+ break;
+ case IDM_COPYLINK:
+ {
+ HGLOBAL hData;
+ if (!OpenClipboard(hwndDlg))
+ break;
+ EmptyClipboard();
+ hData = GlobalAlloc(GMEM_MOVEABLE, lstrlenA(tr.lpstrText) + 1);
+ lstrcpyA(GlobalLock(hData), tr.lpstrText);
+ GlobalUnlock(hData);
+ SetClipboardData(CF_TEXT, hData);
+ CloseClipboard();
+ break;
+ }
+ }
+ free(tr.lpstrText);
+ DestroyMenu(hMenu);
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ else {
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) tr.lpstrText);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ }
+
+ free(tr.lpstrText);
+ break;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case HM_EVENTSENT:
+ {
+ ACKDATA *ack = (ACKDATA *) lParam;
+ DBEVENTINFO dbei = { 0 };
+ HANDLE hNewEvent;
+
+ if (ack->type != ACKTYPE_MESSAGE)
+ break;
+ if (dat->sendCount==0)
+ break;
+ switch (ack->result) {
+ case ACKRESULT_FAILED:
+ KillTimer(hwndDlg, TIMERID_MSGSEND);
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ EnableWindow(hwndDlg, FALSE);
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGSENDERROR), hwndDlg, ErrorDlgProc, (ack->lParam == 0) ? 0 : (LPARAM) strdup((char *) ack->lParam));
+ return 0;
+ }
+ if (dat->sendBuffer==NULL) return 0;
+ dbei.cbSize = sizeof(dbei);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.flags = DBEF_SENT + (( dat->bIsRtl ) ? DBEF_RTL : 0 );
+
+ dbei.szModule = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->hContact, 0);
+ dbei.timestamp = time(NULL);
+ dbei.cbBlob = lstrlenA(dat->sendBuffer) + 1;
+ #if defined( _UNICODE )
+ dbei.cbBlob *= sizeof(TCHAR) + 1;
+ #endif
+ dbei.pBlob = (PBYTE) dat->sendBuffer;
+ hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) dat->hContact, (LPARAM) & dbei);
+ SkinPlaySound("SendMsg");
+ if (dat->hDbEventFirst == NULL) {
+ dat->hDbEventFirst = hNewEvent;
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ }
+
+ dat->hSendId = NULL;
+ {
+ int len;
+ //all messages sent
+ dat->sendCount = 0;
+ KillTimer(hwndDlg, TIMERID_MSGSEND);
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, _T(""));
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETREADONLY, FALSE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REPLAYSAVEDKEYSTROKES, 0, 0);
+ if (GetForegroundWindow() == hwndDlg)
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ UpdateReadChars(hwndDlg, dat->hwndStatus);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), len != 0);
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE))
+ DestroyWindow(hwndDlg);
+ }
+ break;
+ }
+ case WM_DESTROY:
+ NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING);
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) {
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+ }
+ if (dat->hBkgBrush)
+ DeleteObject(dat->hBkgBrush);
+ if (dat->sendBuffer != NULL)
+ free(dat->sendBuffer);
+ if (dat->hwndStatus)
+ DestroyWindow(dat->hwndStatus);
+ tcmdlist_free(dat->cmdList);
+ WindowList_Remove(g_dat->hMessageWindowList, hwndDlg);
+ DBWriteContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", dat->splitterPos);
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_SPLITTER), GWL_WNDPROC, (LONG) OldSplitterProc);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_UNSUBCLASSED, 0, 0);
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_MESSAGE), GWL_WNDPROC, (LONG) OldMessageEditProc);
+ {
+ HFONT hFont;
+ hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0);
+ if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0))
+ DeleteObject(hFont);
+ }
+ {
+ WINDOWPLACEMENT wp = { 0 };
+ HANDLE hContact;
+
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT))
+ hContact = dat->hContact;
+ else
+ hContact = NULL;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwndDlg, &wp);
+ if (!dat->windowWasCascaded) {
+ DBWriteContactSettingDword(hContact, SRMMMOD, "x", wp.rcNormalPosition.left);
+ DBWriteContactSettingDword(hContact, SRMMMOD, "y", wp.rcNormalPosition.top);
+ }
+ DBWriteContactSettingDword(hContact, SRMMMOD, "width", wp.rcNormalPosition.right - wp.rcNormalPosition.left);
+ DBWriteContactSettingDword(hContact, SRMMMOD, "height", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
+ }
+ if (dat->avatarPic)
+ DeleteObject(dat->avatarPic);
+ NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE);
+ if (dat->hContact&&DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP)) {
+ if (DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) {
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)dat->hContact, 0);
+ }
+ }
+ free(dat);
+ SetWindowLong(hwndDlg, GWL_USERDATA, 0);
+ break;
+ }
+ return FALSE;
+}