diff options
Diffstat (limited to 'protocols/JabberG/jabber_notes.cpp')
-rw-r--r-- | protocols/JabberG/jabber_notes.cpp | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/protocols/JabberG/jabber_notes.cpp b/protocols/JabberG/jabber_notes.cpp new file mode 100644 index 0000000000..03a274f0fb --- /dev/null +++ b/protocols/JabberG/jabber_notes.cpp @@ -0,0 +1,869 @@ +/*
+
+Jabber Protocol Plugin for Miranda IM
+Copyright ( C ) 2002-04 Santithorn Bunchua
+Copyright ( C ) 2005-11 George Hazan
+Copyright ( C ) 2007-09 Maxim Mluhov
+Copyright ( C ) 2007-09 Victor Pavlychko
+
+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: 13898 $
+Last change on : $Date: 2011-11-02 05:38:43 +0200 (Ср, 02 ноя 2011) $
+Last change by : $Author: borkra $
+
+*/
+
+#include "jabber.h"
+#include "jabber_list.h"
+#include "jabber_iq.h"
+#include "jabber_caps.h"
+#include "jabber_privacy.h"
+#include "jabber_notes.h"
+
+static TCHAR *StrTrimCopy(TCHAR *str)
+{
+ if (!str) return 0;
+ while (*str && _istspace(*str)) ++str;
+ if (!*str) return mir_tstrdup(str);
+
+ TCHAR *res = mir_tstrdup(str);
+ for (TCHAR *p = res + lstrlen(res) - 1; p >= res; --p)
+ {
+ if (_istspace(*p))
+ *p = 0;
+ else
+ break;
+ }
+
+ return res;
+}
+
+CNoteItem::CNoteItem()
+{
+ m_szTitle =
+ m_szFrom =
+ m_szText =
+ m_szTags =
+ m_szTagsStr = NULL;
+}
+
+CNoteItem::CNoteItem(HXML hXml, TCHAR *szFrom)
+{
+ m_szTitle =
+ m_szFrom =
+ m_szText =
+ m_szTags =
+ m_szTagsStr = NULL;
+
+ SetData(
+ XPathT(hXml, "title"),
+ szFrom ? szFrom : XPathT(hXml, "@from"),
+ XPathT(hXml, "text"),
+ XPathT(hXml, "@tags"));
+}
+
+CNoteItem::~CNoteItem()
+{
+ mir_free(m_szTitle);
+ mir_free(m_szFrom);
+ mir_free(m_szText);
+ mir_free(m_szTags);
+ mir_free(m_szTagsStr);
+}
+
+void CNoteItem::SetData(TCHAR *title, TCHAR *from, TCHAR *text, TCHAR *tags)
+{
+ mir_free(m_szTitle);
+ mir_free(m_szFrom);
+ mir_free(m_szText);
+ mir_free(m_szTags);
+ mir_free(m_szTagsStr);
+
+ m_szTitle = StrTrimCopy(title);
+ m_szText = JabberStrFixLines(text);
+ m_szFrom = StrTrimCopy(from);
+
+ const TCHAR *szTags = tags;
+ TCHAR *p = m_szTags = (TCHAR *)mir_alloc((lstrlen(szTags) + 2 /*for double zero*/) * sizeof(TCHAR));
+ TCHAR *q = m_szTagsStr = (TCHAR *)mir_alloc((lstrlen(szTags) + 1) * sizeof(TCHAR));
+ for ( ; szTags && *szTags; ++szTags)
+ {
+ if (_istspace(*szTags))
+ continue;
+
+ if (*szTags == _T(','))
+ {
+ *q++ = _T(',');
+ *p++ = 0;
+ continue;
+ }
+
+ *q++ = *p++ = *szTags;
+ }
+
+ q[0] = p[0] = p[1] = 0;
+}
+
+bool CNoteItem::HasTag(const TCHAR *szTag)
+{
+ if (!szTag || !*szTag)
+ return true;
+
+ for (TCHAR *p = m_szTags; p && *p; p = p + lstrlen(p) + 1)
+ if (!lstrcmp(p, szTag))
+ return true;
+
+ return false;
+}
+
+int CNoteItem::cmp(const CNoteItem *p1, const CNoteItem *p2)
+{
+ int ret = 0;
+ if (ret = lstrcmp(p1->m_szTitle, p2->m_szTitle)) return ret;
+ if (ret = lstrcmp(p1->m_szText, p2->m_szText)) return ret;
+ if (ret = lstrcmp(p1->m_szTagsStr, p2->m_szTagsStr)) return ret;
+ if (p1 < p2) return -1;
+ if (p1 > p2) return 1;
+ return 0;
+}
+
+void CNoteList::AddNote(HXML hXml, TCHAR *szFrom)
+{
+ m_bIsModified = true;
+ insert(new CNoteItem(hXml, szFrom));
+}
+
+void CNoteList::LoadXml(HXML hXml)
+{
+ destroy();
+ m_bIsModified = false;
+
+ int count = xmlGetChildCount(hXml);
+ for (int i = 0; i < count; ++i)
+ {
+ CNoteItem *pNote = new CNoteItem(xi.getChild(hXml, i));
+ if (pNote->IsNotEmpty())
+ insert(pNote);
+ else
+ delete pNote;
+ }
+}
+
+void CNoteList::SaveXml(HXML hXmlParent)
+{
+ m_bIsModified = false;
+ CNoteList &me = *this;
+
+ for (int i = 0; i < getCount(); ++i)
+ {
+ HXML hXmlItem = hXmlParent << XCHILD(_T("note"));
+ hXmlItem << XATTR(_T("from"), me[i].GetFrom()) << XATTR(_T("tags"), me[i].GetTagsStr());
+ hXmlItem << XCHILD(_T("title"), me[i].GetTitle());
+ hXmlItem << XCHILD(_T("text"), me[i].GetText());
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Single note editor
+
+class CJabberDlgNoteItem : public CJabberDlgBase
+{
+ typedef CJabberDlgBase CSuper;
+ typedef void (CJabberProto::*TFnProcessNote)(CNoteItem *, bool ok);
+
+public:
+ CJabberDlgNoteItem(CJabberDlgBase *parent, CNoteItem *pNote);
+ CJabberDlgNoteItem(CJabberProto *proto, CNoteItem *pNote, TFnProcessNote fnProcess);
+
+protected:
+ void OnInitDialog();
+ int Resizer(UTILRESIZECONTROL *urc);
+
+private:
+ CNoteItem *m_pNote;
+ TFnProcessNote m_fnProcess;
+
+ CCtrlEdit m_txtTitle;
+ CCtrlEdit m_txtText;
+ CCtrlEdit m_txtTags;
+ CCtrlButton m_btnOk;
+
+ void btnOk_OnClick(CCtrlButton *)
+ {
+ TCHAR *szTitle = m_txtTitle.GetText();
+ TCHAR *szText = m_txtText.GetText();
+ TCHAR *szTags = m_txtTags.GetText();
+ TCHAR *szFrom = mir_tstrdup(m_pNote->GetFrom());
+ m_pNote->SetData(szTitle, szFrom, szText, szTags);
+ mir_free(szTitle);
+ mir_free(szText);
+ mir_free(szTags);
+ mir_free(szFrom);
+
+ m_autoClose = false;
+ if (m_fnProcess) (m_proto->*m_fnProcess)(m_pNote, true);
+ EndDialog(m_hwnd, TRUE);
+ }
+
+ void OnClose()
+ {
+ if (m_fnProcess) (m_proto->*m_fnProcess)(m_pNote, false);
+ CSuper::OnClose();
+ }
+};
+
+CJabberDlgNoteItem::CJabberDlgNoteItem(CJabberDlgBase *parent, CNoteItem *pNote):
+ CSuper(parent->GetProto(), IDD_NOTE_EDIT, parent->GetHwnd()),
+ m_pNote(pNote),
+ m_fnProcess(NULL),
+ m_txtTitle(this, IDC_TXT_TITLE),
+ m_txtText(this, IDC_TXT_TEXT),
+ m_txtTags(this, IDC_TXT_TAGS),
+ m_btnOk(this, IDOK)
+{
+ m_btnOk.OnClick = Callback(this, &CJabberDlgNoteItem::btnOk_OnClick);
+}
+
+CJabberDlgNoteItem::CJabberDlgNoteItem(CJabberProto *proto, CNoteItem *pNote, TFnProcessNote fnProcess):
+ CSuper(proto, IDD_NOTE_EDIT, NULL),
+ m_pNote(pNote),
+ m_fnProcess(fnProcess),
+ m_txtTitle(this, IDC_TXT_TITLE),
+ m_txtText(this, IDC_TXT_TEXT),
+ m_txtTags(this, IDC_TXT_TAGS),
+ m_btnOk(this, IDOK)
+{
+ m_btnOk.OnClick = Callback(this, &CJabberDlgNoteItem::btnOk_OnClick);
+}
+
+void CJabberDlgNoteItem::OnInitDialog()
+{
+ CSuper::OnInitDialog();
+ WindowSetIcon( m_hwnd, m_proto, "notes" );
+
+ if (m_fnProcess)
+ {
+ TCHAR buf[256];
+ if (m_fnProcess == &CJabberProto::ProcessIncomingNote)
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("Incoming note from %s"), m_pNote->GetFrom());
+ else
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("Send note to %s"), m_pNote->GetFrom());
+
+ SetWindowText(m_hwnd, buf);
+ }
+
+ m_txtTitle.SetText(m_pNote->GetTitle());
+ m_txtText.SetText(m_pNote->GetText());
+ m_txtTags.SetText(m_pNote->GetTagsStr());
+}
+
+int CJabberDlgNoteItem::Resizer(UTILRESIZECONTROL *urc)
+{
+ switch (urc->wId)
+ {
+ case IDC_TXT_TITLE:
+ return RD_ANCHORX_WIDTH|RD_ANCHORY_TOP;
+ case IDC_TXT_TEXT:
+ return RD_ANCHORX_WIDTH|RD_ANCHORY_HEIGHT;
+ case IDC_ST_TAGS:
+ case IDC_TXT_TAGS:
+ return RD_ANCHORX_WIDTH|RD_ANCHORY_BOTTOM;
+
+ case IDOK:
+ case IDCANCEL:
+ return RD_ANCHORX_RIGHT|RD_ANCHORY_BOTTOM;
+ }
+
+ return CSuper::Resizer(urc);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Notebook window
+
+class CCtrlNotebookList: public CCtrlListBox
+{
+ typedef CCtrlListBox CSuper;
+ bool m_adding;
+ HFONT m_hfntNormal, m_hfntSmall, m_hfntBold;
+
+public:
+ CCtrlNotebookList( CDlgBase* dlg, int ctrlId ): CCtrlListBox( dlg, ctrlId ) {}
+ void SetFonts(HFONT hfntNormal, HFONT hfntSmall, HFONT hfntBold)
+ {
+ m_hfntNormal = hfntNormal;
+ m_hfntSmall = hfntSmall;
+ m_hfntBold = hfntBold;
+ }
+
+ int AddString(TCHAR *text, LPARAM data=0)
+ {
+ m_adding = true;
+ int idx = CCtrlListBox::AddString(text, data);
+ m_adding = false;
+ if (idx == LB_ERR) return idx;
+
+ MEASUREITEMSTRUCT mis = {0};
+ mis.CtlType = ODT_LISTBOX;
+ mis.CtlID = m_idCtrl;
+ mis.itemID = idx;
+ mis.itemData = data;
+ OnMeasureItem(&mis);
+ if (mis.itemHeight) SendMessage(m_hwnd, LB_SETITEMHEIGHT, idx, mis.itemHeight);
+ return idx;
+ }
+
+ void OnInit()
+ {
+ CSuper::OnInit();
+ Subclass();
+ }
+
+ LRESULT CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ if (msg == WM_SIZE)
+ {
+ SendMessage(m_hwnd, WM_SETREDRAW, FALSE, 0);
+ int cnt = GetCount();
+ for (int idx = 0; idx < cnt; ++idx)
+ {
+ MEASUREITEMSTRUCT mis = {0};
+ mis.CtlType = ODT_LISTBOX;
+ mis.CtlID = m_idCtrl;
+ mis.itemID = idx;
+ mis.itemData = GetItemData(idx);
+ OnMeasureItem(&mis);
+ if (mis.itemHeight) SendMessage(m_hwnd, LB_SETITEMHEIGHT, idx, mis.itemHeight);
+ }
+ SendMessage(m_hwnd, WM_SETREDRAW, TRUE, 0);
+ RedrawWindow(m_hwnd, NULL, NULL, RDW_INVALIDATE);
+ }
+
+ return CSuper::CustomWndProc(msg, wParam, lParam);
+ }
+
+ BOOL OnDrawItem(DRAWITEMSTRUCT *lps)
+ {
+ if (m_adding) return FALSE;
+ if (lps->itemID == -1) return TRUE;
+ if (!lps->itemData) return TRUE;
+
+ HDC hdc = lps->hDC;
+ CNoteItem *pNote = (CNoteItem *)lps->itemData;
+
+ SetBkMode(hdc, TRANSPARENT);
+ if (lps->itemState & ODS_SELECTED)
+ {
+ FillRect(hdc, &lps->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ } else
+ {
+ FillRect(hdc, &lps->rcItem, GetSysColorBrush(COLOR_WINDOW));
+ SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
+ }
+
+ if (lps->itemID)
+ {
+ RECT rcTmp = lps->rcItem; rcTmp.bottom = rcTmp.top+1;
+ FillRect(hdc, &rcTmp, GetSysColorBrush(COLOR_BTNSHADOW));
+ }
+
+ RECT rc = lps->rcItem;
+ rc.left += 5;
+ rc.right -= 5;
+ rc.top += 2;
+
+ SelectObject(hdc, m_hfntBold);
+ rc.top += DrawText(hdc, pNote->GetTitle(), -1, &rc, DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS);
+ SelectObject(hdc, m_hfntNormal);
+ if (pNote->GetFrom())
+ {
+ TCHAR buf[256];
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("From: %s"), pNote->GetFrom());
+ rc.top += DrawText(hdc, buf, -1, &rc, DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS);
+ }
+ rc.top += DrawText(hdc, pNote->GetText(), -1, &rc, DT_NOPREFIX|DT_WORDBREAK|DT_EXPANDTABS|DT_END_ELLIPSIS);
+ SelectObject(hdc, m_hfntSmall);
+ rc.top += DrawText(hdc, pNote->GetTagsStr(), -1, &rc, DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS);
+ rc.top += 5;
+
+ int h = min(255, max(0, rc.bottom - rc.top));
+ if (SendMessage(m_hwnd, LB_GETITEMHEIGHT, lps->itemID, 0) != h)
+ SendMessage(m_hwnd, LB_SETITEMHEIGHT, lps->itemID, h);
+
+ return TRUE;
+ }
+
+ BOOL OnMeasureItem(MEASUREITEMSTRUCT *lps)
+ {
+ if (m_adding) return FALSE;
+ if (lps->itemID == -1) return TRUE;
+ if (!lps->itemData) return TRUE;
+
+ HDC hdc = GetDC(m_hwnd);
+ CNoteItem *pNote = (CNoteItem *)lps->itemData;
+
+ RECT rcTmp, rc;
+ GetClientRect(m_hwnd, &rc);
+ int maxHeight = rc.bottom - 10;
+ rc.bottom = 0;
+
+ SelectObject(hdc, m_hfntBold);
+ rcTmp = rc;
+ DrawText(hdc, pNote->GetTitle(), -1, &rcTmp, DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_CALCRECT);
+ lps->itemHeight += rcTmp.bottom;
+ SelectObject(hdc, m_hfntNormal);
+ if (pNote->GetFrom())
+ {
+ TCHAR buf[256];
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("From: %s"), pNote->GetFrom());
+ rcTmp = rc;
+ DrawText(hdc, buf, -1, &rcTmp, DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_CALCRECT);
+ lps->itemHeight += rcTmp.bottom;
+ }
+ rcTmp = rc;
+ DrawText(hdc, pNote->GetText(), -1, &rcTmp, DT_NOPREFIX|DT_WORDBREAK|DT_EXPANDTABS|DT_END_ELLIPSIS|DT_CALCRECT);
+ lps->itemHeight += rcTmp.bottom;
+ SelectObject(hdc, m_hfntSmall);
+ rcTmp = rc;
+ DrawText(hdc, pNote->GetTagsStr(), -1, &rcTmp, DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_CALCRECT);
+ lps->itemHeight += rcTmp.bottom;
+ lps->itemHeight += 5;
+
+ ReleaseDC(m_hwnd, hdc);
+
+ lps->itemWidth = rc.right;
+ lps->itemHeight = min(255, lps->itemHeight); // listbox can't make items taller then 255px
+ return TRUE;
+ }
+};
+
+class CJabberDlgNotes : public CJabberDlgBase
+{
+ typedef CJabberDlgBase CSuper;
+
+public:
+ CJabberDlgNotes(CJabberProto *proto);
+ void UpdateData();
+
+protected:
+ void OnInitDialog();
+ void OnClose();
+ void OnDestroy();
+ int Resizer(UTILRESIZECONTROL *urc);
+
+ void OnProtoCheckOnline(WPARAM wParam, LPARAM lParam);
+ void OnProtoRefresh(WPARAM wParam, LPARAM lParam);
+
+private:
+ CCtrlMButton m_btnAdd;
+ CCtrlMButton m_btnEdit;
+ CCtrlMButton m_btnRemove;
+ CCtrlNotebookList m_lstNotes;
+ CCtrlTreeView m_tvFilter;
+ CCtrlButton m_btnSave;
+
+ HFONT m_hfntNormal, m_hfntSmall, m_hfntBold;
+
+ void EnableControls()
+ {
+ m_btnSave.Enable(m_proto->m_bJabberOnline && m_proto->m_notes.IsModified());
+ m_btnEdit.Enable(m_lstNotes.GetCurSel() != LB_ERR);
+ m_btnRemove.Enable(m_lstNotes.GetCurSel() != LB_ERR);
+ }
+
+ void InsertTag(HTREEITEM htiRoot, const TCHAR *tag, bool bSelect)
+ {
+ TVINSERTSTRUCT tvi = {0};
+ tvi.hParent = htiRoot;
+ tvi.hInsertAfter = TVI_LAST;
+ tvi.itemex.mask = TVIF_TEXT|TVIF_PARAM;
+ tvi.itemex.pszText = (TCHAR *)tag;
+ tvi.itemex.lParam = (LPARAM)mir_tstrdup(tag);
+ HTREEITEM hti = m_tvFilter.InsertItem(&tvi);
+ if (bSelect) m_tvFilter.SelectItem(hti);
+ }
+
+ void PopulateTags(HTREEITEM htiRoot, TCHAR *szActiveTag)
+ {
+ LIST<TCHAR> tagSet(5, _tcscmp);
+ for (int i = 0; i < m_proto->m_notes.getCount(); ++i)
+ {
+ TCHAR *tags = m_proto->m_notes[i].GetTags();
+ for (TCHAR *tag = tags; tag && *tag; tag = tag + lstrlen(tag) + 1)
+ if (!tagSet.find(tag))
+ tagSet.insert(tag);
+ }
+
+ bool selected = false;
+ for (int j = 0; j < tagSet.getCount(); ++j)
+ {
+ bool select = !lstrcmp(szActiveTag, tagSet[j]);
+ selected |= select;
+ InsertTag(htiRoot, tagSet[j], select);
+ }
+
+ if (!selected)
+ m_tvFilter.SelectItem(htiRoot);
+
+ tagSet.destroy();
+ }
+
+ void RebuildTree()
+ {
+ TVITEMEX tvi = {0};
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ tvi.hItem = m_tvFilter.GetSelection();
+ m_tvFilter.GetItem(&tvi);
+ TCHAR *szActiveTag = mir_tstrdup((TCHAR *)tvi.lParam);
+
+ m_tvFilter.DeleteAllItems();
+
+ TVINSERTSTRUCT tvis = {0};
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.itemex.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE;
+ tvis.itemex.stateMask =
+ tvis.itemex.state = TVIS_BOLD|TVIS_EXPANDED;
+ tvis.itemex.pszText = TranslateT("All tags");
+ tvis.itemex.lParam = NULL;
+
+
+ PopulateTags(m_tvFilter.InsertItem(&tvis), szActiveTag);
+ mir_free(szActiveTag);
+ }
+
+ void InsertItem(CNoteItem &item)
+ {
+ m_lstNotes.AddString((TCHAR *)item.GetTitle(), (LPARAM)&item);
+ EnableControls();
+ }
+
+ void ListItems(const TCHAR *tag)
+ {
+ m_lstNotes.ResetContent();
+ for (int i = 0; i < m_proto->m_notes.getCount(); ++i)
+ if (m_proto->m_notes[i].HasTag(tag))
+ InsertItem(m_proto->m_notes[i]);
+ EnableControls();
+ }
+
+ void btnAdd_OnClick(CCtrlFilterListView *)
+ {
+ CNoteItem *pNote = new CNoteItem();
+ CJabberDlgNoteItem dlg(this, pNote);
+ dlg.DoModal();
+
+ if (pNote->IsNotEmpty())
+ {
+ m_proto->m_notes.insert(pNote);
+ m_proto->m_notes.Modify();
+ UpdateData();
+ } else
+ {
+ delete pNote;
+ return;
+ }
+ EnableControls();
+ }
+
+ void btnEdit_OnClick(CCtrlFilterListView *)
+ {
+ int idx = m_lstNotes.GetCurSel();
+ if (idx != LB_ERR)
+ {
+ if (CNoteItem *pItem = (CNoteItem *)m_lstNotes.GetItemData(idx))
+ {
+ CJabberDlgNoteItem dlg(this, pItem);
+ if (dlg.DoModal())
+ {
+ m_proto->m_notes.Modify();
+ RebuildTree();
+ }
+ }
+ }
+ EnableControls();
+ }
+
+ void btnRemove_OnClick(CCtrlFilterListView *)
+ {
+ int idx = m_lstNotes.GetCurSel();
+ if (idx != LB_ERR)
+ {
+ if (CNoteItem *pItem = (CNoteItem *)m_lstNotes.GetItemData(idx))
+ {
+ m_lstNotes.DeleteString(idx);
+ m_proto->m_notes.remove(pItem);
+ }
+ RebuildTree();
+ }
+ EnableControls();
+ }
+
+ void lstNotes_OnSelChange(CCtrlListBox *)
+ {
+ EnableControls();
+ }
+
+ void tvFilter_OnDeleteItem(CCtrlTreeView::TEventInfo *e)
+ {
+ TCHAR *szText = (TCHAR *)e->nmtv->itemOld.lParam;
+ mir_free(szText);
+ EnableControls();
+ }
+
+ void tvFilter_OnSelChanged(CCtrlTreeView::TEventInfo *e)
+ {
+ TCHAR *szText = (TCHAR *)e->nmtv->itemNew.lParam;
+ ListItems(szText);
+ EnableControls();
+ }
+
+ void btnSave_OnClick(CCtrlButton *)
+ {
+ XmlNodeIq iq(_T("set"));
+ HXML query = iq << XQUERY( _T(JABBER_FEAT_PRIVATE_STORAGE));
+ HXML storage = query << XCHILDNS(_T("storage"), _T(JABBER_FEAT_MIRANDA_NOTES));
+ m_proto->m_notes.SaveXml(storage);
+ m_proto->m_ThreadInfo->send(iq);
+ EnableControls();
+ }
+};
+
+CJabberDlgNotes::CJabberDlgNotes(CJabberProto *proto) :
+ CSuper(proto, IDD_NOTEBOOK, NULL),
+ m_btnAdd(this, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add")),
+ m_btnEdit(this, IDC_EDIT, SKINICON_OTHER_RENAME, LPGEN("Edit")),
+ m_btnRemove(this, IDC_REMOVE, SKINICON_OTHER_DELETE, LPGEN("Remove")),
+ m_lstNotes(this, IDC_LST_NOTES),
+ m_tvFilter(this, IDC_TV_FILTER),
+ m_btnSave(this, IDC_APPLY)
+{
+ m_btnAdd.OnClick = Callback(this, &CJabberDlgNotes::btnAdd_OnClick);
+ m_btnEdit.OnClick = Callback(this, &CJabberDlgNotes::btnEdit_OnClick);
+ m_btnRemove.OnClick = Callback(this, &CJabberDlgNotes::btnRemove_OnClick);
+ m_lstNotes.OnDblClick = Callback(this, &CJabberDlgNotes::btnEdit_OnClick);
+ m_lstNotes.OnSelChange = Callback(this, &CJabberDlgNotes::lstNotes_OnSelChange);
+ m_btnSave.OnClick = Callback(this, &CJabberDlgNotes::btnSave_OnClick);
+
+ m_tvFilter.OnSelChanged = Callback(this, &CJabberDlgNotes::tvFilter_OnSelChanged);
+ m_tvFilter.OnDeleteItem = Callback(this, &CJabberDlgNotes::tvFilter_OnDeleteItem);
+}
+
+void CJabberDlgNotes::UpdateData()
+{
+ RebuildTree();
+ //ListItems(NULL);
+ EnableControls();
+}
+
+void CJabberDlgNotes::OnInitDialog()
+{
+ CSuper::OnInitDialog();
+ WindowSetIcon( m_hwnd, m_proto, "notes" );
+
+ LOGFONT lf, lfTmp;
+ m_hfntNormal = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ GetObject(m_hfntNormal, sizeof(lf), &lf);
+ lfTmp = lf; lfTmp.lfWeight = FW_BOLD;
+ m_hfntBold = CreateFontIndirect(&lfTmp);
+ lfTmp = lf; lfTmp.lfHeight *= 0.8;
+ m_hfntSmall = CreateFontIndirect(&lfTmp);
+ m_lstNotes.SetFonts(m_hfntNormal, m_hfntSmall, m_hfntBold);
+
+ Utils_RestoreWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "notesWnd_");
+}
+
+void CJabberDlgNotes::OnClose()
+{
+ if (m_proto->m_notes.IsModified())
+ {
+ if (IDYES != MessageBox(m_hwnd, TranslateT("Notes are not saved, close this window without uploading data to server?"), TranslateT("Are you sure?"), MB_ICONWARNING|MB_YESNO|MB_DEFBUTTON2))
+ {
+ m_lresult = TRUE;
+ return;
+ }
+ }
+
+ Utils_SaveWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "notesWnd_");
+ DeleteObject(m_hfntSmall);
+ DeleteObject(m_hfntBold);
+ CSuper::OnClose();
+}
+
+void CJabberDlgNotes::OnDestroy()
+{
+ m_tvFilter.DeleteAllItems();
+ m_proto->m_pDlgNotes = NULL;
+ CSuper::OnDestroy();
+}
+
+void CJabberDlgNotes::OnProtoCheckOnline(WPARAM, LPARAM)
+{
+ EnableControls();
+}
+
+void CJabberDlgNotes::OnProtoRefresh(WPARAM, LPARAM)
+{
+}
+
+int CJabberDlgNotes::Resizer(UTILRESIZECONTROL *urc)
+{
+ switch ( urc->wId ) {
+ case IDC_TV_FILTER:
+ return RD_ANCHORX_LEFT|RD_ANCHORY_HEIGHT;
+ case IDC_LST_NOTES:
+ return RD_ANCHORX_WIDTH|RD_ANCHORY_HEIGHT;
+ case IDC_APPLY:
+ case IDCANCEL:
+ return RD_ANCHORX_RIGHT|RD_ANCHORY_BOTTOM;
+ case IDC_ADD:
+ case IDC_EDIT:
+ case IDC_REMOVE:
+ return RD_ANCHORX_LEFT|RD_ANCHORY_BOTTOM;
+ }
+ return CSuper::Resizer(urc);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Launches the incoming note window
+
+void CJabberProto::ProcessIncomingNote(CNoteItem *pNote, bool ok)
+{
+ if (ok && pNote->IsNotEmpty())
+ {
+ m_notes.insert(pNote);
+
+ XmlNodeIq iq(_T("set"));
+ HXML query = iq << XQUERY( _T(JABBER_FEAT_PRIVATE_STORAGE));
+ HXML storage = query << XCHILDNS(_T("storage"), _T(JABBER_FEAT_MIRANDA_NOTES));
+ m_notes.SaveXml(storage);
+ m_ThreadInfo->send(iq);
+ } else
+ {
+ delete pNote;
+ }
+}
+
+void CJabberProto::ProcessOutgoingNote(CNoteItem *pNote, bool ok)
+{
+ if (!ok || !pNote->IsNotEmpty())
+ {
+ delete pNote;
+ return;
+ }
+
+ TCHAR buf[1024];
+ mir_sntprintf(buf, SIZEOF(buf), _T("Incoming note: %s\n\n%s\nTags: %s"),
+ pNote->GetTitle(), pNote->GetText(), pNote->GetTagsStr());
+
+ JabberCapsBits jcb = GetResourceCapabilites( pNote->GetFrom(), TRUE );
+
+ if ( jcb & JABBER_RESOURCE_CAPS_ERROR )
+ jcb = JABBER_RESOURCE_CAPS_NONE;
+
+ int nMsgId = SerialNext();
+
+ XmlNode m(_T("message"));
+ m << XATTR(_T("type"), _T("chat")) << XATTR( _T("to"), pNote->GetFrom() ) << XATTRID( nMsgId );
+ m << XCHILD(_T("body"), buf);
+ HXML hXmlItem = m << XCHILDNS(_T("x"), _T(JABBER_FEAT_MIRANDA_NOTES)) << XCHILD(_T("note"));
+ hXmlItem << XATTR(_T("tags"), pNote->GetTagsStr());
+ hXmlItem << XCHILD(_T("title"), pNote->GetTitle());
+ hXmlItem << XCHILD(_T("text"), pNote->GetText());
+
+ // message receipts XEP priority
+ if ( jcb & JABBER_CAPS_MESSAGE_RECEIPTS )
+ m << XCHILDNS( _T("request"), _T(JABBER_FEAT_MESSAGE_RECEIPTS));
+ else if ( jcb & JABBER_CAPS_MESSAGE_EVENTS ) {
+ HXML x = m << XCHILDNS( _T("x"), _T(JABBER_FEAT_MESSAGE_EVENTS));
+ x << XCHILD( _T("delivered")); x << XCHILD( _T("offline"));
+ }
+ else
+ nMsgId = -1;
+
+ m_ThreadInfo->send(m);
+ delete pNote;
+}
+
+bool CJabberProto::OnIncomingNote(const TCHAR *szFrom, HXML hXml)
+{
+ if (!m_options.AcceptNotes)
+ return false;
+
+ if (!szFrom || !hXml) return true;
+ CNoteItem *pItem = new CNoteItem(hXml, (TCHAR *)szFrom);
+ if (!pItem->IsNotEmpty())
+ {
+ delete pItem;
+ return true;
+ }
+
+ if (m_options.AutosaveNotes && HContactFromJID(szFrom))
+ {
+ ProcessIncomingNote(pItem, true);
+ return false;
+ }
+
+ CLISTEVENT cle = {0};
+ char szService[256];
+ mir_snprintf( szService, sizeof(szService),"%s%s", m_szModuleName, JS_INCOMING_NOTE_EVENT );
+ cle.cbSize = sizeof(CLISTEVENT);
+ cle.hIcon = (HICON)LoadIconEx("notes");
+ cle.flags = CLEF_PROTOCOLGLOBAL|CLEF_TCHAR;
+ cle.hDbEvent = (HANDLE)("test");
+ cle.lParam = (LPARAM)pItem;
+ cle.pszService = szService;
+ cle.ptszTooltip = TranslateT("Incoming note");
+ CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle);
+
+ return true;
+}
+
+INT_PTR __cdecl CJabberProto::OnIncomingNoteEvent(WPARAM, LPARAM lParam)
+{
+ CLISTEVENT *pCle = (CLISTEVENT *)lParam;
+ CNoteItem *pNote = (CNoteItem *)pCle->lParam;
+ if ( !pNote )
+ return 0;
+
+ CJabberDlgBase *pDlg = new CJabberDlgNoteItem(this, pNote, &CJabberProto::ProcessIncomingNote);
+ pDlg->Show();
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Menu handling
+
+INT_PTR __cdecl CJabberProto::OnMenuHandleNotes( WPARAM, LPARAM)
+{
+ UI_SAFE_OPEN_EX(CJabberDlgNotes, m_pDlgNotes, pDlg);
+ pDlg->UpdateData();
+ return 0;
+}
+
+INT_PTR __cdecl CJabberProto::OnMenuSendNote(WPARAM wParam, LPARAM)
+{
+ if (!wParam) return 0;
+
+ TCHAR szClientJid[ JABBER_MAX_JID_LEN ];
+ GetClientJID( JGetStringT( (HANDLE)wParam, "jid"), szClientJid, SIZEOF( szClientJid ));
+
+ CNoteItem *pItem = new CNoteItem( NULL, szClientJid );
+ CJabberDlgBase *pDlg = new CJabberDlgNoteItem(this, pItem, &CJabberProto::ProcessOutgoingNote);
+ pDlg->Show();
+
+ return 0;
+}
|