diff options
author | George Hazan <ghazan@miranda.im> | 2019-02-23 15:06:01 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-02-23 15:06:01 +0300 |
commit | 4080ed23db3d8463c9c6aceddd3670dbed9c379e (patch) | |
tree | ce80831675532fe2de97072b23ebbb895ec4cdc0 /protocols/JabberG | |
parent | dffa41d2751a0ae5c05a2943107abffc48fcf0dd (diff) |
Jabber:
- fixes #1844 (Tab button doesn't work in Jabber registration form);
- added Escape handler for any dynamic form to inform parent dialog;
- massive dynamic forms-related XML code cleaning & reordering;
- now form fiields without types are also processed;
- vertical scrollbar is hidden if it's not needed;
- hidden fields do not eat form space anymore
Diffstat (limited to 'protocols/JabberG')
-rw-r--r-- | protocols/JabberG/res/jabber.rc | 9 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_adhoc.cpp | 10 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_agent.cpp | 30 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_form.cpp | 793 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_iqid_muc.cpp | 8 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_proto.h | 16 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_search.cpp | 3 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_strm_mgmt.h | 2 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_thread.cpp | 16 | ||||
-rw-r--r-- | protocols/JabberG/src/resource.h | 1 | ||||
-rwxr-xr-x | protocols/JabberG/src/stdafx.h | 61 |
11 files changed, 471 insertions, 478 deletions
diff --git a/protocols/JabberG/res/jabber.rc b/protocols/JabberG/res/jabber.rc index d11d1ea9c9..1d65978c6a 100644 --- a/protocols/JabberG/res/jabber.rc +++ b/protocols/JabberG/res/jabber.rc @@ -182,11 +182,10 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN
CONTROL "",IDC_WHITERECT,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,0,0,258,25
LTEXT "Instruction:",IDC_TITLE,7,7,243,8,NOT WS_GROUP
- EDITTEXT IDC_INSTRUCTION,17,17,233,1,ES_MULTILINE | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INSTRUCTION,17,17,233,1,ES_MULTILINE | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
CONTROL "",IDC_FRAME1,"Static",SS_ETCHEDHORZ,0,26,258,1
CONTROL "",IDC_FRAME2,"Static",SS_ETCHEDHORZ,0,197,258,1
- LTEXT "",IDC_FRAME,0,27,250,169,NOT WS_GROUP
- EDITTEXT IDC_FRAME_TEXT,18,101,220,33,ES_CENTER | ES_MULTILINE | ES_READONLY | NOT WS_BORDER
+ LTEXT "",IDC_FRAME,0,28,250,168,WS_TABSTOP
SCROLLBAR IDC_VSCROLL,246,28,11,167,SBS_VERT
DEFPUSHBUTTON "Submit",IDC_SUBMIT,146,203,50,14,WS_DISABLED
PUSHBUTTON "Cancel",IDCANCEL,200,203,50,14
@@ -722,6 +721,10 @@ BEGIN BOTTOMMARGIN, 61
END
+ IDD_FORM, DIALOG
+ BEGIN
+ END
+
IDD_PASSWORD, DIALOG
BEGIN
RIGHTMARGIN, 286
diff --git a/protocols/JabberG/src/jabber_adhoc.cpp b/protocols/JabberG/src/jabber_adhoc.cpp index 61fa07179d..ea7e0a3b3e 100644 --- a/protocols/JabberG/src/jabber_adhoc.cpp +++ b/protocols/JabberG/src/jabber_adhoc.cpp @@ -213,7 +213,6 @@ int CJabberProto::AdHoc_OnJAHMProcessResult(HWND hwndDlg, TiXmlElement *workNode if ((xNode = commandNode->FirstChildElement("x"))) {
// use jabber:x:data form
HWND hFrame = GetDlgItem(hwndDlg, IDC_FRAME);
- ShowWindow(GetDlgItem(hwndDlg, IDC_FRAME_TEXT), SW_HIDE);
if (auto *pszText = XmlGetChildText(xNode, "instructions"))
JabberFormSetInstruction(hwndDlg, pszText);
else if (pszText = XmlGetChildText(xNode, "title"))
@@ -225,7 +224,7 @@ int CJabberProto::AdHoc_OnJAHMProcessResult(HWND hwndDlg, TiXmlElement *workNode }
else {
// NO X FORM
- int toHide[] = { IDC_FRAME_TEXT, IDC_FRAME, IDC_VSCROLL, 0 };
+ int toHide[] = { IDC_FRAME, IDC_VSCROLL, 0 };
sttShowControls(hwndDlg, FALSE, toHide);
auto *pszText = XmlGetChildText(commandNode, "note");
@@ -258,7 +257,7 @@ int CJabberProto::AdHoc_OnJAHMProcessResult(HWND hwndDlg, TiXmlElement *workNode }
else if (!mir_strcmp(type, "error")) {
// error occurred here
- int toHide[] = { IDC_FRAME, IDC_FRAME_TEXT, IDC_VSCROLL, IDC_PREV, IDC_NEXT, IDC_COMPLETE, IDC_SUBMIT, 0 };
+ int toHide[] = { IDC_FRAME, IDC_VSCROLL, IDC_PREV, IDC_NEXT, IDC_COMPLETE, IDC_SUBMIT, 0 };
sttShowControls(hwndDlg, FALSE, toHide);
const char *code = "";
@@ -295,8 +294,7 @@ int CJabberProto::AdHoc_SubmitCommandForm(HWND hwndDlg, JabberAdHocData *dat, ch if (action)
command << XATTR("action", action);
- TiXmlElement *dataNode = JabberFormGetData(GetDlgItem(hwndDlg, IDC_FRAME), &iq, xNode);
- command->InsertEndChild(dataNode);
+ JabberFormGetData(GetDlgItem(hwndDlg, IDC_FRAME), command, xNode);
m_ThreadInfo->send(iq);
JabberFormSetInstruction(hwndDlg, TranslateU("In progress. Please Wait..."));
@@ -353,7 +351,7 @@ static INT_PTR CALLBACK JabberAdHoc_CommandDlgProc(HWND hwndDlg, UINT msg, WPARA frameExStyle |= WS_EX_CONTROLPARENT;
SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_FRAME), GWL_EXSTYLE, frameExStyle);
- int toHide[] = { IDC_FRAME, IDC_VSCROLL, IDC_PREV, IDC_NEXT, IDC_COMPLETE, IDC_FRAME_TEXT, 0 };
+ int toHide[] = { IDC_FRAME, IDC_VSCROLL, IDC_PREV, IDC_NEXT, IDC_COMPLETE, 0 };
sttShowControls(hwndDlg, FALSE, toHide);
int toShow[] = { IDC_INSTRUCTION, IDC_SUBMIT, IDCANCEL, 0 };
diff --git a/protocols/JabberG/src/jabber_agent.cpp b/protocols/JabberG/src/jabber_agent.cpp index 61a7176bba..87d9fe01cd 100644 --- a/protocols/JabberG/src/jabber_agent.cpp +++ b/protocols/JabberG/src/jabber_agent.cpp @@ -87,6 +87,7 @@ class CAgentRegDlg : public CJabberDlgBase char *m_jid;
CCtrlButton m_submit;
+ HWND m_statusBar;
public:
CAgentRegDlg(CJabberProto *_ppro, char *_jid) :
@@ -104,7 +105,10 @@ public: m_proto->m_hwndAgentRegInput = m_hwnd;
SetWindowText(m_hwnd, TranslateT("Jabber Agent Registration"));
SetDlgItemText(m_hwnd, IDC_SUBMIT, TranslateT("Register"));
- SetDlgItemText(m_hwnd, IDC_FRAME_TEXT, TranslateT("Please wait..."));
+
+ m_statusBar = CreateWindowExW(0, STATUSCLASSNAME, nullptr, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, m_hwnd, nullptr, g_plugin.getInst(), nullptr);
+ SendMessage(m_statusBar, WM_SIZE, 0, 0);
+ SetWindowTextW(m_statusBar, TranslateT("Please wait..."));
m_proto->m_ThreadInfo->send(
XmlNodeIq(m_proto->AddIQ(&CJabberProto::OnIqResultGetRegister, JABBER_IQ_TYPE_GET, m_jid))
@@ -139,8 +143,8 @@ public: case WM_JABBER_REGINPUT_ACTIVATE:
if (wParam == 1) { // success
// lParam = <iq/> node from agent JID as a result of "get jabber:iq:register"
- HWND hFrame = GetDlgItem(m_hwnd, IDC_FRAME);
- ShowWindow(GetDlgItem(m_hwnd, IDC_FRAME_TEXT), SW_HIDE);
+ HWND hwndFrame = GetDlgItem(m_hwnd, IDC_FRAME);
+ SetWindowTextW(m_statusBar, L"");
if ((m_agentRegIqNode = (TiXmlElement*)lParam) == nullptr)
return TRUE;
@@ -164,11 +168,11 @@ public: if (const char *pszText = XmlGetChildText(xNode, "instructions"))
JabberFormSetInstruction(m_hwnd, pszText);
- JabberFormCreateUI(hFrame, xNode, &m_formHeight /*dummy*/);
+ JabberFormCreateUI(hwndFrame, xNode, &m_formHeight);
}
else {
// use old registration information form
- HJFORMLAYOUT layout_info = JabberFormCreateLayout(hFrame);
+ TJabberFormLayoutInfo layout_info(hwndFrame, false);
for (auto *n : TiXmlEnum(queryNode)) {
const char *pszName = n->Name();
if (pszName) {
@@ -179,13 +183,12 @@ public: // do nothing
}
else if (!mir_strcmp(pszName, "password"))
- JabberFormAppendControl(hFrame, layout_info, JFORM_CTYPE_TEXT_PRIVATE, pszName, n->GetText());
+ layout_info.AppendControl(JFORM_CTYPE_TEXT_PRIVATE, pszName, n->GetText());
else // everything else is a normal text field
- JabberFormAppendControl(hFrame, layout_info, JFORM_CTYPE_TEXT_SINGLE, pszName, n->GetText());
+ layout_info.AppendControl(JFORM_CTYPE_TEXT_SINGLE, pszName, n->GetText());
}
}
- JabberFormLayoutControls(hFrame, layout_info, &m_formHeight);
- mir_free(layout_info);
+ layout_info.OrderControls(&m_formHeight);
}
if (m_formHeight > m_frameHeight) {
@@ -201,7 +204,7 @@ public: }
else if (wParam == 0) {
// lParam = error message
- SetDlgItemText(m_hwnd, IDC_FRAME_TEXT, (const wchar_t *)lParam);
+ SetWindowText(m_statusBar, (const wchar_t *)lParam);
}
return TRUE;
@@ -237,7 +240,7 @@ public: const char *from;
if ((from = m_agentRegIqNode->Attribute("from")) == nullptr) return;
if ((queryNode = m_agentRegIqNode->FirstChildElement("query")) == nullptr) return;
- HWND hFrame = GetDlgItem(m_hwnd, IDC_FRAME);
+ HWND hwndFrame = GetDlgItem(m_hwnd, IDC_FRAME);
wchar_t *str2 = (wchar_t*)alloca(sizeof(wchar_t) * 128);
int id = 0;
@@ -247,8 +250,7 @@ public: if (auto *xNode = queryNode->FirstChildElement("x")) {
// use new jabber:x:data form
- TiXmlElement *n = JabberFormGetData(hFrame, &iq, xNode);
- query->InsertEndChild(n);
+ JabberFormGetData(hwndFrame, query, xNode);
}
else {
// use old registration information form
@@ -266,7 +268,7 @@ public: // do nothing, we will skip these
}
else {
- GetDlgItemText(hFrame, id, str2, 128);
+ GetDlgItemText(hwndFrame, id, str2, 128);
XmlAddChild(query, pszName, T2Utf(str2).get());
id++;
}
diff --git a/protocols/JabberG/src/jabber_form.cpp b/protocols/JabberG/src/jabber_form.cpp index b2566ad6a0..8637f66d91 100644 --- a/protocols/JabberG/src/jabber_form.cpp +++ b/protocols/JabberG/src/jabber_form.cpp @@ -25,7 +25,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h"
#include "jabber_caps.h"
-static LRESULT CALLBACK JabberFormMultiLineWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+struct TJabberFormControlInfo : public MZeroedObject
+{
+ TJabberFormControlType type;
+ int bRequired;
+ SIZE szBlock;
+ POINT ptLabel, ptCtrl;
+ HWND hLabel, hCtrl;
+};
+
+typedef LIST<TJabberFormControlInfo> TJabberFormControlList;
+
+static LRESULT CALLBACK JabberFormItemWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_KEYDOWN:
@@ -35,75 +46,221 @@ static LRESULT CALLBACK JabberFormMultiLineWndProc(HWND hwnd, UINT msg, WPARAM w };
break;
}
- return mir_callNextSubclass(hwnd, JabberFormMultiLineWndProc, msg, wParam, lParam);
+ return mir_callNextSubclass(hwnd, JabberFormItemWndProc, msg, wParam, lParam);
}
-struct TJabberFormControlInfo
+/////////////////////////////////////////////////////////////////////////////////////////
+// TJabberFormLayoutInfo class
+
+TJabberFormLayoutInfo::TJabberFormLayoutInfo(HWND hwndCtrl, bool bCompact) :
+ m_hwnd(hwndCtrl),
+ m_bCompact(bCompact)
{
- TJabberFormControlType type;
- SIZE szBlock;
- POINT ptLabel, ptCtrl;
- HWND hLabel, hCtrl;
-};
-typedef LIST<TJabberFormControlInfo> TJabberFormControlList;
+ RECT frameRect;
+ GetClientRect(hwndCtrl, &frameRect);
+
+ m_ctrlHeight = 20;
+ m_id = 0;
+ m_width = frameRect.right - frameRect.left - 20;
+ if (!bCompact)
+ m_width -= 10;
+ m_ySpacing = bCompact ? 1 : 5;
+ m_maxLabelWidth = m_width * 2 / 5;
+ m_offset = 10;
+ m_yPos = bCompact ? 0 : 14;
+}
-struct TJabberFormLayoutInfo
+TJabberFormControlInfo* TJabberFormLayoutInfo::AppendControl(TJabberFormControlType type, const char *labelStr, const char *valueStr)
{
- int ctrlHeight;
- int offset, width, maxLabelWidth;
- int y_pos, y_spacing;
- int id;
- bool compact;
-};
+ TJabberFormControlList *controls = (TJabberFormControlList *)GetWindowLongPtr(m_hwnd, GWLP_USERDATA);
+ if (!controls) {
+ controls = new TJabberFormControlList(5);
+ SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)controls);
+ }
+
+ TJabberFormControlInfo *item = (TJabberFormControlInfo *)mir_alloc(sizeof(TJabberFormControlInfo));
+ item->type = type;
+ item->hLabel = item->hCtrl = nullptr;
+ Utf2T wszLabel(labelStr), wszValue(valueStr);
+
+ switch (type) {
+ case JFORM_CTYPE_TEXT_PRIVATE:
+ item->hLabel = CreateLabel(wszLabel);
+ item->hCtrl = CreateWindowExW(WS_EX_CLIENTEDGE, L"edit", wszValue,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD,
+ 0, 0, 0, 0,
+ m_hwnd, (HMENU)m_id, g_plugin.getInst(), nullptr);
+ ++m_id;
+ break;
+
+ case JFORM_CTYPE_TEXT_MULTI:
+ item->hLabel = CreateLabel(wszLabel);
+ item->hCtrl = CreateWindowExW(WS_EX_CLIENTEDGE, L"edit", wszValue,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN,
+ 0, 0, 0, 0,
+ m_hwnd, (HMENU)m_id, g_plugin.getInst(), nullptr);
+ ++m_id;
+ break;
-void JabberFormCenterContent(HWND hwndStatic)
+ case JFORM_CTYPE_BOOLEAN:
+ item->hCtrl = CreateWindowExW(0, L"button", wszLabel,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTOCHECKBOX | BS_MULTILINE,
+ 0, 0, 0, 0,
+ m_hwnd, (HMENU)m_id, g_plugin.getInst(), nullptr);
+ if (valueStr && !mir_wstrcmp(wszValue, L"1"))
+ SendMessage(item->hCtrl, BM_SETCHECK, 1, 0);
+ ++m_id;
+ break;
+
+ case JFORM_CTYPE_LIST_SINGLE:
+ item->hLabel = CreateLabel(wszLabel);
+ item->hCtrl = CreateWindowExW(WS_EX_CLIENTEDGE, L"combobox", nullptr,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST,
+ 0, 0, 0, 0,
+ m_hwnd, (HMENU)m_id, g_plugin.getInst(), nullptr);
+ ++m_id;
+ break;
+
+ case JFORM_CTYPE_LIST_MULTI:
+ item->hLabel = CreateLabel(wszLabel);
+ item->hCtrl = CreateWindowExW(WS_EX_CLIENTEDGE, L"listbox",
+ nullptr, WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_MULTIPLESEL,
+ 0, 0, 0, 0,
+ m_hwnd, (HMENU)m_id, g_plugin.getInst(), nullptr);
+ ++m_id;
+ break;
+
+ case JFORM_CTYPE_FIXED:
+ item->hCtrl = CreateWindowExW(0, L"edit", wszValue,
+ WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY | ES_AUTOHSCROLL,
+ 0, 0, 0, 0,
+ m_hwnd, (HMENU)-1, g_plugin.getInst(), nullptr);
+ break;
+
+ case JFORM_CTYPE_HIDDEN:
+ break;
+
+ case JFORM_CTYPE_TEXT_SINGLE:
+ item->hLabel = labelStr ? (CreateLabel(wszLabel)) : nullptr;
+ item->hCtrl = CreateWindowExW(WS_EX_CLIENTEDGE, L"edit", wszValue,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL,
+ 0, 0, 0, 0,
+ m_hwnd, (HMENU)m_id, g_plugin.getInst(), nullptr);
+ ++m_id;
+ break;
+ }
+
+ HFONT hFont = (HFONT)SendMessage(GetParent(m_hwnd), 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);
+
+ if (GetWindowStyle(item->hCtrl) & WS_TABSTOP)
+ mir_subclassWindow(item->hCtrl, JabberFormItemWndProc);
+ }
+
+ PositionControl(item, labelStr, valueStr);
+
+ controls->insert(item);
+ return item;
+}
+
+HWND TJabberFormLayoutInfo::CreateLabel(const wchar_t *pwszLabel)
{
- RECT rcWindow;
- GetWindowRect(hwndStatic, &rcWindow);
- int minX = rcWindow.right;
-
- HWND oldChild = nullptr;
- HWND hWndChild = GetWindow(hwndStatic, GW_CHILD);
- while (hWndChild != oldChild && hWndChild != nullptr) {
- DWORD style = GetWindowLongPtr(hWndChild, GWL_STYLE);
- RECT rc;
- GetWindowRect(hWndChild, &rc);
- if ((style & SS_RIGHT) && !(style & WS_TABSTOP)) {
- RECT calcRect = rc;
- int len = GetWindowTextLength(hWndChild);
- wchar_t *text = (wchar_t*)_alloca(sizeof(wchar_t)*(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);
+ return CreateWindowExW(0, L"static", pwszLabel, WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 0, 0, 0, 0, m_hwnd, (HMENU)-1, g_plugin.getInst(), nullptr);
+}
+
+void TJabberFormLayoutInfo::OrderControls(int *formHeight)
+{
+ TJabberFormControlList *controls = (TJabberFormControlList *)GetWindowLongPtr(m_hwnd, GWLP_USERDATA);
+ if (!controls)
+ return;
+
+ for (auto &it : *controls) {
+ if (it->type == JFORM_CTYPE_HIDDEN)
+ continue;
- oldChild = hWndChild;
- hWndChild = GetWindow(hWndChild, GW_HWNDNEXT);
+ if (it->hLabel)
+ SetWindowPos(it->hLabel, nullptr,
+ m_offset + it->ptLabel.x, m_yPos + it->ptLabel.y, 0, 0,
+ SWP_NOZORDER | SWP_NOSIZE);
+
+ if (it->hCtrl)
+ SetWindowPos(it->hCtrl, nullptr,
+ m_offset + it->ptCtrl.x, m_yPos + it->ptCtrl.y, 0, 0,
+ SWP_NOZORDER | SWP_NOSIZE);
+
+ m_yPos += it->szBlock.cy;
+ m_yPos += m_ySpacing;
}
- if (minX > rcWindow.left + 5) {
- int dx = (minX - rcWindow.left) / 2;
- oldChild = nullptr;
- hWndChild = GetWindow(hwndStatic, GW_CHILD);
- while (hWndChild != oldChild && hWndChild != nullptr) {
- 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);
- }
+ *formHeight = m_yPos + (m_bCompact ? 0 : 9);
+}
+
+void TJabberFormLayoutInfo::PositionControl(TJabberFormControlInfo *item, const char *labelStr, const char *valueStr)
+{
+ Utf2T wszLabel(labelStr), wszValue(valueStr);
+
+ RECT rcLabel = { 0 }, rcCtrl = { 0 };
+ if (item->hLabel) {
+ SetRect(&rcLabel, 0, 0, m_width, 0);
+ HDC hdc = GetDC(item->hLabel);
+ HFONT hfntSave = (HFONT)SelectObject(hdc, (HFONT)SendMessage(item->hLabel, WM_GETFONT, 0, 0));
+ DrawTextW(hdc, wszLabel, -1, &rcLabel, DT_CALCRECT | DT_WORDBREAK);
+ SelectObject(hdc, hfntSave);
+ ReleaseDC(item->hLabel, hdc);
+ }
+
+ int indent = m_bCompact ? 10 : 20;
+
+ if ((m_bCompact && (item->type != JFORM_CTYPE_BOOLEAN) && (item->type != JFORM_CTYPE_FIXED)) ||
+ (rcLabel.right >= m_maxLabelWidth) ||
+ (rcLabel.bottom > m_ctrlHeight) ||
+ (item->type == JFORM_CTYPE_LIST_MULTI) ||
+ (item->type == JFORM_CTYPE_TEXT_MULTI)) {
+ int height = m_ctrlHeight;
+ if ((item->type == JFORM_CTYPE_LIST_MULTI) || (item->type == JFORM_CTYPE_TEXT_MULTI)) height *= 3;
+ SetRect(&rcCtrl, indent, rcLabel.bottom, m_width, rcLabel.bottom + height);
+ }
+ else if (item->type == JFORM_CTYPE_BOOLEAN) {
+ SetRect(&rcCtrl, 0, 0, m_width - 20, 0);
+ HDC hdc = GetDC(item->hCtrl);
+ HFONT hfntSave = (HFONT)SelectObject(hdc, (HFONT)SendMessage(item->hCtrl, WM_GETFONT, 0, 0));
+ DrawText(hdc, wszLabel, -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, m_width, 0);
+ HDC hdc = GetDC(item->hCtrl);
+ HFONT hfntSave = (HFONT)SelectObject(hdc, (HFONT)SendMessage(item->hCtrl, WM_GETFONT, 0, 0));
+ DrawText(hdc, wszValue, -1, &rcCtrl, DT_CALCRECT | DT_EDITCONTROL);
+ rcCtrl.right += 20;
+ SelectObject(hdc, hfntSave);
+ ReleaseDC(item->hCtrl, hdc);
+ }
+ else {
+ SetRect(&rcCtrl, rcLabel.right + 5, 0, m_width, m_ctrlHeight);
+ rcLabel.bottom = rcCtrl.bottom;
+ }
+
+ if (item->hLabel)
+ SetWindowPos(item->hLabel, nullptr, 0, 0, rcLabel.right - rcLabel.left, rcLabel.bottom - rcLabel.top, SWP_NOZORDER | SWP_NOMOVE);
+ if (item->hCtrl)
+ SetWindowPos(item->hCtrl, nullptr, 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 = m_width;
+ item->szBlock.cy = max(rcLabel.bottom, rcCtrl.bottom);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
void JabberFormSetInstruction(HWND hwndForm, const char *text)
{
CMStringW buf(text == nullptr ? "" : text);
@@ -197,162 +354,6 @@ static TJabberFormControlType JabberFormTypeNameToId(const char *type) return JFORM_CTYPE_TEXT_SINGLE;
}
-void JabberFormLayoutSingleControl(TJabberFormControlInfo *item, TJabberFormLayoutInfo *layout_info, const char *labelStr, const char *valueStr)
-{
- Utf2T wszLabel(labelStr), wszValue(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));
- DrawTextW(hdc, wszLabel, -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, wszLabel, -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, wszValue, -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, nullptr, 0, 0, rcLabel.right - rcLabel.left, rcLabel.bottom - rcLabel.top, SWP_NOZORDER | SWP_NOMOVE);
- if (item->hCtrl)
- SetWindowPos(item->hCtrl, nullptr, 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(L"static", wszLabel, WS_CHILD|WS_VISIBLE|SS_CENTERIMAGE, \
- 0, 0, 0, 0, hwndStatic, (HMENU)-1, g_plugin.getInst(), nullptr)
-
-HJFORMCTRL JabberFormAppendControl(HWND hwndStatic, HJFORMLAYOUT layout_info, TJabberFormControlType type, const char *labelStr, const char *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 = nullptr;
- Utf2T wszLabel(labelStr), wszValue(valueStr);
-
- switch (type) {
- case JFORM_CTYPE_TEXT_PRIVATE:
- item->hLabel = JabberFormCreateLabel();
- item->hCtrl = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", wszValue,
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD,
- 0, 0, 0, 0,
- hwndStatic, (HMENU)layout_info->id, g_plugin.getInst(), nullptr);
- ++layout_info->id;
- break;
-
- case JFORM_CTYPE_TEXT_MULTI:
- item->hLabel = JabberFormCreateLabel();
- item->hCtrl = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", wszValue,
- 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, g_plugin.getInst(), nullptr);
- mir_subclassWindow(item->hCtrl, JabberFormMultiLineWndProc);
- ++layout_info->id;
- break;
-
- case JFORM_CTYPE_BOOLEAN:
- item->hCtrl = CreateWindowEx(0, L"button", wszLabel,
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTOCHECKBOX | BS_MULTILINE,
- 0, 0, 0, 0,
- hwndStatic, (HMENU)layout_info->id, g_plugin.getInst(), nullptr);
- if (valueStr && !mir_wstrcmp(wszValue, L"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", nullptr,
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST,
- 0, 0, 0, 0,
- hwndStatic, (HMENU)layout_info->id, g_plugin.getInst(), nullptr);
- ++layout_info->id;
- break;
-
- case JFORM_CTYPE_LIST_MULTI:
- item->hLabel = JabberFormCreateLabel();
- item->hCtrl = CreateWindowExA(WS_EX_CLIENTEDGE, "listbox",
- nullptr, WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_MULTIPLESEL,
- 0, 0, 0, 0,
- hwndStatic, (HMENU)layout_info->id, g_plugin.getInst(), nullptr);
- ++layout_info->id;
- break;
-
- case JFORM_CTYPE_FIXED:
- item->hCtrl = CreateWindow(L"edit", wszValue,
- WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY | ES_AUTOHSCROLL,
- 0, 0, 0, 0,
- hwndStatic, (HMENU)-1, g_plugin.getInst(), nullptr);
- break;
-
- case JFORM_CTYPE_HIDDEN:
- break;
-
- case JFORM_CTYPE_TEXT_SINGLE:
- item->hLabel = labelStr ? (JabberFormCreateLabel()) : nullptr;
- item->hCtrl = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", wszValue,
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL,
- 0, 0, 0, 0,
- hwndStatic, (HMENU)layout_info->id, g_plugin.getInst(), nullptr);
- ++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;
-}
-
static void JabberFormAddListItem(TJabberFormControlInfo *item, const char *text, bool selected)
{
Utf2T wszText(text);
@@ -371,101 +372,45 @@ static void JabberFormAddListItem(TJabberFormControlInfo *item, const char *text }
}
-void JabberFormLayoutControls(HWND hwndStatic, HJFORMLAYOUT layout_info, int *formHeight)
-{
- TJabberFormControlList *controls = (TJabberFormControlList *)GetWindowLongPtr(hwndStatic, GWLP_USERDATA);
- if (!controls) return;
-
- for (auto &it : *controls) {
- if (it->hLabel)
- SetWindowPos(it->hLabel, nullptr,
- layout_info->offset + it->ptLabel.x, layout_info->y_pos + it->ptLabel.y, 0, 0,
- SWP_NOZORDER | SWP_NOSIZE);
-
- if (it->hCtrl)
- SetWindowPos(it->hCtrl, nullptr,
- layout_info->offset + it->ptCtrl.x, layout_info->y_pos + it->ptCtrl.y, 0, 0,
- SWP_NOZORDER | SWP_NOSIZE);
-
- layout_info->y_pos += it->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, TiXmlElement *xNode, int *formHeight, BOOL bCompact)
{
JabberFormDestroyUI(hwndStatic);
- const char *typeName, *str, *valueText, *labelStr;
- char *valueStr;
-
if (xNode == nullptr || xNode->Name() == nullptr || mir_strcmp(xNode->Name(), "x") || hwndStatic == nullptr)
return;
- RECT frameRect;
- 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 (auto *n : TiXmlFilter(xNode, "field")) {
- if ((typeName = n->Attribute("type")) == nullptr)
- continue;
+ TJabberFormLayoutInfo layout_info(hwndStatic, bCompact);
- if (auto *label = n->Attribute("label"))
- labelStr = label;
- else
+ CMStringA valueStr;
+ for (auto *n : TiXmlFilter(xNode, "field")) {
+ const char *labelStr = n->Attribute("label");
+ if (labelStr == nullptr)
labelStr = n->Attribute("var");
- TJabberFormControlType type = JabberFormTypeNameToId(typeName);
+ TJabberFormControlType type = JabberFormTypeNameToId(n->Attribute("type"));
+ const char *str, *valueText;
if (auto *v = n->FirstChildElement("value")) {
valueText = v->GetText();
if (type != JFORM_CTYPE_TEXT_MULTI)
- valueStr = mir_strdup(valueText);
+ valueStr = valueText;
else {
- CMStringA tmp;
+ valueStr.Empty();
for (auto *it : TiXmlEnum(n)) {
if (it->Name() && !mir_strcmp(it->Name(), "value") && it->GetText()) {
- if (!tmp.IsEmpty())
- tmp.Append("\r\n");
- tmp.Append(it->GetText());
+ if (!valueStr.IsEmpty())
+ valueStr.Append("\r\n");
+ valueStr.Append(it->GetText());
}
}
- valueStr = tmp.Detach();
}
}
- else valueText = valueStr = nullptr;
+ else valueText = nullptr, valueStr.Empty();
- TJabberFormControlInfo *item = JabberFormAppendControl(hwndStatic, &layout_info, type, labelStr, valueStr);
+ TJabberFormControlInfo *item = layout_info.AppendControl(type, labelStr, valueStr);
- mir_free(valueStr);
+ if (n->FirstChildElement("required"))
+ item->bRequired = true;
if (type == JFORM_CTYPE_LIST_SINGLE) {
for (auto *o : TiXmlFilter(n, "option")) {
@@ -504,7 +449,7 @@ void JabberFormCreateUI(HWND hwndStatic, TiXmlElement *xNode, int *formHeight, B }
}
- JabberFormLayoutControls(hwndStatic, &layout_info, formHeight);
+ layout_info.OrderControls(formHeight);
}
void JabberFormDestroyUI(HWND hwndStatic)
@@ -518,23 +463,26 @@ void JabberFormDestroyUI(HWND hwndStatic) }
}
-TiXmlElement* JabberFormGetData(HWND hwndStatic, TiXmlDocument *doc, TiXmlElement *xNode)
+void JabberFormGetData(HWND hwndStatic, TiXmlElement *xRoot, TiXmlElement *xNode)
{
- const char *varName, *type, *labelText, *str2;
+ const char *varName, *labelText, *str2;
wchar_t *p, *q, *str;
if (xNode == nullptr || xNode->Name() == nullptr || mir_strcmp(xNode->Name(), "x") || hwndStatic == nullptr)
- return nullptr;
+ return;
HWND hFrame = hwndStatic;
int id = 0;
- XmlNode x("x");
- x << XATTR("xmlns", JABBER_FEAT_DATA_FORMS) << XATTR("type", "submit");
+ auto *x = xRoot << XCHILD("x") << XATTR("xmlns", JABBER_FEAT_DATA_FORMS) << XATTR("type", "submit");
for (auto *n : TiXmlFilter(xNode, "field")) {
- if ((varName = n->Attribute("var")) == nullptr || (type = n->Attribute("type")) == nullptr)
+ if ((varName = n->Attribute("var")) == nullptr)
continue;
+ const char *type = n->Attribute("type");
+ if (type == nullptr)
+ type = "text-single";
+
HWND hCtrl = GetDlgItem(hFrame, id);
TiXmlElement *field = x << XCHILD("field") << XATTR("var", varName);
@@ -617,164 +565,155 @@ TiXmlElement* JabberFormGetData(HWND hwndStatic, TiXmlDocument *doc, TiXmlElemen id++;
}
}
-
- return x.ToElement()->DeepClone(doc)->ToElement();
}
-class CJabberFormDlg : public CJabberDlgBase
+CJabberFormDlg::CJabberFormDlg(CJabberProto *ppro, const TiXmlElement *xNode, char *defTitle, JABBER_FORM_SUBMIT_FUNC pfnSubmit, void *userdata) :
+ CSuper(ppro, IDD_FORM),
+ btnSubmit(this, IDC_SUBMIT),
+ btnCancel(this, IDCANCEL),
+ m_pfnSubmit(pfnSubmit),
+ m_pUserdata(userdata),
+ m_defTitle(mir_strdup(defTitle))
{
- typedef CJabberDlgBase CSuper;
+ m_xNode = xNode->DeepClone(&m_doc)->ToElement();
- TiXmlDocument m_doc;
- TiXmlElement *m_xNode;
+ btnSubmit.OnClick = Callback(this, &CJabberFormDlg::onClick_Submit);
+ btnCancel.OnClick = Callback(this, &CJabberFormDlg::onClick_Cancel);
+}
- ptrA m_defTitle; // Default title if no <title/> in xNode
- JABBER_FORM_SUBMIT_FUNC m_pfnSubmit;
- void *m_pUserdata;
+bool CJabberFormDlg::OnInitDialog()
+{
+ // Set dialog title
+ if (auto *pszText = XmlGetChildText(m_xNode, "title"))
+ SetWindowTextUtf(m_hwnd, pszText);
+ else
+ SetWindowTextUtf(m_hwnd, TranslateU(m_defTitle));
+
+ // Set instruction field
+ if (auto *pszText = XmlGetChildText(m_xNode, "instructions"))
+ JabberFormSetInstruction(m_hwnd, pszText);
+ else if (pszText = XmlGetChildText(m_xNode, "title"))
+ JabberFormSetInstruction(m_hwnd, pszText);
+ else
+ JabberFormSetInstruction(m_hwnd, TranslateU(m_defTitle));
+
+ // Create form
+ if (m_xNode != nullptr) {
+ RECT rect;
+ GetClientRect(GetDlgItem(m_hwnd, IDC_FRAME), &m_frameRect);
+ GetClientRect(GetDlgItem(m_hwnd, IDC_VSCROLL), &rect);
+ m_frameRect.right -= (rect.right - rect.left);
+ GetClientRect(GetDlgItem(m_hwnd, IDC_FRAME), &rect);
+ m_frameHeight = rect.bottom - rect.top;
+ JabberFormCreateUI(GetDlgItem(m_hwnd, IDC_FRAME), m_xNode, &m_formHeight);
+ }
- RECT m_frameRect; // Clipping region of the frame to scroll
- int m_frameHeight; // Height of the frame (can be eliminated, redundant to frameRect)
- int m_formHeight; // Actual height of the form
- int m_curPos; // Current scroll position
+ m_curPos = 0;
+ HWND hwndScroll = GetDlgItem(m_hwnd, IDC_VSCROLL);
+ if (m_formHeight > m_frameHeight) {
+ EnableWindow(hwndScroll, TRUE);
+ SetScrollRange(hwndScroll, SB_CTL, 0, m_formHeight - m_frameHeight, FALSE);
+ }
+ else {
+ ShowWindow(hwndScroll, SW_HIDE);
+ SetScrollRange(hwndScroll, SB_CTL, 0, 0, FALSE);
+ }
- CCtrlButton btnSubmit;
+ // Enable WS_EX_CONTROLPARENT on IDC_FRAME (so tab stop goes through all its children)
+ LONG frameExStyle = GetWindowLongPtr(GetDlgItem(m_hwnd, IDC_FRAME), GWL_EXSTYLE);
+ frameExStyle |= WS_EX_CONTROLPARENT;
+ SetWindowLongPtr(GetDlgItem(m_hwnd, IDC_FRAME), GWL_EXSTYLE, frameExStyle);
-public:
- CJabberFormDlg(CJabberProto *ppro, const TiXmlElement *xNode, char *defTitle, JABBER_FORM_SUBMIT_FUNC pfnSubmit, void *userdata) :
- CSuper(ppro, IDD_FORM),
- btnSubmit(this, IDC_SUBMIT),
- m_pfnSubmit(pfnSubmit),
- m_pUserdata(userdata),
- m_defTitle(mir_strdup(defTitle))
- {
- m_xNode = xNode->DeepClone(&m_doc)->ToElement();
+ if (m_pfnSubmit != nullptr)
+ EnableWindow(GetDlgItem(m_hwnd, IDC_SUBMIT), TRUE);
+ return true;
+}
- btnSubmit.OnClick = Callback(this, &CJabberFormDlg::onClick_Submit);
- }
+void CJabberFormDlg::OnDestroy()
+{
+ JabberFormDestroyUI(GetDlgItem(m_hwnd, IDC_FRAME));
+ mir_free(m_pUserdata);
+}
- bool OnInitDialog() override
- {
- ShowWindow(GetDlgItem(m_hwnd, IDC_FRAME_TEXT), SW_HIDE);
-
- // Set dialog title
- if (auto *pszText = XmlGetChildText(m_xNode, "title"))
- SetWindowTextUtf(m_hwnd, pszText);
- else
- SetWindowTextUtf(m_hwnd, TranslateU(m_defTitle));
-
- // Set instruction field
- if (auto *pszText = XmlGetChildText(m_xNode, "instructions"))
- JabberFormSetInstruction(m_hwnd, pszText);
- else if (pszText = XmlGetChildText(m_xNode, "title"))
- JabberFormSetInstruction(m_hwnd, pszText);
- else
- JabberFormSetInstruction(m_hwnd, TranslateU(m_defTitle));
-
- // Create form
- if (m_xNode != nullptr) {
- RECT rect;
- GetClientRect(GetDlgItem(m_hwnd, IDC_FRAME), &(m_frameRect));
- GetClientRect(GetDlgItem(m_hwnd, IDC_VSCROLL), &rect);
- m_frameRect.right -= (rect.right - rect.left);
- GetClientRect(GetDlgItem(m_hwnd, IDC_FRAME), &rect);
- m_frameHeight = rect.bottom - rect.top;
- JabberFormCreateUI(GetDlgItem(m_hwnd, IDC_FRAME), m_xNode, &(m_formHeight));
+INT_PTR CJabberFormDlg::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ 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);
}
-
- if (m_formHeight > m_frameHeight) {
- HWND hwndScroll = GetDlgItem(m_hwnd, IDC_VSCROLL);
- EnableWindow(hwndScroll, TRUE);
- SetScrollRange(hwndScroll, SB_CTL, 0, m_formHeight - m_frameHeight, FALSE);
- m_curPos = 0;
+ return 0;
+
+ case WM_MOUSEWHEEL:
+ {
+ short 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(m_hwnd, WM_VSCROLL, (zDelta < 0) ? SB_LINEDOWN : SB_LINEUP, 0);
+ }
}
+ break;
- // Enable WS_EX_CONTROLPARENT on IDC_FRAME (so tab stop goes through all its children)
- LONG frameExStyle = GetWindowLongPtr(GetDlgItem(m_hwnd, IDC_FRAME), GWL_EXSTYLE);
- frameExStyle |= WS_EX_CONTROLPARENT;
- SetWindowLongPtr(GetDlgItem(m_hwnd, IDC_FRAME), GWL_EXSTYLE, frameExStyle);
-
- if (m_pfnSubmit != nullptr)
- EnableWindow(GetDlgItem(m_hwnd, IDC_SUBMIT), TRUE);
- return true;
- }
-
- void OnDestroy() override
- {
- JabberFormDestroyUI(GetDlgItem(m_hwnd, IDC_FRAME));
- mir_free(m_pUserdata);
- }
-
- INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override
- {
- switch (msg) {
- 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 0;
-
- case WM_MOUSEWHEEL:
- {
- short 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(m_hwnd, WM_VSCROLL, (zDelta < 0) ? SB_LINEDOWN : SB_LINEUP, 0);
- }
- }
+ case WM_VSCROLL:
+ int pos = m_curPos;
+ switch (LOWORD(wParam)) {
+ case SB_LINEDOWN:
+ pos += 15;
break;
-
- case WM_VSCROLL:
- int pos = m_curPos;
- switch (LOWORD(wParam)) {
- case SB_LINEDOWN:
- pos += 15;
- break;
- case SB_LINEUP:
- pos -= 15;
- break;
- case SB_PAGEDOWN:
- pos += (m_frameHeight - 10);
- break;
- case SB_PAGEUP:
- pos -= (m_frameHeight - 10);
- break;
- case SB_THUMBTRACK:
- pos = HIWORD(wParam);
- break;
- }
- if (pos > (m_formHeight - m_frameHeight))
- pos = m_formHeight - m_frameHeight;
- if (pos < 0)
- pos = 0;
- if (m_curPos != pos) {
- ScrollWindow(GetDlgItem(m_hwnd, IDC_FRAME), 0, m_curPos - pos, nullptr, &(m_frameRect));
- SetScrollPos(GetDlgItem(m_hwnd, IDC_VSCROLL), SB_CTL, pos, TRUE);
- m_curPos = pos;
- }
+ case SB_LINEUP:
+ pos -= 15;
+ break;
+ case SB_PAGEDOWN:
+ pos += (m_frameHeight - 10);
break;
+ case SB_PAGEUP:
+ pos -= (m_frameHeight - 10);
+ break;
+ case SB_THUMBTRACK:
+ pos = HIWORD(wParam);
+ break;
+ }
+ if (pos > (m_formHeight - m_frameHeight))
+ pos = m_formHeight - m_frameHeight;
+ if (pos < 0)
+ pos = 0;
+ if (m_curPos != pos) {
+ ScrollWindow(GetDlgItem(m_hwnd, IDC_FRAME), 0, m_curPos - pos, nullptr, &(m_frameRect));
+ SetScrollPos(GetDlgItem(m_hwnd, IDC_VSCROLL), SB_CTL, pos, TRUE);
+ m_curPos = pos;
}
- return CSuper::DlgProc(msg, wParam, lParam);
+ break;
}
+ return CSuper::DlgProc(msg, wParam, lParam);
+}
- void onClick_Submit(CCtrlButton*)
- {
- TiXmlElement *n = JabberFormGetData(GetDlgItem(m_hwnd, IDC_FRAME), &m_doc, m_xNode);
- (m_proto->*(m_pfnSubmit))(n, m_pUserdata);
- Close();
- }
-};
+void CJabberFormDlg::onClick_Submit(CCtrlButton*)
+{
+ (m_proto->*(m_pfnSubmit))(this, m_pUserdata);
+ Close();
+}
+
+void CJabberFormDlg::onClick_Cancel(CCtrlButton*)
+{
+ if (m_pfnCancel)
+ (m_proto->*(m_pfnCancel))(this, m_pUserdata);
+}
static void CALLBACK JabberFormCreateDialogApcProc(void *param)
{
((CJabberFormDlg*)param)->Show();
}
-void CJabberProto::FormCreateDialog(const TiXmlElement *xNode, char *defTitle, JABBER_FORM_SUBMIT_FUNC pfnSubmit, void *userdata)
+void CJabberFormDlg::GetData(TiXmlElement *xDest)
+{
+ JabberFormGetData(GetDlgItem(m_hwnd, IDC_FRAME), xDest, m_xNode);
+}
+
+void CJabberFormDlg::Display()
{
- auto *pDlg = new CJabberFormDlg(this, xNode, defTitle, pfnSubmit, userdata);
- CallFunctionAsync(JabberFormCreateDialogApcProc, pDlg);
+ CallFunctionAsync(JabberFormCreateDialogApcProc, this);
}
diff --git a/protocols/JabberG/src/jabber_iqid_muc.cpp b/protocols/JabberG/src/jabber_iqid_muc.cpp index 2043ac4b45..03c9fff902 100644 --- a/protocols/JabberG/src/jabber_iqid_muc.cpp +++ b/protocols/JabberG/src/jabber_iqid_muc.cpp @@ -27,12 +27,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "jabber_iq.h"
#include "jabber_caps.h"
-void CJabberProto::SetMucConfig(TiXmlElement *node, void *from)
+void CJabberProto::SetMucConfig(CJabberFormDlg *pDlg, void *from)
{
if (m_ThreadInfo && from) {
XmlNodeIq iq("set", SerialNext(), (char*)from);
- TiXmlElement *query = iq << XQUERY(JABBER_FEAT_MUC_OWNER);
- query->InsertEndChild(node);
+ auto *query = iq << XQUERY(JABBER_FEAT_MUC_OWNER);
+ pDlg->GetData(query);
m_ThreadInfo->send(iq);
}
}
@@ -50,7 +50,7 @@ void CJabberProto::OnIqResultGetMuc(const TiXmlElement *iqNode, CJabberIqInfo*) if (!mir_strcmp(type, "result"))
if (auto *queryNode = XmlGetChildByTag(iqNode, "query", "xmlns", JABBER_FEAT_MUC_OWNER))
if (auto *xNode = XmlGetChildByTag(queryNode, "x", "xmlns", JABBER_FEAT_DATA_FORMS))
- FormCreateDialog(xNode, "Jabber Conference Room Configuration", &CJabberProto::SetMucConfig, mir_strdup(from));
+ (new CJabberFormDlg(this, xNode, "Jabber Conference Room Configuration", &CJabberProto::SetMucConfig, mir_strdup(from)))->Display();
}
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index d0f42a7731..4714ce05fa 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -43,6 +43,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. struct CJabberProto;
class CJabberMucJidListDlg;
+class CJabberFormDlg;
+typedef void (CJabberProto::*JABBER_FORM_SUBMIT_FUNC)(CJabberFormDlg *pDlg, void *userdata);
+
enum TJabberGcLogInfoType { INFO_BAN, INFO_STATUS, INFO_CONFIG, INFO_AFFILIATION, INFO_ROLE };
typedef UNIQUE_MAP<wchar_t, TCharKeyCmp> U_TCHAR_MAP;
@@ -456,10 +459,6 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface void RenameParticipantNick(JABBER_LIST_ITEM *item, const char *oldNick, const TiXmlElement *itemNode);
void AcceptGroupchatInvite(const char *roomJid, const char *reason, const char *password);
- //---- jabber_form.c -----------------------------------------------------------------
-
- void FormCreateDialog(const TiXmlElement *xNode, char* defTitle, JABBER_FORM_SUBMIT_FUNC pfnSubmit, void *userdata);
-
//---- jabber_ft.c -------------------------------------------------------------------
void __cdecl FileReceiveThread(filetransfer *ft);
@@ -580,7 +579,7 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface CJabberMucJidListDlg *m_pDlgMucBanList, *m_pDlgMucAdminList, *m_pDlgMucOwnerList;
CJabberMucJidListDlg *& GetMucDlg(JABBER_MUC_JIDLIST_TYPE);
- void SetMucConfig(TiXmlElement *node, void *from);
+ void SetMucConfig(CJabberFormDlg *pDlg, void *from);
void MucShutdown(void);
void OnIqResultMucGetJidList(const TiXmlElement *iqNode, JABBER_MUC_JIDLIST_TYPE listType);
@@ -779,10 +778,6 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface void OnProcessPresence(const TiXmlElement *node, ThreadData *info);
void OnProcessPresenceCapabilites(const TiXmlElement *node, pResourceStatus &resource);
void OnProcessPubsubEvent(const TiXmlElement *node);
- //XEP-0198 specific types handlers
- void OnProcessSMa(const TiXmlElement *node, ThreadData *info);
- void OnProcessSMr(const TiXmlElement *node, ThreadData *info);
-
void OnProcessStreamOpening(const TiXmlElement *node, ThreadData *info);
void OnProcessProtocol(const TiXmlElement *node, ThreadData *info);
@@ -799,7 +794,8 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface BOOL OnProcessJingle(const TiXmlElement *node);
void OnProcessIq(const TiXmlElement *node);
- void SetRegConfig(TiXmlElement *node, void *from);
+ void SetRegConfig(CJabberFormDlg *pDlg, void *from);
+ void CancelRegConfig(CJabberFormDlg *pDlg, void *from);
void OnProcessRegIq(const TiXmlElement *node, ThreadData *info);
void OnPingReply(const TiXmlElement *node, CJabberIqInfo *pInfo);
diff --git a/protocols/JabberG/src/jabber_search.cpp b/protocols/JabberG/src/jabber_search.cpp index 5d7b2f1f1a..05e19da136 100644 --- a/protocols/JabberG/src/jabber_search.cpp +++ b/protocols/JabberG/src/jabber_search.cpp @@ -743,8 +743,7 @@ HWND CJabberProto::SearchAdvanced(HWND hwndDlg) // Forms: XEP-0055 Example 7 if (dat->fSearchRequestIsXForm) { fRequestNotEmpty = TRUE; - TiXmlElement *n = JabberFormGetData(GetDlgItem(hwndDlg, IDC_FRAME), &iq, dat->xNode); - query->InsertEndChild(n); + JabberFormGetData(GetDlgItem(hwndDlg, IDC_FRAME), query, dat->xNode); } else { //and Simple fields: XEP-0055 Example 3 for (int i = 0; i < dat->nJSInfCount; i++) { diff --git a/protocols/JabberG/src/jabber_strm_mgmt.h b/protocols/JabberG/src/jabber_strm_mgmt.h index 5c249e6fad..4bab5e4045 100755 --- a/protocols/JabberG/src/jabber_strm_mgmt.h +++ b/protocols/JabberG/src/jabber_strm_mgmt.h @@ -27,6 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. struct CJabberProto;
+// XEP-0198 processing
+
class strm_mgmt
{
void OnProcessSMa(const TiXmlElement *node);
diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index 40c40ab336..439ed33d69 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -1891,7 +1891,13 @@ void CJabberProto::OnProcessIq(const TiXmlElement *node) }
}
-void CJabberProto::SetRegConfig(TiXmlElement *node, void *from)
+void CJabberProto::CancelRegConfig(CJabberFormDlg*, void*)
+{
+ if (g_pRegInfo)
+ SendMessage(g_pRegInfo->conn.reg_hwndDlg, WM_JABBER_REGDLG_UPDATE, 100, (LPARAM)TranslateT("Registration canceled"));
+}
+
+void CJabberProto::SetRegConfig(CJabberFormDlg *pDlg, void *from)
{
if (g_pRegInfo) {
iqIdRegSetReg = SerialNext();
@@ -1901,7 +1907,7 @@ void CJabberProto::SetRegConfig(TiXmlElement *node, void *from) XmlNodeIq iq("set", iqIdRegSetReg, (const char*)from);
iq << XATTR("from", text);
TiXmlElement *query = iq << XQUERY(JABBER_FEAT_REGISTER);
- query->InsertEndChild(node);
+ pDlg->GetData(query);
g_pRegInfo->send(iq);
}
}
@@ -1924,7 +1930,11 @@ void CJabberProto::OnProcessRegIq(const TiXmlElement *node, ThreadData *info) if (xNode != nullptr) {
if (!mir_strcmp(xNode->Attribute("xmlns"), JABBER_FEAT_DATA_FORMS)) {
g_pRegInfo = info;
- FormCreateDialog(xNode, "Jabber register new user", &CJabberProto::SetRegConfig, mir_strdup(node->Attribute("from")));
+
+ auto *pDlg = new CJabberFormDlg(this, xNode, "Jabber register new user", &CJabberProto::SetRegConfig, mir_strdup(node->Attribute("from")));
+ pDlg->SetParent(info->conn.reg_hwndDlg);
+ pDlg->SetCancel(&CJabberProto::CancelRegConfig);
+ pDlg->Display();
return;
}
}
diff --git a/protocols/JabberG/src/resource.h b/protocols/JabberG/src/resource.h index c87ccee302..3c8e7fb5cf 100644 --- a/protocols/JabberG/src/resource.h +++ b/protocols/JabberG/src/resource.h @@ -105,7 +105,6 @@ #define IDC_AGENT_BROWSE 1029
#define IDC_INSTRUCTION 1030
#define IDC_FRAME 1037
-#define IDC_FRAME_TEXT 1038
#define IDC_SIMPLE 1041
#define IDC_KEEPALIVE 1042
#define IDC_HOST 1043
diff --git a/protocols/JabberG/src/stdafx.h b/protocols/JabberG/src/stdafx.h index 79dfd30f72..1700c5f231 100755 --- a/protocols/JabberG/src/stdafx.h +++ b/protocols/JabberG/src/stdafx.h @@ -511,8 +511,6 @@ struct JABBER_MUC_JIDLIST_INFO : public MZeroedObject wchar_t* type2str(void) const;
};
-typedef void (CJabberProto::*JABBER_FORM_SUBMIT_FUNC)(TiXmlElement *values, void *userdata);
-
//---- jabber_treelist.c ------------------------------------------------
typedef struct TTreeList_ItemInfo *HTREELISTITEM;
@@ -636,17 +634,64 @@ enum TJabberFormControlType JFORM_CTYPE_FIXED, JFORM_CTYPE_HIDDEN, JFORM_CTYPE_TEXT_SINGLE
};
-typedef struct TJabberFormControlInfo *HJFORMCTRL;
-typedef struct TJabberFormLayoutInfo *HJFORMLAYOUT;
+struct TJabberFormControlInfo;
+
+struct TJabberFormLayoutInfo
+{
+ TJabberFormLayoutInfo(HWND hwndCtrl, bool bCompact);
+
+ TJabberFormControlInfo* AppendControl(TJabberFormControlType type, const char *labelStr, const char *valueStr);
+ HWND CreateLabel(const wchar_t *pwszLabel);
+ void OrderControls(int *formHeight);
+ void PositionControl(TJabberFormControlInfo *item, const char *labelStr, const char *valueStr);
+
+ HWND m_hwnd;
+ int m_ctrlHeight;
+ int m_offset, m_width, m_maxLabelWidth;
+ int m_yPos, m_ySpacing;
+ int m_id;
+ bool m_bCompact;
+};
void JabberFormCreateUI(HWND hwndStatic, TiXmlElement *xNode, int *formHeight, BOOL bCompact = FALSE);
void JabberFormDestroyUI(HWND hwndStatic);
+void JabberFormGetData(HWND hwndStatic, TiXmlElement* pRoot, TiXmlElement *xNode);
void JabberFormSetInstruction(HWND hwndForm, const char *text);
-HJFORMLAYOUT JabberFormCreateLayout(HWND hwndStatic); // use mir_free to destroy
-HJFORMCTRL JabberFormAppendControl(HWND hwndStatic, HJFORMLAYOUT layout_info, TJabberFormControlType type, const char *labelStr, const char *valueStr);
-void JabberFormLayoutControls(HWND hwndStatic, HJFORMLAYOUT layout_info, int *formHeight);
-TiXmlElement* JabberFormGetData(HWND hwndStatic, TiXmlDocument *doc, TiXmlElement *xNode);
+class CJabberFormDlg : public CJabberDlgBase
+{
+ typedef CJabberDlgBase CSuper;
+
+ TiXmlDocument m_doc;
+ TiXmlElement *m_xNode;
+
+ ptrA m_defTitle; // Default title if no <title/> in xNode
+ JABBER_FORM_SUBMIT_FUNC m_pfnSubmit, m_pfnCancel = nullptr;
+ void *m_pUserdata;
+
+ RECT m_frameRect; // Clipping region of the frame to scroll
+ int m_frameHeight; // Height of the frame (can be eliminated, redundant to frameRect)
+ int m_formHeight; // Actual height of the form
+ int m_curPos; // Current scroll position
+
+ CCtrlButton btnSubmit, btnCancel;
+ void onClick_Submit(CCtrlButton*);
+ void onClick_Cancel(CCtrlButton*);
+
+public:
+ CJabberFormDlg(CJabberProto *ppro, const TiXmlElement *xNode, char *defTitle, JABBER_FORM_SUBMIT_FUNC pfnSubmit, void *userdata);
+
+ void Display();
+ void GetData(TiXmlElement *xDest);
+
+ void SetCancel(JABBER_FORM_SUBMIT_FUNC pFunc) {
+ m_pfnCancel = pFunc;
+ }
+
+ bool OnInitDialog() override;
+ void OnDestroy() override;
+ INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
+};
//---- jabber_icolib.c ----------------------------------------------
|