#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "resource.h" #include "version.h" #define MODULENAME "QuickSearch" #define QS_SHOWSERVICE "QuickSearch/Show" #define StatusSort 1000 #define QSTS_BYTE 0 #define QSTS_WORD 1 #define QSTS_DWORD 2 #define QSTS_STRING 3 #define QSTS_IP 4 #define QSTS_TIMESTAMP 5 #define QSTS_SIGNED 6 #define QSTS_HEXNUM 7 // must be non-zero for empty-column checking #define QST_SETTING 100 #define QST_SCRIPT 1 #define QST_SERVICE 2 #define QST_CONTACTINFO 3 #define QST_OTHER 200 #define QSTO_LASTSEEN 0 #define QSTO_LASTEVENT 1 #define QSTO_METACONTACT 2 #define QSTO_EVENTCOUNT 3 #define QSTO_DISPLAYNAME 4 #define QSTO_ACCOUNT 5 #define QSO_SORTBYSTATUS 0x00000001 // Sort by status #define QSO_DRAWGRID 0x00000002 // Draw listview grid #define QSO_TOOLSTYLE 0x00000004 // QS window tool style #define QSO_SAVEPATTERN 0x00000008 // Save filter pattern #define QSO_AUTOCLOSE 0x00000010 // Close QS window after action #define QSO_CLIENTICONS 0x00000020 // Show client icons (fingerprint) #define QSO_MAINOPTIONS 0x0000FFFF // mask for common options // QS window options #define QSO_STAYONTOP 0x00010000 // Stay QS window on top #define QSO_SHOWOFFLINE 0x00020000 // Show offline contacts #define QSO_COLORIZE 0x00040000 // Colorize lines #define QSO_SORTASC 0x00080000 // Sort column ascending struct ServiceDescr { char *service; LPARAM wParam, lParam; uint32_t wFlags, lFlags, flags; }; struct ColumnItem : public MZeroedObject { ColumnItem(const wchar_t *pszTitle, int _width = 64, int _setting_type = QST_SETTING); ColumnItem(const ColumnItem &src); ~ColumnItem(); int HasImage(const wchar_t *pwsztext) const; void SetSpecialColumns(); wchar_t *title; uint16_t setting_type = 0; // QST_* constants uint16_t width = 0; union { uint32_t dwFlags = 0; struct { bool bEnabled : 1; bool bInit : 1; bool bFilter : 1; bool isXstatus : 1; bool isGender : 1; bool isAccount : 1; bool isClient : 1; bool isGroup : 1; bool isContainer : 1; }; }; union { // 0: db setting struct { uint16_t datatype; // QSTS_* constants char *module; char *setting; }; // 1: script wchar_t *script; // 2: service ServiceDescr svc; // 3: contact info int cnftype; // CNF_* constants // 4: other int other; // QSTO_* constants }; }; struct ContactIntoColumn : public ColumnItem { ContactIntoColumn(const wchar_t *pwszTitle, int width, int _type) : ColumnItem(pwszTitle, width, QST_CONTACTINFO) { cnftype = _type; } }; ///////////////////////////////////////////////////////////////////////////////////////// #define so_mbottom "mbottom" #define so_mright "mright" #define so_mtop "mtop" #define so_mleft "mleft" #define so_columnsort "columnsort" #define so_flags "flags" #define so_numcolumns "numcolumns" #define so_item "item" #define so_title "title" #define so_width "width" #define so_flags "flags" #define so_setting_type "setting_type" #define so_cnftype "cnftype" #define so_datatype "datatype" #define so_module "module" #define so_setting "setting" #define so_script "script" #define so_service "service" #define so_restype "flags" #define so_wparam "wparam" #define so_lparam "lparam" #define so_other "other" ///////////////////////////////////////////////////////////////////////////////////////// enum ColorCode { bkg_norm, fgr_norm, bkg_odd, fgr_odd, bkg_dis, fgr_dis, bkg_del, fgr_del, bkg_hid, fgr_hid, bkg_meta, fgr_meta, bkg_sub, fgr_sub, color_max }; struct CMPlugin : public PLUGIN { CMPlugin(); COLORREF m_colors[color_max]; RECT m_rect; OBJLIST m_columns; int m_sortOrder; uint32_t m_flags; // QSO_* constants void LoadOptWnd(); void SaveOptWnd(); int LoadColumns(OBJLIST&); void LoadColumn(int n, ColumnItem &col); void LoadParamValue(char *buf, uint32_t &flags, LPARAM &value); void SaveOptions(); void SaveColumn(int n, const ColumnItem &col); void SaveParamValue(char *buf, uint32_t flags, LPARAM value); int Load() override; int Unload() override; }; extern bool g_bVarsInstalled, g_bTipperInstalled, g_bFingerInstalled; ///////////////////////////////////////////////////////////////////////////////////////// // utils.cpp int ColumnToListView(int col); int ListViewToColumn(int col); void LoadDefaultColumns(OBJLIST &dst); void SnapToScreen(RECT &rc); const wchar_t* cnf2str(int); wchar_t* BuildLastSeenTime(uint32_t timestamp); uint32_t BuildLastSeenTimeInt(MCONTACT hContact, const char *szModule); wchar_t* TimeToStrW(uint32_t timestamp); ///////////////////////////////////////////////////////////////////////////////////////// // windows.cpp struct QSFlags { union { uint32_t flags = 0; struct { bool bInList : 1; // in constant list bool bActive : 1; // contact in listview bool bDeleted : 1; // contact deleted bool bPattern : 1; // pattern check passed bool bAccDel : 1; // account deleted bool bAccOff : 1; // account disabled bool bIsMeta : 1; // contact is metacontact bool bIsSub : 1; // contact is part of metacontact }; }; }; struct CRowItem : public QSFlags { CRowItem(MCONTACT _1, class QSMainDlg *pDlg); ~CRowItem(); MCONTACT hContact; const char *szProto; int status = ID_STATUS_OFFLINE; WPARAM wparam = 0; LPARAM lparam = 0; void GetCellColor(int idx, COLORREF &clrBack, COLORREF &clrText); struct Val { wchar_t *text = nullptr; UINT_PTR data = UINT_PTR(-1); wchar_t* getText() const { return (text) ? text : L""; } void LoadOneItem(MCONTACT hContact, const ColumnItem &pCol, class QSMainDlg *pDlg); } *pValues; }; // status bar data struct CStatusBarItem : public QSFlags { CStatusBarItem(const char *_proto, int _flags) : szProto(_proto) { flags = _flags; } const char *szProto; int total = 0; int found = 0; int online = 0; int liston = 0; }; #define WM_CONTACT_ADDED (WM_USER+2) #define WM_CONTACT_DELETED (WM_USER+3) #define WM_STATUS_CHANGED (WM_USER+4) class QSMainDlg : public CDlgBase { friend struct CRowItem; OBJLIST m_rows; OBJLIST m_sbdata; UI_MESSAGE_MAP(QSMainDlg, CDlgBase); UI_MESSAGE(WM_SYSCOMMAND, OnSysCommand); UI_MESSAGE(WM_MOUSEMOVE, OnMouseMove); UI_MESSAGE(WM_KEYDOWN, OnKeydown); UI_MESSAGE(WM_CONTACT_ADDED, OnContactAdded); UI_MESSAGE(WM_CONTACT_DELETED, OnContactDeleted); UI_MESSAGE(WM_STATUS_CHANGED, OnStatusChanged); UI_MESSAGE_MAP_END(); // internal methods void AddColumn(int idx, ColumnItem *pCol); void AddContactToList(MCONTACT hContact, CRowItem *pRow); void AdvancedFilter(); void ChangeStatusPicture(CRowItem *pRow, MCONTACT hContact, LPARAM lParam); void ConvertToMeta(); void CopyMultiLines(); void DeleteByList(); void DeleteOneContact(MCONTACT hContact); wchar_t* DoMeta(MCONTACT hContact); void FillGrid(); void FillProtoCombo(); int FindItem(CRowItem *pRow); int FindMeta(MCONTACT hMeta, WPARAM &metaNum); CRowItem* FindRow(MCONTACT hContact); MCONTACT GetFocusedContact(); int GetLVSubItem(int x, int y); void MoveToContainer(const wchar_t *pwszName); void MoveToGroup(const wchar_t *pwszName); void PrepareTable(bool bReset = false); void ProcessLine(CRowItem *pRow, bool test = true); void SaveColumnOrder(); void ShowContactMenu(MCONTACT, int); void ShowContactMsgDlg(MCONTACT hContact); void ShowMultiPopup(int); void Sort(); void UpdateLVCell(int item, int column, const wchar_t *pwszText = nullptr); __forceinline CRowItem* GetRow(int i) { return (CRowItem *)m_grid.GetItemData(i); } // status bar HWND hwndStatusBar = 0, HintWnd = 0; void DrawSB(); void UpdateSB(); // internal data int hLastMeta; bool TTShowed = false; int tableColumns = 0; HICON hIconF = 0, hIconM = 0; HANDLE hAdd, hDelete, hChange; HGENMENU mnuhandle = 0; // patterns struct Pattern { Pattern(const wchar_t *pwszText) : str(pwszText) {} const wchar_t *str; bool res = false; }; OBJLIST m_patterns; ptrW m_wszPatternBuf; bool bShowOffline; char *szFilterProto = nullptr; bool CheckPattern(CRowItem *pRow); void MakePattern(const wchar_t *pwszPattern); // controls CTimer m_hover; CCtrlEdit edtFilter; CCtrlCheck chkShowOffline, chkColorize; CCtrlCombo cmbProto; CCtrlButton btnRefresh; CCtrlListView m_grid; public: QSMainDlg(const wchar_t *pattern); bool OnInitDialog() override; void OnDestroy() override; int Resizer(UTILRESIZECONTROL *urc) override; void ChangeCellValue(MCONTACT hContact, int col); bool PrepareToFill(); void ToggleColumn(int col); INT_PTR OnSysCommand(UINT, WPARAM, LPARAM); INT_PTR OnMouseMove(UINT, WPARAM, LPARAM); INT_PTR OnKeydown(UINT, WPARAM, LPARAM); INT_PTR OnContactAdded(UINT, WPARAM, LPARAM); INT_PTR OnContactDeleted(UINT, WPARAM, LPARAM); INT_PTR OnStatusChanged(UINT, WPARAM, LPARAM); INT_PTR NewEditProc(UINT, WPARAM, LPARAM); INT_PTR NewLVProc(UINT, WPARAM, LPARAM); void onBuildMenu_Grid(CContextMenuPos *pos); void onColumnClick_Grid(CCtrlListView::TEventInfo *ev); void onCustomDraw_Grid(CCtrlListView::TEventInfo *ev); void onDblClick_Grid(CCtrlListView::TEventInfo *ev); void onSelChange_Proto(CCtrlCombo *); void onChange_Filter(CCtrlEdit *); void onChange_ShowOffline(CCtrlCheck *); void onChange_Colorize(CCtrlCheck *); void onClick_Refresh(CCtrlButton *); void onTimer_Hover(CTimer *); }; int CloseSrWindow(bool = true); int OpenSrWindow(const wchar_t *pwszPattern);