/* Jabber Protocol Plugin for Miranda IM Copyright ( C ) 2002-04 Santithorn Bunchua Copyright ( C ) 2005-11 George Hazan 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. Revision : $Revision: 13618 $ Last change on : $Date: 2011-04-22 17:09:42 +0300 (Пт, 22 апр 2011) $ Last change by : $Author: borkra $ */ #include "jabber.h" #include "jabber_caps.h" static BOOL CALLBACK JabberFormMultiLineWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch ( msg ) { //case WM_GETDLGCODE: // return DLGC_WANTARROWS|DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTALLKEYS; case WM_KEYDOWN: if ( wParam == VK_TAB ) { SetFocus( GetNextDlgTabItem( GetParent( GetParent( hwnd )), hwnd, GetKeyState( VK_SHIFT )<0?TRUE:FALSE )); return TRUE; }; break; } return CallWindowProc(( WNDPROC ) GetWindowLongPtr( hwnd, GWLP_USERDATA ), hwnd, msg, wParam, lParam ); } struct TJabberFormControlInfo { TJabberFormControlType type; SIZE szBlock; POINT ptLabel, ptCtrl; HWND hLabel, hCtrl; }; typedef LIST TJabberFormControlList; struct TJabberFormLayoutInfo { int ctrlHeight; int offset, width, maxLabelWidth; int y_pos, y_spacing; int id; bool compact; }; void JabberFormCenterContent(HWND hwndStatic) { RECT rcWindow; int minX; GetWindowRect(hwndStatic,&rcWindow); minX=rcWindow.right; HWND oldChild=NULL; HWND hWndChild=GetWindow(hwndStatic,GW_CHILD); while (hWndChild!=oldChild && hWndChild!=NULL) { DWORD style=GetWindowLongPtr(hWndChild, GWL_STYLE); RECT rc; GetWindowRect(hWndChild,&rc); if ((style&SS_RIGHT) && !(style&WS_TABSTOP)) { TCHAR * text; RECT calcRect=rc; int len=GetWindowTextLength(hWndChild); text=(TCHAR*)malloc(sizeof(TCHAR)*(len+1)); GetWindowText(hWndChild,text,len+1); HDC hdc=GetDC(hWndChild); HFONT hfntSave = (HFONT)SelectObject(hdc, (HFONT)SendMessage(hWndChild, WM_GETFONT, 0, 0)); DrawText(hdc,text,-1,&calcRect,DT_CALCRECT|DT_WORDBREAK); minX=min(minX, rc.right-(calcRect.right-calcRect.left)); SelectObject(hdc, hfntSave); ReleaseDC(hWndChild,hdc); } else { minX=min(minX,rc.left); } oldChild=hWndChild; hWndChild=GetWindow(hWndChild,GW_HWNDNEXT); } if (minX>rcWindow.left+5) { int dx=(minX-rcWindow.left)/2; oldChild=NULL; hWndChild=GetWindow(hwndStatic,GW_CHILD); while (hWndChild!=oldChild && hWndChild!=NULL ) { DWORD style=GetWindowLongPtr(hWndChild, GWL_STYLE); RECT rc; GetWindowRect(hWndChild,&rc); if ((style&SS_RIGHT) && !(style&WS_TABSTOP)) MoveWindow(hWndChild,rc.left-rcWindow.left,rc.top-rcWindow.top, rc.right-rc.left-dx, rc.bottom-rc.top, TRUE); else MoveWindow(hWndChild,rc.left-dx-rcWindow.left,rc.top-rcWindow.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); oldChild=hWndChild; hWndChild=GetWindow(hWndChild,GW_HWNDNEXT); } } } void JabberFormSetInstruction( HWND hwndForm, const TCHAR *text ) { if (!text) text = _T(""); int len = lstrlen(text); int fixedLen = len; for (int i = 1; i < len; ++i) if ((text[i - 1] == _T('\n')) && (text[i] != _T('\r'))) ++fixedLen; TCHAR *fixedText = NULL; if (fixedLen != len) { fixedText = (TCHAR *)mir_alloc(sizeof(TCHAR) * (fixedLen+1)); TCHAR *p = fixedText; for (int i = 0; i < len; ++i) { *p = text[i]; if (i && (text[i] == _T('\n')) && (text[i] != _T('\r'))) { *p++ = _T('\r'); *p = _T('\n'); } ++p; } *p = 0; text = fixedText; } SetDlgItemText( hwndForm, IDC_INSTRUCTION, text ); RECT rcText; GetWindowRect(GetDlgItem(hwndForm, IDC_INSTRUCTION), &rcText); int oldWidth = rcText.right-rcText.left; int deltaHeight = -(rcText.bottom-rcText.top); SetRect(&rcText, 0, 0, rcText.right-rcText.left, 0); HDC hdcEdit = GetDC(GetDlgItem(hwndForm, IDC_INSTRUCTION)); HFONT hfntSave = (HFONT)SelectObject(hdcEdit, (HFONT)SendDlgItemMessage(hwndForm, IDC_INSTRUCTION, WM_GETFONT, 0, 0)); DrawTextEx(hdcEdit, (TCHAR *)text, lstrlen(text), &rcText, DT_CALCRECT|DT_EDITCONTROL|DT_TOP|DT_WORDBREAK, NULL); SelectObject(hdcEdit, hfntSave); ReleaseDC(GetDlgItem(hwndForm, IDC_INSTRUCTION), hdcEdit); RECT rcWindow; GetClientRect(hwndForm, &rcWindow); if (rcText.bottom-rcText.top > (rcWindow.bottom-rcWindow.top)/5) { HWND hwndEdit = GetDlgItem(hwndForm, IDC_INSTRUCTION); SetWindowLongPtr(hwndEdit, GWL_STYLE, WS_VSCROLL | GetWindowLongPtr(hwndEdit, GWL_STYLE)); rcText.bottom = rcText.top + (rcWindow.bottom-rcWindow.top)/5; } else { HWND hwndEdit = GetDlgItem(hwndForm, IDC_INSTRUCTION); SetWindowLongPtr(hwndEdit, GWL_STYLE, ~WS_VSCROLL & GetWindowLongPtr(hwndEdit, GWL_STYLE)); } deltaHeight += rcText.bottom-rcText.top; SetWindowPos(GetDlgItem(hwndForm, IDC_INSTRUCTION), 0, 0, 0, oldWidth, rcText.bottom-rcText.top, SWP_NOMOVE|SWP_NOZORDER); GetWindowRect(GetDlgItem(hwndForm, IDC_WHITERECT), &rcText); MapWindowPoints(NULL, hwndForm, (LPPOINT)&rcText, 2); rcText.bottom += deltaHeight; SetWindowPos(GetDlgItem(hwndForm, IDC_WHITERECT), 0, 0, 0, rcText.right-rcText.left, rcText.bottom-rcText.top, SWP_NOMOVE|SWP_NOZORDER); GetWindowRect(GetDlgItem(hwndForm, IDC_FRAME1), &rcText); MapWindowPoints(NULL, hwndForm, (LPPOINT)&rcText, 2); rcText.top += deltaHeight; SetWindowPos(GetDlgItem(hwndForm, IDC_FRAME1), 0, rcText.left, rcText.top, 0, 0, SWP_NOSIZE|SWP_NOZORDER); GetWindowRect(GetDlgItem(hwndForm, IDC_FRAME), &rcText); MapWindowPoints(NULL, hwndForm, (LPPOINT)&rcText, 2); rcText.top += deltaHeight; SetWindowPos(GetDlgItem(hwndForm, IDC_FRAME), 0, rcText.left, rcText.top, rcText.right-rcText.left, rcText.bottom-rcText.top, SWP_NOZORDER); GetWindowRect(GetDlgItem(hwndForm, IDC_VSCROLL), &rcText); MapWindowPoints(NULL, hwndForm, (LPPOINT)&rcText, 2); rcText.top += deltaHeight; SetWindowPos(GetDlgItem(hwndForm, IDC_VSCROLL), 0, rcText.left, rcText.top, rcText.right-rcText.left, rcText.bottom-rcText.top, SWP_NOZORDER); if (fixedText) mir_free(fixedText); } static TJabberFormControlType JabberFormTypeNameToId( const TCHAR *type ) { if ( !_tcscmp( type, _T("text-private"))) return JFORM_CTYPE_TEXT_PRIVATE; if ( !_tcscmp( type, _T("text-multi")) || !_tcscmp( type, _T("jid-multi"))) return JFORM_CTYPE_TEXT_MULTI; if ( !_tcscmp( type, _T("boolean"))) return JFORM_CTYPE_BOOLEAN; if ( !_tcscmp( type, _T("list-single"))) return JFORM_CTYPE_LIST_SINGLE; if ( !_tcscmp( type, _T("list-multi"))) return JFORM_CTYPE_LIST_MULTI; if ( !_tcscmp( type, _T("fixed"))) return JFORM_CTYPE_FIXED; if ( !_tcscmp( type, _T("hidden"))) return JFORM_CTYPE_HIDDEN; // else return JFORM_CTYPE_TEXT_SINGLE; } void JabberFormLayoutSingleControl(TJabberFormControlInfo *item, TJabberFormLayoutInfo *layout_info, const TCHAR *labelStr, const TCHAR *valueStr) { RECT rcLabel = {0}, rcCtrl = {0}; if (item->hLabel) { SetRect(&rcLabel, 0, 0, layout_info->width, 0); HDC hdc = GetDC( item->hLabel ); HFONT hfntSave = (HFONT)SelectObject(hdc, (HFONT)SendMessage(item->hLabel, WM_GETFONT, 0, 0)); DrawText( hdc, labelStr, -1, &rcLabel, DT_CALCRECT|DT_WORDBREAK ); SelectObject(hdc, hfntSave); ReleaseDC(item->hLabel, hdc); } int indent = layout_info->compact ? 10 : 20; if ((layout_info->compact && (item->type != JFORM_CTYPE_BOOLEAN) && (item->type != JFORM_CTYPE_FIXED))|| (rcLabel.right >= layout_info->maxLabelWidth) || (rcLabel.bottom > layout_info->ctrlHeight) || (item->type == JFORM_CTYPE_LIST_MULTI) || (item->type == JFORM_CTYPE_TEXT_MULTI)) { int height = layout_info->ctrlHeight; if ((item->type == JFORM_CTYPE_LIST_MULTI) || (item->type == JFORM_CTYPE_TEXT_MULTI)) height *= 3; SetRect(&rcCtrl, indent, rcLabel.bottom, layout_info->width, rcLabel.bottom + height); } else if (item->type == JFORM_CTYPE_BOOLEAN) { SetRect(&rcCtrl, 0, 0, layout_info->width-20, 0); HDC hdc = GetDC( item->hCtrl ); HFONT hfntSave = (HFONT)SelectObject(hdc, (HFONT)SendMessage(item->hCtrl, WM_GETFONT, 0, 0)); DrawText( hdc, labelStr, -1, &rcCtrl, DT_CALCRECT|DT_RIGHT|DT_WORDBREAK ); SelectObject(hdc, hfntSave); ReleaseDC(item->hCtrl, hdc); rcCtrl.right += 20; } else if (item->type == JFORM_CTYPE_FIXED) { SetRect(&rcCtrl, 0, 0, layout_info->width, 0); HDC hdc = GetDC( item->hCtrl ); HFONT hfntSave = (HFONT)SelectObject(hdc, (HFONT)SendMessage(item->hCtrl, WM_GETFONT, 0, 0)); DrawText( hdc, valueStr, -1, &rcCtrl, DT_CALCRECT|DT_EDITCONTROL ); rcCtrl.right += 20; SelectObject(hdc, hfntSave); ReleaseDC(item->hCtrl, hdc); } else { SetRect(&rcCtrl, rcLabel.right+5, 0, layout_info->width, layout_info->ctrlHeight); rcLabel.bottom = rcCtrl.bottom; } if (item->hLabel) SetWindowPos(item->hLabel, 0, 0, 0, rcLabel.right-rcLabel.left, rcLabel.bottom-rcLabel.top, SWP_NOZORDER|SWP_NOMOVE); if (item->hCtrl) SetWindowPos(item->hCtrl, 0, 0, 0, rcCtrl.right-rcCtrl.left, rcCtrl.bottom-rcCtrl.top, SWP_NOZORDER|SWP_NOMOVE); item->ptLabel.x = rcLabel.left; item->ptLabel.y = rcLabel.top; item->ptCtrl.x = rcCtrl.left; item->ptCtrl.y = rcCtrl.top; item->szBlock.cx = layout_info->width; item->szBlock.cy = max(rcLabel.bottom, rcCtrl.bottom); } #define JabberFormCreateLabel() \ CreateWindow( _T("static"), labelStr, WS_CHILD|WS_VISIBLE|SS_CENTERIMAGE, \ 0, 0, 0, 0, hwndStatic, ( HMENU )-1, hInst, NULL ) TJabberFormControlInfo *JabberFormAppendControl(HWND hwndStatic, TJabberFormLayoutInfo *layout_info, TJabberFormControlType type, const TCHAR *labelStr, const TCHAR *valueStr) { TJabberFormControlList *controls = (TJabberFormControlList *)GetWindowLongPtr(hwndStatic, GWLP_USERDATA); if (!controls) { controls = new TJabberFormControlList(5); SetWindowLongPtr(hwndStatic, GWLP_USERDATA, (LONG_PTR)controls); } TJabberFormControlInfo *item = (TJabberFormControlInfo *)mir_alloc(sizeof(TJabberFormControlInfo)); item->type = type; item->hLabel = item->hCtrl = NULL; switch (type) { case JFORM_CTYPE_TEXT_PRIVATE: { item->hLabel = JabberFormCreateLabel(); item->hCtrl = CreateWindowEx( WS_EX_CLIENTEDGE, _T("edit"), valueStr, WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_LEFT|ES_AUTOHSCROLL|ES_PASSWORD, 0, 0, 0, 0, hwndStatic, ( HMENU ) layout_info->id, hInst, NULL ); ++layout_info->id; break; } case JFORM_CTYPE_TEXT_MULTI: { item->hLabel = JabberFormCreateLabel(); item->hCtrl = CreateWindowEx( WS_EX_CLIENTEDGE, _T("edit"), valueStr, WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_VSCROLL|ES_LEFT|ES_MULTILINE|ES_AUTOVSCROLL|ES_WANTRETURN, 0, 0, 0, 0, hwndStatic, ( HMENU ) layout_info->id, hInst, NULL ); WNDPROC oldWndProc = ( WNDPROC ) SetWindowLongPtr( item->hCtrl, GWLP_WNDPROC, ( LONG_PTR )JabberFormMultiLineWndProc ); SetWindowLongPtr( item->hCtrl, GWLP_USERDATA, ( LONG_PTR ) oldWndProc ); ++layout_info->id; break; } case JFORM_CTYPE_BOOLEAN: { item->hCtrl = CreateWindowEx( 0, _T("button"), labelStr, WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX|BS_MULTILINE, 0, 0, 0, 0, hwndStatic, ( HMENU ) layout_info->id, hInst, NULL ); if ( valueStr && !_tcscmp( valueStr, _T("1"))) SendMessage( item->hCtrl, BM_SETCHECK, 1, 0 ); ++layout_info->id; break; } case JFORM_CTYPE_LIST_SINGLE: { item->hLabel = JabberFormCreateLabel(); item->hCtrl = CreateWindowExA( WS_EX_CLIENTEDGE, "combobox", NULL, WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST, 0, 0, 0, 0, hwndStatic, ( HMENU ) layout_info->id, hInst, NULL ); ++layout_info->id; break; } case JFORM_CTYPE_LIST_MULTI: { item->hLabel = JabberFormCreateLabel(); item->hCtrl = CreateWindowExA( WS_EX_CLIENTEDGE, "listbox", NULL, WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_MULTIPLESEL, 0, 0, 0, 0, hwndStatic, ( HMENU ) layout_info->id, hInst, NULL ); ++layout_info->id; break; } case JFORM_CTYPE_FIXED: { item->hCtrl = CreateWindow( _T("edit"), valueStr, WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY|ES_AUTOHSCROLL, 0, 0, 0, 0, hwndStatic, ( HMENU )-1, hInst, NULL ); break; } case JFORM_CTYPE_HIDDEN: { break; } case JFORM_CTYPE_TEXT_SINGLE: { item->hLabel = labelStr ? (JabberFormCreateLabel()) : NULL; item->hCtrl = CreateWindowEx( WS_EX_CLIENTEDGE, _T("edit"), valueStr, WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_LEFT|ES_AUTOHSCROLL, 0, 0, 0, 0, hwndStatic, ( HMENU ) layout_info->id, hInst, NULL ); ++layout_info->id; break; } } HFONT hFont = ( HFONT ) SendMessage( GetParent(hwndStatic), WM_GETFONT, 0, 0 ); if (item->hLabel) SendMessage( item->hLabel, WM_SETFONT, ( WPARAM ) hFont, 0 ); if (item->hCtrl) SendMessage( item->hCtrl, WM_SETFONT, ( WPARAM ) hFont, 0 ); JabberFormLayoutSingleControl(item, layout_info, labelStr, valueStr); controls->insert(item); return item; } void JabberFormAddListItem(TJabberFormControlInfo *item, TCHAR *text, bool selected) { DWORD dwIndex; switch (item->type) { case JFORM_CTYPE_LIST_MULTI: dwIndex = SendMessage(item->hCtrl, LB_ADDSTRING, 0, (LPARAM)text); if (selected) SendMessage(item->hCtrl, LB_SETSEL, TRUE, dwIndex); break; case JFORM_CTYPE_LIST_SINGLE: dwIndex = SendMessage(item->hCtrl, CB_ADDSTRING, 0, (LPARAM)text); if (selected) SendMessage(item->hCtrl, CB_SETCURSEL, dwIndex, 0); break; } } void JabberFormLayoutControls(HWND hwndStatic, TJabberFormLayoutInfo *layout_info, int *formHeight) { TJabberFormControlList *controls = (TJabberFormControlList *)GetWindowLongPtr(hwndStatic, GWLP_USERDATA); if (!controls) return; for (int i = 0; i < controls->getCount(); ++i) { if ((*controls)[i]->hLabel) SetWindowPos((*controls)[i]->hLabel, 0, layout_info->offset+(*controls)[i]->ptLabel.x, layout_info->y_pos+(*controls)[i]->ptLabel.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE); if ((*controls)[i]->hCtrl) SetWindowPos((*controls)[i]->hCtrl, 0, layout_info->offset+(*controls)[i]->ptCtrl.x, layout_info->y_pos+(*controls)[i]->ptCtrl.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE); layout_info->y_pos += (*controls)[i]->szBlock.cy; layout_info->y_pos += layout_info->y_spacing; } *formHeight = layout_info->y_pos + (layout_info->compact ? 0 : 9); } HJFORMLAYOUT JabberFormCreateLayout(HWND hwndStatic) { RECT frameRect; GetClientRect( hwndStatic, &frameRect ); TJabberFormLayoutInfo *layout_info = (TJabberFormLayoutInfo *)mir_alloc(sizeof(TJabberFormLayoutInfo)); layout_info->compact = false; layout_info->ctrlHeight = 20; layout_info->id = 0; layout_info->width = frameRect.right - frameRect.left - 20 - 10; layout_info->y_spacing = 5; layout_info->maxLabelWidth = layout_info->width*2/5; layout_info->offset = 10; layout_info->y_pos = 14; return layout_info; } void JabberFormCreateUI( HWND hwndStatic, HXML xNode, int *formHeight, BOOL bCompact ) { JabberFormDestroyUI(hwndStatic); HXML v, o, vs; int i, j, k; const TCHAR* label, *typeName, *varStr, *str, *valueText; TCHAR *labelStr, *valueStr, *p; RECT frameRect; if ( xNode==NULL || xmlGetName( xNode )==NULL || lstrcmp( xmlGetName( xNode ), _T("x")) || hwndStatic==NULL ) return; GetClientRect( hwndStatic, &frameRect ); TJabberFormLayoutInfo layout_info; layout_info.compact = bCompact ? true : false; layout_info.ctrlHeight = 20; layout_info.id = 0; layout_info.width = frameRect.right - frameRect.left - 20; if (!bCompact) layout_info.width -= 10; layout_info.y_spacing = bCompact ? 1 : 5; layout_info.maxLabelWidth = layout_info.width*2/5; layout_info.offset = 10; layout_info.y_pos = bCompact ? 0 : 14; for ( i=0; ; i++ ) { HXML n = xmlGetChild( xNode ,i); if ( !n ) break; if ( xmlGetName( n )) { if ( !lstrcmp( xmlGetName( n ), _T("field"))) { varStr = xmlGetAttrValue( n, _T("var")); if (( typeName = xmlGetAttrValue( n, _T("type"))) != NULL ) { if (( label = xmlGetAttrValue( n, _T("label"))) != NULL ) labelStr = mir_tstrdup( label ); else labelStr = mir_tstrdup( varStr ); TJabberFormControlType type = JabberFormTypeNameToId(typeName); if (( v = xmlGetChild( n , "value" )) != NULL ) { valueText = xmlGetText( v ); if (type != JFORM_CTYPE_TEXT_MULTI) { valueStr = mir_tstrdup( valueText ); } else { size_t size = 1; for ( j=0; ; j++ ) { v = xmlGetChild( n ,j); if ( !v ) break; if ( xmlGetName( v ) && !lstrcmp( xmlGetName( v ), _T("value")) && xmlGetText( v )) size += _tcslen( xmlGetText( v )) + 2; } valueStr = ( TCHAR* )mir_alloc( sizeof(TCHAR)*size ); valueStr[0] = '\0'; for ( j=0; ; j++ ) { v = xmlGetChild( n ,j); if ( !v ) break; if ( xmlGetName( v ) && !lstrcmp( xmlGetName( v ), _T("value")) && xmlGetText( v )) { if ( valueStr[0] ) _tcscat( valueStr, _T("\r\n")); _tcscat( valueStr, xmlGetText( v )); } } } } else { valueText = valueStr = NULL; } TJabberFormControlInfo *item = JabberFormAppendControl(hwndStatic, &layout_info, type, labelStr, valueStr); mir_free( labelStr ); mir_free( valueStr ); if (type == JFORM_CTYPE_LIST_SINGLE) { for ( j=0; ; j++ ) { o = xmlGetChild( n ,j); if ( !o ) break; if ( xmlGetName( o ) && !lstrcmp( xmlGetName( o ), _T("option"))) { if (( v = xmlGetChild( o , "value" )) != NULL && xmlGetText( v )) { if (( str = xmlGetAttrValue( o, _T("label"))) == NULL ) str = xmlGetText( v ); if (( p = mir_tstrdup( str )) != NULL ) { bool selected = false; if ( valueText != NULL && !_tcscmp( valueText, xmlGetText( v ))) selected = true; JabberFormAddListItem(item, p, selected); mir_free( p ); } } } } } else if (type == JFORM_CTYPE_LIST_MULTI) { for ( j=0; ; j++ ) { o = xmlGetChild( n ,j); if ( !o ) break; if ( xmlGetName( o ) && !lstrcmp( xmlGetName( o ), _T("option"))) { if (( v = xmlGetChild( o , "value" )) != NULL && xmlGetText( v )) { if (( str = xmlGetAttrValue( o, _T("label"))) == NULL ) str = xmlGetText( v ); if (( p = mir_tstrdup( str )) != NULL ) { bool selected = false; for ( k=0; ; k++ ) { vs = xmlGetChild( n ,k); if ( !vs ) break; if ( !lstrcmp( xmlGetName( vs ), _T("value")) && xmlGetText( vs ) && !_tcscmp( xmlGetText( vs ), xmlGetText( v ))) { selected = true; break; } } JabberFormAddListItem( item, p, selected ); mir_free( p ); } } } } } } } } } JabberFormLayoutControls(hwndStatic, &layout_info, formHeight); } void JabberFormDestroyUI(HWND hwndStatic) { TJabberFormControlList *controls = (TJabberFormControlList *)GetWindowLongPtr(hwndStatic, GWLP_USERDATA); if (controls) { for ( int i = 0; i < controls->getCount(); i++ ) mir_free((*controls)[i]); controls->destroy(); delete controls; SetWindowLongPtr(hwndStatic, GWLP_USERDATA, 0); } } HXML JabberFormGetData( HWND hwndStatic, HXML xNode ) { HWND hFrame, hCtrl; HXML n, v, o; int id, j, k, len; const TCHAR *varName, *type, *fieldStr, *labelText, *str2; TCHAR *p, *q, *str; if ( xNode == NULL || xmlGetName( xNode ) == NULL || lstrcmp( xmlGetName( xNode ), _T("x")) || hwndStatic == NULL ) return NULL; hFrame = hwndStatic; id = 0; XmlNode x( _T("x")); x << XATTR( _T("xmlns"), _T(JABBER_FEAT_DATA_FORMS)) << XATTR( _T("type"), _T("submit")); for ( int i=0; ; i++ ) { n = xmlGetChild( xNode ,i); if ( !n ) break; fieldStr = NULL; if ( lstrcmp( xmlGetName( n ), _T("field"))) continue; if (( varName = xmlGetAttrValue( n, _T("var"))) == NULL || ( type = xmlGetAttrValue( n, _T("type"))) == NULL ) continue; hCtrl = GetDlgItem( hFrame, id ); HXML field = x << XCHILD( _T("field")) << XATTR( _T("var"), varName ); if ( !_tcscmp( type, _T("text-multi")) || !_tcscmp( type, _T("jid-multi"))) { len = GetWindowTextLength( GetDlgItem( hFrame, id )); str = ( TCHAR* )mir_alloc( sizeof(TCHAR)*( len+1 )); GetDlgItemText( hFrame, id, str, len+1 ); p = str; while ( p != NULL ) { if (( q = _tcsstr( p, _T("\r\n"))) != NULL ) *q = '\0'; field << XCHILD( _T("value"), p ); p = q ? q+2 : NULL; } mir_free( str ); id++; } else if ( !_tcscmp( type, _T("boolean"))) { TCHAR buf[ 10 ]; _itot( IsDlgButtonChecked( hFrame, id ) == BST_CHECKED ? 1 : 0, buf, 10 ); field << XCHILD( _T("value"), buf ); id++; } else if ( !_tcscmp( type, _T("list-single"))) { len = GetWindowTextLength( GetDlgItem( hFrame, id )); str = ( TCHAR* )mir_alloc( sizeof( TCHAR )*( len+1 )); GetDlgItemText( hFrame, id, str, len+1 ); v = NULL; for ( j=0; ; j++ ) { o = xmlGetChild( n ,j); if ( !o ) break; if ( !lstrcmp( xmlGetName( o ), _T("option"))) { if (( v = xmlGetChild( o , "value" )) != NULL && xmlGetText( v )) { if (( str2 = xmlGetAttrValue( o, _T("label"))) == NULL ) str2 = xmlGetText( v ); if ( !lstrcmp( str2, str )) break; } } } if ( o ) field << XCHILD( _T("value"), xmlGetText( v )); mir_free( str ); id++; } else if ( !_tcscmp( type, _T("list-multi"))) { int count = SendMessage( hCtrl, LB_GETCOUNT, 0, 0 ); for ( j=0; j 0 ) { // an entry is selected len = SendMessage( hCtrl, LB_GETTEXTLEN, j, 0 ); if (( str = ( TCHAR* )mir_alloc(( len+1 )*sizeof( TCHAR ))) != NULL ) { SendMessage( hCtrl, LB_GETTEXT, j, ( LPARAM )str ); for ( k=0; ; k++ ) { o = xmlGetChild( n ,k); if ( !o ) break; if ( xmlGetName( o ) && !lstrcmp( xmlGetName( o ), _T("option"))) { if (( v = xmlGetChild( o , "value" )) != NULL && xmlGetText( v )) { if (( labelText = xmlGetAttrValue( o, _T("label"))) == NULL ) labelText = xmlGetText( v ); if ( !lstrcmp( labelText, str )) field << XCHILD( _T("value"), xmlGetText( v )); } } } mir_free( str ); } } } id++; } else if ( !_tcscmp( type, _T("fixed")) || !_tcscmp( type, _T("hidden"))) { v = xmlGetChild( n , "value" ); if ( v != NULL && xmlGetText( v ) != NULL ) field << XCHILD( _T("value"), xmlGetText( v )); } else { // everything else is considered "text-single" or "text-private" len = GetWindowTextLength( GetDlgItem( hFrame, id )); str = ( TCHAR* )mir_alloc( sizeof(TCHAR)*( len+1 )); GetDlgItemText( hFrame, id, str, len+1 ); field << XCHILD( _T("value"), str ); mir_free( str ); id++; } } return xi.copyNode( x ); } struct JABBER_FORM_INFO { ~JABBER_FORM_INFO(); CJabberProto* ppro; HXML xNode; TCHAR defTitle[128]; // Default title if no in xNode RECT frameRect; // Clipping region of the frame to scroll int frameHeight; // Height of the frame ( can be eliminated, redundant to frameRect ) int formHeight; // Actual height of the form int curPos; // Current scroll position JABBER_FORM_SUBMIT_FUNC pfnSubmit; void *userdata; }; static INT_PTR CALLBACK JabberFormDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { JABBER_FORM_INFO *jfi; switch ( msg ) { case WM_INITDIALOG: { HXML n; LONG frameExStyle; // lParam is ( JABBER_FORM_INFO * ) TranslateDialogDefault( hwndDlg ); ShowWindow( GetDlgItem( hwndDlg, IDC_FRAME_TEXT ), SW_HIDE ); jfi = ( JABBER_FORM_INFO * ) lParam; if ( jfi != NULL ) { // Set dialog title if ( jfi->xNode!=NULL && ( n = xmlGetChild( jfi->xNode , "title" )) != NULL && xmlGetText( n ) != NULL ) SetWindowText( hwndDlg, xmlGetText( n )); else if ( jfi->defTitle != NULL ) SetWindowText( hwndDlg, TranslateTS( jfi->defTitle )); // Set instruction field if ( jfi->xNode!=NULL && ( n = xmlGetChild( jfi->xNode , "instructions" )) != NULL && xmlGetText( n ) != NULL ) JabberFormSetInstruction( hwndDlg, xmlGetText( n )); else { if ( jfi->xNode != NULL && ( n = xmlGetChild( jfi->xNode , "title" )) != NULL && xmlGetText( n ) != NULL ) JabberFormSetInstruction( hwndDlg, xmlGetText( n )); else if ( jfi->defTitle != NULL ) JabberFormSetInstruction( hwndDlg, TranslateTS( jfi->defTitle )); } // Create form if ( jfi->xNode != NULL ) { RECT rect; GetClientRect( GetDlgItem( hwndDlg, IDC_FRAME ), &( jfi->frameRect )); GetClientRect( GetDlgItem( hwndDlg, IDC_VSCROLL ), &rect ); jfi->frameRect.right -= ( rect.right - rect.left ); GetClientRect( GetDlgItem( hwndDlg, IDC_FRAME ), &rect ); jfi->frameHeight = rect.bottom - rect.top; JabberFormCreateUI( GetDlgItem( hwndDlg, IDC_FRAME ), jfi->xNode, &( jfi->formHeight )); } } if ( jfi->formHeight > jfi->frameHeight ) { HWND hwndScroll; hwndScroll = GetDlgItem( hwndDlg, IDC_VSCROLL ); EnableWindow( hwndScroll, TRUE ); SetScrollRange( hwndScroll, SB_CTL, 0, jfi->formHeight - jfi->frameHeight, FALSE ); jfi->curPos = 0; } // Enable WS_EX_CONTROLPARENT on IDC_FRAME ( so tab stop goes through all its children ) frameExStyle = GetWindowLongPtr( GetDlgItem( hwndDlg, IDC_FRAME ), GWL_EXSTYLE ); frameExStyle |= WS_EX_CONTROLPARENT; SetWindowLongPtr( GetDlgItem( hwndDlg, IDC_FRAME ), GWL_EXSTYLE, frameExStyle ); SetWindowLongPtr( hwndDlg, GWLP_USERDATA, ( LONG_PTR ) jfi ); if ( jfi->pfnSubmit != NULL ) EnableWindow( GetDlgItem( hwndDlg, IDC_SUBMIT ), TRUE ); } return TRUE; case WM_CTLCOLORSTATIC: if ((GetWindowLongPtr((HWND)lParam, GWL_ID) == IDC_WHITERECT) || (GetWindowLongPtr((HWND)lParam, GWL_ID) == IDC_INSTRUCTION) || (GetWindowLongPtr((HWND)lParam, GWL_ID) == IDC_TITLE)) { return (INT_PTR)GetStockObject(WHITE_BRUSH); } return NULL; case WM_MOUSEWHEEL: { int zDelta = GET_WHEEL_DELTA_WPARAM( wParam ); if ( zDelta ) { int nScrollLines=0; SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, (void*)&nScrollLines, 0 ); for (int i = 0; i < ( nScrollLines + 1 ) / 2; i++ ) SendMessage( hwndDlg, WM_VSCROLL, ( zDelta < 0 ) ? SB_LINEDOWN : SB_LINEUP, 0 ); } } break; case WM_VSCROLL: jfi = ( JABBER_FORM_INFO * ) GetWindowLongPtr( hwndDlg, GWLP_USERDATA ); if ( jfi != NULL ) { int pos = jfi->curPos; switch ( LOWORD( wParam )) { case SB_LINEDOWN: pos += 15; break; case SB_LINEUP: pos -= 15; break; case SB_PAGEDOWN: pos += ( jfi->frameHeight - 10 ); break; case SB_PAGEUP: pos -= ( jfi->frameHeight - 10 ); break; case SB_THUMBTRACK: pos = HIWORD( wParam ); break; } if ( pos > ( jfi->formHeight - jfi->frameHeight )) pos = jfi->formHeight - jfi->frameHeight; if ( pos < 0 ) pos = 0; if ( jfi->curPos != pos ) { ScrollWindow( GetDlgItem( hwndDlg, IDC_FRAME ), 0, jfi->curPos - pos, NULL, &( jfi->frameRect )); SetScrollPos( GetDlgItem( hwndDlg, IDC_VSCROLL ), SB_CTL, pos, TRUE ); jfi->curPos = pos; } } break; case WM_COMMAND: switch ( LOWORD( wParam )) { case IDC_SUBMIT: jfi = ( JABBER_FORM_INFO * ) GetWindowLongPtr( hwndDlg, GWLP_USERDATA ); if ( jfi != NULL ) { HXML n = JabberFormGetData( GetDlgItem( hwndDlg, IDC_FRAME ), jfi->xNode ); ( jfi->ppro->*(jfi->pfnSubmit))( n, jfi->userdata ); xi.destroyNode( n ); } // fall through case IDCANCEL: case IDCLOSE: DestroyWindow( hwndDlg ); return TRUE; } break; case WM_CLOSE: DestroyWindow( hwndDlg ); break; case WM_DESTROY: JabberFormDestroyUI( GetDlgItem( hwndDlg, IDC_FRAME )); jfi = ( JABBER_FORM_INFO * ) GetWindowLongPtr( hwndDlg, GWLP_USERDATA ); delete jfi; break; } return FALSE; } static VOID CALLBACK JabberFormCreateDialogApcProc( void* param ) { CreateDialogParam( hInst, MAKEINTRESOURCE( IDD_FORM ), NULL, JabberFormDlgProc, ( LPARAM )param ); } void CJabberProto::FormCreateDialog( HXML xNode, TCHAR* defTitle, JABBER_FORM_SUBMIT_FUNC pfnSubmit, void *userdata ) { JABBER_FORM_INFO *jfi = new JABBER_FORM_INFO; memset( jfi, 0, sizeof( JABBER_FORM_INFO )); jfi->ppro = this; jfi->xNode = xi.copyNode( xNode ); if ( defTitle ) _tcsncpy( jfi->defTitle, defTitle, SIZEOF( jfi->defTitle )); jfi->pfnSubmit = pfnSubmit; jfi->userdata = userdata; CallFunctionAsync( JabberFormCreateDialogApcProc, jfi ); } //======================================================================================= JABBER_FORM_INFO::~JABBER_FORM_INFO() { xi.destroyNode( xNode ); mir_free( userdata ); }