From 3b55a62fdcb1f8222de3c2c8fbed530792c419a0 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Fri, 12 Oct 2012 14:53:57 +0000 Subject: GTalkExt, ICQ, IRC, Jabber: folders restructurization git-svn-id: http://svn.miranda-ng.org/main/trunk@1890 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/JabberG/src/jabber_userinfo.cpp | 896 ++++++++++++++++++++++++++++++ 1 file changed, 896 insertions(+) create mode 100644 protocols/JabberG/src/jabber_userinfo.cpp (limited to 'protocols/JabberG/src/jabber_userinfo.cpp') diff --git a/protocols/JabberG/src/jabber_userinfo.cpp b/protocols/JabberG/src/jabber_userinfo.cpp new file mode 100644 index 0000000000..9d8b476851 --- /dev/null +++ b/protocols/JabberG/src/jabber_userinfo.cpp @@ -0,0 +1,896 @@ +/* + +Jabber Protocol Plugin for Miranda IM +Copyright ( C ) 2002-04 Santithorn Bunchua +Copyright ( C ) 2005-12 George Hazan +Copyright ( C ) 2007 Maxim Mluhov + +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 "jabber.h" +#include "m_icolib.h" + +#include +#include +#include + +#include "jabber_list.h" + +static HANDLE hUserInfoList = NULL; + +struct UserInfoStringBuf +{ + enum { STRINGBUF_INCREMENT = 1024 }; + + TCHAR *buf; + int size; + int offset; + + UserInfoStringBuf() { buf = 0; size = 0; offset = 0; } + ~UserInfoStringBuf() { mir_free(buf); } + + void append( TCHAR *str ) { + if ( !str ) return; + + int length = lstrlen( str ); + if ( size - offset < length + 1 ) { + size += ( length + STRINGBUF_INCREMENT ); + buf = ( TCHAR * )mir_realloc( buf, size * sizeof( TCHAR )); + } + lstrcpy( buf + offset, str ); + offset += length; + } + + TCHAR *allocate( int length ) { + if ( size - offset < length ) { + size += ( length + STRINGBUF_INCREMENT ); + buf = ( TCHAR * )mir_realloc( buf, size * sizeof( TCHAR )); + } + return buf + offset; + } + + void actualize() { + if ( buf ) offset = lstrlen( buf ); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// JabberUserInfoDlgProc - main user info dialog + +struct JabberUserInfoDlgData +{ + CJabberProto* ppro; + HANDLE hContact; + JABBER_LIST_ITEM* item; + int resourceCount; +}; + +enum +{ + INFOLINE_DELETE = 0x80000000, + INFOLINE_MASK = 0x7fffffff, + INFOLINE_BAD_ID = 0x7fffffff, + + INFOLINE_NAME = 1, + INFOLINE_MOOD, + INFOLINE_ACTIVITY, + INFOLINE_TUNE, + INFOLINE_OFFLINE, + INFOLINE_MESSAGE, + INFOLINE_SOFTWARE, + INFOLINE_VERSION, + INFOLINE_SYSTEM, + INFOLINE_PRIORITY, + INFOLINE_IDLE, + INFOLINE_CAPS, + INFOLINE_SOFTWARE_INFORMATION, + INFOLINE_SUBSCRIPTION, + INFOLINE_LOGOFF, + INFOLINE_LOGOFF_MSG, + INFOLINE_LASTACTIVE, +}; + +__forceinline DWORD sttInfoLineId(DWORD res, DWORD type, DWORD line=0) +{ + return + ( type << 24 ) & 0x7f000000 | + ( res << 12 ) & 0x00fff000 | + ( line ) & 0x00000fff; +} + +static HTREEITEM sttFindInfoLine( HWND hwndTree, HTREEITEM htiRoot, LPARAM id=INFOLINE_BAD_ID ) +{ + if ( id == INFOLINE_BAD_ID ) return NULL; + for (HTREEITEM hti = TreeView_GetChild(hwndTree, htiRoot); hti; hti = TreeView_GetNextSibling(hwndTree, hti)) + { + TVITEMEX tvi = {0}; + tvi.mask = TVIF_HANDLE|TVIF_PARAM; + tvi.hItem = hti; + TreeView_GetItem(hwndTree, &tvi); + if ((tvi.lParam&INFOLINE_MASK) == (id&INFOLINE_MASK)) + return hti; + } + return NULL; +} + +void sttCleanupInfo(HWND hwndTree, int stage) +{ + HTREEITEM hItem = TreeView_GetRoot(hwndTree); + while (hItem) { + TVITEMEX tvi = {0}; + tvi.mask = TVIF_HANDLE|TVIF_PARAM; + tvi.hItem = hItem; + TreeView_GetItem(hwndTree, &tvi); + + switch (stage) { + case 0: + tvi.lParam |= INFOLINE_DELETE; + TreeView_SetItem(hwndTree, &tvi); + break; + + case 1: + if (tvi.lParam & INFOLINE_DELETE) { + hItem = TreeView_GetNextSibling(hwndTree, hItem); + TreeView_DeleteItem(hwndTree, tvi.hItem); + continue; + } + break; + } + + HTREEITEM hItemTmp = 0; + if (hItemTmp = TreeView_GetChild(hwndTree, hItem)) + hItem = hItemTmp; + else if (hItemTmp = TreeView_GetNextSibling(hwndTree, hItem)) + hItem = hItemTmp; + else { + while (1) { + if (!(hItem = TreeView_GetParent(hwndTree, hItem))) break; + if (hItemTmp = TreeView_GetNextSibling(hwndTree, hItem)) { + hItem = hItemTmp; + break; + } + } + } + } +} + +static HTREEITEM sttFillInfoLine( HWND hwndTree, HTREEITEM htiRoot, HICON hIcon, TCHAR *title, TCHAR *value, LPARAM id=INFOLINE_BAD_ID, bool expand=false ) +{ + HTREEITEM hti = sttFindInfoLine(hwndTree, htiRoot, id); + + TCHAR buf[256]; + if ( title ) + mir_sntprintf( buf, SIZEOF(buf), _T("%s: %s"), title, value ); + else + lstrcpyn( buf, value, SIZEOF( buf )); + + TVINSERTSTRUCT tvis = {0}; + tvis.hParent = htiRoot; + tvis.hInsertAfter = TVI_LAST; + tvis.itemex.mask = TVIF_TEXT|TVIF_PARAM; + tvis.itemex.pszText = buf; + tvis.itemex.lParam = id; + + if ( hIcon ) { + HIMAGELIST himl = TreeView_GetImageList( hwndTree, TVSIL_NORMAL ); + tvis.itemex.mask |= TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvis.itemex.iImage = + tvis.itemex.iSelectedImage = ImageList_AddIcon( himl, hIcon ); + g_ReleaseIcon( hIcon ); + } + + if ( hti ) { + tvis.itemex.mask |= TVIF_HANDLE; + tvis.itemex.hItem = hti; + TreeView_SetItem( hwndTree, &tvis.itemex ); + } + else { + tvis.itemex.mask |= TVIF_STATE; + tvis.itemex.stateMask = TVIS_EXPANDED; + tvis.itemex.state = expand ? TVIS_EXPANDED : 0; + hti = TreeView_InsertItem( hwndTree, &tvis ); + } + + return hti; +} + +static void sttFillResourceInfo( CJabberProto* ppro, HWND hwndTree, HTREEITEM htiRoot, JABBER_LIST_ITEM *item, int resource ) +{ + TCHAR buf[256]; + HTREEITEM htiResource = htiRoot; + JABBER_RESOURCE_STATUS *res = resource ? &item->resource[resource-1] : &item->itemResource; + + if ( res->resourceName && *res->resourceName ) + htiResource = sttFillInfoLine( hwndTree, htiRoot, LoadSkinnedProtoIcon( ppro->m_szModuleName, res->status ), + TranslateT("Resource"), res->resourceName, sttInfoLineId(resource, INFOLINE_NAME), true ); + + // StatusMsg + sttFillInfoLine( hwndTree, htiResource, NULL /*LoadSkinnedIcon( SKINICON_EVENT_MESSAGE )*/, + TranslateT( "Message" ), res->statusMessage ? res->statusMessage : TranslateT( "" ), + sttInfoLineId(resource, INFOLINE_MESSAGE)); + + // Software + HICON hIcon = NULL; + if (ServiceExists(MS_FP_GETCLIENTICONT)) { + if (res->software != NULL) { + mir_sntprintf(buf, SIZEOF(buf), _T("%s %s"), res->software, res->version); + hIcon = (HICON)CallService( MS_FP_GETCLIENTICONT, (WPARAM)buf, 0 ); + } } + + sttFillInfoLine( hwndTree, htiResource, hIcon, TranslateT( "Software" ), + res->software ? res->software : TranslateT( "" ), + sttInfoLineId(resource, INFOLINE_SOFTWARE)); + + if(hIcon) + DestroyIcon(hIcon); + + // Version + sttFillInfoLine( hwndTree, htiResource, NULL, TranslateT( "Version" ), + res->version ? res->version : TranslateT( "" ), + sttInfoLineId(resource, INFOLINE_VERSION)); + + // System + sttFillInfoLine( hwndTree, htiResource, NULL, TranslateT( "System" ), + res->system ? res->system : TranslateT( "" ), + sttInfoLineId(resource, INFOLINE_SYSTEM)); + + // Resource priority + TCHAR szPriority[128]; + mir_sntprintf( szPriority, SIZEOF( szPriority ), _T("%d"), (int)res->priority ); + sttFillInfoLine( hwndTree, htiResource, NULL, TranslateT( "Resource priority" ), szPriority, sttInfoLineId(resource, INFOLINE_PRIORITY)); + + // Idle + if ( res->idleStartTime > 0 ) { + lstrcpyn(buf, _tctime( &res->idleStartTime ), SIZEOF( buf )); + int len = lstrlen(buf); + if (len > 0) buf[len-1] = 0; + } + else if ( !res->idleStartTime ) + lstrcpyn(buf, TranslateT( "unknown" ), SIZEOF( buf )); + else + lstrcpyn(buf, TranslateT( "" ), SIZEOF( buf )); + + sttFillInfoLine( hwndTree, htiResource, NULL, TranslateT("Idle since"), buf, sttInfoLineId(resource, INFOLINE_IDLE)); + + // caps + mir_sntprintf( buf, SIZEOF(buf), _T("%s/%s"), item->jid, res->resourceName ); + JabberCapsBits jcb = ppro->GetResourceCapabilites( buf, TRUE ); + + if ( !( jcb & JABBER_RESOURCE_CAPS_ERROR )) { + HTREEITEM htiCaps = sttFillInfoLine( hwndTree, htiResource, ppro->LoadIconEx( "main" ), NULL, TranslateT( "Client capabilities" ), sttInfoLineId(resource, INFOLINE_CAPS)); + int i; + for ( i = 0; g_JabberFeatCapPairs[i].szFeature; i++ ) + if ( jcb & g_JabberFeatCapPairs[i].jcbCap ) { + TCHAR szDescription[ 1024 ]; + if ( g_JabberFeatCapPairs[i].szDescription ) + mir_sntprintf( szDescription, SIZEOF( szDescription ), _T("%s (%s)"), TranslateTS(g_JabberFeatCapPairs[i].szDescription), g_JabberFeatCapPairs[i].szFeature ); + else + mir_sntprintf( szDescription, SIZEOF( szDescription ), _T("%s"), g_JabberFeatCapPairs[i].szFeature ); + sttFillInfoLine( hwndTree, htiCaps, NULL, NULL, szDescription, sttInfoLineId(resource, INFOLINE_CAPS, i)); + } + + for ( int j = 0; j < ppro->m_lstJabberFeatCapPairsDynamic.getCount(); j++, i++ ) + if ( jcb & ppro->m_lstJabberFeatCapPairsDynamic[j]->jcbCap ) { + TCHAR szDescription[ 1024 ]; + if ( ppro->m_lstJabberFeatCapPairsDynamic[j]->szDescription ) + mir_sntprintf( szDescription, SIZEOF( szDescription ), _T("%s (%s)"), TranslateTS(ppro->m_lstJabberFeatCapPairsDynamic[j]->szDescription), ppro->m_lstJabberFeatCapPairsDynamic[j]->szFeature ); + else + mir_sntprintf( szDescription, SIZEOF( szDescription ), _T("%s"), ppro->m_lstJabberFeatCapPairsDynamic[j]->szFeature ); + sttFillInfoLine( hwndTree, htiCaps, NULL, NULL, szDescription, sttInfoLineId(resource, INFOLINE_CAPS, i)); + } + } + + // Software info + if ( res->pSoftwareInfo ) { + HTREEITEM htiSoftwareInfo = sttFillInfoLine( hwndTree, htiResource, ppro->LoadIconEx( "main" ), NULL, TranslateT( "Software information" ), sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION)); + int nLineId = 0; + if ( res->pSoftwareInfo->szOs ) + sttFillInfoLine( hwndTree, htiSoftwareInfo, NULL, TranslateT("Operating system"), res->pSoftwareInfo->szOs, sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION, nLineId++)); + if ( res->pSoftwareInfo->szOsVersion ) + sttFillInfoLine( hwndTree, htiSoftwareInfo, NULL, TranslateT("Operating system version"), res->pSoftwareInfo->szOsVersion, sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION, nLineId++)); + if ( res->pSoftwareInfo->szSoftware ) + sttFillInfoLine( hwndTree, htiSoftwareInfo, NULL, TranslateT("Software"), res->pSoftwareInfo->szSoftware, sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION, nLineId++)); + if ( res->pSoftwareInfo->szSoftwareVersion ) + sttFillInfoLine( hwndTree, htiSoftwareInfo, NULL, TranslateT("Software version"), res->pSoftwareInfo->szSoftwareVersion, sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION, nLineId++)); + if ( res->pSoftwareInfo->szXMirandaCoreVersion ) { + sttFillInfoLine( hwndTree, htiSoftwareInfo, NULL, TranslateT("Miranda NG core version"), res->pSoftwareInfo->szXMirandaCoreVersion, sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION, nLineId++)); + sttFillInfoLine( hwndTree, htiSoftwareInfo, NULL, TranslateT("Unicode build"), res->pSoftwareInfo->bXMirandaIsUnicode ? TranslateT("Yes") : TranslateT("No"), sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION, nLineId++)); + sttFillInfoLine( hwndTree, htiSoftwareInfo, NULL, TranslateT("Alpha build"), res->pSoftwareInfo->bXMirandaIsAlpha ? TranslateT("Yes") : TranslateT("No"), sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION, nLineId++)); + sttFillInfoLine( hwndTree, htiSoftwareInfo, NULL, TranslateT("Debug build"), res->pSoftwareInfo->bXMirandaIsDebug ? TranslateT("Yes") : TranslateT("No"), sttInfoLineId(resource, INFOLINE_SOFTWARE_INFORMATION, nLineId++)); + } + } +} + +static void sttFillAdvStatusInfo( CJabberProto* ppro, HWND hwndTree, HTREEITEM htiRoot, DWORD dwInfoLine, HANDLE hContact, TCHAR *szTitle, char *pszSlot ) +{ + char *szAdvStatusIcon = ppro->ReadAdvStatusA(hContact, pszSlot, ADVSTATUS_VAL_ICON); + TCHAR *szAdvStatusTitle = ppro->ReadAdvStatusT(hContact, pszSlot, ADVSTATUS_VAL_TITLE); + TCHAR *szAdvStatusText = ppro->ReadAdvStatusT(hContact, pszSlot, ADVSTATUS_VAL_TEXT); + + if (szAdvStatusIcon && szAdvStatusTitle && *szAdvStatusTitle) { + TCHAR szText[2048]; + if ( szAdvStatusText && *szAdvStatusText ) + mir_sntprintf(szText, 2047, _T("%s (%s)"), TranslateTS(szAdvStatusTitle), szAdvStatusText); + else + mir_sntprintf(szText, 2047, _T("%s"), TranslateTS(szAdvStatusTitle)); + sttFillInfoLine( hwndTree, htiRoot, (HICON)CallService(MS_SKIN2_GETICON, 0, + (LPARAM)szAdvStatusIcon), szTitle, szText, dwInfoLine); + } + + mir_free(szAdvStatusIcon); + mir_free(szAdvStatusTitle); + mir_free(szAdvStatusText); +} + +static void sttFillUserInfo( CJabberProto* ppro, HWND hwndTree, JABBER_LIST_ITEM *item ) +{ + SendMessage( hwndTree, WM_SETREDRAW, FALSE, 0 ); + + sttCleanupInfo(hwndTree, 0); + + HTREEITEM htiRoot = sttFillInfoLine( hwndTree, NULL, ppro->LoadIconEx( "main" ), _T( "JID" ), item->jid, sttInfoLineId(0, INFOLINE_NAME), true ); + TCHAR buf[256]; + + if (HANDLE hContact = ppro->HContactFromJID(item->jid)) { + sttFillAdvStatusInfo( ppro, hwndTree, htiRoot, sttInfoLineId(0, INFOLINE_MOOD), hContact, TranslateT("Mood"), ADVSTATUS_MOOD ); + sttFillAdvStatusInfo( ppro, hwndTree, htiRoot, sttInfoLineId(0, INFOLINE_ACTIVITY), hContact, TranslateT("Activity"), ADVSTATUS_ACTIVITY ); + sttFillAdvStatusInfo( ppro, hwndTree, htiRoot, sttInfoLineId(0, INFOLINE_TUNE), hContact, TranslateT("Tune"), ADVSTATUS_TUNE ); + } + + // subscription + switch ( item->subscription ) { + case SUB_BOTH: + sttFillInfoLine( hwndTree, htiRoot, NULL, TranslateT( "Subscription" ), TranslateT( "both" ), sttInfoLineId(0, INFOLINE_SUBSCRIPTION)); + break; + case SUB_TO: + sttFillInfoLine( hwndTree, htiRoot, NULL, TranslateT( "Subscription" ), TranslateT( "to" ), sttInfoLineId(0, INFOLINE_SUBSCRIPTION)); + break; + case SUB_FROM: + sttFillInfoLine( hwndTree, htiRoot, NULL, TranslateT( "Subscription" ), TranslateT( "from" ), sttInfoLineId(0, INFOLINE_SUBSCRIPTION)); + break; + default: + sttFillInfoLine( hwndTree, htiRoot, NULL, TranslateT( "Subscription" ), TranslateT( "none" ), sttInfoLineId(0, INFOLINE_SUBSCRIPTION)); + break; + } + + // logoff + if ( item->itemResource.idleStartTime > 0 ) { + lstrcpyn( buf, _tctime( &item->itemResource.idleStartTime ), SIZEOF( buf )); + int len = lstrlen(buf); + if (len > 0) buf[len-1] = 0; + } + else if ( !item->itemResource.idleStartTime ) + lstrcpyn( buf, TranslateT( "unknown" ), SIZEOF( buf )); + else + lstrcpyn( buf, TranslateT( "" ), SIZEOF( buf )); + + sttFillInfoLine( hwndTree, htiRoot, NULL, + ( item->jid && _tcschr( item->jid, _T( '@' ))) ? TranslateT( "Last logoff time" ) : TranslateT( "Uptime"), buf, + sttInfoLineId(0, INFOLINE_LOGOFF)); + + // logoff msg + sttFillInfoLine( hwndTree, htiRoot, NULL, TranslateT( "Logoff message" ), + item->itemResource.statusMessage ? item->itemResource.statusMessage : TranslateT( "" ), sttInfoLineId(0, INFOLINE_LOGOFF_MSG)); + + // activity + if (( item->lastSeenResource >= 0 ) && ( item->lastSeenResource < item->resourceCount )) + lstrcpyn( buf, item->resource[item->lastSeenResource].resourceName, SIZEOF( buf )); + else + lstrcpyn( buf, TranslateT( "" ), SIZEOF( buf )); + + sttFillInfoLine( hwndTree, htiRoot, NULL, TranslateT( "Last active resource" ), buf, + sttInfoLineId(0, INFOLINE_LASTACTIVE)); + + // resources + if ( item->resourceCount ) { + for (int i = 0; i < item->resourceCount; ++i) + sttFillResourceInfo( ppro, hwndTree, htiRoot, item, i+1 ); + } + else if ( !_tcschr(item->jid, _T('@')) || (item->itemResource.status != ID_STATUS_OFFLINE)) + sttFillResourceInfo( ppro, hwndTree, htiRoot, item, 0 ); + + sttCleanupInfo(hwndTree, 1); + SendMessage( hwndTree, WM_SETREDRAW, TRUE, 0 ); + + RedrawWindow( hwndTree, NULL, NULL, RDW_INVALIDATE ); +} + +static void sttGetNodeText( HWND hwndTree, HTREEITEM hti, UserInfoStringBuf *buf, int indent = 0 ) +{ + for ( int i = 0; i < indent; ++i ) + buf->append( _T( "\t" )); + + TVITEMEX tvi = {0}; + tvi.mask = TVIF_HANDLE|TVIF_TEXT|TVIF_STATE; + tvi.hItem = hti; + tvi.cchTextMax = 256; + tvi.pszText = buf->allocate( tvi.cchTextMax ); + if (!TreeView_GetItem( hwndTree, &tvi )) { // failure, maybe item was removed... + buf->buf[ buf->offset ] = 0; + buf->actualize(); + return; + } + + buf->actualize(); + buf->append( _T( "\r\n" )); + + if ( tvi.state & TVIS_EXPANDED ) + for ( hti = TreeView_GetChild( hwndTree, hti ); hti; hti = TreeView_GetNextSibling( hwndTree, hti )) + sttGetNodeText( hwndTree, hti, buf, indent + 1 ); +} + +static INT_PTR CALLBACK JabberUserInfoDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + JabberUserInfoDlgData *dat = (JabberUserInfoDlgData *)GetWindowLongPtr( hwndDlg, GWLP_USERDATA ); + + switch ( msg ) { + case WM_INITDIALOG: + // lParam is hContact + TranslateDialogDefault( hwndDlg ); + + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIconBig(SKINICON_OTHER_USERDETAILS)); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_USERDETAILS)); + + dat = (JabberUserInfoDlgData *)mir_alloc(sizeof(JabberUserInfoDlgData)); + ZeroMemory(dat, sizeof(JabberUserInfoDlgData)); + dat->resourceCount = -1; + + if ( CallService(MS_DB_CONTACT_IS, (WPARAM)lParam, 0 )) + dat->hContact = (HANDLE)lParam; + else if (!IsBadReadPtr((void *)lParam, sizeof(JABBER_LIST_ITEM))) { + dat->hContact = NULL; + dat->item = (JABBER_LIST_ITEM *)lParam; + } + + { + RECT rc; GetClientRect( hwndDlg, &rc ); + MoveWindow( GetDlgItem( hwndDlg, IDC_TV_INFO ), 5, 5, rc.right-10, rc.bottom-10, TRUE ); + + HIMAGELIST himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR|ILC_COLOR32|ILC_MASK, 5, 1); + ImageList_AddIcon_Icolib(himl, LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT)); + TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TV_INFO), himl, TVSIL_NORMAL); + + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + WindowList_Add(hUserInfoList, hwndDlg, dat->hContact); + } + break; + + case WM_JABBER_REFRESH: + if ( !dat ) break; + + if ( !dat->item ) { + DBVARIANT dbv = {0}; + if ( dat->ppro->JGetStringT(dat->hContact, "jid", &dbv)) + break; + + if (!(dat->item = dat->ppro->ListGetItemPtr(LIST_VCARD_TEMP, dbv.ptszVal))) + dat->item = dat->ppro->ListGetItemPtr(LIST_ROSTER, dbv.ptszVal); + + if (!dat->item) + { + HWND hwndTree = GetDlgItem(hwndDlg, IDC_TV_INFO); + TreeView_DeleteAllItems( hwndTree ); + HTREEITEM htiRoot = sttFillInfoLine( hwndTree, NULL, dat->ppro->LoadIconEx( "main" ), _T( "JID" ), dbv.ptszVal, sttInfoLineId(0, INFOLINE_NAME), true ); + sttFillInfoLine( hwndTree, htiRoot, dat->ppro->LoadIconEx("vcard"), NULL, + TranslateT("Please switch online to see more details.")); + + JFreeVariant(&dbv); + break; + } + + JFreeVariant(&dbv); + } + sttFillUserInfo( dat->ppro, GetDlgItem(hwndDlg, IDC_TV_INFO), dat->item); + break; + + case WM_SIZE: + MoveWindow(GetDlgItem(hwndDlg, IDC_TV_INFO), 5, 5, LOWORD(lParam)-10, HIWORD(lParam)-10, TRUE); + break; + + case WM_CONTEXTMENU: + if ( GetWindowLongPtr(( HWND )wParam, GWL_ID ) == IDC_TV_INFO ) { + HWND hwndTree = GetDlgItem( hwndDlg, IDC_TV_INFO ); + POINT pt = { (signed short)LOWORD( lParam ), (signed short)HIWORD( lParam ) }; + HTREEITEM hItem = 0; + + if (( pt.x == -1 ) && ( pt.y == -1 )) { + if (hItem = TreeView_GetSelection( hwndTree )) { + RECT rc; + TreeView_GetItemRect( hwndTree, hItem, &rc, TRUE ); + pt.x = rc.left; + pt.y = rc.bottom; + ClientToScreen( hwndTree, &pt ); + } + } + else { + TVHITTESTINFO tvhti = {0}; + tvhti.pt = pt; + ScreenToClient( hwndTree, &tvhti.pt ); + TreeView_HitTest( hwndTree, &tvhti ); + if ( tvhti.flags & TVHT_ONITEM ) { + hItem = tvhti.hItem; + TreeView_Select(hwndTree, hItem, TVGN_CARET); + } } + + if ( hItem ) { + HMENU hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy")); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy only this value")); + AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel")); + int nReturnCmd = TrackPopupMenu( hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL ); + if ( nReturnCmd == 1 ) { + UserInfoStringBuf buf; + sttGetNodeText( hwndTree, hItem, &buf ); + JabberCopyText( hwndDlg, buf.buf ); + } + else if ( nReturnCmd == 2 ) { + TCHAR szBuffer[ 1024 ]; + TVITEMEX tvi = {0}; + tvi.mask = TVIF_HANDLE|TVIF_TEXT|TVIF_STATE; + tvi.hItem = hItem; + tvi.cchTextMax = SIZEOF( szBuffer ); + tvi.pszText = szBuffer; + if ( TreeView_GetItem( hwndTree, &tvi )) { + if (TCHAR *str = _tcsstr(szBuffer, _T(": "))) + JabberCopyText( hwndDlg, str+2 ); + else + JabberCopyText( hwndDlg, szBuffer ); + } } + DestroyMenu( hMenu ); + } } + break; + + case WM_NOTIFY: + if (( ( LPNMHDR )lParam )->idFrom == 0 ) { + switch (( ( LPNMHDR )lParam )->code ) { + case PSN_INFOCHANGED: + { + HANDLE hContact = ( HANDLE ) (( LPPSHNOTIFY ) lParam )->lParam; + SendMessage( hwndDlg, WM_JABBER_REFRESH, 0, ( LPARAM )hContact ); + } + break; + + case PSN_PARAMCHANGED: + dat->ppro = ( CJabberProto* )( CJabberProto* )(( PSHNOTIFY* )lParam )->lParam; + if ( dat->hContact != NULL ) { + DBVARIANT dbv = {0}; + if ( dat->ppro->JGetStringT(dat->hContact, "jid", &dbv)) + break; + + if ( !(dat->item = dat->ppro->ListGetItemPtr( LIST_VCARD_TEMP, dbv.ptszVal ))) + dat->item = dat->ppro->ListGetItemPtr( LIST_ROSTER, dbv.ptszVal ); + JFreeVariant(&dbv); + } + break; + } } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + WindowList_Remove(hUserInfoList, hwndDlg); + if ( dat ) { + mir_free(dat); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + } + ImageList_Destroy(TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TV_INFO), NULL, TVSIL_NORMAL)); + WindowFreeIcon( hwndDlg ); + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// JabberUserPhotoDlgProc - Jabber photo dialog + +struct USER_PHOTO_INFO +{ + HANDLE hContact; + HBITMAP hBitmap; + CJabberProto* ppro; +}; + +static INT_PTR CALLBACK JabberUserPhotoDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + USER_PHOTO_INFO *photoInfo; + + photoInfo = ( USER_PHOTO_INFO * ) GetWindowLongPtr( hwndDlg, GWLP_USERDATA ); + + switch ( msg ) { + case WM_INITDIALOG: + // lParam is hContact + TranslateDialogDefault( hwndDlg ); + photoInfo = ( USER_PHOTO_INFO * ) mir_alloc( sizeof( USER_PHOTO_INFO )); + photoInfo->hContact = ( HANDLE ) lParam; + photoInfo->ppro = NULL; + photoInfo->hBitmap = NULL; + SetWindowLongPtr( hwndDlg, GWLP_USERDATA, ( LONG_PTR ) photoInfo ); + SendDlgItemMessage( hwndDlg, IDC_SAVE, BM_SETIMAGE, IMAGE_ICON, ( LPARAM )LoadImage( hInst, MAKEINTRESOURCE( IDI_SAVE ), IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), 0 )); + SendDlgItemMessage( hwndDlg, IDC_SAVE, BUTTONSETASFLATBTN, TRUE, 0); + ShowWindow( GetDlgItem( hwndDlg, IDC_LOAD ), SW_HIDE ); + ShowWindow( GetDlgItem( hwndDlg, IDC_DELETE ), SW_HIDE ); + break; + + case WM_NOTIFY: + switch ((( LPNMHDR )lParam )->idFrom ) { + case 0: + switch ((( LPNMHDR )lParam )->code ) { + case PSN_INFOCHANGED: + SendMessage( hwndDlg, WM_JABBER_REFRESH, 0, 0 ); + break; + + case PSN_PARAMCHANGED: + photoInfo->ppro = ( CJabberProto* )(( PSHNOTIFY* )lParam )->lParam; + break; + } + break; + } + break; + + case WM_JABBER_REFRESH: + { + JABBER_LIST_ITEM *item; + DBVARIANT dbv; + + if ( photoInfo->hBitmap ) { + DeleteObject( photoInfo->hBitmap ); + photoInfo->hBitmap = NULL; + } + ShowWindow( GetDlgItem( hwndDlg, IDC_SAVE ), SW_HIDE ); + if ( !photoInfo->ppro->JGetStringT( photoInfo->hContact, "jid", &dbv )) { + TCHAR* jid = dbv.ptszVal; + if (( item = photoInfo->ppro->ListGetItemPtr( LIST_VCARD_TEMP, jid )) == NULL) + item = photoInfo->ppro->ListGetItemPtr( LIST_ROSTER, jid ); + if ( item != NULL ) { + if ( item->photoFileName ) { + photoInfo->ppro->Log( "Showing picture from " TCHAR_STR_PARAM, item->photoFileName ); + char* p = mir_t2a( item->photoFileName ); + photoInfo->hBitmap = ( HBITMAP ) CallService( MS_UTILS_LOADBITMAP, 0, ( LPARAM )p ); + mir_free( p ); + JabberBitmapPremultiplyChannels(photoInfo->hBitmap); + ShowWindow( GetDlgItem( hwndDlg, IDC_SAVE ), SW_SHOW ); + } + } + JFreeVariant( &dbv ); + } + InvalidateRect( hwndDlg, NULL, TRUE ); + UpdateWindow( hwndDlg ); + } + break; + + case WM_COMMAND: + switch ( LOWORD( wParam )) { + case IDC_SAVE: + { + DBVARIANT dbv; + JABBER_LIST_ITEM *item; + HANDLE hFile; + static TCHAR szFilter[512]; + unsigned char buffer[3]; + TCHAR szFileName[MAX_PATH]; + DWORD n; + + if ( photoInfo->ppro->JGetStringT( photoInfo->hContact, "jid", &dbv )) + break; + + TCHAR* jid = dbv.ptszVal; + if (( item = photoInfo->ppro->ListGetItemPtr( LIST_VCARD_TEMP, jid )) == NULL) + item = photoInfo->ppro->ListGetItemPtr( LIST_ROSTER, jid ); + if ( item != NULL ) { + if (( hFile=CreateFile( item->photoFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )) != INVALID_HANDLE_VALUE ) { + if ( ReadFile( hFile, buffer, 3, &n, NULL ) && n==3 ) { + if ( !strncmp(( char* )buffer, "BM", 2 )) { + mir_sntprintf( szFilter, SIZEOF( szFilter ), _T("BMP %s ( *.bmp )"), TranslateT( "format" )); + n = (DWORD)_tcslen( szFilter ); + _tcsncpy( szFilter+n+1, _T("*.BMP"), SIZEOF( szFilter )-n-2 ); + } + else if ( !strncmp(( char* )buffer, "GIF", 3 )) { + mir_sntprintf( szFilter, SIZEOF( szFilter ), _T("GIF %s ( *.gif )"), TranslateT( "format" )); + n = (DWORD)_tcslen( szFilter ); + _tcsncpy( szFilter+n+1, _T("*.GIF"), SIZEOF( szFilter )-n-2 ); + } + else if ( buffer[0]==0xff && buffer[1]==0xd8 && buffer[2]==0xff ) { + mir_sntprintf( szFilter, SIZEOF( szFilter ), _T("JPEG %s ( *.jpg;*.jpeg )"), TranslateT( "format" )); + n = (DWORD)_tcslen( szFilter ); + _tcsncpy( szFilter+n+1, _T("*.JPG;*.JPEG"), SIZEOF( szFilter )-n-2 ); + } + else { + mir_sntprintf( szFilter, SIZEOF( szFilter ), _T("%s ( *.* )"), TranslateT( "Unknown format" )); + n = (DWORD)_tcslen( szFilter ); + _tcsncpy( szFilter+n+1, _T("*.*"), SIZEOF( szFilter )-n-2 ); + } + szFilter[SIZEOF( szFilter )-1] = 0; + + OPENFILENAME ofn = { 0 }; + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwndDlg; + ofn.hInstance = NULL; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 0; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = _MAX_PATH; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.lpstrTitle = NULL; + ofn.Flags = OFN_OVERWRITEPROMPT; + ofn.nFileOffset = 0; + ofn.nFileExtension = 0; + ofn.lpstrDefExt = NULL; + ofn.lCustData = 0L; + ofn.lpfnHook = NULL; + ofn.lpTemplateName = NULL; + szFileName[0] = '\0'; + if ( GetSaveFileName( &ofn )) { + photoInfo->ppro->Log( "File selected is %s", szFileName ); + CopyFile( item->photoFileName, szFileName, FALSE ); + } + } + CloseHandle( hFile ); + } + } + JFreeVariant( &dbv ); + + } + break; + } + break; + + case WM_PAINT: + if ( !photoInfo->ppro->m_bJabberOnline ) + SetDlgItemText( hwndDlg, IDC_CANVAS, TranslateT( "" )); + else if ( !photoInfo->hBitmap ) + SetDlgItemText( hwndDlg, IDC_CANVAS, TranslateT( "" )); + else { + BITMAP bm; + POINT ptSize, ptOrg, pt, ptFitSize; + RECT rect; + + SetDlgItemTextA( hwndDlg, IDC_CANVAS, "" ); + HBITMAP hBitmap = photoInfo->hBitmap; + HWND hwndCanvas = GetDlgItem( hwndDlg, IDC_CANVAS ); + HDC hdcCanvas = GetDC( hwndCanvas ); + HDC hdcMem = CreateCompatibleDC( hdcCanvas ); + SelectObject( hdcMem, hBitmap ); + SetMapMode( hdcMem, GetMapMode( hdcCanvas )); + GetObject( hBitmap, sizeof( BITMAP ), ( LPVOID ) &bm ); + ptSize.x = bm.bmWidth; + ptSize.y = bm.bmHeight; + DPtoLP( hdcCanvas, &ptSize, 1 ); + ptOrg.x = ptOrg.y = 0; + DPtoLP( hdcMem, &ptOrg, 1 ); + GetClientRect( hwndCanvas, &rect ); + InvalidateRect( hwndCanvas, NULL, TRUE ); + UpdateWindow( hwndCanvas ); + if ( ptSize.x<=rect.right && ptSize.y<=rect.bottom ) { + pt.x = ( rect.right - ptSize.x )/2; + pt.y = ( rect.bottom - ptSize.y )/2; + ptFitSize = ptSize; + } + else { + if (( ( float )( ptSize.x-rect.right ))/ptSize.x > (( float )( ptSize.y-rect.bottom ))/ptSize.y ) { + ptFitSize.x = rect.right; + ptFitSize.y = ( ptSize.y*rect.right )/ptSize.x; + pt.x = 0; + pt.y = ( rect.bottom - ptFitSize.y )/2; + } + else { + ptFitSize.x = ( ptSize.x*rect.bottom )/ptSize.y; + ptFitSize.y = rect.bottom; + pt.x = ( rect.right - ptFitSize.x )/2; + pt.y = 0; + } + } + + if (JabberIsThemeActive && JabberDrawThemeParentBackground && JabberIsThemeActive()) { + RECT rc; GetClientRect(hwndCanvas, &rc); + JabberDrawThemeParentBackground(hwndCanvas, hdcCanvas, &rc); + } + else { + RECT rc; GetClientRect(hwndCanvas, &rc); + FillRect(hdcCanvas, &rc, (HBRUSH)GetSysColorBrush(COLOR_BTNFACE)); + } + + if (JabberAlphaBlend && bm.bmBitsPixel == 32 ) { + BLENDFUNCTION bf = {0}; + bf.AlphaFormat = AC_SRC_ALPHA; + bf.BlendOp = AC_SRC_OVER; + bf.SourceConstantAlpha = 255; + JabberAlphaBlend( hdcCanvas, pt.x, pt.y, ptFitSize.x, ptFitSize.y, hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y, bf ); + } + else { + SetStretchBltMode( hdcCanvas, COLORONCOLOR ); + StretchBlt( hdcCanvas, pt.x, pt.y, ptFitSize.x, ptFitSize.y, hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y, SRCCOPY ); + } + + DeleteDC( hdcMem ); + } + break; + + case WM_DESTROY: + DestroyIcon(( HICON )SendDlgItemMessage( hwndDlg, IDC_SAVE, BM_SETIMAGE, IMAGE_ICON, 0 )); + if ( photoInfo->hBitmap ) { + photoInfo->ppro->Log( "Delete bitmap" ); + DeleteObject( photoInfo->hBitmap ); + } + if ( photoInfo ) mir_free( photoInfo ); + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// OnInfoInit - initializes user info option dialogs + +int CJabberProto::OnUserInfoInit( WPARAM wParam, LPARAM lParam ) +{ + if ( !CallService( MS_PROTO_ISPROTOCOLLOADED, 0, ( LPARAM )m_szModuleName )) + return 0; + + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof( odp ); + odp.hInstance = hInst; + odp.dwInitParam = ( LPARAM )this; + + HANDLE hContact = ( HANDLE )lParam; + if ( hContact ) { + char* szProto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM ) hContact, 0 ); + if ( szProto != NULL && !strcmp( szProto, m_szModuleName )) { + odp.pfnDlgProc = JabberUserInfoDlgProc; + odp.position = -2000000000; + odp.pszTemplate = MAKEINTRESOURCEA( IDD_INFO_JABBER ); + odp.pszTitle = LPGEN("Account"); + UserInfo_AddPage(wParam, &odp); + + odp.pfnDlgProc = JabberUserPhotoDlgProc; + odp.position = 2000000000; + odp.pszTemplate = MAKEINTRESOURCEA( IDD_VCARD_PHOTO ); + odp.pszTitle = LPGEN("Photo"); + UserInfo_AddPage(wParam, &odp); + } + } + else { + // Show our vcard + OnUserInfoInit_VCard(wParam, lParam); + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// JabberUserInfoUpdate + +void JabberUserInfoInit() +{ + hUserInfoList = ( HANDLE )CallService( MS_UTILS_ALLOCWINDOWLIST, 0, 0 ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// JabberUserInfoUpdate + +void JabberUserInfoUpdate( HANDLE hContact ) +{ + if ( !hContact ) + WindowList_BroadcastAsync( hUserInfoList, WM_JABBER_REFRESH, 0, 0 ); + else if ( HWND hwnd = WindowList_Find( hUserInfoList, hContact )) + PostMessage( hwnd, WM_JABBER_REFRESH, 0, 0 ); +} -- cgit v1.2.3