diff options
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/JabberG/res/jabber.rc | 2 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_opt.cpp | 553 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_proto.h | 25 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_roster.cpp | 580 | ||||
-rw-r--r-- | protocols/JabberG/src/resource.h | 2 |
5 files changed, 590 insertions, 572 deletions
diff --git a/protocols/JabberG/res/jabber.rc b/protocols/JabberG/res/jabber.rc index eb425da70b..3083e80746 100644 --- a/protocols/JabberG/res/jabber.rc +++ b/protocols/JabberG/res/jabber.rc @@ -76,7 +76,7 @@ BEGIN COMBOBOX IDC_SERVER,0,11,92,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
END
-IDD_OPT_JABBER3 DIALOGEX 0, 0, 424, 288
+IDD_ROSTER_EDITOR DIALOGEX 0, 0, 424, 288
STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_CONTROLPARENT
CAPTION "Roster Editor"
diff --git a/protocols/JabberG/src/jabber_opt.cpp b/protocols/JabberG/src/jabber_opt.cpp index 61f2491cf0..3ade180008 100755 --- a/protocols/JabberG/src/jabber_opt.cpp +++ b/protocols/JabberG/src/jabber_opt.cpp @@ -910,553 +910,6 @@ public: }
};
-//////////////////////////////////////////////////////////////////////////
-// roster editor
-//
-
-#include <io.h>
-#define JM_STATUSCHANGED WM_USER+0x0001
-#define fopent(name, mode) _wfopen(name, mode)
-
-enum
-{
- RRA_FILLLIST = 0,
- RRA_SYNCROSTER,
- RRA_SYNCDONE
-};
-
-struct ROSTEREDITDAT
-{
- HWND hList;
- int index;
- int subindex;
-};
-
-static int _RosterInsertListItem(HWND hList, const char *jid, const char *nick, const char *group, const char *subscr, BOOL bChecked)
-{
- LVITEM item = { 0 };
- item.mask = LVIF_TEXT | LVIF_STATE;
- item.iItem = ListView_GetItemCount(hList);
- item.pszText = (wchar_t*)jid;
-
- int index = ListView_InsertItem(hList, &item);
- if (index < 0)
- return index;
-
- ListView_SetCheckState(hList, index, bChecked);
-
- ListView_SetItemText(hList, index, 0, Utf2T(jid));
- ListView_SetItemText(hList, index, 1, Utf2T(nick));
- ListView_SetItemText(hList, index, 2, Utf2T(group));
- ListView_SetItemText(hList, index, 3, Utf2T(subscr));
- return index;
-}
-
-static void _RosterListClear(HWND hwndDlg)
-{
- HWND hList = GetDlgItem(hwndDlg, IDC_ROSTER);
- if (!hList)
- return;
-
- ListView_DeleteAllItems(hList);
- while (ListView_DeleteColumn(hList, 0));
-
- LV_COLUMN column = { 0 };
- column.mask = LVCF_TEXT;
- column.cx = 500;
-
- column.pszText = TranslateT("JID");
- ListView_InsertColumn(hList, 1, &column);
-
- column.pszText = TranslateT("Nickname");
- ListView_InsertColumn(hList, 2, &column);
-
- column.pszText = TranslateT("Group");
- ListView_InsertColumn(hList, 3, &column);
-
- column.pszText = TranslateT("Subscription");
- ListView_InsertColumn(hList, 4, &column);
-
- RECT rc;
- GetClientRect(hList, &rc);
- int width = rc.right - rc.left;
-
- ListView_SetColumnWidth(hList, 0, width * 40 / 100);
- ListView_SetColumnWidth(hList, 1, width * 25 / 100);
- ListView_SetColumnWidth(hList, 2, width * 20 / 100);
- ListView_SetColumnWidth(hList, 3, width * 10 / 100);
-}
-
-void CJabberProto::_RosterHandleGetRequest(const TiXmlElement *node, CJabberIqInfo*)
-{
- HWND hList = GetDlgItem(rrud.hwndDlg, IDC_ROSTER);
- if (rrud.bRRAction == RRA_FILLLIST) {
- _RosterListClear(rrud.hwndDlg);
- auto *query = XmlFirstChild(node, "query");
- if (query == nullptr) return;
-
- for (auto *item : TiXmlFilter(query, "item")) {
- const char *jid = XmlGetAttr(item, "jid");
- if (jid == nullptr)
- continue;
-
- const char *name = XmlGetAttr(item, "name");
- const char *subscription = XmlGetAttr(item, "subscription");
- const char *group = XmlGetChildText(item, "group");
- _RosterInsertListItem(hList, jid, name, group, subscription, TRUE);
- }
-
- // now it is require to process whole contact list to add not in roster contacts
- for (auto &hContact : AccContacts()) {
- ptrW tszJid(getWStringA(hContact, "jid"));
- if (tszJid == nullptr)
- continue;
-
- LVFINDINFO lvfi = { 0 };
- lvfi.flags = LVFI_STRING;
- lvfi.psz = tszJid;
- wchar_t *p = wcschr(tszJid, '@');
- if (p) {
- p = wcschr(tszJid, '/');
- if (p) *p = 0;
- }
- if (ListView_FindItem(hList, -1, &lvfi) == -1) {
- ptrA tszName(db_get_utfa(hContact, "CList", "MyHandle"));
- ptrA tszGroup(db_get_utfa(hContact, "CList", "Group"));
- _RosterInsertListItem(hList, T2Utf(tszJid), tszName, tszGroup, nullptr, FALSE);
- }
- }
- rrud.bReadyToDownload = FALSE;
- rrud.bReadyToUpload = TRUE;
- SetDlgItemText(rrud.hwndDlg, IDC_DOWNLOAD, TranslateT("Download"));
- SetDlgItemText(rrud.hwndDlg, IDC_UPLOAD, TranslateT("Upload"));
- SendMessage(rrud.hwndDlg, JM_STATUSCHANGED, 0, 0);
- return;
- }
-
- if (rrud.bRRAction == RRA_SYNCROSTER) {
- SetDlgItemText(rrud.hwndDlg, IDC_UPLOAD, TranslateT("Uploading..."));
- auto *queryRoster = XmlFirstChild(node, "query");
- if (!queryRoster)
- return;
-
- XmlNodeIq iq(AddIQ(&CJabberProto::_RosterHandleGetRequest, JABBER_IQ_TYPE_SET));
-
- TiXmlElement *query = iq << XCHILDNS("query", JABBER_FEAT_IQ_ROSTER);
-
- int itemCount = 0;
- int ListItemCount = ListView_GetItemCount(hList);
- for (int index = 0; index < ListItemCount; index++) {
- wchar_t jid[JABBER_MAX_JID_LEN] = L"";
- wchar_t name[260];
- wchar_t group[260];
- wchar_t subscr[260];
- ListView_GetItemText(hList, index, 0, jid, _countof(jid));
- ListView_GetItemText(hList, index, 1, name, _countof(name));
- ListView_GetItemText(hList, index, 2, group, _countof(group));
- ListView_GetItemText(hList, index, 3, subscr, _countof(subscr));
-
- T2Utf szJid(jid), szName(name), szGroup(group), szSubscr(subscr);
- auto *itemRoster = XmlGetChildByTag(queryRoster, "item", "jid", szJid);
- BOOL bRemove = !ListView_GetCheckState(hList, index);
- if (itemRoster && bRemove) {
- //delete item
- query << XCHILD("item") << XATTR("jid", szJid) << XATTR("subscription", "remove");
- itemCount++;
- }
- else if (!bRemove) {
- BOOL bPushed = itemRoster ? TRUE : FALSE;
- if (!bPushed) {
- const char *rosterName = XmlGetAttr(itemRoster, "name");
- if ((rosterName != nullptr || name[0] != 0) && mir_strcmpi(rosterName, szName))
- bPushed = TRUE;
- if (!bPushed) {
- rosterName = XmlGetAttr(itemRoster, "subscription");
- if ((rosterName != nullptr || subscr[0] != 0) && mir_strcmpi(rosterName, T2Utf(subscr)))
- bPushed = TRUE;
- }
- if (!bPushed) {
- auto *rosterGroup = XmlGetChildText(itemRoster, "group");
- if (rosterGroup != nullptr && mir_strcmpi(rosterGroup, szGroup))
- bPushed = TRUE;
- }
- }
- if (bPushed) {
- TiXmlElement *item = query << XCHILD("item");
- if (mir_wstrlen(group))
- item << XCHILD("group", szGroup);
- if (mir_wstrlen(name))
- item << XATTR("name", szName);
- item << XATTR("jid", szJid) << XATTR("subscription", subscr[0] ? szSubscr : "none");
- itemCount++;
- }
- }
- }
- rrud.bRRAction = RRA_SYNCDONE;
- if (itemCount)
- m_ThreadInfo->send(iq);
- else
- _RosterSendRequest(rrud.hwndDlg, RRA_FILLLIST);
- }
- else {
- SetDlgItemText(rrud.hwndDlg, IDC_UPLOAD, TranslateT("Upload"));
- rrud.bReadyToUpload = rrud.bReadyToDownload = FALSE;
- SendMessage(rrud.hwndDlg, JM_STATUSCHANGED, 0, 0);
- SetDlgItemText(rrud.hwndDlg, IDC_DOWNLOAD, TranslateT("Downloading..."));
- _RosterSendRequest(rrud.hwndDlg, RRA_FILLLIST);
- }
-}
-
-void CJabberProto::_RosterSendRequest(HWND hwndDlg, BYTE rrAction)
-{
- rrud.bRRAction = rrAction;
- rrud.hwndDlg = hwndDlg;
-
- m_ThreadInfo->send(
- XmlNodeIq(AddIQ(&CJabberProto::_RosterHandleGetRequest, JABBER_IQ_TYPE_GET))
- << XCHILDNS("query", JABBER_FEAT_IQ_ROSTER));
-}
-
-static void _RosterItemEditEnd(HWND hEditor, ROSTEREDITDAT * edat, BOOL bCancel)
-{
- if (!bCancel) {
- int len = GetWindowTextLength(hEditor) + 1;
- wchar_t *buff = (wchar_t*)mir_alloc(len*sizeof(wchar_t));
- if (buff) {
- GetWindowText(hEditor, buff, len);
- ListView_SetItemText(edat->hList, edat->index, edat->subindex, buff);
- }
- mir_free(buff);
- }
- DestroyWindow(hEditor);
-}
-
-static LRESULT CALLBACK _RosterItemNewEditProc(HWND hEditor, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- ROSTEREDITDAT * edat = (ROSTEREDITDAT *)GetWindowLongPtr(hEditor, GWLP_USERDATA);
- if (!edat) return 0;
- switch (msg) {
- case WM_KEYDOWN:
- switch (wParam) {
- case VK_RETURN:
- _RosterItemEditEnd(hEditor, edat, FALSE);
- return 0;
- case VK_ESCAPE:
- _RosterItemEditEnd(hEditor, edat, TRUE);
- return 0;
- }
- break;
-
- case WM_GETDLGCODE:
- if (lParam) {
- MSG *msg2 = (MSG*)lParam;
- if (msg2->message == WM_KEYDOWN && msg2->wParam == VK_TAB) return 0;
- if (msg2->message == WM_CHAR && msg2->wParam == '\t') return 0;
- }
- return DLGC_WANTMESSAGE;
-
- case WM_KILLFOCUS:
- _RosterItemEditEnd(hEditor, edat, FALSE);
- return 0;
-
- case WM_DESTROY:
- SetWindowLongPtr(hEditor, GWLP_USERDATA, (LONG_PTR)0);
- free(edat);
- return 0;
- }
-
- return mir_callNextSubclass(hEditor, _RosterItemNewEditProc, msg, wParam, lParam);
-}
-
-void CJabberProto::_RosterExportToFile(HWND hwndDlg)
-{
- wchar_t filename[MAX_PATH] = { 0 };
-
- wchar_t filter[MAX_PATH];
- mir_snwprintf(filter, L"%s (*.xml)%c*.xml%c%c", TranslateT("XML for MS Excel (UTF-8 encoded)"), 0, 0, 0);
- OPENFILENAME ofn = { 0 };
- ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
- ofn.hwndOwner = hwndDlg;
- ofn.hInstance = nullptr;
- ofn.lpstrFilter = filter;
- ofn.lpstrFile = filename;
- ofn.Flags = OFN_HIDEREADONLY;
- ofn.nMaxFile = _countof(filename);
- ofn.nMaxFileTitle = MAX_PATH;
- ofn.lpstrDefExt = L"xml";
- if (!GetSaveFileName(&ofn)) return;
-
- FILE * fp = fopent(filename, L"wb");
- if (!fp) return;
- HWND hList = GetDlgItem(hwndDlg, IDC_ROSTER);
- int ListItemCount = ListView_GetItemCount(hList);
-
- XmlNode root("Workbook");
- root << XATTR("xmlns", "urn:schemas-microsoft-com:office:spreadsheet")
- << XATTR("xmlns:o", "urn:schemas-microsoft-com:office:office")
- << XATTR("xmlns:x", "urn:schemas-microsoft-com:office:excel")
- << XATTR("xmlns:ss", "urn:schemas-microsoft-com:office:spreadsheet")
- << XATTR("xmlns:html", "http://www.w3.org/TR/REC-html40");
- root << XCHILD("ExcelWorkbook")
- << XATTR("xmlns", "urn:schemas-microsoft-com:office:excel");
- TiXmlElement *table = root << XCHILD("Worksheet") << XATTR("ss:Name", "Exported roster")
- << XCHILD("Table");
-
- for (int index = 0; index < ListItemCount; index++) {
- wchar_t jid[JABBER_MAX_JID_LEN] = L"";
- wchar_t name[260] = L"";
- wchar_t group[260] = L"";
- wchar_t subscr[260] = L"";
- ListView_GetItemText(hList, index, 0, jid, _countof(jid));
- ListView_GetItemText(hList, index, 1, name, _countof(name));
- ListView_GetItemText(hList, index, 2, group, _countof(group));
- ListView_GetItemText(hList, index, 3, subscr, _countof(subscr));
-
- TiXmlElement *node = table << XCHILD("Row");
- node << XCHILD("Cell") << XCHILD("Data", "+") << XATTR("ss:Type", "String");
- node << XCHILD("Cell") << XCHILD("Data", T2Utf(jid)) << XATTR("ss:Type", "String");
- node << XCHILD("Cell") << XCHILD("Data", T2Utf(name)) << XATTR("ss:Type", "String");
- node << XCHILD("Cell") << XCHILD("Data", T2Utf(group)) << XATTR("ss:Type", "String");
- node << XCHILD("Cell") << XCHILD("Data", T2Utf(subscr)) << XATTR("ss:Type", "String");
-
- }
-
- char header[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?mso-application progid=\"Excel.Sheet\"?>\n";
- fwrite(header, 1, sizeof(header) - 1 /* for zero terminator */, fp);
-
- tinyxml2::XMLPrinter printer(0);
- root.Print(&printer);
- fputs(printer.CStr(), fp);
- fclose(fp);
-}
-
-void CJabberProto::_RosterImportFromFile(HWND hwndDlg)
-{
- wchar_t filename[MAX_PATH] = { 0 };
- wchar_t *filter = L"XML for MS Excel (UTF-8 encoded)(*.xml)\0*.xml\0\0";
-
- OPENFILENAME ofn = { 0 };
- ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
- ofn.hwndOwner = hwndDlg;
- ofn.hInstance = nullptr;
- ofn.lpstrFilter = filter;
- ofn.lpstrFile = filename;
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
- ofn.nMaxFile = _countof(filename);
- ofn.nMaxFileTitle = MAX_PATH;
- ofn.lpstrDefExt = L"xml";
- if (!GetOpenFileNameW(&ofn))
- return;
-
- FILE * fp = _wfopen(filename, L"rb");
- if (!fp)
- return;
-
- TiXmlDocument doc;
- int ret = doc.LoadFile(fp);
- fclose(fp);
- if (ret != 0)
- return;
-
- _RosterListClear(hwndDlg);
-
- const TiXmlElement *Table = TiXmlConst(&doc)["Workbook"]["Worksheet"]["Table"].ToElement();
- if (Table) {
- HWND hList = GetDlgItem(hwndDlg, IDC_ROSTER);
- for (auto *Row : TiXmlFilter(Table, "Row")) {
- BOOL bAdd = FALSE;
- const char *jid = nullptr;
- const char *name = nullptr;
- const char *group = nullptr;
- const char *subscr = nullptr;
- auto *Cell = XmlFirstChild(Row, "Cell");
- auto *Data = XmlFirstChild(Cell, "Data");
- if (Data) {
- if (!mir_strcmpi(Data->GetText(), "+")) bAdd = TRUE;
- else if (mir_strcmpi(Data->GetText(), "-")) continue;
-
- Cell = Cell->NextSiblingElement("Cell");
- if (Cell) Data = XmlFirstChild(Cell, "Data");
- else Data = nullptr;
- if (Data) {
- jid = Data->GetText();
- if (!jid || mir_strlen(jid) == 0) continue;
- }
-
- Cell = Cell->NextSiblingElement("Cell");
- if (Cell) Data = XmlFirstChild(Cell, "Data");
- else Data = nullptr;
- if (Data) name = Data->GetText();
-
- Cell = Cell->NextSiblingElement("Cell");
- if (Cell) Data = XmlFirstChild(Cell, "Data");
- else Data = nullptr;
- if (Data) group = Data->GetText();
-
- Cell = Cell->NextSiblingElement("Cell");
- if (Cell) Data = XmlFirstChild(Cell, "Data");
- else Data = nullptr;
- if (Data) subscr = Data->GetText();
- }
- _RosterInsertListItem(hList, jid, name, group, subscr, bAdd);
- }
- }
-
- SendMessage(hwndDlg, JM_STATUSCHANGED, 0, 0);
-}
-
-static LRESULT CALLBACK _RosterNewListProc(HWND hList, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- if (msg == WM_MOUSEWHEEL || msg == WM_NCLBUTTONDOWN || msg == WM_NCRBUTTONDOWN)
- SetFocus(hList);
-
- if (msg == WM_LBUTTONDOWN) {
- POINT pt;
- GetCursorPos(&pt);
- ScreenToClient(hList, &pt);
-
- LVHITTESTINFO lvhti = { 0 };
- lvhti.pt = pt;
- ListView_SubItemHitTest(hList, &lvhti);
- if (lvhti.flags&LVHT_ONITEM && lvhti.iSubItem != 0) {
- RECT rc;
- wchar_t buff[260];
- ListView_GetSubItemRect(hList, lvhti.iItem, lvhti.iSubItem, LVIR_BOUNDS, &rc);
- ListView_GetItemText(hList, lvhti.iItem, lvhti.iSubItem, buff, _countof(buff));
- HWND hEditor = CreateWindow(TEXT("EDIT"), buff, WS_CHILD | ES_AUTOHSCROLL, rc.left + 3, rc.top + 2, rc.right - rc.left - 3, rc.bottom - rc.top - 3, hList, nullptr, g_plugin.getInst(), nullptr);
- SendMessage(hEditor, WM_SETFONT, (WPARAM)SendMessage(hList, WM_GETFONT, 0, 0), 0);
- ShowWindow(hEditor, SW_SHOW);
- SetWindowText(hEditor, buff);
- ClientToScreen(hList, &pt);
- ScreenToClient(hEditor, &pt);
- mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
- mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
-
- ROSTEREDITDAT * edat = (ROSTEREDITDAT *)malloc(sizeof(ROSTEREDITDAT));
- mir_subclassWindow(hEditor, _RosterItemNewEditProc);
- edat->hList = hList;
- edat->index = lvhti.iItem;
- edat->subindex = lvhti.iSubItem;
- SetWindowLongPtr(hEditor, GWLP_USERDATA, (LONG_PTR)edat);
- }
- }
- return mir_callNextSubclass(hList, _RosterNewListProc, msg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// JabberRosterOptDlgProc - advanced options dialog procedure
-
-static int sttRosterEditorResizer(HWND /*hwndDlg*/, LPARAM, UTILRESIZECONTROL *urc)
-{
- switch (urc->wId) {
- case IDC_HEADERBAR:
- return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH;
- case IDC_ROSTER:
- return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORY_HEIGHT | RD_ANCHORX_WIDTH;
- case IDC_DOWNLOAD:
- case IDC_UPLOAD:
- return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
- case IDC_EXPORT:
- case IDC_IMPORT:
- return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
- }
- return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
-}
-
-static INT_PTR CALLBACK JabberRosterOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CJabberProto *ppro = (CJabberProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- ppro = (CJabberProto*)lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
-
- TranslateDialogDefault(hwndDlg);
- Window_SetIcon_IcoLib(hwndDlg, g_GetIconHandle(IDI_AGENTS));
-
- Utils_RestoreWindowPosition(hwndDlg, 0, ppro->m_szModuleName, "rosterCtrlWnd_");
-
- ListView_SetExtendedListViewStyle(GetDlgItem(hwndDlg, IDC_ROSTER), LVS_EX_CHECKBOXES | LVS_EX_BORDERSELECT /*| LVS_EX_FULLROWSELECT*/ | LVS_EX_GRIDLINES /*| LVS_EX_HEADERDRAGDROP*/);
- mir_subclassWindow(GetDlgItem(hwndDlg, IDC_ROSTER), _RosterNewListProc);
- _RosterListClear(hwndDlg);
- ppro->rrud.hwndDlg = hwndDlg;
- ppro->rrud.bReadyToDownload = TRUE;
- ppro->rrud.bReadyToUpload = FALSE;
- SendMessage(hwndDlg, JM_STATUSCHANGED, 0, 0);
- return TRUE;
-
- case JM_STATUSCHANGED:
- {
- int count = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_ROSTER));
- EnableWindow(GetDlgItem(hwndDlg, IDC_DOWNLOAD), ppro->m_bJabberOnline);
- EnableWindow(GetDlgItem(hwndDlg, IDC_UPLOAD), count && ppro->m_bJabberOnline);
- EnableWindow(GetDlgItem(hwndDlg, IDC_EXPORT), count > 0);
- }
- break;
-
- case WM_CLOSE:
- DestroyWindow(hwndDlg);
- break;
-
- case WM_DESTROY:
- Utils_SaveWindowPosition(hwndDlg, 0, ppro->m_szModuleName, "rosterCtrlWnd_");
- ppro->rrud.hwndDlg = nullptr;
- Window_FreeIcon_IcoLib(hwndDlg);
- break;
-
- case WM_GETMINMAXINFO:
- {
- LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam;
- lpmmi->ptMinTrackSize.x = 550;
- lpmmi->ptMinTrackSize.y = 390;
- return 0;
- }
-
- case WM_SIZE:
- Utils_ResizeDialog(hwndDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_OPT_JABBER3), sttRosterEditorResizer);
- break;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDC_DOWNLOAD:
- ppro->rrud.bReadyToUpload = FALSE;
- ppro->rrud.bReadyToDownload = FALSE;
- SendMessage(ppro->rrud.hwndDlg, JM_STATUSCHANGED, 0, 0);
- SetDlgItemText(ppro->rrud.hwndDlg, IDC_DOWNLOAD, TranslateT("Downloading..."));
- ppro->_RosterSendRequest(hwndDlg, RRA_FILLLIST);
- break;
-
- case IDC_UPLOAD:
- ppro->rrud.bReadyToUpload = FALSE;
- SendMessage(ppro->rrud.hwndDlg, JM_STATUSCHANGED, 0, 0);
- SetDlgItemText(ppro->rrud.hwndDlg, IDC_UPLOAD, TranslateT("Connecting..."));
- ppro->_RosterSendRequest(hwndDlg, RRA_SYNCROSTER);
- break;
-
- case IDC_EXPORT:
- ppro->_RosterExportToFile(hwndDlg);
- break;
-
- case IDC_IMPORT:
- ppro->_RosterImportFromFile(hwndDlg);
- break;
- }
- break;
- }
- return FALSE;
-}
-
-INT_PTR __cdecl CJabberProto::OnMenuHandleRosterControl(WPARAM, LPARAM)
-{
- if (rrud.hwndDlg && IsWindow(rrud.hwndDlg))
- SetForegroundWindow(rrud.hwndDlg);
- else
- CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_OPT_JABBER3), nullptr, JabberRosterOptDlgProc, (LPARAM)this);
-
- return 0;
-}
-
/////////////////////////////////////////////////////////////////////////////////////////
// JabberOptInit - initializes all options dialogs
@@ -2175,12 +1628,6 @@ INT_PTR CJabberProto::SvcCreateAccMgrUI(WPARAM, LPARAM lParam) return (INT_PTR)dlg->GetHwnd();
}
-void CJabberProto::JabberUpdateDialogs(BOOL)
-{
- if (rrud.hwndDlg)
- SendMessage(rrud.hwndDlg, JM_STATUSCHANGED, 0, 0);
-}
-
INT_PTR __cdecl CJabberProto::OnMenuOptions(WPARAM, LPARAM)
{
g_plugin.openOptions(L"Network", m_tszUserName, L"Account");
diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index b2b0ed2a3e..fb20d8838f 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -42,6 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. struct CJabberProto;
class CJabberMucJidListDlg;
+class CRosterEditorDlg;
class CJabberFormDlg;
typedef void (CJabberProto::*JABBER_FORM_SUBMIT_FUNC)(CJabberFormDlg *pDlg, void *userdata);
@@ -52,14 +53,6 @@ typedef UNIQUE_MAP<wchar_t, TCharKeyCmp> U_TCHAR_MAP; #define JABBER_DEFAULT_RECENT_COUNT 10
-struct ROSTERREQUSERDATA
-{
- HWND hwndDlg;
- BYTE bRRAction;
- BOOL bReadyToDownload;
- BOOL bReadyToUpload;
-};
-
struct TFilterInfo
{
enum Type { T_JID, T_XMLNS, T_ANY, T_OFF };
@@ -663,20 +656,11 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface CMStringA ExtractImage(const TiXmlElement *node);
const char* GetSoftName(const char *wszName);
- //---- jabber_opt.cpp ----------------------------------------------------------------
- INT_PTR __cdecl OnMenuHandleRosterControl(WPARAM wParam, LPARAM lParam);
-
- void _RosterExportToFile(HWND hwndDlg);
- void _RosterImportFromFile(HWND hwndDlg);
- void _RosterSendRequest(HWND hwndDlg, BYTE rrAction);
- void _RosterHandleGetRequest(const TiXmlElement *node, CJabberIqInfo*);
-
//---- jabber_password.cpp --------------------------------------------------------------
INT_PTR __cdecl OnMenuHandleChangePassword(WPARAM wParam, LPARAM lParam);
//---- jabber_privacy.cpp ------------------------------------------------------------
- ROSTERREQUSERDATA rrud;
INT_PTR __cdecl menuSetPrivacyList(WPARAM wParam, LPARAM lParam, LPARAM iList);
INT_PTR __cdecl OnMenuHandlePrivacyLists(WPARAM wParam, LPARAM lParam);
@@ -708,6 +692,13 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface int RcGetUnreadEventsCount(void);
+ //---- jabber_rostereditor.cpp -------------------------------------------------------
+
+ CRosterEditorDlg *m_hwndRosterEditor;
+
+ INT_PTR __cdecl OnMenuHandleRosterControl(WPARAM wParam, LPARAM lParam);
+ void _RosterHandleGetRequest(const TiXmlElement *node, CJabberIqInfo*);
+
//---- jabber_search.cpp -------------------------------------------------------------
void SearchReturnResults(HANDLE id, void* pvUsersInfo, U_TCHAR_MAP *pmAllFields);
diff --git a/protocols/JabberG/src/jabber_roster.cpp b/protocols/JabberG/src/jabber_roster.cpp new file mode 100644 index 0000000000..727f77ea9a --- /dev/null +++ b/protocols/JabberG/src/jabber_roster.cpp @@ -0,0 +1,580 @@ +/* + +Jabber Protocol Plugin for Miranda NG + +Copyright (c) 2002-04 Santithorn Bunchua +Copyright (c) 2005-12 George Hazan +Copyright (C) 2012-19 Miranda NG team + +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 "stdafx.h" + +#include <io.h> + +////////////////////////////////////////////////////////////////////////// +// roster editor +// + +enum +{ + RRA_FILLLIST = 0, + RRA_SYNCROSTER, + RRA_SYNCDONE +}; + +struct ROSTEREDITDAT +{ + HWND hList; + int index; + int subindex; +}; + +static void _RosterItemEditEnd(HWND hEditor, ROSTEREDITDAT *edat, BOOL bCancel) +{ + if (!bCancel) { + int len = GetWindowTextLength(hEditor) + 1; + wchar_t *buff = (wchar_t*)mir_alloc(len*sizeof(wchar_t)); + if (buff) { + GetWindowText(hEditor, buff, len); + ListView_SetItemText(edat->hList, edat->index, edat->subindex, buff); + } + mir_free(buff); + } + DestroyWindow(hEditor); +} + +static LRESULT CALLBACK _RosterItemNewEditProc(HWND hEditor, UINT msg, WPARAM wParam, LPARAM lParam) +{ + ROSTEREDITDAT * edat = (ROSTEREDITDAT *)GetWindowLongPtr(hEditor, GWLP_USERDATA); + if (!edat) return 0; + switch (msg) { + case WM_KEYDOWN: + switch (wParam) { + case VK_RETURN: + _RosterItemEditEnd(hEditor, edat, FALSE); + return 0; + case VK_ESCAPE: + _RosterItemEditEnd(hEditor, edat, TRUE); + return 0; + } + break; + + case WM_GETDLGCODE: + if (lParam) { + MSG *msg2 = (MSG*)lParam; + if (msg2->message == WM_KEYDOWN && msg2->wParam == VK_TAB) return 0; + if (msg2->message == WM_CHAR && msg2->wParam == '\t') return 0; + } + return DLGC_WANTMESSAGE; + + case WM_KILLFOCUS: + _RosterItemEditEnd(hEditor, edat, FALSE); + return 0; + + case WM_DESTROY: + SetWindowLongPtr(hEditor, GWLP_USERDATA, (LONG_PTR)0); + free(edat); + return 0; + } + + return mir_callNextSubclass(hEditor, _RosterItemNewEditProc, msg, wParam, lParam); +} + +static LRESULT CALLBACK _RosterNewListProc(HWND hList, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_MOUSEWHEEL || msg == WM_NCLBUTTONDOWN || msg == WM_NCRBUTTONDOWN) + SetFocus(hList); + + if (msg == WM_LBUTTONDOWN) { + POINT pt; + GetCursorPos(&pt); + ScreenToClient(hList, &pt); + + LVHITTESTINFO lvhti = { 0 }; + lvhti.pt = pt; + ListView_SubItemHitTest(hList, &lvhti); + if (lvhti.flags&LVHT_ONITEM && lvhti.iSubItem != 0) { + RECT rc; + wchar_t buff[260]; + ListView_GetSubItemRect(hList, lvhti.iItem, lvhti.iSubItem, LVIR_BOUNDS, &rc); + ListView_GetItemText(hList, lvhti.iItem, lvhti.iSubItem, buff, _countof(buff)); + HWND hEditor = CreateWindow(TEXT("EDIT"), buff, WS_CHILD | ES_AUTOHSCROLL, rc.left + 3, rc.top + 2, rc.right - rc.left - 3, rc.bottom - rc.top - 3, hList, nullptr, g_plugin.getInst(), nullptr); + SendMessage(hEditor, WM_SETFONT, (WPARAM)SendMessage(hList, WM_GETFONT, 0, 0), 0); + ShowWindow(hEditor, SW_SHOW); + SetWindowText(hEditor, buff); + ClientToScreen(hList, &pt); + ScreenToClient(hEditor, &pt); + mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); + mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); + + ROSTEREDITDAT * edat = (ROSTEREDITDAT *)malloc(sizeof(ROSTEREDITDAT)); + mir_subclassWindow(hEditor, _RosterItemNewEditProc); + edat->hList = hList; + edat->index = lvhti.iItem; + edat->subindex = lvhti.iSubItem; + SetWindowLongPtr(hEditor, GWLP_USERDATA, (LONG_PTR)edat); + } + } + return mir_callNextSubclass(hList, _RosterNewListProc, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// JabberRosterOptDlgProc - advanced options dialog procedure + +class CRosterEditorDlg : public CJabberDlgBase +{ + friend struct CJabberProto; + typedef CJabberDlgBase CSuper; + + BYTE m_bRRAction; + BOOL m_bReadyToDownload = true; + BOOL m_bReadyToUpload = false; + + void _RosterSendRequest(BYTE rrAction) + { + m_bRRAction = rrAction; + + m_proto->m_ThreadInfo->send( + XmlNodeIq(m_proto->AddIQ(&CJabberProto::_RosterHandleGetRequest, JABBER_IQ_TYPE_GET)) + << XCHILDNS("query", JABBER_FEAT_IQ_ROSTER)); + } + + int _RosterInsertListItem(const char *jid, const char *nick, const char *group, const char *subscr, bool bChecked) + { + Utf2T wszJid(jid); + LVITEM item = { 0 }; + item.mask = LVIF_TEXT | LVIF_STATE; + item.iItem = m_list.GetItemCount(); + item.pszText = wszJid; + + int index = m_list.InsertItem(&item); + if (index < 0) + return index; + + m_list.SetCheckState(index, bChecked); + + m_list.SetItemText(index, 1, Utf2T(nick)); + m_list.SetItemText(index, 2, Utf2T(group)); + m_list.SetItemText(index, 3, Utf2T(subscr)); + return index; + } + + void _RosterListClear() + { + m_list.DeleteAllItems(); + while (m_list.GetColumnWidth(0) > 0) + m_list.DeleteColumn(0); + + LV_COLUMN column = { 0 }; + column.mask = LVCF_TEXT; + + column.pszText = TranslateT("JID"); + m_list.InsertColumn(1, &column); + + column.pszText = TranslateT("Nickname"); + m_list.InsertColumn(2, &column); + + column.pszText = TranslateT("Group"); + m_list.InsertColumn(3, &column); + + column.pszText = TranslateT("Subscription"); + m_list.InsertColumn(4, &column); + + RECT rc; + GetClientRect(m_list.GetHwnd(), &rc); + ResizeColumns(rc.right - rc.left); + } + + void ResizeColumns(int width) + { + m_list.SetColumnWidth(0, width * 40 / 100); + m_list.SetColumnWidth(1, width * 25 / 100); + m_list.SetColumnWidth(2, width * 20 / 100); + m_list.SetColumnWidth(3, width * 12 / 100); + } + + void OnChangeStatus() + { + int count = m_list.GetItemCount(); + btnDownload.Enable(m_proto->m_bJabberOnline); + btnUpload.Enable(count && m_proto->m_bJabberOnline); + btnExport.Enable(count > 0); + } + + CCtrlButton btnDownload, btnUpload, btnExport, btnImport; + CCtrlListView m_list; + +public: + CRosterEditorDlg(CJabberProto *m_proto) : + CSuper(m_proto, IDD_ROSTER_EDITOR), + m_list(this, IDC_ROSTER), + btnExport(this, IDC_EXPORT), + btnImport(this, IDC_IMPORT), + btnUpload(this, IDC_UPLOAD), + btnDownload(this, IDC_DOWNLOAD) + { + btnExport.OnClick = Callback(this, &CRosterEditorDlg::onClick_Export); + btnImport.OnClick = Callback(this, &CRosterEditorDlg::onClick_Import); + btnUpload.OnClick = Callback(this, &CRosterEditorDlg::onClick_Upload); + btnDownload.OnClick = Callback(this, &CRosterEditorDlg::onClick_Download); + } + + bool OnInitDialog() override + { + Window_SetIcon_IcoLib(m_hwnd, g_GetIconHandle(IDI_AGENTS)); + + Utils_RestoreWindowPosition(m_hwnd, 0, m_proto->m_szModuleName, "rosterCtrlWnd_"); + + m_list.SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_BORDERSELECT | LVS_EX_GRIDLINES); + mir_subclassWindow(m_list.GetHwnd(), _RosterNewListProc); + _RosterListClear(); + OnChangeStatus(); + return true; + } + + void OnDestroy() override + { + m_proto->m_hwndRosterEditor = nullptr; + Utils_SaveWindowPosition(m_hwnd, 0, m_proto->m_szModuleName, "rosterCtrlWnd_"); + Window_FreeIcon_IcoLib(m_hwnd); + } + + int Resizer(UTILRESIZECONTROL *urc) override + { + switch (urc->wId) { + case IDC_HEADERBAR: + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH; + case IDC_ROSTER: + ResizeColumns(urc->rcItem.right - urc->rcItem.left + urc->dlgNewSize.cx - urc->dlgOriginalSize.cx); + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORY_HEIGHT | RD_ANCHORX_WIDTH; + case IDC_DOWNLOAD: + case IDC_UPLOAD: + return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; + case IDC_EXPORT: + case IDC_IMPORT: + return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; + } + + void HandleNode(const TiXmlElement *node) + { + if (m_bRRAction == RRA_FILLLIST) { + _RosterListClear(); + auto *query = XmlFirstChild(node, "query"); + if (query == nullptr) return; + + for (auto *item : TiXmlFilter(query, "item")) { + const char *jid = XmlGetAttr(item, "jid"); + if (jid == nullptr) + continue; + + const char *name = XmlGetAttr(item, "name"); + const char *subscription = XmlGetAttr(item, "subscription"); + const char *group = XmlGetChildText(item, "group"); + _RosterInsertListItem(jid, name, group, subscription, true); + } + + // now it is require to process whole contact list to add not in roster contacts + for (auto &hContact : m_proto->AccContacts()) { + ptrW tszJid(m_proto->getWStringA(hContact, "jid")); + if (tszJid == nullptr) + continue; + + LVFINDINFO lvfi = { 0 }; + lvfi.flags = LVFI_STRING; + lvfi.psz = tszJid; + wchar_t *p = wcschr(tszJid, '@'); + if (p) { + p = wcschr(tszJid, '/'); + if (p) *p = 0; + } + if (m_list.FindItem(-1, &lvfi) == -1) { + ptrA tszName(db_get_utfa(hContact, "CList", "MyHandle")); + ptrA tszGroup(db_get_utfa(hContact, "CList", "Group")); + _RosterInsertListItem(T2Utf(tszJid), tszName, tszGroup, nullptr, FALSE); + } + } + m_bReadyToDownload = FALSE; + m_bReadyToUpload = TRUE; + btnDownload.SetText(TranslateT("Download")); + btnUpload.SetText(TranslateT("Upload")); + OnChangeStatus(); + return; + } + + if (m_bRRAction == RRA_SYNCROSTER) { + btnUpload.SetText(TranslateT("Uploading...")); + auto *queryRoster = XmlFirstChild(node, "query"); + if (!queryRoster) + return; + + XmlNodeIq iq(m_proto->AddIQ(&CJabberProto::_RosterHandleGetRequest, JABBER_IQ_TYPE_SET)); + + TiXmlElement *query = iq << XCHILDNS("query", JABBER_FEAT_IQ_ROSTER); + + int itemCount = 0; + int ListItemCount = m_list.GetItemCount(); + for (int index = 0; index < ListItemCount; index++) { + wchar_t jid[JABBER_MAX_JID_LEN] = L""; + wchar_t name[260]; + wchar_t group[260]; + wchar_t subscr[260]; + m_list.GetItemText(index, 0, jid, _countof(jid)); + m_list.GetItemText(index, 1, name, _countof(name)); + m_list.GetItemText(index, 2, group, _countof(group)); + m_list.GetItemText(index, 3, subscr, _countof(subscr)); + + T2Utf szJid(jid), szName(name), szGroup(group), szSubscr(subscr); + auto *itemRoster = XmlGetChildByTag(queryRoster, "item", "jid", szJid); + BOOL bRemove = !m_list.GetCheckState(index); + if (itemRoster && bRemove) { + //delete item + query << XCHILD("item") << XATTR("jid", szJid) << XATTR("subscription", "remove"); + itemCount++; + } + else if (!bRemove) { + BOOL bPushed = itemRoster ? TRUE : FALSE; + if (!bPushed) { + const char *rosterName = XmlGetAttr(itemRoster, "name"); + if ((rosterName != nullptr || name[0] != 0) && mir_strcmpi(rosterName, szName)) + bPushed = TRUE; + if (!bPushed) { + rosterName = XmlGetAttr(itemRoster, "subscription"); + if ((rosterName != nullptr || subscr[0] != 0) && mir_strcmpi(rosterName, T2Utf(subscr))) + bPushed = TRUE; + } + if (!bPushed) { + auto *rosterGroup = XmlGetChildText(itemRoster, "group"); + if (rosterGroup != nullptr && mir_strcmpi(rosterGroup, szGroup)) + bPushed = TRUE; + } + } + if (bPushed) { + TiXmlElement *item = query << XCHILD("item"); + if (mir_wstrlen(group)) + item << XCHILD("group", szGroup); + if (mir_wstrlen(name)) + item << XATTR("name", szName); + item << XATTR("jid", szJid) << XATTR("subscription", subscr[0] ? szSubscr : "none"); + itemCount++; + } + } + } + m_bRRAction = RRA_SYNCDONE; + if (itemCount) + m_proto->m_ThreadInfo->send(iq); + else + _RosterSendRequest(RRA_FILLLIST); + return; + } + + btnUpload.SetText(TranslateT("Upload")); + onClick_Download(nullptr); + }; + + void onClick_Download(CCtrlButton*) + { + m_bReadyToUpload = m_bReadyToDownload = false; + OnChangeStatus(); + btnDownload.SetText(TranslateT("Downloading...")); + _RosterSendRequest(RRA_FILLLIST); + } + + void onClick_Upload(CCtrlButton*) + { + m_bReadyToUpload = false; + OnChangeStatus(); + btnUpload.SetText(TranslateT("Connecting...")); + _RosterSendRequest(RRA_SYNCROSTER); + } + + void onClick_Export(CCtrlButton*) + { + wchar_t filename[MAX_PATH] = { 0 }; + + wchar_t filter[MAX_PATH]; + mir_snwprintf(filter, L"%s (*.xml)%c*.xml%c%c", TranslateT("XML for MS Excel (UTF-8 encoded)"), 0, 0, 0); + OPENFILENAME ofn = { 0 }; + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = m_hwnd; + ofn.hInstance = nullptr; + ofn.lpstrFilter = filter; + ofn.lpstrFile = filename; + ofn.Flags = OFN_HIDEREADONLY; + ofn.nMaxFile = _countof(filename); + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = L"xml"; + if (!GetSaveFileName(&ofn)) + return; + + FILE * fp = _wfopen(filename, L"wb"); + if (!fp) + return; + + int ListItemCount = m_list.GetItemCount(); + + XmlNode root("Workbook"); + root << XATTR("xmlns", "urn:schemas-microsoft-com:office:spreadsheet") + << XATTR("xmlns:o", "urn:schemas-microsoft-com:office:office") + << XATTR("xmlns:x", "urn:schemas-microsoft-com:office:excel") + << XATTR("xmlns:ss", "urn:schemas-microsoft-com:office:spreadsheet") + << XATTR("xmlns:html", "http://www.w3.org/TR/REC-html40"); + root << XCHILD("ExcelWorkbook") + << XATTR("xmlns", "urn:schemas-microsoft-com:office:excel"); + TiXmlElement *table = root << XCHILD("Worksheet") << XATTR("ss:Name", "Exported roster") + << XCHILD("Table"); + + for (int index = 0; index < ListItemCount; index++) { + wchar_t jid[JABBER_MAX_JID_LEN] = L""; + wchar_t name[260] = L""; + wchar_t group[260] = L""; + wchar_t subscr[260] = L""; + m_list.GetItemText(index, 0, jid, _countof(jid)); + m_list.GetItemText(index, 1, name, _countof(name)); + m_list.GetItemText(index, 2, group, _countof(group)); + m_list.GetItemText(index, 3, subscr, _countof(subscr)); + + TiXmlElement *node = table << XCHILD("Row"); + node << XCHILD("Cell") << XCHILD("Data", "+") << XATTR("ss:Type", "String"); + node << XCHILD("Cell") << XCHILD("Data", T2Utf(jid)) << XATTR("ss:Type", "String"); + node << XCHILD("Cell") << XCHILD("Data", T2Utf(name)) << XATTR("ss:Type", "String"); + node << XCHILD("Cell") << XCHILD("Data", T2Utf(group)) << XATTR("ss:Type", "String"); + node << XCHILD("Cell") << XCHILD("Data", T2Utf(subscr)) << XATTR("ss:Type", "String"); + + } + + char header[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?mso-application progid=\"Excel.Sheet\"?>\n"; + fwrite(header, 1, sizeof(header) - 1 /* for zero terminator */, fp); + + tinyxml2::XMLPrinter printer(0); + root.Print(&printer); + fputs(printer.CStr(), fp); + fclose(fp); + } + + void onClick_Import(CCtrlButton*) + { + wchar_t filename[MAX_PATH] = { 0 }; + wchar_t *filter = L"XML for MS Excel (UTF-8 encoded)(*.xml)\0*.xml\0\0"; + + OPENFILENAME ofn = { 0 }; + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = m_hwnd; + ofn.hInstance = nullptr; + ofn.lpstrFilter = filter; + ofn.lpstrFile = filename; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.nMaxFile = _countof(filename); + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = L"xml"; + if (!GetOpenFileNameW(&ofn)) + return; + + FILE * fp = _wfopen(filename, L"rb"); + if (!fp) + return; + + TiXmlDocument doc; + int ret = doc.LoadFile(fp); + fclose(fp); + if (ret != 0) + return; + + _RosterListClear(); + + const TiXmlElement *Table = TiXmlConst(&doc)["Workbook"]["Worksheet"]["Table"].ToElement(); + if (Table) { + for (auto *Row : TiXmlFilter(Table, "Row")) { + BOOL bAdd = FALSE; + const char *jid = nullptr; + const char *name = nullptr; + const char *group = nullptr; + const char *subscr = nullptr; + auto *Cell = XmlFirstChild(Row, "Cell"); + auto *Data = XmlFirstChild(Cell, "Data"); + if (Data) { + if (!mir_strcmpi(Data->GetText(), "+")) bAdd = TRUE; + else if (mir_strcmpi(Data->GetText(), "-")) continue; + + Cell = Cell->NextSiblingElement("Cell"); + if (Cell) Data = XmlFirstChild(Cell, "Data"); + else Data = nullptr; + if (Data) { + jid = Data->GetText(); + if (!jid || mir_strlen(jid) == 0) continue; + } + + Cell = Cell->NextSiblingElement("Cell"); + if (Cell) Data = XmlFirstChild(Cell, "Data"); + else Data = nullptr; + if (Data) name = Data->GetText(); + + Cell = Cell->NextSiblingElement("Cell"); + if (Cell) Data = XmlFirstChild(Cell, "Data"); + else Data = nullptr; + if (Data) group = Data->GetText(); + + Cell = Cell->NextSiblingElement("Cell"); + if (Cell) Data = XmlFirstChild(Cell, "Data"); + else Data = nullptr; + if (Data) subscr = Data->GetText(); + } + _RosterInsertListItem(jid, name, group, subscr, bAdd); + } + } + + OnChangeStatus(); + } + + INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override + { + if (msg == WM_GETMINMAXINFO) { + LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam; + lpmmi->ptMinTrackSize.x = 550; + lpmmi->ptMinTrackSize.y = 390; + return 0; + } + + return CSuper::DlgProc(msg, wParam, lParam); + } +}; + +INT_PTR __cdecl CJabberProto::OnMenuHandleRosterControl(WPARAM, LPARAM) +{ + if (m_hwndRosterEditor) + SetForegroundWindow(m_hwndRosterEditor->GetHwnd()); + else { + m_hwndRosterEditor = new CRosterEditorDlg(this); + m_hwndRosterEditor->Show(); + } + + return 0; +} + +void CJabberProto::_RosterHandleGetRequest(const TiXmlElement *node, CJabberIqInfo*) +{ + if (m_hwndRosterEditor) + m_hwndRosterEditor->HandleNode(node); +} + +void CJabberProto::JabberUpdateDialogs(BOOL) +{ + if (m_hwndRosterEditor) + m_hwndRosterEditor->OnChangeStatus(); +} diff --git a/protocols/JabberG/src/resource.h b/protocols/JabberG/src/resource.h index 7e5b5dd938..3a216aa680 100644 --- a/protocols/JabberG/src/resource.h +++ b/protocols/JabberG/src/resource.h @@ -46,7 +46,7 @@ #define IDD_JIDLIST 171
#define IDD_GROUPCHAT_INVITE 183
#define IDD_GROUPCHAT_INVITE_ACCEPT 184
-#define IDD_OPT_JABBER3 185
+#define IDD_ROSTER_EDITOR 185
#define IDI_LOGIN 186
#define IDI_COMMAND 188
#define IDI_DISCO_OK 190
|