From 60338d55bb73d0c45b6e092703c4bb88a3c49755 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 23 Jul 2012 13:03:18 +0000 Subject: Rate, RecentContacts, Scriver: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1121 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Scriver/src/msgdialog.cpp | 2107 +++++++++++++++++++++++++++++++++++++ 1 file changed, 2107 insertions(+) create mode 100644 plugins/Scriver/src/msgdialog.cpp (limited to 'plugins/Scriver/src/msgdialog.cpp') diff --git a/plugins/Scriver/src/msgdialog.cpp b/plugins/Scriver/src/msgdialog.cpp new file mode 100644 index 0000000000..a5bb8d92dd --- /dev/null +++ b/plugins/Scriver/src/msgdialog.cpp @@ -0,0 +1,2107 @@ +/* +Scriver + +Copyright 2000-2012 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. +*/ +#include "commonheaders.h" +#include "statusicon.h" +#include "infobar.h" + +#define TIMERID_MSGSEND 0 +#define TIMERID_FLASHWND 1 +#define TIMERID_TYPE 2 +#define TIMERID_UNREAD 3 +#define TIMEOUT_TYPEOFF 10000 //send type off after 10 seconds of inactivity +#define TIMEOUT_UNREAD 800 //multiple-send bombproofing: send max 3 messages every 4 seconds +#define VALID_AVATAR(x) (x==PA_FORMAT_PNG||x==PA_FORMAT_JPEG||x==PA_FORMAT_ICON||x==PA_FORMAT_BMP||x==PA_FORMAT_GIF) + +#define ENTERCLICKTIME 1000 //max time in ms during which a double-tap on enter will cause a send + +extern HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand, hDragCursor; +extern HANDLE hHookWinEvt; +extern HANDLE hHookWinPopup; +extern CREOleCallback reOleCallback, reOleCallback2; + +static void UpdateReadChars(HWND hwndDlg, struct SrmmWindowData * dat); + +static WNDPROC OldMessageEditProc, OldLogEditProc; +static ToolbarButton toolbarButtons[] = { + {_T("Quote"), IDC_QUOTE, 0, 4, 24}, + {_T("Smiley"), IDC_SMILEYS, 0, 10, 24}, + {_T("Add Contact"), IDC_ADD, 0, 10, 24}, + {_T("User Menu"), IDC_USERMENU, 1, 0, 24}, + {_T("User Details"), IDC_DETAILS, 1, 0, 24}, + {_T("History"), IDC_HISTORY, 1, 0, 24}, + {_T("Send"), IDOK, 1, 0, 38} +}; + +static DWORD CALLBACK StreamOutCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + MessageSendQueueItem * msi = (MessageSendQueueItem *) dwCookie; + msi->sendBuffer = (char *)mir_realloc(msi->sendBuffer, msi->sendBufferSize + cb + 2); + memcpy (msi->sendBuffer + msi->sendBufferSize, pbBuff, cb); + msi->sendBufferSize += cb; + *((TCHAR *)(msi->sendBuffer+msi->sendBufferSize)) = '\0'; + *pcb = cb; + return 0; +} + +static TCHAR *GetIEViewSelection(struct SrmmWindowData *dat) { + IEVIEWEVENT event; + ZeroMemory(&event, sizeof(event)); + event.cbSize = sizeof(event); + event.dwFlags = 0; + event.codepage = dat->windowData.codePage; + event.hwnd = dat->windowData.hwndLog; + event.hContact = dat->windowData.hContact; + event.iType = IEE_GET_SELECTION; + return mir_tstrdup((TCHAR *)CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event)); +} + +static TCHAR *GetQuotedTextW(TCHAR * text) { + int i, j, l, newLine, wasCR; + TCHAR *out; + l = (int)wcslen(text); + newLine = 1; + wasCR = 0; + for (i=j=0; i';i++) j--; + j+=2; + } + newLine = 0; + wasCR = 0; + } + } + j+=3; + out = (TCHAR *)mir_alloc(sizeof(TCHAR) * j); + newLine = 1; + wasCR = 0; + for (i=j=0; i';i++) j--; + } + newLine = 0; + wasCR = 0; + out[j++]=text[i]; + } + } + out[j++]='\r'; + out[j++]='\n'; + out[j++]='\0'; + return out; +} + +static void saveDraftMessage(HWND hwnd, HANDLE hContact, int codepage) { + char *textBuffer = GetRichTextEncoded(hwnd, codepage); + if (textBuffer != NULL) { + g_dat->draftList = tcmdlist_append2(g_dat->draftList, hContact, textBuffer); + mir_free(textBuffer); + } else { + g_dat->draftList = tcmdlist_remove2(g_dat->draftList, hContact); + } +} + +void NotifyLocalWinEvent(HANDLE hContact, HWND hwnd, unsigned int type) { + MessageWindowEventData mwe = { 0 }; + BOOL bChat = FALSE; + 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; + bChat = (WindowList_Find(g_dat->hMessageWindowList, hContact) == NULL); + mwe.hwndInput = GetDlgItem(hwnd, bChat ? IDC_CHAT_MESSAGE : IDC_MESSAGE); + mwe.hwndLog = GetDlgItem(hwnd, bChat ? IDC_CHAT_LOG : IDC_LOG); + NotifyEventHooks(hHookWinEvt, 0, (LPARAM)&mwe); +} + +static BOOL IsUtfSendAvailable(HANDLE hContact) +{ + char* szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if ( szProto == NULL ) + return FALSE; + + return ( CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF ) ? TRUE : FALSE; +} + +int RTL_Detect(WCHAR *pszwText) +{ + WORD *infoTypeC2; + int i; + int iLen = lstrlenW(pszwText); + + infoTypeC2 = (WORD *)mir_alloc(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) { + mir_free(infoTypeC2); + return 1; + } + } + mir_free(infoTypeC2); + } + return 0; +} + +static void AddToFileList(TCHAR ***pppFiles,int *totalCount,const TCHAR* szFilename) +{ + *pppFiles=(TCHAR**)mir_realloc(*pppFiles,(++*totalCount+1)*sizeof(TCHAR*)); + (*pppFiles)[*totalCount] = NULL; + (*pppFiles)[*totalCount-1] = mir_tstrdup( szFilename ); + + if ( GetFileAttributes(szFilename) & FILE_ATTRIBUTE_DIRECTORY ) { + WIN32_FIND_DATA fd; + HANDLE hFind; + TCHAR szPath[MAX_PATH]; + lstrcpy(szPath,szFilename); + lstrcat(szPath,_T("\\*")); + if (( hFind = FindFirstFile( szPath, &fd )) != INVALID_HANDLE_VALUE ) { + do { + if ( !lstrcmp(fd.cFileName,_T(".")) || !lstrcmp(fd.cFileName,_T(".."))) continue; + lstrcpy(szPath,szFilename); + lstrcat(szPath,_T("\\")); + lstrcat(szPath,fd.cFileName); + AddToFileList(pppFiles,totalCount,szPath); + } + while( FindNextFile( hFind,&fd )); + FindClose( hFind ); +} } } + +static void SetDialogToType(HWND hwndDlg) +{ + BOOL showToolbar = SendMessage(GetParent(hwndDlg), CM_GETTOOLBARSTATUS, 0, 0); + struct SrmmWindowData *dat = (struct SrmmWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + ParentWindowData *pdat = dat->parent; + + if (pdat->flags2 & SMF2_SHOWINFOBAR) { + ShowWindow(dat->infobarData->hWnd, SW_SHOW); + } else { + ShowWindow(dat->infobarData->hWnd, SW_HIDE); + } + if (dat->windowData.hContact) { + ShowToolbarControls(hwndDlg, SIZEOF(toolbarButtons), toolbarButtons, g_dat->buttonVisibility, showToolbar ? SW_SHOW : SW_HIDE); + if (!DBGetContactSettingByte(dat->windowData.hContact, "CList", "NotOnList", 0)) { + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE); + } + if (!g_dat->smileyAddInstalled) { + ShowWindow(GetDlgItem(hwndDlg, IDC_SMILEYS), SW_HIDE); + } + } else { + ShowToolbarControls(hwndDlg, SIZEOF(toolbarButtons), toolbarButtons, g_dat->buttonVisibility, SW_HIDE); + } + ShowWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), SW_SHOW); + if (dat->windowData.hwndLog != NULL) { + ShowWindow (GetDlgItem(hwndDlg, IDC_LOG), SW_HIDE); + } else { + ShowWindow (GetDlgItem(hwndDlg, IDC_LOG), SW_SHOW); + } + ShowWindow(GetDlgItem(hwndDlg, IDC_SPLITTER), SW_SHOW); + UpdateReadChars(hwndDlg, dat); + EnableWindow(GetDlgItem(hwndDlg, IDOK), GetRichTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE), dat->windowData.codePage, FALSE)?TRUE:FALSE); + SendMessage(hwndDlg, DM_CLISTSETTINGSCHANGED, 0, 0); + SendMessage(hwndDlg, WM_SIZE, 0, 0); +} + + +void SetStatusIcon(struct SrmmWindowData *dat) { + if (dat->szProto != NULL) { + char *szProto = dat->szProto; + HANDLE hContact = dat->windowData.hContact; + + char* szMetaProto = (char*)CallService(MS_MC_GETPROTOCOLNAME, 0, 0); + if ((INT_PTR)szMetaProto != CALLSERVICE_NOTFOUND && strcmp(dat->szProto, szMetaProto) == 0 && + DBGetContactSettingByte(NULL,"CLC","Meta",0) == 0) { + hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,(WPARAM)dat->windowData.hContact, 0); + if (hContact != NULL) { + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0); + } else { + hContact = dat->windowData.hContact; + } + } + + CallService(MS_SKIN2_RELEASEICON, (WPARAM)dat->statusIcon, 0); + dat->statusIcon = LoadSkinnedProtoIcon(szProto, dat->wStatus); + + CallService(MS_SKIN2_RELEASEICON, (WPARAM)dat->statusIconBig, 0); + dat->statusIconBig = LoadSkinnedProtoIconBig(szProto, dat->wStatus); + if ((int)dat->statusIconBig == CALLSERVICE_NOTFOUND) { + dat->statusIconBig = NULL; + } + if (dat->statusIconOverlay != NULL) DestroyIcon(dat->statusIconOverlay); + { + int index = ImageList_ReplaceIcon(g_dat->hHelperIconList, 0, dat->statusIcon); + dat->statusIconOverlay = ImageList_GetIcon(g_dat->hHelperIconList, index, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1)); + } + } +} + +void GetTitlebarIcon(struct SrmmWindowData *dat, TitleBarData *tbd) { + if (dat->showTyping && (g_dat->flags2 & SMF2_SHOWTYPINGWIN)) { + tbd->hIconNot = tbd->hIcon = GetCachedIcon("scriver_TYPING"); + } else if (dat->showUnread && (GetActiveWindow() != dat->hwndParent || GetForegroundWindow() != dat->hwndParent)) { + tbd->hIcon = (g_dat->flags & SMF_STATUSICON) ? dat->statusIcon : g_dat->hMsgIcon; + tbd->hIconNot = (g_dat->flags & SMF_STATUSICON) ? g_dat->hMsgIcon : GetCachedIcon("scriver_OVERLAY"); + } else { + tbd->hIcon = (g_dat->flags & SMF_STATUSICON) ? dat->statusIcon : g_dat->hMsgIcon; + tbd->hIconNot = NULL; + } + tbd->hIconBig = (g_dat->flags & SMF_STATUSICON) ? dat->statusIconBig : g_dat->hMsgIconBig; +} + +HICON GetTabIcon(struct SrmmWindowData *dat) { + if (dat->showTyping) { + return GetCachedIcon("scriver_TYPING"); + } else if (dat->showUnread != 0) { + return dat->statusIconOverlay; + } + return dat->statusIcon; +} + + +struct MsgEditSubclassData +{ + DWORD lastEnterTime; +}; + +static LRESULT CALLBACK LogEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static BOOL inMenu = FALSE; + switch (msg) { + case WM_MEASUREITEM: + MeasureMenuItem(wParam, lParam); + return TRUE; + case WM_DRAWITEM: + return DrawMenuItem(wParam, lParam); + case WM_SETCURSOR: + if (inMenu) { + SetCursor(LoadCursor(NULL, IDC_ARROW)); + return TRUE; + } + break; + case WM_CONTEXTMENU: + { + HMENU hMenu, hSubMenu; + TCHAR *pszWord; + POINT pt; + POINTL ptl; + int uID; + CHARRANGE sel, all = { 0, -1 }; + hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + hSubMenu = GetSubMenu(hMenu, 0); + TranslateMenu(hSubMenu); + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) & sel); + if (sel.cpMin == sel.cpMax) + EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + + if (lParam == 0xFFFFFFFF) { + SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM) & pt, (LPARAM) sel.cpMax); + ClientToScreen(hwnd, &pt); + } else { + pt.x = (short) LOWORD(lParam); + pt.y = (short) HIWORD(lParam); + } + ptl.x = (LONG)pt.x; + ptl.y = (LONG)pt.y; + ScreenToClient(hwnd, (LPPOINT)&ptl); + pszWord = GetRichTextWord(hwnd, &ptl); + if ( pszWord && pszWord[0] ) { + TCHAR szMenuText[4096]; + mir_sntprintf( szMenuText, 4096, TranslateT("Look up \'%s\':"), pszWord ); + ModifyMenu( hSubMenu, 5, MF_STRING|MF_BYPOSITION, 5, szMenuText ); + SetSearchEngineIcons(hMenu, g_dat->hSearchEngineIconList); + } + else ModifyMenu( hSubMenu, 5, MF_STRING|MF_GRAYED|MF_BYPOSITION, 5, TranslateT( "No word to look up" )); + inMenu = TRUE; + uID = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL); + inMenu = FALSE; + switch (uID) { + case IDM_COPY: + SendMessage(hwnd, WM_COPY, 0, 0); + break; + case IDM_COPYALL: + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & all); + SendMessage(hwnd, WM_COPY, 0, 0); + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & sel); + break; + case IDM_SELECTALL: + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & all); + break; + case IDM_CLEAR: + SendMessage(GetParent(hwnd), DM_CLEARLOG, 0, 0); + break; + case IDM_SEARCH_GOOGLE: + case IDM_SEARCH_BING: + case IDM_SEARCH_YAHOO: + case IDM_SEARCH_WIKIPEDIA: + case IDM_SEARCH_FOODNETWORK: + case IDM_SEARCH_GOOGLE_MAPS: + case IDM_SEARCH_GOOGLE_TRANSLATE: + SearchWord(pszWord, uID - IDM_SEARCH_GOOGLE + SEARCHENGINE_GOOGLE); + PostMessage(GetParent(hwnd), WM_MOUSEACTIVATE, 0, 0 ); + break; + } + DestroyMenu(hMenu); + mir_free(pszWord); + return TRUE; + } + } + return CallWindowProc(OldLogEditProc, hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int result = -1; + struct MsgEditSubclassData *dat; + struct SrmmWindowData *pdat; + CommonWindowData *windowData; + BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000; + BOOL isAlt = GetKeyState(VK_MENU) & 0x8000; + dat = (struct MsgEditSubclassData *) GetWindowLongPtr(hwnd, GWLP_USERDATA); + pdat=(struct SrmmWindowData *)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); + windowData = &pdat->windowData; + + result = InputAreaShortcuts(hwnd, msg, wParam, lParam, windowData); + if (result != -1) { + return result; + } + + switch (msg) { + case EM_SUBCLASSED: + dat = (struct MsgEditSubclassData *) mir_alloc(sizeof(struct MsgEditSubclassData)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) dat); + dat->lastEnterTime = 0; + return 0; + + case WM_KEYDOWN: + { + if (wParam == VK_RETURN) { + if ((isCtrl != 0) ^ (0 != (g_dat->flags & SMF_SENDONENTER))) { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + if (g_dat->flags & SMF_SENDONDBLENTER) { + if (dat->lastEnterTime + ENTERCLICKTIME < GetTickCount()) + dat->lastEnterTime = GetTickCount(); + else { + SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0); + SendMessage(hwnd, WM_KEYUP, VK_BACK, 0); + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + } + } + else + dat->lastEnterTime = 0; + if (((wParam == VK_INSERT && (GetKeyState(VK_SHIFT) & 0x8000)) || (wParam == 'V' && (GetKeyState(VK_CONTROL) & 0x8000))) && + !(GetKeyState(VK_MENU) & 0x8000)) + { + SendMessage(hwnd, WM_PASTE, 0, 0); + return 0; + } + + } + break; + //fall through + case WM_MOUSEWHEEL: + if ((GetWindowLongPtr(hwnd, GWL_STYLE) & WS_VSCROLL) == 0) { + SendMessage(GetDlgItem(GetParent(hwnd), IDC_LOG), WM_MOUSEWHEEL, wParam, lParam); + } + break; + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_KILLFOCUS: + dat->lastEnterTime = 0; + break; + case WM_SYSCHAR: + dat->lastEnterTime = 0; + if ((wParam == 's' || wParam == 'S') && isAlt) { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + break; + case WM_PASTE: + if (IsClipboardFormatAvailable(CF_HDROP)) + { + if (OpenClipboard(hwnd)) + { + HANDLE hDrop = GetClipboardData(CF_HDROP); + if (hDrop) + SendMessage(hwnd, WM_DROPFILES, (WPARAM)hDrop, 0); + CloseClipboard(); + } + } + else + SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); + return 0; + case WM_DROPFILES: + SendMessage(GetParent(hwnd), WM_DROPFILES, wParam, lParam); + return 0; + case WM_CONTEXTMENU: + InputAreaContextMenu(hwnd, wParam, lParam, pdat->windowData.hContact); + return TRUE; + case EM_UNSUBCLASSED: + mir_free(dat); + return 0; + } + return CallWindowProc(OldMessageEditProc, hwnd, msg, wParam, lParam); +} + +static void SubclassMessageEdit(HWND hwnd) { + OldMessageEditProc = (WNDPROC) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) MessageEditSubclassProc); + SendMessage(hwnd, EM_SUBCLASSED, 0, 0); +} + +static void UnsubclassMessageEdit(HWND hwnd) { + SendMessage(hwnd, EM_UNSUBCLASSED, 0, 0); + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) OldMessageEditProc); +} + +static void SubclassLogEdit(HWND hwnd) { + OldLogEditProc = (WNDPROC) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) LogEditSubclassProc); + SendMessage(hwnd, EM_SUBCLASSED, 0, 0); +} + +static void UnsubclassLogEdit(HWND hwnd) { + SendMessage(hwnd, EM_UNSUBCLASSED, 0, 0); + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) OldLogEditProc); +} + +static void MessageDialogResize(HWND hwndDlg, struct SrmmWindowData *dat, int w, int h) { + HDWP hdwp; + ParentWindowData *pdat = dat->parent; + int hSplitterPos = dat->splitterPos, toolbarHeight = pdat->flags2&SMF2_SHOWTOOLBAR ? IsToolbarVisible(SIZEOF(toolbarButtons), g_dat->buttonVisibility) ? dat->toolbarSize.cy : dat->toolbarSize.cy / 3 : 0; + int hSplitterMinTop = toolbarHeight + dat->windowData.minLogBoxHeight, hSplitterMinBottom = dat->windowData.minEditBoxHeight; + int infobarHeight = INFO_BAR_INNER_HEIGHT; + int avatarWidth = 0, avatarHeight = 0; + int toolbarWidth = w; + int messageEditWidth = w - 2; + int logY, logH; + + if (!(pdat->flags2 & SMF2_SHOWINFOBAR)) { + infobarHeight = 0; + } + hSplitterPos = dat->desiredInputAreaHeight + SPLITTER_HEIGHT + 3; + if (h - hSplitterPos - INFO_BAR_HEIGHT< hSplitterMinTop) { + hSplitterPos = h - hSplitterMinTop - INFO_BAR_HEIGHT; + } + if (hSplitterPos < avatarHeight) { + hSplitterPos = avatarHeight; + } + if (hSplitterPos < hSplitterMinBottom) { + hSplitterPos = hSplitterMinBottom; + } + if (!(pdat->flags2 & SMF2_SHOWINFOBAR)) { + if (dat->avatarPic && (g_dat->flags&SMF_AVATAR)) { + avatarWidth = BOTTOM_RIGHT_AVATAR_HEIGHT; + avatarHeight = toolbarHeight + hSplitterPos - 2; + if (avatarHeight < BOTTOM_RIGHT_AVATAR_HEIGHT) { + avatarHeight = BOTTOM_RIGHT_AVATAR_HEIGHT; + hSplitterPos = avatarHeight - toolbarHeight + 2; + } else { + avatarHeight = BOTTOM_RIGHT_AVATAR_HEIGHT; + } + avatarWidth = avatarHeight; + if (avatarWidth > BOTTOM_RIGHT_AVATAR_HEIGHT && avatarWidth > w/4) { + avatarWidth = w /4; + } + if ((toolbarWidth - avatarWidth - 2) < dat->toolbarSize.cx) { + avatarWidth = toolbarWidth - dat->toolbarSize.cx - 2; + } + toolbarWidth -= avatarWidth + 2; + messageEditWidth -= avatarWidth + 1; + } + } + + dat->splitterPos = hSplitterPos; + + logY = infobarHeight; + logH = h-hSplitterPos-toolbarHeight - infobarHeight; + hdwp = BeginDeferWindowPos(15); + hdwp = DeferWindowPos(hdwp, dat->infobarData->hWnd, 0, 1, 0, w - 2, infobarHeight - 2, SWP_NOZORDER); + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_LOG), 0, 1, logY, w-2, logH, SWP_NOZORDER); + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_MESSAGE), 0, 1, h - hSplitterPos + SPLITTER_HEIGHT, messageEditWidth, hSplitterPos - SPLITTER_HEIGHT - 1, SWP_NOZORDER); + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_AVATAR), 0, w-avatarWidth - 1, h - (avatarHeight + avatarWidth) / 2 - 1, avatarWidth, avatarWidth, SWP_NOZORDER); + + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_SPLITTER), 0, 0, h - hSplitterPos-1, toolbarWidth, SPLITTER_HEIGHT, SWP_NOZORDER); + hdwp = ResizeToolbar(hwndDlg, hdwp, toolbarWidth, h - hSplitterPos - toolbarHeight + 1, toolbarHeight, SIZEOF(toolbarButtons), toolbarButtons, g_dat->buttonVisibility); + + /* + if (hSplitterPos - SPLITTER_HEIGHT - toolbarHeight - 2< dat->avatarHeight) { + hSplitterPos = dat->avatarHeight + SPLITTER_HEIGHT + toolbarHeight + 2; + } + dat->splitterPos = hSplitterPos; + hdwp = BeginDeferWindowPos(12); + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_LOG), 0, 0, 0, w-vSplitterPos, h-hSplitterPos, SWP_NOZORDER); + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_MESSAGE), 0, 0, h - hSplitterPos + SPLITTER_HEIGHT, w, hSplitterPos - SPLITTER_HEIGHT - toolbarHeight -2, SWP_NOZORDER); + hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_SPLITTER), 0, 0, h - hSplitterPos-1, w, SPLITTER_HEIGHT + 1, SWP_NOZORDER); + if (dat->avatarHeight + 1 < hSplitterPos - toolbarHeight) { + aPos = h - (hSplitterPos + toolbarHeight + dat->avatarHeight - 1) / 2; + } else { + aPos = h - (hSplitterPos + toolbarHeight + dat->avatarHeight + 1) / 2; + } + vPos = h - toolbarHeight; + hdwp = ResizeToolbar(hwndDlg, hdwp, w, vPos, toolbarHeight, SIZEOF(buttonControls), + buttonControls, buttonWidth, buttonSpacing, buttonAlignment, g_dat->buttonVisibility); + +*/ + EndDeferWindowPos(hdwp); + if (dat->windowData.hwndLog != NULL) { + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_SETPOS; + ieWindow.parent = hwndDlg; + ieWindow.hwnd = dat->windowData.hwndLog; + ieWindow.x = 0; + ieWindow.y = logY; + ieWindow.cx = w; + ieWindow.cy = logH; + CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow); + } else { + RedrawWindow(GetDlgItem(hwndDlg, IDC_LOG), NULL, NULL, RDW_INVALIDATE); + } + RedrawWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE); + + RefreshInfobar(dat->infobarData); + + RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE); +} + +static void UpdateReadChars(HWND hwndDlg, struct SrmmWindowData * dat) +{ + if (dat->parent->hwndActive == hwndDlg) { + TCHAR szText[256]; + StatusBarData sbd; + int len = GetRichTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE), dat->windowData.codePage, FALSE); + sbd.iItem = 1; + sbd.iFlags = SBDF_TEXT | SBDF_ICON; + sbd.hIcon = NULL; + sbd.pszText = szText; + mir_sntprintf(szText, SIZEOF(szText), _T("%d"), len); + SendMessage(dat->hwndParent, CM_UPDATESTATUSBAR, (WPARAM)&sbd, (LPARAM)hwndDlg); + } +} + +void ShowAvatar(HWND hwndDlg, struct SrmmWindowData *dat) +{ + INT_PTR res = CallService(MS_AV_GETAVATARBITMAP, (WPARAM)dat->windowData.hContact, 0); + dat->ace = res != CALLSERVICE_NOTFOUND ? (AVATARCACHEENTRY*)res : NULL; + dat->avatarPic = (dat->ace != NULL && (dat->ace->dwFlags & AVS_HIDEONCLIST) == 0) ? dat->ace->hbmPic : NULL; + SendMessage(hwndDlg, WM_SIZE, 0, 0); + + RefreshInfobar(dat->infobarData); + + RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE); +} + +static BOOL IsTypingNotificationSupported(struct SrmmWindowData *dat) { + DWORD typeCaps; + if (!dat->windowData.hContact) + return FALSE; + if (!dat->szProto) + return FALSE; + typeCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0); + if (!(typeCaps & PF4_SUPPORTTYPING)) + return FALSE; + return TRUE; +} + +static BOOL IsTypingNotificationEnabled(struct SrmmWindowData *dat) { + DWORD protoStatus; + DWORD protoCaps; + if (!DBGetContactSettingByte(dat->windowData.hContact, SRMMMOD, SRMSGSET_TYPING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW))) + return FALSE; + protoStatus = CallProtoService(dat->szProto, PS_GETSTATUS, 0, 0); + if (protoStatus < ID_STATUS_ONLINE) + return FALSE; + protoCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1, 0); + if (protoCaps & PF1_VISLIST && DBGetContactSettingWord(dat->windowData.hContact, dat->szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE) + return FALSE; + if (protoCaps & PF1_INVISLIST && protoStatus == ID_STATUS_INVISIBLE && DBGetContactSettingWord(dat->windowData.hContact, dat->szProto, "ApparentMode", 0) != ID_STATUS_ONLINE) + return FALSE; + if (DBGetContactSettingByte(dat->windowData.hContact, "CList", "NotOnList", 0) + && !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN)) + return FALSE; + return TRUE; +} + +// 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. +static void NotifyTyping(struct SrmmWindowData *dat, int mode) { + if (!IsTypingNotificationSupported(dat)) { + return; + } + if (!IsTypingNotificationEnabled(dat)) { + return; + } + // End user check + dat->nTypeMode = mode; + CallService(MS_PROTO_SELFISTYPING, (WPARAM) dat->windowData.hContact, dat->nTypeMode); +} + +static INT_PTR CALLBACK ConfirmSendAllDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + RECT rcParent, rcChild; + TranslateDialogDefault( hwndDlg ); + GetWindowRect(GetParent(hwndDlg), &rcParent); + GetWindowRect(hwndDlg, &rcChild); + rcChild.bottom -= rcChild.top; + rcChild.right -= rcChild.left; + rcParent.bottom -= rcParent.top; + rcParent.right -= rcParent.left; + rcChild.left = rcParent.left + (rcParent.right - rcChild.right) / 2; + rcChild.top = rcParent.top + (rcParent.bottom - rcChild.bottom) / 2; + MoveWindow(hwndDlg, rcChild.left, rcChild.top, rcChild.right, rcChild.bottom, FALSE); + } + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDYES: + case IDNO: + case IDCANCEL: + { + int result = LOWORD(wParam); + if (IsDlgButtonChecked(hwndDlg, IDC_REMEMBER)) { + result |= 0x10000; + } + EndDialog(hwndDlg, result); + } + return TRUE; + } + break; + } + + return FALSE; +} + + +INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HMENU hToolbarMenu; + struct SrmmWindowData *dat; + dat = (struct SrmmWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + if (!dat && msg!=WM_INITDIALOG) return FALSE; + switch (msg) { + case WM_INITDIALOG: + { + int len = 0; + int notifyUnread = 0; + RECT minEditInit; + NewMessageWindowLParam *newData = (NewMessageWindowLParam *) lParam; + //TranslateDialogDefault(hwndDlg); + dat = (struct SrmmWindowData *) mir_alloc(sizeof(struct SrmmWindowData)); + ZeroMemory(dat, sizeof(struct SrmmWindowData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dat); + dat->windowData.hContact = newData->hContact; + NotifyLocalWinEvent(dat->windowData.hContact, hwndDlg, MSG_WINDOW_EVT_OPENING); +// SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTMODE, TM_PLAINTEXT, 0); + + dat->hwnd = hwndDlg; + dat->hwndParent = GetParent(hwndDlg); + dat->parent = (ParentWindowData *) GetWindowLongPtr(dat->hwndParent, GWLP_USERDATA); + dat->windowData.hwndLog = NULL; + dat->szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->windowData.hContact, 0); + dat->avatarPic = 0; + if (dat->windowData.hContact && dat->szProto != NULL) + dat->wStatus = DBGetContactSettingWord(dat->windowData.hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + else + dat->wStatus = ID_STATUS_OFFLINE; + dat->hDbEventFirst = NULL; + dat->hDbEventLast = NULL; + dat->hDbUnreadEventFirst = NULL; + dat->messagesInProgress = 0; + dat->nTypeSecs = 0; + dat->nLastTyping = 0; + dat->showTyping = 0; + dat->showUnread = 0; + dat->sendAllConfirm = 0; + dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF; + SetTimer(hwndDlg, TIMERID_TYPE, 1000, NULL); + dat->lastMessage = 0; + dat->lastEventType = -1; + dat->lastEventTime = time(NULL); + dat->startTime = time(NULL); + dat->flags = 0; + if (DBGetContactSettingByte(dat->windowData.hContact, SRMMMOD, "UseRTL", (BYTE) 0)) { + dat->flags |= SMF_RTL; + } + dat->flags |= ServiceExists(MS_IEVIEW_WINDOW) ? g_dat->flags & SMF_USEIEVIEW : 0; + { + PARAFORMAT2 pf2; + ZeroMemory((void *)&pf2, sizeof(pf2)); + pf2.cbSize = sizeof(pf2); + pf2.dwMask = PFM_RTLPARA; + if (!(dat->flags & SMF_RTL)) { + pf2.wEffects = 0; + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE),GWL_EXSTYLE,GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE),GWL_EXSTYLE) & ~(WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR)); + } else { + pf2.wEffects = PFE_RTLPARA; + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE),GWL_EXSTYLE,GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE),GWL_EXSTYLE) | WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR); + } + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + /* Workaround to make Richedit display RTL messages correctly */ + ZeroMemory((void *)&pf2, sizeof(pf2)); + pf2.cbSize = sizeof(pf2); + pf2.dwMask = PFM_RTLPARA | PFM_OFFSETINDENT | PFM_RIGHTINDENT; + pf2.wEffects = PFE_RTLPARA; + pf2.dxStartIndent = 30; + pf2.dxRightIndent = 30; + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + pf2.dwMask = PFM_RTLPARA; + pf2.wEffects = 0; + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + if (dat->flags & SMF_RTL) { + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG),GWL_EXSTYLE,GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG),GWL_EXSTYLE) | WS_EX_LEFTSCROLLBAR); + } else { + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG),GWL_EXSTYLE,GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG),GWL_EXSTYLE) & ~WS_EX_LEFTSCROLLBAR); + } + } + dat->windowData.codePage = DBGetContactSettingWord(dat->windowData.hContact, SRMMMOD, "CodePage", (WORD) CP_ACP); + dat->ace = NULL; + GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &minEditInit); + dat->windowData.minEditBoxHeight = minEditInit.bottom - minEditInit.top; + dat->windowData.minLogBoxHeight = dat->windowData.minEditBoxHeight; + dat->toolbarSize.cy = TOOLBAR_HEIGHT; + dat->toolbarSize.cx = GetToolbarWidth(SIZEOF(toolbarButtons), toolbarButtons); + if (dat->splitterPos == -1) { + dat->splitterPos = dat->windowData.minEditBoxHeight; + } + WindowList_Add(g_dat->hMessageWindowList, hwndDlg, dat->windowData.hContact); + + if (newData->szInitialText) { + if (newData->isWchar) + SetDlgItemText(hwndDlg, IDC_MESSAGE, (TCHAR *)newData->szInitialText); + else + SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText); + } else if (g_dat->flags & SMF_SAVEDRAFTS) { + TCmdList *draft = tcmdlist_get2(g_dat->draftList, dat->windowData.hContact); + if (draft != NULL) { + len = SetRichTextEncoded(GetDlgItem(hwndDlg, IDC_MESSAGE), draft->szCmd, dat->windowData.codePage); + } + PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, len, len); + } + + SendMessage(hwndDlg, DM_CHANGEICONS, 0, 0); + // Make them flat buttons + { + int i; + for (i = 0; i < SIZEOF(toolbarButtons) ; i++) + SendMessage(GetDlgItem(hwndDlg, toolbarButtons[i].controlId), BUTTONSETASFLATBTN, TRUE, 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); + + SendMessage(GetDlgItem(hwndDlg, IDC_QUOTE), BUTTONADDTOOLTIP, (WPARAM) Translate("Quote Text"), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_SMILEYS), BUTTONADDTOOLTIP, (WPARAM) Translate("Insert Emoticon"), 0); + SendMessage(GetDlgItem(hwndDlg, IDOK), BUTTONADDTOOLTIP, (WPARAM) Translate("Send Message"), 0); + + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK | ENM_KEYEVENTS); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~(IMF_AUTOKEYBOARD | IMF_AUTOFONTSIZEADJUST)); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0)); + /* duh, how come we didnt use this from the start? */ + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, (WPARAM) TRUE, 0); + + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback2); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_CHANGE | ENM_REQUESTRESIZE); + if (dat->windowData.hContact) { + if (dat->szProto) { + int nMax; + nMax = CallProtoService(dat->szProto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM) dat->windowData.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); + RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_MESSAGE)); + RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_LOG)); + SubclassLogEdit(GetDlgItem(hwndDlg, IDC_LOG)); + SubclassMessageEdit(GetDlgItem(hwndDlg, IDC_MESSAGE)); + dat->infobarData = CreateInfobar(hwndDlg, dat); + if (dat->flags & SMF_USEIEVIEW) { + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_CREATE; + ieWindow.dwFlags = 0; + ieWindow.dwMode = IEWM_SCRIVER; + ieWindow.parent = hwndDlg; + ieWindow.x = 0; + ieWindow.y = 0; + ieWindow.cx = 200; + ieWindow.cy = 300; + CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow); + dat->windowData.hwndLog = ieWindow.hwnd; + if (dat->windowData.hwndLog == NULL) { + dat->flags ^= SMF_USEIEVIEW; + } + } + if (dat->windowData.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->windowData.hContact, 0); + if (dat->hDbEventFirst != NULL) { + DBEVENTINFO dbei = { 0 }; + dbei.cbSize = sizeof(dbei); + CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei); + if (DbEventIsMessageOrCustom(&dbei) && !(dbei.flags & DBEF_READ) && !(dbei.flags & DBEF_SENT)) { + notifyUnread = 1; + } + } + 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->windowData.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); + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->windowData.hContact, 0); + } else { + CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei); + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0); + } + firstTime = dbei.timestamp - 60 * DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME); + for (;;) { + if (hPrevEvent == NULL) + break; + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) & dbei); + if (dbei.timestamp < firstTime) + break; + if (DbEventIsShown(&dbei, dat)) + dat->hDbEventFirst = hPrevEvent; + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) hPrevEvent, 0); + } + break; + } + } + } + SendMessage(dat->hwndParent, CM_ADDCHILD, (WPARAM) hwndDlg, (LPARAM) dat->windowData.hContact); + { + DBEVENTINFO dbei = { 0 }; + HANDLE hdbEvent; + + dbei.cbSize = sizeof(dbei); + hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->windowData.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; + break; + } + } + while ((hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) hdbEvent, 0))); + } + } + SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 0, 0); + SendMessage(GetParent(hwndDlg), CM_POPUPWINDOW, (WPARAM) (newData->flags & NMWLP_INCOMING), (LPARAM) hwndDlg); + if (notifyUnread) { + if (GetForegroundWindow() != dat->hwndParent || dat->parent->hwndActive != hwndDlg) { + dat->showUnread = 1; + SendMessage(hwndDlg, DM_UPDATEICON, 0, 0); + SetTimer(hwndDlg, TIMERID_UNREAD, TIMEOUT_UNREAD, NULL); + } + SendMessage(dat->hwndParent, CM_STARTFLASHING, 0, 0); + } + dat->messagesInProgress = ReattachSendQueueItems(hwndDlg, dat->windowData.hContact); + if (dat->messagesInProgress > 0) { + SendMessage(hwndDlg, DM_SHOWMESSAGESENDING, 0, 0); + } + NotifyLocalWinEvent(dat->windowData.hContact, hwndDlg, MSG_WINDOW_EVT_OPEN); + return TRUE; + } + case DM_GETCONTEXTMENU: + { + HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->windowData.hContact, 0); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)hMenu); + return TRUE; + } + case WM_CONTEXTMENU: + if (dat->hwndParent == (HWND) wParam) { + POINT pt; + HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->windowData.hContact, 0); + GetCursorPos(&pt); + TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwndDlg, NULL); + DestroyMenu(hMenu); + } + break; + case WM_LBUTTONDBLCLK: + SendMessage(dat->hwndParent, WM_SYSCOMMAND, SC_MINIMIZE, 0); + break; + case WM_RBUTTONUP: + { + int i; + POINT pt; + MENUITEMINFO mii; + hToolbarMenu = CreatePopupMenu(); + for (i = 0; i < SIZEOF(toolbarButtons); i++) { + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_STRING | MIIM_STATE | MIIM_DATA | MIIM_BITMAP; + mii.fType = MFT_STRING; + mii.fState = (g_dat->buttonVisibility & (1<< i)) ? MFS_CHECKED : MFS_UNCHECKED; + mii.wID = i + 1; + mii.dwItemData = (ULONG_PTR)g_dat->hButtonIconList; + mii.hbmpItem = HBMMENU_CALLBACK; + mii.dwTypeData = TranslateTS((toolbarButtons[i].name)); + InsertMenuItem(hToolbarMenu, i, TRUE, &mii); + } +// TranslateMenu(hToolbarMenu); + pt.x = (short) LOWORD(GetMessagePos()); + pt.y = (short) HIWORD(GetMessagePos()); + i = TrackPopupMenu(hToolbarMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); + if (i > 0) { + g_dat->buttonVisibility ^= (1 << (i - 1)); + DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_BUTTONVISIBILITY, g_dat->buttonVisibility); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); + } + DestroyMenu(hToolbarMenu); + return TRUE; + } + 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->windowData.hContact!=NULL) { + TCHAR szFilename[MAX_PATH]; + HDROP hDrop = (HDROP)wParam; + int fileCount = DragQueryFile(hDrop,-1,NULL,0), totalCount = 0, i; + TCHAR** ppFiles = NULL; + for ( i=0; i < fileCount; i++ ) { + DragQueryFile(hDrop, i, szFilename, SIZEOF(szFilename)); + AddToFileList(&ppFiles, &totalCount, szFilename); + } + CallServiceSync(MS_FILE_SENDSPECIFICFILEST, (WPARAM)dat->windowData.hContact, (LPARAM)ppFiles); + for(i=0;ppFiles[i];i++) mir_free(ppFiles[i]); + mir_free(ppFiles); + } + break; + + case DM_AVATARCHANGED: + ShowAvatar(hwndDlg, dat); + break; + + case DM_GETAVATAR: + { + PROTO_AVATAR_INFORMATIONT ai = { sizeof(ai), dat->windowData.hContact }; + CallProtoService(dat->szProto, PS_GETAVATARINFOT, GAIF_FORCE, (LPARAM)&ai); + ShowAvatar(hwndDlg, dat); + break; + } + case DM_TYPING: + dat->nTypeSecs = (int) lParam > 0 ? (int) lParam : 0; + break; + case DM_CHANGEICONS: + SendDlgItemMessage(hwndDlg, IDC_ADD, BM_SETIMAGE, IMAGE_ICON, (LPARAM) GetCachedIcon("scriver_ADD")); + SendDlgItemMessage(hwndDlg, IDC_DETAILS, BM_SETIMAGE, IMAGE_ICON, (LPARAM) GetCachedIcon("scriver_USERDETAILS")); + SendDlgItemMessage(hwndDlg, IDC_HISTORY, BM_SETIMAGE, IMAGE_ICON, (LPARAM) GetCachedIcon("scriver_HISTORY")); + SendDlgItemMessage(hwndDlg, IDC_QUOTE, BM_SETIMAGE, IMAGE_ICON, (LPARAM) GetCachedIcon("scriver_QUOTE")); + SendDlgItemMessage(hwndDlg, IDC_SMILEYS, BM_SETIMAGE, IMAGE_ICON, (LPARAM) GetCachedIcon("scriver_SMILEY")); + SendDlgItemMessage(hwndDlg, IDOK, BM_SETIMAGE, IMAGE_ICON, (LPARAM) GetCachedIcon("scriver_SEND")); + SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0); + SetStatusIcon(dat); + + case DM_UPDATEICON: + { + TitleBarData tbd = {0}; + TabControlData tcd; + tbd.iFlags = TBDF_ICON; + GetTitlebarIcon(dat, &tbd); + SendMessage(dat->hwndParent, CM_UPDATETITLEBAR, (WPARAM)&tbd, (LPARAM)hwndDlg); + tcd.iFlags = TCDF_ICON; + tcd.hIcon = GetTabIcon(dat); + SendMessage(dat->hwndParent, CM_UPDATETABCONTROL, (WPARAM)&tcd, (LPARAM)hwndDlg); + SendDlgItemMessage(hwndDlg, IDC_USERMENU, BM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->statusIcon); + } + break; + case DM_UPDATETABCONTROL: + { + TabControlData tcd; + tcd.iFlags = TCDF_TEXT | TCDF_ICON; + tcd.hIcon = GetTabIcon(dat); + tcd.pszText = GetTabName((HANDLE *)dat->windowData.hContact); + SendMessage(dat->hwndParent, CM_UPDATETABCONTROL, (WPARAM)&tcd, (LPARAM)hwndDlg); + mir_free(tcd.pszText); + } + break; + case DM_UPDATETITLEBAR: + { + TitleBarData tbd = {0}; + tbd.iFlags = TBDF_TEXT | TBDF_ICON; + GetTitlebarIcon(dat, &tbd); + tbd.pszText = GetWindowTitle((HANDLE *)dat->windowData.hContact, dat->szProto); + SendMessage(dat->hwndParent, CM_UPDATETITLEBAR, (WPARAM)&tbd, (LPARAM)hwndDlg); + mir_free(tbd.pszText); + } + break; + + case DM_CLISTSETTINGSCHANGED: + { + if ((HANDLE)wParam == dat->windowData.hContact) { + if (dat->windowData.hContact && dat->szProto) { + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; + char idbuf[128]; + char buf[128]; + GetContactUniqueId(dat, idbuf, sizeof(idbuf)); + mir_snprintf(buf, sizeof(buf), Translate("User Menu - %s"), idbuf); + SendMessage(GetDlgItem(hwndDlg, IDC_USERMENU), BUTTONADDTOOLTIP, (WPARAM) buf, 0); + + if (!cws || (!strcmp(cws->szModule, dat->szProto) && !strcmp(cws->szSetting, "Status"))) { + DWORD wStatus; + wStatus = DBGetContactSettingWord( dat->windowData.hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + // log status change - should be moved to a separate place + if (dat->wStatus != wStatus && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)) { + DBEVENTINFO dbei; + TCHAR buffer[512]; + char blob[2048]; + HANDLE hNewEvent; + int iLen; + TCHAR *szOldStatus = mir_tstrdup((TCHAR *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wStatus, GSMDF_TCHAR)); + TCHAR *szNewStatus = mir_tstrdup((TCHAR *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) wStatus, GSMDF_TCHAR)); + if (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->wStatus == 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); + } + mir_free(szOldStatus); + mir_free(szNewStatus); + + { + int ansiLen = WideCharToMultiByte(CP_ACP, 0, buffer, -1, blob, sizeof(blob), 0, 0); + memcpy( blob+ansiLen, buffer, sizeof(TCHAR)*(iLen+1)); + dbei.cbBlob = ansiLen + sizeof(TCHAR)*(iLen+1); + } + + //iLen = strlen(buffer) + 1; + //MultiByteToWideChar(CP_ACP, 0, buffer, iLen, (LPWSTR) & buffer[iLen], iLen); + dbei.cbSize = sizeof(dbei); + dbei.pBlob = (PBYTE) blob; + // dbei.cbBlob = (strlen(buffer) + 1) * (sizeof(TCHAR) + 1); + dbei.eventType = EVENTTYPE_STATUSCHANGE; + dbei.flags = 0; + dbei.timestamp = time(NULL); + dbei.szModule = dat->szProto; + hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) dat->windowData.hContact, (LPARAM) & dbei); + if (dat->hDbEventFirst == NULL) { + dat->hDbEventFirst = hNewEvent; + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + } + } + dat->wStatus = wStatus; + } + SetStatusIcon(dat); + SendMessage(hwndDlg, DM_UPDATEICON, 0, 0); + SendMessage(hwndDlg, DM_UPDATETITLEBAR, 0, 0); + SendMessage(hwndDlg, DM_UPDATETABCONTROL, 0, 0); + ShowAvatar(hwndDlg, dat); + } + } + break; + } + case DM_OPTIONSAPPLIED: + { + PARAFORMAT2 pf2; + memset(&pf2, 0, sizeof(pf2)); + CHARFORMAT2 cf2; + memset(&cf2, 0, sizeof(cf2)); + LOGFONT lf; + COLORREF colour; + dat->flags &= ~SMF_USEIEVIEW; + dat->flags |= ServiceExists(MS_IEVIEW_WINDOW) ? g_dat->flags & SMF_USEIEVIEW : 0; + if (dat->flags & SMF_USEIEVIEW && dat->windowData.hwndLog == NULL) { + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_CREATE; + ieWindow.dwFlags = 0; + ieWindow.dwMode = IEWM_SCRIVER; + ieWindow.parent = hwndDlg; + ieWindow.x = 0; + ieWindow.y = 0; + ieWindow.cx = 200; + ieWindow.cy = 300; + CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow); + dat->windowData.hwndLog = ieWindow.hwnd; + if (dat->windowData.hwndLog == NULL) { + dat->flags ^= SMF_USEIEVIEW; + } + } else if (!(dat->flags & SMF_USEIEVIEW) && dat->windowData.hwndLog != NULL) { + if (dat->windowData.hwndLog != NULL) { + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_DESTROY; + ieWindow.hwnd = dat->windowData.hwndLog; + CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow); + } + dat->windowData.hwndLog = NULL; + } + + SendMessage(hwndDlg, DM_GETAVATAR, 0, 0); + SetDialogToType(hwndDlg); + + colour = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETBKGNDCOLOR, 0, colour); + colour = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_INPUTBKGCOLOUR, SRMSGDEFSET_INPUTBKGCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETBKGNDCOLOR, 0, colour); + InvalidateRect(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, FALSE); + LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, &lf, &colour, FALSE); + cf2.cbSize = sizeof(cf2); + cf2.dwMask = CFM_COLOR | CFM_FACE | CFM_CHARSET | CFM_SIZE | CFM_WEIGHT | CFM_BOLD | CFM_ITALIC; + cf2.crTextColor = colour; + cf2.bCharSet = lf.lfCharSet; + _tcsncpy(cf2.szFaceName, lf.lfFaceName, LF_FACESIZE); + cf2.dwEffects = ((lf.lfWeight >= FW_BOLD) ? CFE_BOLD : 0) | (lf.lfItalic ? CFE_ITALIC : 0); + cf2.wWeight = (WORD)lf.lfWeight; + cf2.bPitchAndFamily = lf.lfPitchAndFamily; + cf2.yHeight = abs(lf.lfHeight) * 1440 / g_dat->logPixelSY; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&cf2); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD); + + pf2.cbSize = sizeof(pf2); + pf2.dwMask = PFM_OFFSET; + pf2.dxOffset = (g_dat->flags & SMF_INDENTTEXT) ? g_dat->indentSize * 1440 / g_dat->logPixelSX : 0; + SetDlgItemText(hwndDlg, IDC_LOG, _T("")); + 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 | IMF_AUTOFONTSIZEADJUST)); + + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + SendMessage(hwndDlg, DM_UPDATETITLEBAR, 0, 0); + SendMessage(hwndDlg, DM_UPDATETABCONTROL, 0, 0); + SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REQUESTRESIZE, 0, 0); + SetupInfobar(dat->infobarData); + break; + } + case DM_USERNAMETOCLIP: + { + char buf[128]; + HGLOBAL hData; + + if (dat->windowData.hContact) { + GetContactUniqueId(dat, buf, sizeof(buf)); + if (!OpenClipboard(hwndDlg) || !lstrlenA(buf)) break; + EmptyClipboard(); + hData = GlobalAlloc(GMEM_MOVEABLE, lstrlenA(buf) + 1); + lstrcpyA((LPSTR)GlobalLock(hData), buf); + GlobalUnlock(hData); + SetClipboardData(CF_TEXT, hData); + CloseClipboard(); + } + break; + } + case DM_SWITCHINFOBAR: + case DM_SWITCHTOOLBAR: + SetDialogToType(hwndDlg); +// SendMessage(dat->hwndParent, DM_SWITCHTOOLBAR, 0, 0); + break; + case DM_GETCODEPAGE: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, dat->windowData.codePage); + return TRUE; + case DM_SETCODEPAGE: + dat->windowData.codePage = (int) lParam; + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + break; + case DM_SWITCHTYPING: + if (IsTypingNotificationSupported(dat)) { + StatusIconData sid = {0}; + sid.cbSize = sizeof(sid); + sid.szModule = SRMMMOD; + sid.dwId = 1; + { + BYTE typingNotify = (DBGetContactSettingByte(dat->windowData.hContact, SRMMMOD, SRMSGSET_TYPING, + DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW))); + DBWriteContactSettingByte(dat->windowData.hContact, SRMMMOD, SRMSGSET_TYPING, (BYTE)!typingNotify); + sid.flags = typingNotify ? MBF_DISABLED : 0; + } + ModifyStatusIcon((WPARAM)dat->windowData.hContact, (LPARAM) &sid); + } + break; + case DM_SWITCHRTL: + { + PARAFORMAT2 pf2; + ZeroMemory((void *)&pf2, sizeof(pf2)); + pf2.cbSize = sizeof(pf2); + pf2.dwMask = PFM_RTLPARA; + dat->flags ^= SMF_RTL; + if (dat->flags&SMF_RTL) { + pf2.wEffects = PFE_RTLPARA; + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE),GWL_EXSTYLE,GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE),GWL_EXSTYLE) | WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG),GWL_EXSTYLE,GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG),GWL_EXSTYLE) | WS_EX_LEFTSCROLLBAR); + } else { + pf2.wEffects = 0; + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE),GWL_EXSTYLE,GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE),GWL_EXSTYLE) &~ (WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR)); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG),GWL_EXSTYLE,GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG),GWL_EXSTYLE) &~ (WS_EX_LEFTSCROLLBAR)); + } + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + } + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + break; + case DM_GETWINDOWSTATE: + { + UINT state = 0; + + state |= MSG_WINDOW_STATE_EXISTS; + if (IsWindowVisible(hwndDlg)) + state |= MSG_WINDOW_STATE_VISIBLE; + if (GetForegroundWindow()==dat->hwndParent) + state |= MSG_WINDOW_STATE_FOCUS; + if (IsIconic(dat->hwndParent)) + state |= MSG_WINDOW_STATE_ICONIC; + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, state); + return TRUE; + + } + case DM_ACTIVATE: + case WM_ACTIVATE: + if (LOWORD(wParam) != WA_ACTIVE) + break; + //fall through + case WM_MOUSEACTIVATE: + if (dat->hDbUnreadEventFirst != NULL) { + HANDLE hDbEvent = dat->hDbUnreadEventFirst; + dat->hDbUnreadEventFirst = NULL; + while (hDbEvent != NULL) { + DBEVENTINFO dbei; + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei); + if (!(dbei.flags & DBEF_SENT) && (DbEventIsMessageOrCustom(&dbei) || dbei.eventType == EVENTTYPE_URL)) { + CallService(MS_CLIST_REMOVEEVENT, (WPARAM) dat->windowData.hContact, (LPARAM) hDbEvent); + } + hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hDbEvent, 0); + } + } + if (dat->showUnread) { + dat->showUnread = 0; + KillTimer(hwndDlg, TIMERID_UNREAD); + SendMessage(hwndDlg, DM_UPDATEICON, 0, 0); + } + break; + case WM_LBUTTONDOWN: + SendMessage(dat->hwndParent, WM_LBUTTONDOWN, wParam, lParam); + return TRUE; + case DM_SETFOCUS: + if (lParam == WM_MOUSEACTIVATE) { + HWND hLog; + RECT rc; + POINT pt; + GetCursorPos(&pt); + if (dat->windowData.hwndLog != NULL) { + hLog = dat->windowData.hwndLog; + } else { + hLog = GetDlgItem(hwndDlg, IDC_LOG); + } + GetWindowRect(hLog, &rc); + if (pt.x >= rc.left && pt.x <= rc.right && pt.y >= rc.top && pt.y <=rc.bottom) { + // SetFocus(hLog); + return TRUE; + } + } + if (g_dat->hFocusWnd == hwndDlg) { + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + } + return TRUE; + case WM_SETFOCUS: + SendMessage(dat->hwndParent, CM_ACTIVATECHILD, 0, (LPARAM)hwndDlg); + g_dat->hFocusWnd = hwndDlg; + PostMessage(hwndDlg, DM_SETFOCUS, 0, 0); + return TRUE; + case DM_SETPARENT: + dat->hwndParent = (HWND) lParam; + dat->parent = (ParentWindowData *) GetWindowLongPtr(dat->hwndParent, GWLP_USERDATA); + SetParent(hwndDlg, dat->hwndParent); + return TRUE; + case WM_GETMINMAXINFO: + { + MINMAXINFO *mmi = (MINMAXINFO *) lParam; + mmi->ptMinTrackSize.x = dat->toolbarSize.cx + BOTTOM_RIGHT_AVATAR_HEIGHT; + mmi->ptMinTrackSize.y = dat->windowData.minLogBoxHeight + dat->toolbarSize.cy + dat->windowData.minEditBoxHeight + max(INFO_BAR_HEIGHT, BOTTOM_RIGHT_AVATAR_HEIGHT - dat->toolbarSize.cy) + 5; + return 0; + } + case WM_SIZE: + { + if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED) { + RECT rc; + int dlgWidth, dlgHeight; + dlgWidth = LOWORD(lParam); + dlgHeight = HIWORD(lParam); + /*if (dlgWidth == 0 && dlgHeight ==0) */{ + GetClientRect(hwndDlg, &rc); + dlgWidth = rc.right - rc.left; + dlgHeight = rc.bottom - rc.top; + } + MessageDialogResize(hwndDlg, dat, dlgWidth, dlgHeight); + } + return TRUE; + } + case DM_SPLITTERMOVED: + { + POINT pt; + RECT rc; + RECT rcLog; + if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SPLITTER)) { + int oldSplitterY; + GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog); + GetClientRect(hwndDlg, &rc); + pt.x = 0; + pt.y = wParam; + ScreenToClient(hwndDlg, &pt); + oldSplitterY = dat->splitterPos; + dat->splitterPos = rc.bottom - pt.y; + SendMessage(hwndDlg, WM_SIZE, 0, 0); + } + break; + } + case DM_REMAKELOG: + dat->lastEventType = -1; + if (wParam == 0 || (HANDLE) wParam == dat->windowData.hContact) { + //StreamInEvents(hwndDlg, dat->hDbEventFirst, 0, 0); + StreamInEvents(hwndDlg, dat->hDbEventFirst, -1, 0); + } + InvalidateRect(GetDlgItem(hwndDlg, IDC_LOG), NULL, FALSE); + break; + case DM_APPENDTOLOG: //takes wParam=hDbEvent + StreamInEvents(hwndDlg, (HANDLE) wParam, 1, 1); + break; + case DM_SCROLLLOGTOBOTTOM: + if (dat->windowData.hwndLog == NULL) { + SCROLLINFO si = { 0 }; + if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL) == 0) + break; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + if (GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si)) { + if (GetDlgItem(hwndDlg, IDC_LOG) != GetFocus()) { +// if (si.nPos + si.nPage >= si.nMax) { + 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); + } + } + RedrawWindow(GetDlgItem(hwndDlg, IDC_LOG), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } else { + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_SCROLLBOTTOM; + ieWindow.hwnd = dat->windowData.hwndLog; + CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow); + } + break; + case HM_DBEVENTADDED: + if ((HANDLE) wParam == dat->windowData.hContact) + { + 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 (DbEventIsShown(&dbei, dat)) { + int heFlags = HistoryEvents_GetFlags(dbei.eventType); + if (heFlags != -1 && (heFlags & HISTORYEVENTS_FLAG_DEFAULT)) + heFlags = -1; + + if (DbEventIsMessageOrCustom(&dbei) && !(dbei.flags & (DBEF_SENT))) { + /* store the event when the container is hidden so that clist notifications can be removed */ + if (!IsWindowVisible(GetParent(hwndDlg)) && dat->hDbUnreadEventFirst == NULL) + dat->hDbUnreadEventFirst = (HANDLE) lParam; + dat->lastMessage = dbei.timestamp; + SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0); + if (GetForegroundWindow()==dat->hwndParent && dat->parent->hwndActive == hwndDlg) + SkinPlaySound("RecvMsgActive"); + else SkinPlaySound("RecvMsgInactive"); + if ((g_dat->flags2 & SMF2_SWITCHTOACTIVE) && (IsIconic(dat->hwndParent) || GetActiveWindow() != dat->hwndParent) && IsWindowVisible(dat->hwndParent)) { + SendMessage(dat->hwndParent, CM_ACTIVATECHILD, 0, (LPARAM) hwndDlg); + } + if (IsAutoPopup(dat->windowData.hContact)) { + SendMessage(GetParent(hwndDlg), CM_POPUPWINDOW, (WPARAM) 1, (LPARAM) hwndDlg); + } + } + 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 (!(dbei.flags & DBEF_SENT) && dbei.eventType != EVENTTYPE_STATUSCHANGE && dbei.eventType != EVENTTYPE_JABBER_CHATSTATES && dbei.eventType != EVENTTYPE_JABBER_PRESENCE && (heFlags == -1 || (heFlags & HISTORYEVENTS_FLAG_FLASH_MSG_WINDOW))) { + if (GetActiveWindow() != dat->hwndParent || GetForegroundWindow() != dat->hwndParent || dat->parent->hwndActive != hwndDlg) { + dat->showUnread = 1; + SendMessage(hwndDlg, DM_UPDATEICON, 0, 0); + SetTimer(hwndDlg, TIMERID_UNREAD, TIMEOUT_UNREAD, NULL); + } + SendMessage(dat->hwndParent, CM_STARTFLASHING, 0, 0); + } + } + } + break; + case DM_UPDATESTATUSBAR: + if (dat->parent->hwndActive == hwndDlg) { + TCHAR szText[256]; + StatusBarData sbd= {0}; + StatusIconData sid = {0}; + sbd.iFlags = SBDF_TEXT | SBDF_ICON; + if (dat->messagesInProgress && (g_dat->flags & SMF_SHOWPROGRESS)) { + sbd.hIcon = GetCachedIcon("scriver_DELIVERING"); + sbd.pszText = szText; + mir_sntprintf(szText, SIZEOF(szText), TranslateT("Sending in progress: %d message(s) left..."), dat->messagesInProgress); + } else if (dat->nTypeSecs) { + TCHAR *szContactName = GetNickname(dat->windowData.hContact, dat->szProto); + sbd.hIcon = GetCachedIcon("scriver_TYPING"); + sbd.pszText = szText; + mir_sntprintf(szText, SIZEOF(szText), TranslateT("%s is typing a message..."), szContactName); + mir_free(szContactName); + dat->nTypeSecs--; + } else if (dat->lastMessage) { + TCHAR date[64], time[64]; + tmi.printTimeStamp(NULL, dat->lastMessage, _T("d"), date, SIZEOF(date), 0); + tmi.printTimeStamp(NULL, dat->lastMessage, _T("t"), time, SIZEOF(time), 0); + mir_sntprintf(szText, SIZEOF(szText), TranslateT("Last message received on %s at %s."), date, time); + sbd.pszText = szText; + } else { + sbd.pszText = _T(""); + } + SendMessage(dat->hwndParent, CM_UPDATESTATUSBAR, (WPARAM)&sbd, (LPARAM)hwndDlg); + UpdateReadChars(hwndDlg, dat); + sid.cbSize = sizeof(sid); + sid.szModule = SRMMMOD; + sid.flags = MBF_DISABLED; + ModifyStatusIcon((WPARAM)dat->windowData.hContact, (LPARAM) &sid); + sid.dwId = 1; + if (IsTypingNotificationSupported(dat) && g_dat->flags2 & SMF2_SHOWTYPINGSWITCH) { + sid.flags = (DBGetContactSettingByte(dat->windowData.hContact, SRMMMOD, SRMSGSET_TYPING, + DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW))) ? 0 : MBF_DISABLED; + } else { + sid.flags = MBF_HIDDEN; + } + ModifyStatusIcon((WPARAM)dat->windowData.hContact, (LPARAM) &sid); + } + break; + case DM_CLEARLOG: + // IEVIew MOD Begin + if (dat->windowData.hwndLog != NULL) { + IEVIEWEVENT event; + ZeroMemory(&event, sizeof(event)); + event.cbSize = sizeof(event); + event.iType = IEE_CLEAR_LOG; + event.dwFlags = ((dat->flags & SMF_RTL) ? IEEF_RTL : 0); + event.hwnd = dat->windowData.hwndLog; + event.hContact = dat->windowData.hContact; + event.codepage = dat->windowData.codePage; + event.pszProto = dat->szProto; + CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event); + } + // IEVIew MOD End + SetDlgItemText(hwndDlg, IDC_LOG, _T("")); + dat->hDbEventFirst = NULL; + dat->lastEventType = -1; + break; + case WM_TIMER: + if (wParam == TIMERID_MSGSEND) { + ReportSendQueueTimeouts(hwndDlg); + } 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--; + } + else { + dat->showTyping = 0; + SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0); + SendMessage(hwndDlg, DM_UPDATEICON, 0, 0); + } + } + else { + if (dat->nTypeSecs) { + dat->showTyping = 1; + SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0); + SendMessage(hwndDlg, DM_UPDATEICON, 0, 0); + } + } + } else if (wParam == TIMERID_UNREAD) { + TabControlData tcd; + tcd.iFlags = TCDF_ICON; + if (!dat->showTyping) { + dat->showUnread++; + if (dat->showUnread & 1) { + tcd.hIcon = dat->statusIconOverlay; + } else { + tcd.hIcon = dat->statusIcon; + } + SendMessage(dat->hwndParent, CM_UPDATETABCONTROL, (WPARAM)&tcd, (LPARAM)hwndDlg); + } + } + break; + case DM_SENDMESSAGE: + if (lParam) { + MessageSendQueueItem *msi = (MessageSendQueueItem *)lParam; + MessageSendQueueItem *item = CreateSendQueueItem(hwndDlg); + item->hContact = dat->windowData.hContact; + item->proto = mir_strdup(dat->szProto); + item->flags = msi->flags; + item->codepage = dat->windowData.codePage; + if ( IsUtfSendAvailable( dat->windowData.hContact )) { + char* szMsgUtf; + szMsgUtf = mir_utf8encodeW( (TCHAR *)&msi->sendBuffer[strlen(msi->sendBuffer) + 1] ); + item->flags &= ~PREF_UNICODE; + if (!szMsgUtf) { + break; + } + if (*szMsgUtf == 0) { + mir_free(szMsgUtf); + break; + } + item->sendBufferSize = (int)strlen(szMsgUtf) + 1; + item->sendBuffer = szMsgUtf; + item->flags |= PREF_UTF; + } else { + item->sendBufferSize = msi->sendBufferSize; + item->sendBuffer = (char *) mir_alloc(msi->sendBufferSize); + memcpy(item->sendBuffer, msi->sendBuffer, msi->sendBufferSize); + } + SendMessage(hwndDlg, DM_STARTMESSAGESENDING, 0, 0); + SendSendQueueItem(item); + } + break; + case DM_STARTMESSAGESENDING: + dat->messagesInProgress++; + case DM_SHOWMESSAGESENDING: + SetTimer(hwndDlg, TIMERID_MSGSEND, 1000, NULL); + if (g_dat->flags & SMF_SHOWPROGRESS) { + SendMessage(dat->hwnd, DM_UPDATESTATUSBAR, 0, 0); + } + break; + case DM_STOPMESSAGESENDING: + if (dat->messagesInProgress>0) { + dat->messagesInProgress--; + if (g_dat->flags & SMF_SHOWPROGRESS) { + SendMessage(dat->hwnd, DM_UPDATESTATUSBAR, 0, 0); + } + } + if (dat->messagesInProgress == 0) { + KillTimer(hwndDlg, TIMERID_MSGSEND); + } + break; + case DM_SHOWERRORMESSAGE: + if (lParam) { + ErrorWindowData *ewd = (ErrorWindowData *) lParam; + SendMessage(hwndDlg, DM_STOPMESSAGESENDING, 0, 0); + ewd->queueItem->hwndErrorDlg = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGSENDERROR), hwndDlg, ErrorDlgProc, (LPARAM) ewd);//hwndDlg + } + break; + case DM_ERRORDECIDED: + { + MessageSendQueueItem *item = (MessageSendQueueItem *) lParam; + item->hwndErrorDlg = NULL; + switch (wParam) { + case MSGERROR_CANCEL: + RemoveSendQueueItem(item); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + break; + case MSGERROR_RETRY: + SendMessage(hwndDlg, DM_STARTMESSAGESENDING, 0, 0); + SendSendQueueItem(item); + break; + } + } + break; + case WM_MEASUREITEM: + if (!MeasureMenuItem(wParam, lParam)) { + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + } + return TRUE; + + case WM_DRAWITEM: + if (!DrawMenuItem(wParam, lParam)) { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; + if (dis->hwndItem == GetDlgItem(hwndDlg, IDC_AVATAR)) { + RECT rect; + HDC hdcMem = CreateCompatibleDC(dis->hDC); + int avatarWidth = 0; + int avatarHeight = 0; + int itemWidth = dis->rcItem.right - dis->rcItem.left + 1; + int itemHeight = dis->rcItem.bottom - dis->rcItem.top + 1; + HBITMAP hbmMem = CreateCompatibleBitmap(dis->hDC, itemWidth, itemHeight); + hbmMem = (HBITMAP) SelectObject(hdcMem, hbmMem); + rect.top = 0; + rect.left = 0; + rect.right = itemWidth - 1; + rect.bottom = itemHeight - 1; + FillRect(hdcMem, &rect, GetSysColorBrush(COLOR_BTNFACE)); + + if (dat->avatarPic && (g_dat->flags&SMF_AVATAR)) { + BITMAP bminfo; + GetObject(dat->avatarPic, sizeof(bminfo), &bminfo); + if ( bminfo.bmWidth != 0 && bminfo.bmHeight != 0 ) { + AVATARDRAWREQUEST adr; + avatarHeight = itemHeight; + avatarWidth = bminfo.bmWidth * avatarHeight / bminfo.bmHeight; + if (avatarWidth > itemWidth) { + avatarWidth = itemWidth; + avatarHeight = bminfo.bmHeight * avatarWidth / bminfo.bmWidth; + } + ZeroMemory(&adr, sizeof(adr)); + adr.cbSize = sizeof (AVATARDRAWREQUEST); + adr.hContact = dat->windowData.hContact; + adr.hTargetDC = hdcMem; + adr.rcDraw.left = (itemWidth - avatarWidth) / 2; + adr.rcDraw.top = (itemHeight - avatarHeight) / 2; + adr.rcDraw.right = avatarWidth - 1; + adr.rcDraw.bottom = avatarHeight - 1; + adr.dwFlags = AVDRQ_DRAWBORDER | AVDRQ_HIDEBORDERONTRANSPARENCY; + + CallService(MS_AV_DRAWAVATAR, (WPARAM)0, (LPARAM)&adr); + } + } + BitBlt(dis->hDC, 0, 0, itemWidth, itemHeight, hdcMem, 0, 0, SRCCOPY); + hbmMem = (HBITMAP) SelectObject(hdcMem, hbmMem); + DeleteObject(hbmMem); + DeleteDC(hdcMem); + return TRUE; + } + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + } + case WM_COMMAND: + if (!lParam && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) dat->windowData.hContact)) + break; + switch (LOWORD(wParam)) { + case IDC_SENDALL: + { + int result; + if (dat->sendAllConfirm == 0) { + result = DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_CONFIRM_SENDALL), hwndDlg, ConfirmSendAllDlgProc, (LPARAM)hwndDlg); + if (result & 0x10000) { + dat->sendAllConfirm = result; + } + } else { + result = dat->sendAllConfirm; + } + if (LOWORD(result) != IDYES) { + break; + } + + } + case IDOK: + //this is a 'send' button + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDOK))) + break; + //if (GetKeyState(VK_CTRL) & 0x8000) { // copy user name + //SendMessage(hwndDlg, DM_USERNAMETOCLIP, 0, 0); + //} + if (dat->windowData.hContact != NULL) { + GETTEXTEX gt = {0}; + PARAFORMAT2 pf2; + MessageSendQueueItem msi = { 0 }; + int bufSize; + int ansiBufSize = GetRichTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE), dat->windowData.codePage, TRUE) + 1; + bufSize = ansiBufSize; + ZeroMemory((void *)&pf2, sizeof(pf2)); + pf2.cbSize = sizeof(pf2); + pf2.dwMask = PFM_RTLPARA; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETPARAFORMAT, 0, (LPARAM)&pf2); + if (pf2.wEffects & PFE_RTLPARA) + msi.flags |= PREF_RTL; + bufSize += GetRichTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE), 1200, TRUE) + 2; + + msi.sendBufferSize = bufSize; + msi.sendBuffer = (char *) mir_alloc(msi.sendBufferSize); + msi.flags |= PREF_TCHAR; + + gt.flags = GT_USECRLF; + gt.cb = ansiBufSize; + gt.codepage = dat->windowData.codePage; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETTEXTEX, (WPARAM) >, (LPARAM) msi.sendBuffer); + gt.cb = bufSize - ansiBufSize; + gt.codepage = 1200; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETTEXTEX, (WPARAM) >, (LPARAM) &msi.sendBuffer[ansiBufSize]); + if ( RTL_Detect((wchar_t *)&msi.sendBuffer[ansiBufSize] )) + msi.flags |= PREF_RTL; + + if (msi.sendBuffer[0] == 0) { + mir_free (msi.sendBuffer); + break; + } + { + /* Store messaging history */ + char *msgText = GetRichTextEncoded(GetDlgItem(hwndDlg, IDC_MESSAGE), dat->windowData.codePage); + TCmdList *cmdListNew = tcmdlist_last(dat->windowData.cmdList); + while (cmdListNew != NULL && cmdListNew->temporary) { + dat->windowData.cmdList = tcmdlist_remove(dat->windowData.cmdList, cmdListNew); + cmdListNew = tcmdlist_last(dat->windowData.cmdList); + } + if (msgText != NULL) { + dat->windowData.cmdList = tcmdlist_append(dat->windowData.cmdList, msgText, 20, FALSE); + mir_free(msgText); + } + dat->windowData.cmdListCurrent = NULL; + } + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + + SetDlgItemText(hwndDlg, IDC_MESSAGE, _T("")); + EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)) + ShowWindow(dat->hwndParent, SW_MINIMIZE); + if (LOWORD(wParam) == IDC_SENDALL) { + SendMessage(dat->hwndParent, DM_SENDMESSAGE, 0, (LPARAM) &msi); + } else { + SendMessage(hwndDlg, DM_SENDMESSAGE, 0, (LPARAM) &msi); + } + mir_free (msi.sendBuffer); + } + return TRUE; + case IDCANCEL: + DestroyWindow(hwndDlg); + return TRUE; + case IDC_USERMENU: + { + 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->windowData.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->windowData.hContact, 0); + break; + case IDC_DETAILS: + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) dat->windowData.hContact, 0); + break; + case IDC_SMILEYS: + if (g_dat->smileyAddInstalled) { + SMADD_SHOWSEL3 smaddInfo; + RECT rc; + smaddInfo.cbSize = sizeof(SMADD_SHOWSEL3); + smaddInfo.hwndParent = dat->hwndParent; + smaddInfo.hwndTarget = GetDlgItem(hwndDlg, IDC_MESSAGE); + smaddInfo.targetMessage = EM_REPLACESEL; + smaddInfo.targetWParam = TRUE; + smaddInfo.Protocolname = dat->szProto; + if (dat->szProto!=NULL && strcmp(dat->szProto,"MetaContacts")==0) { + HANDLE hContact = (HANDLE) CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM) dat->windowData.hContact, 0); + if (hContact!=NULL) { + smaddInfo.Protocolname = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + } + } + GetWindowRect(GetDlgItem(hwndDlg, IDC_SMILEYS), &rc); + smaddInfo.Direction = 0; + smaddInfo.xPosition = rc.left; + smaddInfo.yPosition = rc.bottom; + smaddInfo.hContact = dat->windowData.hContact; + CallService(MS_SMILEYADD_SHOWSELECTION, 0, (LPARAM) &smaddInfo); + } + break; + case IDC_QUOTE: + { + DBEVENTINFO dbei = { 0 }; + SETTEXTEX st; + TCHAR *buffer = NULL; + st.flags = ST_SELECTION; + st.codepage = 1200; + + if (dat->hDbEventLast==NULL) break; + if (dat->windowData.hwndLog != NULL) { + buffer = GetIEViewSelection(dat); + } else { + buffer = GetRichEditSelection(GetDlgItem(hwndDlg, IDC_LOG)); + } + if (buffer!=NULL) { + TCHAR *quotedBuffer = GetQuotedTextW(buffer); + SendMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETTEXTEX, (WPARAM) &st, (LPARAM)quotedBuffer); + mir_free(quotedBuffer); + mir_free(buffer); + } else { + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM) dat->hDbEventLast, 0); + if (dbei.cbBlob == 0xFFFFFFFF) break; + dbei.pBlob = (PBYTE) mir_alloc(dbei.cbBlob); + CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventLast, (LPARAM) & dbei); + if (DbEventIsMessageOrCustom(&dbei) || dbei.eventType == EVENTTYPE_STATUSCHANGE) { + TCHAR *buffer = DbGetEventTextT( &dbei, CP_ACP ); + if (buffer!=NULL) { + TCHAR *quotedBuffer = GetQuotedTextW(buffer); + SendMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETTEXTEX, (WPARAM) &st, (LPARAM)quotedBuffer); + mir_free(quotedBuffer); + mir_free(buffer); + } + } + mir_free(dbei.pBlob); + } + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + break; + } + case IDC_ADD: + { + ADDCONTACTSTRUCT acs = { 0 }; + + acs.handle = dat->windowData.hContact; + acs.handleType = HANDLE_CONTACT; + acs.szProto = 0; + CallService(MS_ADDCONTACT_SHOW, (WPARAM) hwndDlg, (LPARAM) & acs); + } + if (!DBGetContactSettingByte(dat->windowData.hContact, "CList", "NotOnList", 0)) { + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE); + } + case IDC_MESSAGE: + if (HIWORD(wParam) == EN_CHANGE) { + int len = GetRichTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE), dat->windowData.codePage, FALSE); + dat->windowData.cmdListCurrent = NULL; + UpdateReadChars(hwndDlg, dat); + EnableWindow(GetDlgItem(hwndDlg, IDOK), len != 0); + if (!(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000)) { + dat->nLastTyping = GetTickCount(); + if (len != 0) { + 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: + { + LPNMHDR pNmhdr; + pNmhdr = (LPNMHDR)lParam; + switch (pNmhdr->idFrom) { + case IDC_LOG: + switch (pNmhdr->code) { + case EN_MSGFILTER: + { + int result = InputAreaShortcuts(GetDlgItem(hwndDlg, IDC_MESSAGE), ((MSGFILTER *) lParam)->msg, ((MSGFILTER *) lParam)->wParam, ((MSGFILTER *) lParam)->lParam, &dat->windowData); + if (result != -1) { + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + } + switch (((MSGFILTER *) lParam)->msg) { + case WM_CHAR: + if (!(GetKeyState(VK_CONTROL) & 0x8000)) { + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + SendMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), ((MSGFILTER *) lParam)->msg, ((MSGFILTER *) lParam)->wParam, ((MSGFILTER *) lParam)->lParam); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + } + return TRUE; + 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)) { + SetWindowLongPtr(hwndDlg, DWLP_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: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + break; + case EN_LINK: + switch (((ENLINK *) lParam)->msg) { + case WM_SETCURSOR: + SetCursor(hCurHyperlinkHand); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + if (HandleLinkClick(g_hInst, hwndDlg, GetDlgItem(hwndDlg, IDC_MESSAGE),(ENLINK*)lParam)) { + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + break; + } + } + break; + case IDC_MESSAGE: + switch (((NMHDR *) lParam)->code) { + case EN_MSGFILTER: + switch (((MSGFILTER *) lParam)->msg) { + case WM_RBUTTONUP: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + break; + case EN_REQUESTRESIZE: + { + REQRESIZE *rr = (REQRESIZE *)lParam; + int height = rr->rc.bottom - rr->rc.top + 1; + if (height < g_dat->minInputAreaHeight) { + height = g_dat->minInputAreaHeight; + } + if (dat->desiredInputAreaHeight != height) { + dat->desiredInputAreaHeight = height; + SendMessage(hwndDlg, WM_SIZE, 0, 0); + PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); + } + } + break; + } + } + } + break; + case WM_CHAR: + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + SendMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), msg, wParam, lParam); + break; + case WM_DESTROY: + NotifyLocalWinEvent(dat->windowData.hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING); + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) { + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + } + CallService(MS_SKIN2_RELEASEICON, (WPARAM)dat->statusIcon, 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)dat->statusIconBig , 0); + if (dat->statusIconOverlay != NULL) DestroyIcon(dat->statusIconOverlay); + dat->statusIcon = NULL; + dat->statusIconOverlay = NULL; + ReleaseSendQueueItems(hwndDlg); + if (g_dat->flags & SMF_SAVEDRAFTS) { + saveDraftMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), dat->windowData.hContact, dat->windowData.codePage); + } else { + g_dat->draftList = tcmdlist_remove2(g_dat->draftList, dat->windowData.hContact); + } + tcmdlist_free(dat->windowData.cmdList); + WindowList_Remove(g_dat->hMessageWindowList, hwndDlg); + UnsubclassMessageEdit(GetDlgItem(hwndDlg, IDC_MESSAGE)); + UnsubclassLogEdit(GetDlgItem(hwndDlg, IDC_LOG)); + { + 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); + } + DBWriteContactSettingByte(dat->windowData.hContact, SRMMMOD, "UseRTL", (BYTE) ((dat->flags & SMF_RTL) ? 1 : 0)); + DBWriteContactSettingWord(dat->windowData.hContact, SRMMMOD, "CodePage", (WORD) dat->windowData.codePage); + if (dat->windowData.hContact && (g_dat->flags & SMF_DELTEMP)) { + if (DBGetContactSettingByte(dat->windowData.hContact, "CList", "NotOnList", 0)) { + CallService(MS_DB_CONTACT_DELETE, (WPARAM)dat->windowData.hContact, 0); + } + } + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + SendMessage(dat->hwndParent, CM_REMOVECHILD, 0, (LPARAM) hwndDlg); + if (dat->windowData.hwndLog != NULL) { + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_DESTROY; + ieWindow.hwnd = dat->windowData.hwndLog; + CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow); + } + NotifyLocalWinEvent(dat->windowData.hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE); + mir_free(dat); + break; + } + return FALSE; +} -- cgit v1.2.3