From 9bd135eb5be03099a8cfbc81ac9903a97044ae0f Mon Sep 17 00:00:00 2001 From: Vlad Mironov Date: Thu, 20 Sep 2012 12:00:44 +0000 Subject: =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20Traf?= =?UTF-8?q?ficCounter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://svn.miranda-ng.org/main/trunk@1607 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/TrafficCounter/.cproject | 168 ++ plugins/TrafficCounter/.project | 70 + plugins/TrafficCounter/TrafficCounter.c | 1744 ++++++++++++++++++++ plugins/TrafficCounter/TrafficCounter.h | 85 + plugins/TrafficCounter/TrafficCounter_10.vcxproj | 675 ++++++++ .../TrafficCounter_10.vcxproj.filters | 64 + plugins/TrafficCounter/commonheaders.c | 1 + plugins/TrafficCounter/commonheaders.h | 160 ++ plugins/TrafficCounter/misc.c | 303 ++++ plugins/TrafficCounter/misc.h | 32 + plugins/TrafficCounter/opttree.c | 416 +++++ plugins/TrafficCounter/opttree.h | 54 + plugins/TrafficCounter/res/network.ico | Bin 0 -> 1150 bytes plugins/TrafficCounter/resource.h | 457 +++++ plugins/TrafficCounter/resource.rc | 233 +++ plugins/TrafficCounter/statistics.c | 751 +++++++++ plugins/TrafficCounter/statistics.h | 45 + plugins/TrafficCounter/vars.c | 185 +++ plugins/TrafficCounter/vars.h | 9 + plugins/TrafficCounter/version.h | 3 + 20 files changed, 5455 insertions(+) create mode 100644 plugins/TrafficCounter/.cproject create mode 100644 plugins/TrafficCounter/.project create mode 100644 plugins/TrafficCounter/TrafficCounter.c create mode 100644 plugins/TrafficCounter/TrafficCounter.h create mode 100644 plugins/TrafficCounter/TrafficCounter_10.vcxproj create mode 100644 plugins/TrafficCounter/TrafficCounter_10.vcxproj.filters create mode 100644 plugins/TrafficCounter/commonheaders.c create mode 100644 plugins/TrafficCounter/commonheaders.h create mode 100644 plugins/TrafficCounter/misc.c create mode 100644 plugins/TrafficCounter/misc.h create mode 100644 plugins/TrafficCounter/opttree.c create mode 100644 plugins/TrafficCounter/opttree.h create mode 100644 plugins/TrafficCounter/res/network.ico create mode 100644 plugins/TrafficCounter/resource.h create mode 100644 plugins/TrafficCounter/resource.rc create mode 100644 plugins/TrafficCounter/statistics.c create mode 100644 plugins/TrafficCounter/statistics.h create mode 100644 plugins/TrafficCounter/vars.c create mode 100644 plugins/TrafficCounter/vars.h create mode 100644 plugins/TrafficCounter/version.h (limited to 'plugins') diff --git a/plugins/TrafficCounter/.cproject b/plugins/TrafficCounter/.cproject new file mode 100644 index 0000000000..137e6305dc --- /dev/null +++ b/plugins/TrafficCounter/.cproject @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/TrafficCounter/.project b/plugins/TrafficCounter/.project new file mode 100644 index 0000000000..9662d3935a --- /dev/null +++ b/plugins/TrafficCounter/.project @@ -0,0 +1,70 @@ + + + TrafficCounter + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.buildLocation + ${workspace_loc:/tcounter/Debug} + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/plugins/TrafficCounter/TrafficCounter.c b/plugins/TrafficCounter/TrafficCounter.c new file mode 100644 index 0000000000..b0e4f3ee17 --- /dev/null +++ b/plugins/TrafficCounter/TrafficCounter.c @@ -0,0 +1,1744 @@ +/* +Traffic Counter plugin for Miranda IM +Copyright 2007-2012 Mironych. + +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 "commonheaders.h" +#include "m_skin_eng.h" + +/*-------------------------------------------------------------------------------------------------------------------*/ +//GLOBAL +/*-------------------------------------------------------------------------------------------------------------------*/ +HINSTANCE hInst; + +int hLangpack = 0; // Поддержка плагинозависимого перевода. + +TCHAR* TRAFFIC_COUNTER_WINDOW_CLASS = _T("TrafficCounterWnd"); + +/*-------------------------------------------------------------------------------------------------------------------*/ +//TRAFFIC COUNTER +/*-------------------------------------------------------------------------------------------------------------------*/ +OPTTREE_OPTION *pOptions; // Через этот указатель модуль opttree.c может добраться до списка опций. +WORD notify_send_size = 0; +WORD notify_recv_size = 0; +// +// Цвет шрифта и фона +COLORREF Traffic_BkColor,Traffic_FontColor; + +//notify +int Traffic_PopupBkColor; +int Traffic_PopupFontColor; +char Traffic_Notify_time_value; +short int Traffic_Notify_size_value; +char Traffic_PopupTimeoutDefault; +char Traffic_PopupTimeoutValue; + +unsigned short int Traffic_LineHeight; +// +TCHAR Traffic_CounterFormat[512]; +TCHAR Traffic_TooltipFormat[512]; +// +HANDLE Traffic_FrameID = NULL; + +char Traffic_AdditionSpace; + +HANDLE h_OptInit; +HANDLE h_ModulesLoaded; +HANDLE h_SystemShutDown; +HANDLE h_OnRecv, h_OnSend; +HANDLE h_OnAccListChange; +HANDLE h_FontReload; + +HFONT Traffic_h_font = NULL; +HMENU TrafficPopupMenu = NULL; +HGENMENU hTrafficMainMenuItem = NULL; + +/*-------------------------------------------------------------------------------------------------------------------*/ +//TIME COUNTER +/*-------------------------------------------------------------------------------------------------------------------*/ +static HANDLE h_AckHook; +BYTE online_count = 0; + +/*-------------------------------------------------------------------------------------------------------------------*/ +//font service support +/*-------------------------------------------------------------------------------------------------------------------*/ +int TrafficFontHeight = 0; +FontIDT TrafficFontID; +ColourIDT TrafficBackgroundColorID; + +//--------------------------------------------------------------------------------------------- +// Для ToolTip +//--------------------------------------------------------------------------------------------- +BOOL TooltipShowing; +POINT TooltipPosition; + +// Вспомогательные переменные чтобы заставить работать ключевой цвет +BOOL UseKeyColor; +COLORREF KeyColor; + +// Внутренние функции модуля. +void Traffic_AddMainMenuItem(void); + +// {82181510-5DFA-49d7-B469-33871E2AE8B5} +#define MIID_TRAFFICCOUNTER {0x82181510, 0x5dfa, 0x49d7, { 0xb4, 0x69, 0x33, 0x87, 0x1e, 0x2a, 0xe8, 0xb5}} + +PLUGININFOEX pluginInfoEx = +{ + sizeof(PLUGININFOEX), + "Traffic Counter", + 0, // Начиная с версии ядра 0.92.1.0 поле с версией не используется. + "Adding traffic and time counters", + "Ghost, Mironych", + "", + "© 2002-2006 Ghost, © 2007-2012 Mironych ["__DATE__" "__TIME__"]", + "", + UNICODE_AWARE, + MIID_TRAFFICCOUNTER +}; + +__declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) +{ + mirandaVer = mirandaVersion; + return &pluginInfoEx; +} + +static const MUUID interfaces[] = {MIID_TRAFFICCOUNTER, MIID_LAST}; + +__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ +/* switch(fdwReason) + { + case DLL_PROCESS_ATTACH:*/ + hInst = hinstDLL; +/* DisableThreadLibraryCalls(hInst); + break; + + case DLL_PROCESS_DETACH: + PostMessage(TrafficHwnd,WM_USER+697,0,666); + // + break; + }*/ + // + return TRUE; +} + +int __declspec(dllexport) Load(void) +{ + if (mirandaVer < PLUGIN_MAKE_VERSION(0, 92, 2, 0)) return -1; + + // Получаем дескриптор языкового пакета. + mir_getLP(&pluginInfoEx); + + h_OptInit = HookEvent(ME_OPT_INITIALISE,TrafficCounterOptInitialise); + h_ModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED,TrafficCounterModulesLoaded); + h_AckHook = HookEvent(ME_PROTO_ACK,ProtocolAckHook); + h_OnAccListChange = HookEvent(ME_PROTO_ACCLISTCHANGED, OnAccountsListChange); + h_SystemShutDown = HookEvent(ME_SYSTEM_OKTOEXIT, TrafficCounterShutdown); + + return 0; +} + +int __declspec(dllexport) Unload(void) +{ + return 0; +} + +int TrafficCounterShutdown(WPARAM wParam, LPARAM lParam) +{ + KillTimer(TrafficHwnd, TIMER_REDRAW); + KillTimer(TrafficHwnd, TIMER_NOTIFY_TICK); + + // Отказываемся от обработки событий. + UnhookEvent(h_FontReload); + UnhookEvent(h_OnAccListChange); + UnhookEvent(h_AckHook); + UnhookEvent(h_ModulesLoaded); + UnhookEvent(h_OnRecv); + UnhookEvent(h_OnSend); + UnhookEvent(h_OptInit); + UnhookEvent(h_SystemShutDown); + + SaveSettings(0); + + // Удаляем пункт главного меню. + if (hTrafficMainMenuItem) + { + CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)hTrafficMainMenuItem, 0); + hTrafficMainMenuItem = NULL; + } + // Удаляем контекстное меню. + if (TrafficPopupMenu) + { + DestroyMenu(TrafficPopupMenu); + TrafficPopupMenu = NULL; + } + // Разрегистрируем процедуру отрисовки фрейма. + CallService(MS_SKINENG_REGISTERPAINTSUB, (WPARAM)TrafficHwnd, (LPARAM)NULL); + // Удаляем фрейм. + if( (ServiceExists(MS_CLIST_FRAMES_REMOVEFRAME)) && Traffic_FrameID ) + { + CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)Traffic_FrameID, 0); + Traffic_FrameID = NULL; + } + // Разрегистрируем горячую клавишу. + CallService(MS_HOTKEY_UNREGISTER, 0, (LPARAM)"TC_Show_Hide"); + // Разрегистрируем функцию переключения видимости окна. + DestroyServiceFunction(MenuCommand_TrafficShowHide); + // Удаляем шрифт. + if (Traffic_h_font) + { + DeleteObject(Traffic_h_font); + Traffic_h_font = NULL; + } + + // Убиваем все рабочие данные. + DestroyProtocolList(); + + return 0; +} + +int TrafficCounterModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + DBVARIANT dbv; + + CreateProtocolList(); + + // Читаем флаги + unOptions.Flags = DBGetContactSettingDword(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, 0x0882); + Stat_SelAcc = DBGetContactSettingWord(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_STAT_ACC_OPT, 0x01); + + //settings for notification + Traffic_PopupBkColor = DBGetContactSettingDword(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_BKCOLOR,RGB(200,255,200)); + Traffic_PopupFontColor = DBGetContactSettingDword(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_FONTCOLOR,RGB(0,0,0)); + // + Traffic_Notify_time_value = DBGetContactSettingByte(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_TIME_VALUE,10); + // + Traffic_Notify_size_value = DBGetContactSettingWord(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_SIZE_VALUE,100); + // + //popup timeout + Traffic_PopupTimeoutDefault = DBGetContactSettingByte(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_DEFAULT,1); + Traffic_PopupTimeoutValue = DBGetContactSettingByte(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_VALUE,5); + + // Формат счётчика для каждого активного протокола + if (DBGetContactSettingTString(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_COUNTER_FORMAT, &dbv) == 0) + { + if(lstrlen(dbv.ptszVal) > 0) + lstrcpyn(Traffic_CounterFormat, dbv.ptszVal, SIZEOF(Traffic_CounterFormat)); + // + DBFreeVariant(&dbv); + } + else //defaults here + { + _tcscpy(Traffic_CounterFormat, _T("{I4}\x0D\x0A\x0A\ +{R65}?tc_GetTraffic(%extratext%,now,sent,d)\x0D\x0A\x0A\ +{R115}?tc_GetTraffic(%extratext%,now,received,d)\x0D\x0A\x0A\ +{R165}?tc_GetTraffic(%extratext%,total,both,d)\x0D\x0A\x0A\ +{L180}?if3(?tc_GetTime(%extratext%,now,hh:mm:ss),)\x0D\x0A\x0A\ +{L230}?if3(?tc_GetTime(%extratext%,total,d hh:mm),)")); + } + + // Формат всплывающих подсказок + if (DBGetContactSettingTString(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_TOOLTIP_FORMAT, &dbv) == 0) + { + if(lstrlen(dbv.ptszVal) > 0) + lstrcpyn(Traffic_TooltipFormat, dbv.ptszVal, SIZEOF(Traffic_TooltipFormat)); + // + DBFreeVariant(&dbv); + } + else //defaults here + { + _tcscpy(Traffic_TooltipFormat, _T("Traffic Counter")); + } + + Traffic_AdditionSpace = DBGetContactSettingByte(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_ADDITION_SPACE, 0); + + // Счётчик времени онлайна + OverallInfo.Total.Timer = DBGetContactSettingDword(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_TOTAL_ONLINE_TIME, 0); + + //register traffic font + TrafficFontID.cbSize = sizeof(FontIDT); + _tcscpy(TrafficFontID.group, LPGENT("Traffic counter")); + _tcscpy(TrafficFontID.name, LPGENT("Font")); + strcpy(TrafficFontID.dbSettingsGroup, TRAFFIC_SETTINGS_GROUP); + strcpy(TrafficFontID.prefix, "Font"); + TrafficFontID.flags = FIDF_DEFAULTVALID | FIDF_SAVEPOINTSIZE; + TrafficFontID.deffontsettings.charset = DEFAULT_CHARSET; + TrafficFontID.deffontsettings.colour = GetSysColor(COLOR_BTNTEXT); + TrafficFontID.deffontsettings.size = 12; + TrafficFontID.deffontsettings.style = 0; + _tcscpy(TrafficFontID.deffontsettings.szFace, _T("Arial")); + TrafficFontID.order = 0; + FontRegisterT(&TrafficFontID); + + // Регистрируем цвет фона + TrafficBackgroundColorID.cbSize = sizeof(ColourIDT); + _tcscpy(TrafficBackgroundColorID.group, LPGENT("Traffic counter")); + _tcscpy(TrafficBackgroundColorID.name, LPGENT("Font")); + strcpy(TrafficBackgroundColorID.dbSettingsGroup, TRAFFIC_SETTINGS_GROUP); + strcpy(TrafficBackgroundColorID.setting, "FontBkColor"); + TrafficBackgroundColorID.defcolour = GetSysColor(COLOR_BTNFACE); + ColourRegisterT(&TrafficBackgroundColorID); + + h_FontReload = HookEvent(ME_FONT_RELOAD, UpdateFonts); + + // Добавляем поддержку плагина Variables + RegisterVariablesTokens(); + + CreateServiceFunction("TrafficCounter/ShowHide", MenuCommand_TrafficShowHide); + // Регистрируем горячую клавишу для показа/скрытия фрейма + { + HOTKEYDESC hkd = {0}; + hkd.cbSize = sizeof(hkd); + hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL|HOTKEYF_SHIFT,'T'); + hkd.pszSection = "Traffic Counter"; + hkd.pszDescription = "Show/Hide frame"; + hkd.pszName = "TC_Show_Hide"; + hkd.pszService = "TrafficCounter/ShowHide"; + Hotkey_Register(&hkd); + } + + // Добавляем пункт в главное меню. + if (unOptions.ShowMainMenuItem) + Traffic_AddMainMenuItem(); + + // Создаём контекстное меню. + if (TrafficPopupMenu = CreatePopupMenu()) + { + AppendMenu(TrafficPopupMenu,MF_STRING,POPUPMENU_HIDE,TranslateT("Hide traffic window")); + AppendMenu(TrafficPopupMenu,MF_STRING,POPUPMENU_CLEAR_NOW,TranslateT("Clear the current (Now:) value")); + } + + // Регистрируем обработчики событий Netlib + h_OnRecv = HookEvent(ME_NETLIB_FASTRECV, TrafficRecv); + h_OnSend = HookEvent(ME_NETLIB_FASTSEND, TrafficSend); + + CreateTrafficWindow((HWND)CallService(MS_CLUI_GETHWND, 0, 0)); + UpdateFonts(0, 0); //Load and create fonts here + + return 0; +} + +static BOOL CALLBACK DlgProcPopupsTraffic(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + // + CheckDlgButton(hwndDlg,IDC_NOTIFYSIZE,(unOptions.NotifyBySize) ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt(hwndDlg,IDC_ENOTIFYSIZE,Traffic_Notify_size_value,0); + SendDlgItemMessage(hwndDlg,IDC_ENOTIFYSIZE,EM_LIMITTEXT,4,0); + if (!unOptions.NotifyBySize) EnableWindow(GetDlgItem(hwndDlg,IDC_ENOTIFYSIZE),0); + CheckDlgButton(hwndDlg,IDC_NOTIFYTIME,(unOptions.NotifyByTime) ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt(hwndDlg,IDC_ENOTIFYTIME,Traffic_Notify_time_value,0); + SendDlgItemMessage(hwndDlg,IDC_ENOTIFYTIME,EM_LIMITTEXT,2,0); + if (!unOptions.NotifyByTime) EnableWindow(GetDlgItem(hwndDlg,IDC_ENOTIFYTIME),0); + //colors + SendDlgItemMessage(hwndDlg,IDC_COLOR1,CPM_SETDEFAULTCOLOUR,0,RGB(200,255,200)); + SendDlgItemMessage(hwndDlg,IDC_COLOR1,CPM_SETCOLOUR,0,Traffic_PopupBkColor); + SendDlgItemMessage(hwndDlg,IDC_COLOR2,CPM_SETDEFAULTCOLOUR,0,RGB(0,0,0)); + SendDlgItemMessage(hwndDlg,IDC_COLOR2,CPM_SETCOLOUR,0,Traffic_PopupFontColor); + //timeout + CheckDlgButton(hwndDlg,IDC_RADIO_FROMPOPUP,(Traffic_PopupTimeoutDefault != 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,IDC_RADIO_CUSTOM,(Traffic_PopupTimeoutDefault == 0) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg,IDC_POPUP_TIMEOUT),Traffic_PopupTimeoutDefault == 0); + SetDlgItemInt(hwndDlg,IDC_POPUP_TIMEOUT,Traffic_PopupTimeoutValue,0); + SendDlgItemMessage(hwndDlg,IDC_POPUP_TIMEOUT,EM_LIMITTEXT,2,0); + + return 0; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_NOTIFYSIZE: + EnableWindow(GetDlgItem(hwndDlg,IDC_ENOTIFYSIZE),IsDlgButtonChecked(hwndDlg,IDC_NOTIFYSIZE)); + break; + + case IDC_ENOTIFYSIZE: + if (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus()) return 0; + break; + + case IDC_NOTIFYTIME: + EnableWindow(GetDlgItem(hwndDlg,IDC_ENOTIFYTIME),IsDlgButtonChecked(hwndDlg,IDC_NOTIFYTIME)); + break; + + case IDC_ENOTIFYTIME: + if (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus()) return 0; + break; + + case IDC_RESETCOLORS: + SendDlgItemMessage(hwndDlg,IDC_COLOR1,CPM_SETDEFAULTCOLOUR,0,RGB(200,255,200)); + SendDlgItemMessage(hwndDlg,IDC_COLOR1,CPM_SETCOLOUR,0,RGB(200,255,200)); + SendDlgItemMessage(hwndDlg,IDC_COLOR2,CPM_SETDEFAULTCOLOUR,0,RGB(0,0,0)); + SendDlgItemMessage(hwndDlg,IDC_COLOR2,CPM_SETCOLOUR,0,RGB(0,0,0)); + break; + + case IDC_RADIO_FROMPOPUP: + case IDC_RADIO_CUSTOM: + EnableWindow(GetDlgItem(hwndDlg,IDC_POPUP_TIMEOUT),IsDlgButtonChecked(hwndDlg,IDC_RADIO_CUSTOM)); + break; + + case IDC_TEST: + NotifyOnRecv(); + NotifyOnSend(); + return 0; + + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + return 0; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + if (((LPNMHDR)lParam)->code == PSN_APPLY ) { + unOptions.NotifyBySize = IsDlgButtonChecked(hwndDlg,IDC_NOTIFYSIZE); + Traffic_Notify_size_value = GetDlgItemInt(hwndDlg,IDC_ENOTIFYSIZE,NULL,0); + unOptions.NotifyByTime = IsDlgButtonChecked(hwndDlg,IDC_NOTIFYTIME); + Traffic_Notify_time_value = GetDlgItemInt(hwndDlg,IDC_ENOTIFYTIME,NULL,0); + // + Traffic_PopupBkColor = SendDlgItemMessage(hwndDlg,IDC_COLOR1,CPM_GETCOLOUR,0,0); + Traffic_PopupFontColor = SendDlgItemMessage(hwndDlg,IDC_COLOR2,CPM_GETCOLOUR,0,0); + // + Traffic_PopupTimeoutDefault = IsDlgButtonChecked(hwndDlg,IDC_RADIO_FROMPOPUP); + if (Traffic_PopupTimeoutDefault == 0) Traffic_PopupTimeoutValue = GetDlgItemInt(hwndDlg,IDC_POPUP_TIMEOUT,NULL,0); + // + UpdateNotifyTimer(); + return TRUE; + } + break; + } + break; + } + return 0; +} + +static BOOL CALLBACK DlgProcTCOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD i, j, l; + BOOL result; + static BYTE Initialized = 0; + static WORD optionCount = 0; + static OPTTREE_OPTION options[] = + { + {0, LPGENT("Display/") LPGENT("Icon"), + OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, "DrawProtoIcon"}, + {0, LPGENT("Display/") LPGENT("Account name"), + OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, "DrawProtoName"}, + {0, LPGENT("Display/") LPGENT("Current traffic"), + OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, "DrawCurrentTraffic"}, + {0, LPGENT("Display/") LPGENT("Total traffic"), + OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, "DrawTotalTraffic"}, + {0, LPGENT("Display/") LPGENT("Current online"), + OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, "DrawCurrentTime"}, + {0, LPGENT("Display/") LPGENT("Total online"), + OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, "DrawTotalTime"}, + {0, LPGENT("General/") LPGENT("Draw frame as skin element"), + OPTTREE_CHECK, 1, NULL, "DrawFrmAsSkin"}, + {0, LPGENT("General/") LPGENT("Show tooltip in traffic window"), + OPTTREE_CHECK, 1, NULL, "ShowTooltip"}, + {0, LPGENT("General/") LPGENT("\"Toggle traffic counter\" in main menu"), + OPTTREE_CHECK, 1, NULL, "ShowMainMenuItem"}, + // Резервируем место под активные и видимые протоколы + // Максимум 16 позиций видимых и 16 активных + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, NULL, OPTTREE_CHECK, OPTTREE_INVISIBLE, NULL, NULL}, + {0, LPGENT("Visible accounts/") LPGENT("Summary traffic for visible accounts"), + OPTTREE_CHECK, 1, NULL, "ShowSummary"}, + {0, LPGENT("Visible accounts/") LPGENT("Overall traffic"), + OPTTREE_CHECK, 1, NULL, "ShowOverall"}, + }; + + if (!Initialized) + { + pOptions = options; + optionCount = SIZEOF(options); + // Если нет Variables, активируем галочки для старого метода рисования + if (!ServiceExists(MS_VARS_FORMATSTRING)) + { + for (i = 0; i < 8; i++) options[i].dwFlag = 1; + } + + // Флажки для видимости аккаунтов создаются в любом случае. + for (i = j = 0; (j < NumberOfAccounts) && (i < optionCount) ; i++) + if ((options[i].dwFlag & OPTTREE_INVISIBLE) && !options[i].szSettingName) + { + options[i].szSettingName = (char*)mir_alloc(1 + strlen(ProtoList[j].name)); + strcpy(options[i].szSettingName, ProtoList[j].name); + l = 20 + _tcslen(ProtoList[j].tszAccountName); + options[i].szOptionName = (TCHAR*)mir_alloc(sizeof(TCHAR) * l); + mir_sntprintf(options[i].szOptionName, + l, + _T("Visible accounts/%s"), + ProtoList[j].tszAccountName); + options[i].dwFlag = (ProtoList[j++].Enabled ? 1 : OPTTREE_INVISIBLE) + | OPTTREE_NOTRANSLATE; + } + Initialized = 1; + } + + if (OptTree_ProcessMessage(hwndDlg, msg, wParam, lParam, &result, IDC_APPEARANCEOPTIONS, options, optionCount)) + return result; + + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + SendDlgItemMessage(hwndDlg, IDC_SPIN1, UDM_SETRANGE, 0, MAKELONG(15, 0)); + SendDlgItemMessage(hwndDlg, IDC_SPIN1, UDM_SETPOS, 0, GetDlgItemInt(hwndDlg, IDC_EDIT_SPACE, NULL, FALSE)); + + //show/hide button + SetDlgItemText(hwndDlg,IDC_BSHOWHIDE,(IsWindowVisible(TrafficHwnd) != 0)? TranslateT("Hide now") : TranslateT("Show now")); + + // Строки формата для счётчиков + EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT_COUNTER_FORMAT),ServiceExists(MS_VARS_FORMATSTRING)); + SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT_COUNTER_FORMAT), Traffic_CounterFormat); + + // Формат всплывающей подсказки + EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT_TOOLTIP_FORMAT), + ServiceExists("mToolTip/ShowTipW") || ServiceExists("mToolTip/ShowTip")); + SetWindowText(GetDlgItem(hwndDlg, IDC_EDIT_TOOLTIP_FORMAT), Traffic_TooltipFormat); + + // Display traffic for current... + SendDlgItemMessage(hwndDlg, IDC_COMBO_AUTO_CLEAR, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Day")); + SendDlgItemMessage(hwndDlg, IDC_COMBO_AUTO_CLEAR, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Week")); + SendDlgItemMessage(hwndDlg, IDC_COMBO_AUTO_CLEAR, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Month")); + SendDlgItemMessage(hwndDlg, IDC_COMBO_AUTO_CLEAR, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Year")); + SendDlgItemMessage(hwndDlg, IDC_COMBO_AUTO_CLEAR, CB_SETCURSEL, unOptions.PeriodForShow, 0); + + // Интервал между строками + SetDlgItemInt(hwndDlg, IDC_EDIT_SPACE, Traffic_AdditionSpace, 0); + SendDlgItemMessage(hwndDlg, IDC_EDIT_SPACE, EM_LIMITTEXT, 2, 0); + + // Appearance + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.DrawProtoIcon, "DrawProtoIcon"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.DrawProtoName, "DrawProtoName"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.DrawCurrentTraffic, "DrawCurrentTraffic"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.DrawTotalTraffic, "DrawTotalTraffic"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.DrawCurrentTimeCounter, "DrawCurrentTime"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.DrawTotalTimeCounter, "DrawTotalTime"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.DrawFrmAsSkin, "DrawFrmAsSkin"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.ShowSummary , "ShowSummary"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.ShowTooltip, "ShowTooltip"); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.ShowMainMenuItem, "ShowMainMenuItem"); + + // Настройки видимости протоколов + for (i = 0; i < NumberOfAccounts; i++) + { + char buffer[32]; + strcpy(buffer, ProtoList[i].name); + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, ProtoList[i].Visible, buffer); + } + OptTree_SetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, unOptions.ShowOverall, "ShowOverall"); + + EnableWindow(GetDlgItem(GetParent(hwndDlg),IDC_APPLY),FALSE); + return 0; + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDC_BSHOWHIDE: + MenuCommand_TrafficShowHide(0, 0); + SetDlgItemText(hwndDlg,IDC_BSHOWHIDE,IsWindowVisible(TrafficHwnd)? TranslateT("Hide now") : TranslateT("Show now")); + return 0; + + case IDC_EDIT_SPACE: + case IDC_EDIT_COUNTER_FORMAT: + case IDC_EDIT_OVERALL_COUNTER_FORMAT: + case IDC_EDIT_TOOLTIP_FORMAT: + if (HIWORD(wParam) == EN_CHANGE) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case IDC_COMBO_AUTO_CLEAR: + if (HIWORD(wParam) == CBN_SELCHANGE) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + break; + } + + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR)lParam; + + switch (lpnmhdr->code) + { + case PSN_APPLY: + { + unOptions.PeriodForShow = (char)SendDlgItemMessage(hwndDlg,IDC_COMBO_AUTO_CLEAR,CB_GETCURSEL,0,0); + + // Интервал между строками + Traffic_AdditionSpace = GetDlgItemInt(hwndDlg, IDC_EDIT_SPACE, NULL, 0); + // Настройки Appearance + unOptions.DrawProtoIcon = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "DrawProtoIcon"); + unOptions.DrawProtoName = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "DrawProtoName"); + unOptions.DrawCurrentTraffic = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "DrawCurrentTraffic"); + unOptions.DrawTotalTraffic = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "DrawTotalTraffic"); + unOptions.DrawTotalTimeCounter = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "DrawTotalTime"); + unOptions.DrawCurrentTimeCounter = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "DrawCurrentTime"); + unOptions.DrawTotalTimeCounter = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "DrawTotalTime"); + unOptions.DrawFrmAsSkin = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "DrawFrmAsSkin"); + unOptions.ShowSummary = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "ShowSummary"); + unOptions.ShowTooltip = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "ShowTooltip"); + unOptions.ShowMainMenuItem = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "ShowMainMenuItem"); + + // Настройки видимости протоколов + for (i = 0; i < NumberOfAccounts; i++) + { + char buffer[32]; + strcpy(buffer, ProtoList[i].name); + ProtoList[i].Visible = (BYTE)OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, buffer); + } + unOptions.ShowOverall = OptTree_GetOptions(hwndDlg, IDC_APPEARANCEOPTIONS, options, optionCount, "ShowOverall"); + + // Формат счётчиков + GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT_COUNTER_FORMAT), Traffic_CounterFormat, 512); + // Формат всплывающей подсказки + GetWindowText(GetDlgItem(hwndDlg, IDC_EDIT_TOOLTIP_FORMAT), Traffic_TooltipFormat, 512); + + // Ключевой цвет + UseKeyColor = DBGetContactSettingByte(NULL, "ModernSettings", "UseKeyColor", 1); + KeyColor = DBGetContactSettingDword(NULL, "ModernSettings", "KeyColor", 0); + + // Перерисовываем фрейм + UpdateTrafficWindowSize(); + + // Если отключается показ пункта главного меню, то удаляем его. + if (!unOptions.ShowMainMenuItem && hTrafficMainMenuItem) + { + CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)hTrafficMainMenuItem, 0); + hTrafficMainMenuItem = NULL; + } + // Если включается, то создаём. + if (unOptions.ShowMainMenuItem && !hTrafficMainMenuItem) + Traffic_AddMainMenuItem(); + + SaveSettings(0); + // + return TRUE; + } // case PSN_APPLY + } // switch + } + + case WM_DESTROY: + return FALSE; + } + return 0; +} + +int TrafficCounterOptInitialise(WPARAM wParam,LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp={0}; + // Main options page + odp.cbSize=sizeof(odp); + odp.position=900000000; + odp.groupPosition = 1; + odp.hInstance=hInst; + odp.pszTemplate=MAKEINTRESOURCEA(IDD_OPT_TRAFFIC); + odp.pszGroup = LPGEN("Services"); + odp.pszTab = LPGEN("Options"); + odp.pszTitle = LPGEN("Traffic counter"); + odp.pfnDlgProc=DlgProcTCOptions; + odp.flags=ODPF_BOLDGROUPS; + odp.expertOnlyControls=0; + odp.nExpertOnlyControls=0; + Options_AddPage(wParam, &odp); + + // Statistics options page + odp.pszTemplate=MAKEINTRESOURCEA(IDD_OPT_STATS); + odp.pszTab = LPGEN("Statistics"); + odp.pfnDlgProc = DlgProcOptStatistics; + Options_AddPage(wParam, &odp); + + // Popups option page + if (ServiceExists(MS_POPUP_ADDPOPUP)) + { + odp.groupPosition = 100; + odp.pszTemplate=MAKEINTRESOURCEA(IDD_OPT_TRAFFIC_POPUPS); + odp.pszGroup=LPGEN("PopUps"); + odp.pszTitle=LPGEN("Traffic counter"); + odp.pfnDlgProc=DlgProcPopupsTraffic; + odp.flags=ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + } + + return 0; +} + +void SaveSettings(BYTE OnlyCnt) +{ + unsigned short int i; + + // Сохраняем счётчик времени онлайна + DBWriteContactSettingDword(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_TOTAL_ONLINE_TIME, OverallInfo.Total.Timer); + + if (OnlyCnt) return; + + // Для каждого протокола сохраняем флаги + for (i = 0; i < NumberOfAccounts; i++) + { + if (!ProtoList[i].name) continue; + DBWriteContactSettingByte(NULL, ProtoList[i].name, SETTINGS_PROTO_FLAGS, ProtoList[i].Flags); + } + + //settings for notification + DBWriteContactSettingDword(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_BKCOLOR,Traffic_PopupBkColor); + DBWriteContactSettingDword(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_FONTCOLOR,Traffic_PopupFontColor); + // + DBWriteContactSettingByte(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_TIME_VALUE,Traffic_Notify_time_value); + // + DBWriteContactSettingWord(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_SIZE_VALUE,Traffic_Notify_size_value); + // + //popup timeout + DBWriteContactSettingByte(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_DEFAULT,Traffic_PopupTimeoutDefault); + DBWriteContactSettingByte(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_VALUE,Traffic_PopupTimeoutValue); + // + // Формат счётчиков + DBWriteContactSettingTString(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_COUNTER_FORMAT, Traffic_CounterFormat); + + DBWriteContactSettingTString(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_TOOLTIP_FORMAT, Traffic_TooltipFormat); + + DBWriteContactSettingByte(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_ADDITION_SPACE, Traffic_AdditionSpace); + // Сохраняем флаги + DBWriteContactSettingDword(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, unOptions.Flags); + DBWriteContactSettingWord(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_STAT_ACC_OPT, Stat_SelAcc); +} + +/*--------------------------------------------------------------------------------------------*/ +int TrafficRecv(WPARAM wParam,LPARAM lParam) +{ + NETLIBNOTIFY *nln = (NETLIBNOTIFY*)wParam; + NETLIBUSER *nlu = (NETLIBUSER*)lParam; + int i; + + if (nln->result > 0) + for (i = 0; i < NumberOfAccounts; i++) + if (!strcmp(ProtoList[i].name, nlu->szSettingsModule)) + InterlockedExchangeAdd(&ProtoList[i].AllStatistics[ProtoList[i].NumberOfRecords-1].Incoming, nln->result); + return 0; +} + +int TrafficSend(WPARAM wParam,LPARAM lParam) +{ + NETLIBNOTIFY *nln = (NETLIBNOTIFY*)wParam; + NETLIBUSER *nlu = (NETLIBUSER*)lParam; + int i; + + if (nln->result > 0) + for (i = 0; i < NumberOfAccounts; i++) + if (!strcmp(ProtoList[i].name, nlu->szSettingsModule)) + InterlockedExchangeAdd(&ProtoList[i].AllStatistics[ProtoList[i].NumberOfRecords-1].Outgoing, nln->result); + return 0; +} + +int TrafficCounter_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData) +{ + return TrafficCounter_Draw(hWnd,hDC); +} + +int TrafficCounter_Draw(HWND hwnd, HDC hDC) +{ + if (hwnd==(HWND)-1) return 0; + if (GetParent(hwnd) == (HWND)CallService(MS_CLUI_GETHWND, 0, 0)) + return PaintTrafficCounterWindow(hwnd, hDC); + else + InvalidateRect(hwnd,NULL,FALSE); + return 0; +} + +static void TC_AlphaText(HDC hDC, LPCTSTR lpString, RECT* lpRect, UINT format, BYTE ClistModernPresent) +{ + int nCount = lstrlen( lpString ); + + if (ClistModernPresent) + AlphaText(hDC, lpString, nCount, lpRect, format, Traffic_FontColor); + else + DrawText( hDC, lpString, nCount, lpRect, format ); +} + +static void TC_DrawIconEx( HDC hdc,int xLeft,int yTop,HICON hIcon, HBRUSH hbrFlickerFreeDraw, BYTE ClistModernPresent) +{ + if (ClistModernPresent) + mod_DrawIconEx_helper( hdc, xLeft, yTop, hIcon, 16, 16, 0, hbrFlickerFreeDraw, DI_NORMAL ); + else + DrawIconEx( hdc, xLeft, yTop, hIcon, 16, 16, 0, hbrFlickerFreeDraw, DI_NORMAL ); +} + +int PaintTrafficCounterWindow(HWND hwnd, HDC hDC) +{ + RECT rect, rect2; + HFONT old_font; + int i, dx, height, width; + HBRUSH b, t; + HDC hdc; + HBITMAP hbmp, oldbmp; + BITMAPINFO RGB32BitsBITMAPINFO = {0}; + BLENDFUNCTION aga = {AC_SRC_OVER, 0, 0xFF, AC_SRC_ALPHA}; + DWORD SummarySession, SummaryTotal; + + BYTE ClistModernPresent = (GetModuleHandleA("clist_modern.dll") || GetModuleHandleA("clist_modern_dora.dll")) + && !DBGetContactSettingByte(NULL, "ModernData", "DisableEngine", 0) + && DBGetContactSettingByte(NULL, "ModernData", "EnableLayering", 1); + + GetClientRect (hwnd, &rect); + height = rect.bottom - rect.top; + width = rect.right - rect.left; + + // Свой контекст устройства. + hdc = CreateCompatibleDC(hDC); + // + RGB32BitsBITMAPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + RGB32BitsBITMAPINFO.bmiHeader.biWidth = width; + RGB32BitsBITMAPINFO.bmiHeader.biHeight = height; + RGB32BitsBITMAPINFO.bmiHeader.biPlanes = 1; + RGB32BitsBITMAPINFO.bmiHeader.biBitCount = 32; + RGB32BitsBITMAPINFO.bmiHeader.biCompression = BI_RGB; + hbmp = CreateDIBSection(NULL, + &RGB32BitsBITMAPINFO, + DIB_RGB_COLORS, + NULL, + NULL, 0); + oldbmp = (HBITMAP)SelectObject(hdc, hbmp); + + b = CreateSolidBrush(Traffic_BkColor); + t = CreateSolidBrush(KeyColor); + + if ( ClistModernPresent + && unOptions.DrawFrmAsSkin) + { + SKINDRAWREQUEST rq; + + rq.hDC = hdc; + rq.rcDestRect = rect; + rq.rcClipRect = rect; + strncpy(rq.szObjectID, "Main,ID=EventArea", sizeof(rq.szObjectID)); + if (CallService(MS_SKIN_DRAWGLYPH, (WPARAM)&rq, 0)) + { + strncpy(rq.szObjectID, "Main,ID=StatusBar", sizeof(rq.szObjectID)); + CallService(MS_SKIN_DRAWGLYPH, (WPARAM)&rq, 0); + } + } + else + { + SetTextColor(hdc, Traffic_FontColor); + SetBkColor(hdc, Traffic_BkColor); + FillRect(hdc, &rect, b); + AlphaBlend(hdc, 0, 0, width, height, hdc, 0, 0, width, height, aga); + } + + old_font = (HFONT)SelectObject(hdc, Traffic_h_font); + + // Ограничиваем область рисования + rect.top += 2; + rect.left += 3; + rect.bottom -= 2; + rect.right -= 3; + +//------------------- +// Если нет плагина Variables, рисуем упрощённо. +//------------------- + if (!ServiceExists(MS_VARS_FORMATSTRING)) + { + SummarySession = SummaryTotal = 0; + // Для каждого аккаунта + for (i = 0; i < NumberOfAccounts; i++) + { + // Только если разрешено его отображение. + if (ProtoList[i].Visible && ProtoList[i].Enabled) + { + dx = 0; + // Изображаем иконку аккаунта. + if (unOptions.DrawProtoIcon) + { + TC_DrawIconEx(hdc, rect.left, rect.top, + LoadSkinnedProtoIcon(ProtoList[i].name, CallProtoService(ProtoList[i].name,PS_GETSTATUS,0,0)), b, ClistModernPresent); + dx = 19; + } + // Изображаем имя аккаунта + if (unOptions.DrawProtoName) + { + rect.left += dx; + TC_AlphaText(hdc, ProtoList[i].tszAccountName, &rect, DT_SINGLELINE | DT_LEFT | DT_TOP, ClistModernPresent); + rect.left -= dx; + } + // Следующие позиции строятся от правого края. + // Общее время. + if (unOptions.DrawTotalTimeCounter) + { + TCHAR bu[32]; + + GetDurationFormatM(ProtoList[i].Total.Timer, _T("h:mm:ss"), bu, 32); + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + } + // Текущее время. + if (unOptions.DrawCurrentTimeCounter) + { + TCHAR bu[32]; + + GetDurationFormatM(ProtoList[i].Session.Timer, _T("h:mm:ss"), bu, 32); + rect.right -= 50; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + rect.right += 50; + } + // Изображаем общий трафик. + if (unOptions.DrawTotalTraffic) + { + TCHAR bu[32]; + + GetFormattedTraffic(ProtoList[i].TotalSentTraffic + ProtoList[i].TotalRecvTraffic, 3, bu, 32); + rect.right -= 100; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + rect.right += 100; + + if (ProtoList[i].Visible) + SummaryTotal += ProtoList[i].TotalRecvTraffic + ProtoList[i].TotalSentTraffic; + } + // Изображаем текущий трафик. + if (unOptions.DrawCurrentTraffic) + { + TCHAR bu[32]; + + GetFormattedTraffic(ProtoList[i].CurrentRecvTraffic + ProtoList[i].CurrentSentTraffic, 3, bu, 32); + rect.right -= 150; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + rect.right += 150; + + if (ProtoList[i].Visible) + SummarySession += ProtoList[i].CurrentRecvTraffic + ProtoList[i].CurrentSentTraffic; + } + + rect.top += Traffic_LineHeight + Traffic_AdditionSpace; + } + } + // Рисуем суммарный трафик выбранных аккаунтов. + if (unOptions.ShowSummary) + { + // Изображаем иконку. + dx = 0; + if (unOptions.DrawProtoIcon) + { + TC_DrawIconEx(hdc, rect.left, rect.top, + LoadSkinnedIcon(SKINICON_OTHER_MIRANDA), b, ClistModernPresent); + dx = 19; + } + // Выводим текст + // Изображаем имя + if (unOptions.DrawProtoName) + { + TCHAR *bu = mir_a2t("Summary"); + + rect.left += dx; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_LEFT | DT_TOP, ClistModernPresent); + rect.left -= dx; + mir_free(bu); + } + // Общее время. + if (unOptions.DrawTotalTimeCounter) + { + TCHAR bu[32]; + + GetDurationFormatM(OverallInfo.Total.Timer, _T("h:mm:ss"), bu, 32); + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + } + // Текущее время. + if (unOptions.DrawCurrentTimeCounter) + { + TCHAR bu[32]; + + GetDurationFormatM(OverallInfo.Session.Timer, _T("h:mm:ss"), bu, 32); + rect.right -= 50; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + rect.right += 50; + } + // Изображаем общий трафик. + if (unOptions.DrawTotalTraffic) + { + TCHAR bu[32]; + + GetFormattedTraffic(SummaryTotal, 3, bu, 32); + rect.right -= 100; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + rect.right += 100; + } + // Изображаем текущий трафик. + if (unOptions.DrawCurrentTraffic) + { + TCHAR bu[32]; + + GetFormattedTraffic(SummarySession, 3, bu, 32); + rect.right -= 150; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + rect.right += 150; + } + } + rect.top += Traffic_LineHeight + Traffic_AdditionSpace; + // Рисуем всеобщий трафик. + if (unOptions.ShowOverall) + { + // Изображаем иконку. + dx = 0; + if (unOptions.DrawProtoIcon) + { + TC_DrawIconEx(hdc, rect.left, rect.top, + LoadSkinnedIcon(SKINICON_OTHER_MIRANDA), b, ClistModernPresent); + dx = 19; + } + // Выводим текст + // Изображаем имя + if (unOptions.DrawProtoName) + { + TCHAR *bu = mir_a2t("Overall"); + + rect.left += dx; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_LEFT | DT_TOP, ClistModernPresent); + rect.left -= dx; + mir_free(bu); + } + // Следующие позиции строятся от правого края. + // Изображаем общий трафик. + if (unOptions.DrawTotalTraffic) + { + TCHAR bu[32]; + + GetFormattedTraffic(OverallInfo.TotalSentTraffic + OverallInfo.TotalRecvTraffic, 3, bu, 32); + rect.right -= 100; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + rect.right += 100; + } + // Изображаем текущий трафик. + if (unOptions.DrawCurrentTraffic) + { + TCHAR bu[32]; + + GetFormattedTraffic(OverallInfo.CurrentRecvTraffic + OverallInfo.CurrentSentTraffic, 3, bu, 32); + rect.right -= 150; + TC_AlphaText(hdc, bu, &rect, DT_SINGLELINE | DT_RIGHT | DT_TOP, ClistModernPresent); + rect.right += 150; + } + } + } + else +//------------- +// Если есть Variables - рисуем по-новому +//------------- + { + RowItemInfo *ItemsList; + WORD ItemsNumber, RowsNumber; + TCHAR **ExtraText; + HICON *ahIcon; + + // Готовим список строк для Variables и иконок. + ExtraText = (TCHAR**)mir_alloc(sizeof(TCHAR*)); + ahIcon = (HICON*)mir_alloc(sizeof(HICON)); + RowsNumber = 0; + // Цикл по аккаунтам. + for (i = 0; i < NumberOfAccounts; i++) + { + if (ProtoList[i].Visible && ProtoList[i].Enabled) + { + ExtraText = (TCHAR**)mir_realloc(ExtraText, sizeof(TCHAR*) * (RowsNumber + 1)); + ahIcon = (HICON*)mir_realloc(ahIcon, sizeof(HICON) * (RowsNumber + 1)); + + ExtraText[RowsNumber] = mir_a2t(ProtoList[i].name); + ahIcon[RowsNumber++] = LoadSkinnedProtoIcon(ProtoList[i].name, CallProtoService(ProtoList[i].name, PS_GETSTATUS, 0, 0)); + } + } + // Ещё 2 особых элемента. + if (unOptions.ShowSummary) + { + ExtraText = (TCHAR**)mir_realloc(ExtraText, sizeof(TCHAR*) * (RowsNumber + 1)); + ahIcon = (HICON*)mir_realloc(ahIcon, sizeof(HICON) * (RowsNumber + 1)); + + ExtraText[RowsNumber] = mir_a2t("summary"); + ahIcon[RowsNumber++] = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + } + if (unOptions.ShowOverall) + { + ExtraText = (TCHAR**)mir_realloc(ExtraText, sizeof(TCHAR*) * (RowsNumber + 1)); + ahIcon = (HICON*)mir_realloc(ahIcon, sizeof(HICON) * (RowsNumber + 1)); + + ExtraText[RowsNumber] = mir_a2t("overall"); + ahIcon[RowsNumber++] = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + } + + // Рисуем свой счётчик для каждого из выбранных протоколов + for (i = 0; i < RowsNumber; i++) + { + TCHAR *buf; + + buf = variables_parse(Traffic_CounterFormat, ExtraText[i], NULL); + if (ItemsNumber = GetRowItems(buf, &ItemsList)) + { + // Рисуем текст. + for (dx = 0; dx < ItemsNumber; dx++) + { + // Делаем копию прямоугольника для рисования. + memcpy(&rect2, &rect, sizeof(RECT)); + rect2.bottom = rect2.top + Traffic_LineHeight; + // Что за тег? + switch (ItemsList[dx].Alignment) + { + case 'I': + TC_DrawIconEx(hdc, ItemsList[dx].Interval, rect2.top, ahIcon[i], b, ClistModernPresent); + break; + case 'i': + TC_DrawIconEx(hdc, width - 16 - ItemsList[dx].Interval, rect2.top, ahIcon[i], b, ClistModernPresent); + break; + case 'L': + rect2.left = ItemsList[dx].Interval; + TC_AlphaText(hdc, ItemsList[dx].String, &rect2, DT_SINGLELINE | DT_LEFT | DT_VCENTER, ClistModernPresent); + break; + case 'R': + rect2.right = width - ItemsList[dx].Interval; + TC_AlphaText(hdc, ItemsList[dx].String, &rect2, DT_SINGLELINE | DT_RIGHT | DT_VCENTER, ClistModernPresent); + break; + default: + continue; + } + + } + + // Нужно освободить память. + for (; ItemsNumber--; ) + { + mir_free(ItemsList[ItemsNumber].String); + } + mir_free(ItemsList); + } + dx = CallService(MS_VARS_FREEMEMORY, (WPARAM)(void*)buf, 0); + rect.top += Traffic_LineHeight + Traffic_AdditionSpace; + } + + // Удаляем список строк. + for (; RowsNumber--; ) + mir_free(ExtraText[RowsNumber]); + mir_free(ExtraText); + } + + DeleteObject(b); + DeleteObject(t); + SelectObject(hdc, old_font); + + if (ClistModernPresent) + { + AlphaBlend(hDC, 0, 0, width, height, hdc, 0, 0, width, height, aga); + } + else + { + BitBlt(hDC, 0, 0, width, height, hdc, 0, 0, SRCCOPY); + } + + SelectObject(hdc, oldbmp); + DeleteObject(hbmp); + DeleteDC(hdc); + + return 0; +} + +void ProtocolIsOnLine(int num) +{ + DWORD CurrentTimeMs; + + if (ProtoList[num].State) return; + + online_count++; + CurrentTimeMs = GetTickCount(); + + ProtoList[num].State = 1; + ProtoList[num].Session.TimeAtStart = CurrentTimeMs; + ProtoList[num].Total.TimeAtStart = CurrentTimeMs + - 1000 * ProtoList[num].AllStatistics[ProtoList[num].NumberOfRecords - 1].Time; + ProtoList[num].Session.Timer = 0; + + if (online_count == 1) // Хотя бы один аккаунт перешёл в онлайн - готовимся считать суммарное время. + { + OverallInfo.Session.TimeAtStart = CurrentTimeMs - 1000 * OverallInfo.Session.Timer; + OverallInfo.Total.TimeAtStart = CurrentTimeMs - 1000 * OverallInfo.Total.Timer; + } +} + +void ProtocolIsOffLine(int num) +{ + if (!ProtoList[num].State) return; + + online_count--; + ProtoList[num].State = 0; +} + +static POINT ptMouse = {0}; + +LRESULT CALLBACK TrafficCounterWndProc_MW(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + POINT p; + int i; + // + switch (msg) + { + case (WM_USER+697): + if (lParam == 666) + DestroyWindow(hwnd); + break; + + case WM_PAINT: + { + if ( !DBGetContactSettingByte(NULL, "ModernData", "DisableEngine", 0) + && DBGetContactSettingByte(NULL, "ModernData", "EnableLayering", 1) + && ServiceExists(MS_SKINENG_INVALIDATEFRAMEIMAGE)) + CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE, (WPARAM)TrafficHwnd, 0); + else + { + HDC hdc; + hdc = GetDC(hwnd); + PaintTrafficCounterWindow(hwnd, hdc); + ReleaseDC(hwnd, hdc); + } + } + break; + + case WM_ERASEBKGND: + return 1; + + case WM_LBUTTONDOWN : + if (DBGetContactSettingByte(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) + { + ClientToScreen(GetParent(hwnd),&p); + return SendMessage(GetParent(hwnd), WM_SYSCOMMAND, SC_MOVE|HTCAPTION,MAKELPARAM(p.x,p.y)); + } + break; + + case WM_RBUTTONDOWN : + p.x = GET_X_LPARAM(lParam); + p.y = GET_Y_LPARAM(lParam); + ClientToScreen(hwnd,&p); + TrackPopupMenu(TrafficPopupMenu,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,p.x,p.y,0,hwnd,NULL); + break; + + case WM_COMMAND : + switch (wParam) + { + case POPUPMENU_HIDE: + MenuCommand_TrafficShowHide(0, 0); + break; + + case POPUPMENU_CLEAR_NOW: + for (i = 0; i < NumberOfAccounts; i++) + { + ProtoList[i].StartIncoming = + ProtoList[i].AllStatistics[ProtoList[i].NumberOfRecords - 1].Incoming; + ProtoList[i].StartOutgoing = + ProtoList[i].AllStatistics[ProtoList[i].NumberOfRecords - 1].Outgoing; + ProtoList[i].Session.TimeAtStart = GetTickCount(); + } + OverallInfo.CurrentRecvTraffic = OverallInfo.CurrentSentTraffic = 0; + } + break; + + case WM_SETCURSOR: + { + POINT pt; + + GetCursorPos(&pt); + if ( (abs(pt.x - ptMouse.x) < 20) + && (abs(pt.y - ptMouse.y) < 20) ) + return 1; + + if (TooltipShowing) + { + KillTimer(TrafficHwnd, TIMER_TOOLTIP); + CallService("mToolTip/HideTip", 0, 0); + TooltipShowing = FALSE; + } + KillTimer(TrafficHwnd, TIMER_TOOLTIP); + SetTimer(TrafficHwnd, TIMER_TOOLTIP, CallService(MS_CLC_GETINFOTIPHOVERTIME, 0, 0), 0); + break; + } + + case WM_TIMER : + switch(wParam) + { + case TIMER_NOTIFY_TICK: + NotifyOnRecv(); + NotifyOnSend(); + break; + + case TIMER_REDRAW: // Перерисовка раз в полсекунды. + { + DWORD CurrentTimeMs; + SYSTEMTIME stNow; + + SaveSettings(1); + // Перед подсчётом суммарного трафика обнуляем счётчики. + OverallInfo.CurrentRecvTraffic = + OverallInfo.CurrentSentTraffic = + OverallInfo.TotalRecvTraffic = + OverallInfo.TotalSentTraffic = 0; + + CurrentTimeMs = GetTickCount(); + + for (i = 0; i < NumberOfAccounts; i++) + { + if (ProtoList[i].State) + { + ProtoList[i].AllStatistics[ProtoList[i].NumberOfRecords-1].Time = + (CurrentTimeMs - ProtoList[i].Total.TimeAtStart) / 1000; + ProtoList[i].Session.Timer = + (CurrentTimeMs - ProtoList[i].Session.TimeAtStart) / 1000; + } + + Stat_CheckStatistics(i); + + { // Здесь на основании статистики вычисляются значения всех трафиков и времени. + DWORD Sum1, Sum2; + unsigned long int j; + + // Значения для текущей сессии. + for (Sum1 = Sum2 = 0, j = ProtoList[i].StartIndex; j < ProtoList[i].NumberOfRecords; j++) + { + Sum1 += ProtoList[i].AllStatistics[j].Incoming; + Sum2 += ProtoList[i].AllStatistics[j].Outgoing; + } + ProtoList[i].CurrentRecvTraffic = Sum1 - ProtoList[i].StartIncoming; + ProtoList[i].CurrentSentTraffic = Sum2 - ProtoList[i].StartOutgoing; + OverallInfo.CurrentRecvTraffic += ProtoList[i].CurrentRecvTraffic; + OverallInfo.CurrentSentTraffic += ProtoList[i].CurrentSentTraffic; + // Значения для выбранного периода. + ProtoList[i].TotalRecvTraffic = + Stat_GetItemValue(1 << i, + unOptions.PeriodForShow + 1, + Stat_GetRecordsNumber(i, unOptions.PeriodForShow + 1) - 1, + 1); + ProtoList[i].TotalSentTraffic = + Stat_GetItemValue(1 << i, + unOptions.PeriodForShow + 1, + Stat_GetRecordsNumber(i, unOptions.PeriodForShow + 1) - 1, + 2); + ProtoList[i].Total.Timer = + Stat_GetItemValue(1 << i, + unOptions.PeriodForShow + 1, + Stat_GetRecordsNumber(i, unOptions.PeriodForShow + 1) - 1, + 4); + OverallInfo.TotalRecvTraffic += ProtoList[i].TotalRecvTraffic; + OverallInfo.TotalSentTraffic += ProtoList[i].TotalSentTraffic; + } + } + // Не пора ли уведомить? + if (unOptions.NotifyBySize && Traffic_Notify_size_value) + { + if (!((OverallInfo.CurrentRecvTraffic >> 10) % Traffic_Notify_size_value) + && notify_recv_size != OverallInfo.CurrentRecvTraffic >> 10 ) + NotifyOnRecv(); + + if (!((OverallInfo.CurrentSentTraffic >> 10) % Traffic_Notify_size_value) + && notify_send_size != OverallInfo.CurrentSentTraffic >> 10) + NotifyOnSend(); + } + + // Счётчики суммарного времени. + GetLocalTime(&stNow); + + // Не пора ли сбросить общий счётчик? + if ( (unOptions.PeriodForShow == 0 + && stNow.wHour == 0 + && stNow.wMinute == 0 + && stNow.wSecond == 0) + || (unOptions.PeriodForShow == 1 + && DayOfWeek(stNow.wDay, stNow.wMonth, stNow.wYear) == 1 + && stNow.wHour == 0 + && stNow.wMinute == 0 + && stNow.wSecond == 0) + || (unOptions.PeriodForShow == 2 + && stNow.wDay == 1 + && stNow.wHour == 0 + && stNow.wMinute == 0 + && stNow.wSecond == 0) + || (unOptions.PeriodForShow == 3 + && stNow.wMonth == 1 + && stNow.wDay == 1 + && stNow.wHour == 0 + && stNow.wMinute == 0 + && stNow.wSecond == 0) ) + OverallInfo.Total.TimeAtStart = CurrentTimeMs; + + if (online_count > 0) + { + OverallInfo.Session.Timer = + (CurrentTimeMs - OverallInfo.Session.TimeAtStart) / 1000; + OverallInfo.Total.Timer = + (CurrentTimeMs - OverallInfo.Total.TimeAtStart) / 1000; + } + + CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)Traffic_FrameID, FU_FMREDRAW); + } + break; + + case TIMER_TOOLTIP: + { + TCHAR *TooltipText; + CLCINFOTIP ti = {0}; + RECT rt; + + GetCursorPos(&TooltipPosition); + if (!TooltipShowing && unOptions.ShowTooltip ) + { + KillTimer(TrafficHwnd, TIMER_TOOLTIP); + ScreenToClient(TrafficHwnd, &TooltipPosition); + GetClientRect(TrafficHwnd, &rt); + if (PtInRect(&rt, TooltipPosition)) + { + GetCursorPos(&ptMouse); + ti.rcItem.left = TooltipPosition.x - 10; + ti.rcItem.right = TooltipPosition.x + 10; + ti.rcItem.top = TooltipPosition.y - 10; + ti.rcItem.bottom = TooltipPosition.y + 10; + ti.cbSize = sizeof( ti ); + TooltipText = variables_parsedup(Traffic_TooltipFormat, NULL, NULL); +#ifdef _UNICODE + CallService("mToolTip/ShowTipW", (WPARAM)TooltipText, (LPARAM)&ti); +#else + CallService("mToolTip/ShowTip", (WPARAM)TooltipText, (LPARAM)&ti); +#endif + TooltipShowing = TRUE; + free(TooltipText); + } + } + } + break; + } + break; + + default: + return DefWindowProc(hwnd,msg,wParam,lParam); + } + // + return DefWindowProc(hwnd,msg,wParam,lParam); +} + +void CreateTrafficWindow(HWND hCluiWnd) +{ + WNDCLASSEX wcx = {0}; + CLISTFrame f; + + wcx.cbSize = sizeof( WNDCLASSEX ); + wcx.style = 0; + wcx.lpfnWndProc = TrafficCounterWndProc_MW; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = hInst; + wcx.hIcon = NULL; + wcx.hCursor = LoadCursor(hInst,IDC_ARROW); + wcx.hbrBackground = 0; + wcx.lpszMenuName = NULL; + wcx.lpszClassName = TRAFFIC_COUNTER_WINDOW_CLASS; + wcx.hIconSm = NULL; + RegisterClassEx( &wcx ); + TrafficHwnd = CreateWindowEx(WS_EX_TOOLWINDOW, TRAFFIC_COUNTER_WINDOW_CLASS, + TRAFFIC_COUNTER_WINDOW_CLASS, + WS_CHILDWINDOW | WS_CLIPCHILDREN, + 0, 0, 0, 0, hCluiWnd, NULL, hInst, NULL); + + if ( ServiceExists(MS_CLIST_FRAMES_ADDFRAME) ) + { + // Готовимся создавать фрейм + ZeroMemory( &f, sizeof(CLISTFrame) ); + f.align = alBottom; + f.cbSize = sizeof(CLISTFrame); + f.height = TrafficWindowHeight(); + f.Flags= unOptions.FrameIsVisible | F_LOCKED | F_NOBORDER | F_NO_SUBCONTAINER; + f.hWnd = TrafficHwnd; + f.TBname = ("Traffic counter"); + f.name = ("Traffic counter"); + // Создаём фрейм + Traffic_FrameID = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&f,(LPARAM)0); + CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)f.hWnd,(LPARAM)TrafficCounter_PaintCallbackProc); + } + + // Создаём таймеры. + SetTimer(TrafficHwnd, TIMER_REDRAW, 500, NULL); + UpdateNotifyTimer(); +} + +int MenuCommand_TrafficShowHide(WPARAM wParam,LPARAM lParam) +{ + unOptions.FrameIsVisible = !unOptions.FrameIsVisible; + if (Traffic_FrameID == NULL) + ShowWindow(TrafficHwnd, unOptions.FrameIsVisible ? SW_SHOW : SW_HIDE); + else + CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)Traffic_FrameID, 0); + DBWriteContactSettingDword(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, unOptions.Flags); + // + return 0; +} + +void Traffic_AddMainMenuItem(void) +{ + CLISTMENUITEM mi; + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.position = -0x7FFFFFFF; + mi.flags = 0; + mi.hIcon = NULL; + mi.pszName = Translate("Toggle traffic counter"); + mi.pszService="TrafficCounter/ShowHide"; + + hTrafficMainMenuItem = Menu_AddMainMenuItem(&mi); +} + +/*-------------------------------------------------------------------------------------------------------------------*/ +void UpdateNotifyTimer(void) +{ + if (!ServiceExists(MS_POPUP_ADDPOPUP)) return; + + if (Traffic_Notify_time_value && unOptions.NotifyByTime) + SetTimer(TrafficHwnd, TIMER_NOTIFY_TICK, Traffic_Notify_time_value * 1000 * 60, NULL); + else + KillTimer(TrafficHwnd, TIMER_NOTIFY_TICK); +} + +void NotifyOnSend(void) +{ + POPUPDATAT ppd; + + ZeroMemory(&ppd, sizeof(ppd)); + ppd.lchContact = NULL; + ppd.lchIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + _tcscpy(ppd.lptzContactName, TranslateT("Traffic counter notification")); + // + _stprintf(ppd.lptzText, TranslateT("%d kilobytes sent"), + notify_send_size = OverallInfo.CurrentSentTraffic >> 10); + // + ppd.colorBack = Traffic_PopupBkColor; + ppd.colorText = Traffic_PopupFontColor; + ppd.PluginWindowProc = NULL; + if (Traffic_PopupTimeoutDefault) ppd.iSeconds = 0; + else ppd.iSeconds = Traffic_PopupTimeoutValue; + CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&ppd, 0); +} + +void NotifyOnRecv(void) +{ + POPUPDATAT ppd; + + ZeroMemory(&ppd, sizeof(ppd)); + ppd.lchContact = NULL; + ppd.lchIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + _tcscpy(ppd.lptzContactName, TranslateT("Traffic counter notification")); + // + _stprintf(ppd.lptzText,TranslateT("%d kilobytes received"), + notify_recv_size = OverallInfo.CurrentRecvTraffic >> 10); + // + ppd.colorBack = Traffic_PopupBkColor; + ppd.colorText = Traffic_PopupFontColor; + ppd.PluginWindowProc = NULL; + if (Traffic_PopupTimeoutDefault) ppd.iSeconds = 0; + else ppd.iSeconds = Traffic_PopupTimeoutValue; + CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&ppd, 0); +} + +void CreateProtocolList(void) +{ + int i; + PROTOACCOUNT **acc; + // + CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)(int*)&NumberOfAccounts, (LPARAM)(PROTOACCOUNT***)&acc); + // + ProtoList = (PROTOLIST*)mir_alloc(sizeof(PROTOLIST)*(NumberOfAccounts)); + // + for (i = 0; i < NumberOfAccounts; i++) + { + ProtoList[i].name = (char*)mir_alloc(strlen(acc[i]->szModuleName) + 1); + strcpy(ProtoList[i].name, acc[i]->szModuleName); + ProtoList[i].tszAccountName = (TCHAR*)mir_alloc(sizeof(TCHAR) * (1 + _tcslen(acc[i]->tszAccountName))); + _tcscpy(ProtoList[i].tszAccountName, acc[i]->tszAccountName); + // + ProtoList[i].Flags = DBGetContactSettingByte(NULL, ProtoList[i].name, SETTINGS_PROTO_FLAGS, 3); + ProtoList[i].CurrentRecvTraffic = + ProtoList[i].CurrentSentTraffic = + ProtoList[i].Session.Timer = 0; + // + ProtoList[i].Enabled = acc[i]->bIsEnabled; + ProtoList[i].State = 0; + + Stat_ReadFile(i); + ProtoList[i].StartIndex = ProtoList[i].NumberOfRecords - 1; + ProtoList[i].StartIncoming = ProtoList[i].AllStatistics[ProtoList[i].StartIndex].Incoming; + ProtoList[i].StartOutgoing = ProtoList[i].AllStatistics[ProtoList[i].StartIndex].Outgoing; + } // цикл по аккаунтам + // Начальные значения для суммарной информации. + OverallInfo.Session.Timer = OverallInfo.Total.Timer = 0; +} + +void DestroyProtocolList(void) +{ + int i; + // + for (i = 0; i < NumberOfAccounts; i++) + { + Stat_CheckStatistics(i); + CloseHandle(ProtoList[i].hFile); + mir_free(ProtoList[i].name); + mir_free(ProtoList[i].AllStatistics); + } + // + mir_free(ProtoList); +} + +int ProtocolAckHook(WPARAM wParam,LPARAM lParam) +{ + ACKDATA* pAck=(ACKDATA*)lParam; + WORD i; + + if (ACKTYPE_STATUS == pAck->type) + { + if(ID_STATUS_OFFLINE == pAck->lParam) + { + for (i = 0; i < NumberOfAccounts; i++) + { + if (!ProtoList[i].name) continue; + if (!strcmp(ProtoList[i].name, pAck->szModule)) + { + ProtocolIsOffLine(i); + break; + } + } + } + else + { + if ((pAck->lParam >= ID_STATUS_ONLINE) && (pAck->lParam <= ID_STATUS_OUTTOLUNCH)) + { + for (i = 0; i < NumberOfAccounts; i++) + if (!strcmp(ProtoList[i].name, pAck->szModule)) + { + ProtocolIsOnLine(i); + break; + } + } + } + } + return 0; +} + +int UpdateFonts(WPARAM wParam, LPARAM lParam) +{ + LOGFONT logfont; + //if no font service + if (!ServiceExists(MS_FONT_GETT)) return 0; + //update traffic font + if (Traffic_h_font) DeleteObject(Traffic_h_font); + Traffic_FontColor = CallService(MS_FONT_GETT, (WPARAM)&TrafficFontID, (LPARAM)&logfont); + Traffic_h_font = CreateFontIndirect(&logfont); + // + TrafficFontHeight = abs(logfont.lfHeight) + 1; + Traffic_BkColor = CallService(MS_COLOUR_GETT, (WPARAM)&TrafficBackgroundColorID, 0); + + // Ключевой цвет + UseKeyColor = DBGetContactSettingByte(NULL, "ModernSettings", "UseKeyColor", 1); + KeyColor = DBGetContactSettingDword(NULL, "ModernSettings", "KeyColor", 0); + + UpdateTrafficWindowSize(); + return 0; +} + +void UpdateTrafficWindowSize(void) +{ + if (Traffic_FrameID != NULL) + { + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_HEIGHT, Traffic_FrameID), TrafficWindowHeight()); + } +} + +unsigned short int TrafficWindowHeight(void) +{ + BYTE HeightLineTime = (unOptions.DrawProtoIcon) ? 16 : TrafficFontHeight, + i, ActProto; + WORD MaxWndHeight; + + for (i = 0, ActProto = unOptions.ShowOverall + unOptions.ShowSummary; i < NumberOfAccounts; i++) + ActProto += ProtoList[i].Visible && ProtoList[i].Enabled; + + // Высота строки минимум 16 пикселей (для иконки). + Traffic_LineHeight = TrafficFontHeight > 16 ? TrafficFontHeight: 16; + + // Высота фрейма равна количеству строк. + MaxWndHeight = ActProto * Traffic_LineHeight + + Traffic_AdditionSpace * (ActProto - 1) + + 4; + + return (MaxWndHeight < TrafficFontHeight) ? 0 : MaxWndHeight; +} + +// Функция вносит изменения в ProtoList при коммутации аккаунтов +int OnAccountsListChange(WPARAM wParam, LPARAM lParam) +{ + BYTE i; + PROTOACCOUNT *acc = (PROTOACCOUNT*)lParam; + + switch (wParam) + { + case PRAC_ADDED: + case PRAC_REMOVED: + DestroyProtocolList(); + CreateProtocolList(); + break; + case PRAC_CHANGED: + case PRAC_CHECKED: + for (i = 0; i < NumberOfAccounts; i++) + if (!strcmp(acc->szModuleName, ProtoList[i].name)) + ProtoList[i].Enabled = acc->bIsEnabled; + break; + } + UpdateTrafficWindowSize(); + return 0; +} diff --git a/plugins/TrafficCounter/TrafficCounter.h b/plugins/TrafficCounter/TrafficCounter.h new file mode 100644 index 0000000000..2ce9267e84 --- /dev/null +++ b/plugins/TrafficCounter/TrafficCounter.h @@ -0,0 +1,85 @@ +/* +Traffic Counter plugin for Miranda IM +Copyright 2007-2011 Mironych. + +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. +*/ + +#ifndef _TrafficCounter_H +#define _TrafficCounter_H + +int TrafficRecv(WPARAM wParam,LPARAM lParam); +int TrafficSend(WPARAM wParam,LPARAM lParam); + +//--------------------------------------------------------------------------------------------- +// Имена параметров с настройками в базе +//--------------------------------------------------------------------------------------------- +#define TRAFFIC_SETTINGS_GROUP "TrafficCounter" + +#define SETTINGS_COUNTER_FORMAT "CounterFormat" +#define SETTINGS_TOOLTIP_FORMAT "TooltipFormat" +#define SETTINGS_STAT_ACC_OPT "Stat_SelAcc" +#define SETTINGS_ADDITION_SPACE "traffic_addition_space" +// +//notify +#define SETTINGS_POPUP_BKCOLOR "popup_bkcolor" +#define SETTINGS_POPUP_FONTCOLOR "popup_font_color" +#define SETTINGS_POPUP_NOTIFY_SIZE_VALUE "popup_size_value" +#define SETTINGS_POPUP_NOTIFY_TIME_VALUE "popup_time_value" +#define SETTINGS_POPUP_TIMEOUT_DEFAULT "popup_timeout_default" +#define SETTINGS_POPUP_TIMEOUT_VALUE "popup_timeout_value" +//timer notify +#define TIMER_SAVE_TICK (3001 + 1) +#define TIMER_NOTIFY_TICK (3001 + 2) +//popup menu +#define POPUPMENU_HIDE (3001 + 4) +#define POPUPMENU_ONTOP (3001 + 5) +#define POPUPMENU_CLEAR_NOW (3001 + 8) +//time counter +#define TIMER_REDRAW 3300 +#define TIMER_TOOLTIP 3301 +#define SETTINGS_TOTAL_ONLINE_TIME "TotalOnlineTime" +// Разные флажки +#define SETTINGS_WHAT_DRAW "WhatDraw" + +// Настройки для протоколов - сохраняются в ветке протокола +#define SETTINGS_PROTO_FLAGS "tc_Flags" + +/*====== ФУНКЦИИ МОДУЛЯ =====*/ +int TrafficCounterOptInitialise(WPARAM wParam,LPARAM lParam); +int TrafficCounterModulesLoaded(WPARAM wParam,LPARAM lParam); +int TrafficCounterShutdown(WPARAM wParam,LPARAM lParam); +void SaveSettings(BYTE); +void CreateTrafficWindow(HWND); +//popup +void UpdateNotifyTimer(void); +void NotifyOnSend(void); +void NotifyOnRecv(void); +//time counter +int ProtocolAckHook(WPARAM wParam,LPARAM lParam); +void CreateProtocolList(void); +void DestroyProtocolList(void); +int OnAccountsListChange(WPARAM wParam, LPARAM lParam); +//font service suppot +int UpdateFonts(WPARAM wParam, LPARAM lParam); +void UpdateTrafficWindowSize(void); +unsigned short int TrafficWindowHeight(void); +// Рисование +int TrafficCounter_Draw(HWND, HDC); +int PaintTrafficCounterWindow(HWND, HDC); +// Вспомогательные функции +int MenuCommand_TrafficShowHide(WPARAM, LPARAM); + +#endif; diff --git a/plugins/TrafficCounter/TrafficCounter_10.vcxproj b/plugins/TrafficCounter/TrafficCounter_10.vcxproj new file mode 100644 index 0000000000..fbbab8aa4d --- /dev/null +++ b/plugins/TrafficCounter/TrafficCounter_10.vcxproj @@ -0,0 +1,675 @@ +п»ї + + + + Debug Unicode + Win32 + + + Debug Unicode + Win32 + + + Debug Unicode + x64 + + + Debug Unicode + x64 + + + Debug + Win32 + + + Debug + Win32 + + + Debug + x64 + + + Debug + x64 + + + Release Unicode Static + Win32 + + + Release Unicode Static + x64 + + + Release Unicode + Win32 + + + Release Unicode + Win32 + + + Release Unicode + x64 + + + Release Unicode + x64 + + + Release + Win32 + + + Release + Win32 + + + Release + x64 + + + Release + x64 + + + + TrafficCounter + {885010EA-D008-4E38-85D4-487693F0BA00} + TrafficCounter + + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + Unicode + false + + + DynamicLibrary + false + Unicode + true + + + DynamicLibrary + false + Unicode + true + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + Unicode + + + DynamicLibrary + false + Unicode + true + + + DynamicLibrary + false + Unicode + true + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + true + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + true + true + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + true + ..\..\..\..\VC\atlmfc\include;$(IncludePath) + ..\..\..\..\VC\atlmfc\include;$(IncludePath) + ..\..\..\..\VC\atlmfc\include;$(IncludePath) + ..\..\..\..\VC\atlmfc\include;$(IncludePath) + ..\..\..\..\VC\atlmfc\include;$(IncludePath) + true + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/TrafficCounter.tlb + + + + + Full + OnlyExplicitInline + Size + true + ../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + commonheaders.h + Level3 + true + 4996;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;comctl32.lib;%(AdditionalDependencies) + true + true + true + true + UseLinkTimeCodeGeneration + false + + + $(IntDir)$(TargetName).lib + MachineX86 + false + + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/TrafficCounter.tlb + + + + + Disabled + ../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + commonheaders.h + Level3 + true + EditAndContinue + CompileAsC + 4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;comctl32.lib;%(AdditionalDependencies) + true + true + false + + + $(IntDir)$(TargetName).lib + MachineX86 + false + + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/TrafficCounter.tlb + + + + + Disabled + ../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + false + + + MultiThreadedDebugDLL + commonheaders.h + true + Level3 + true + ProgramDatabase + Default + 4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;comctl32.lib;%(AdditionalDependencies) + true + false + true + true + false + + + $(IntDir)$(TargetName).lib + MachineX86 + $(IntDir)$(TargetName)$(TargetExt).intermediate.manifest + + + + + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/TrafficCounter.tlb + + + + + Full + OnlyExplicitInline + Size + true + ../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + commonheaders.h + Level3 + true + ProgramDatabase + 4996;%(DisableSpecificWarnings) + NotSet + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;comctl32.lib;%(AdditionalDependencies) + false + true + true + true + UseLinkTimeCodeGeneration + false + + + $(IntDir)$(TargetName).lib + MachineX86 + $(IntDir)$(TargetName)$(TargetExt).intermediate.manifest + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/TrafficCounter.tlb + + + + + Full + OnlyExplicitInline + Size + true + ../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + commonheaders.h + Level3 + true + ProgramDatabase + 4996;%(DisableSpecificWarnings) + NotSet + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;comctl32.lib;%(AdditionalDependencies) + false + true + true + true + UseLinkTimeCodeGeneration + false + + + $(IntDir)$(TargetName).lib + MachineX86 + $(IntDir)$(TargetName)$(TargetExt).intermediate.manifest + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Release/TrafficCounter.tlb + + + + + Full + OnlyExplicitInline + Size + true + ../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + commonheaders.h + Level3 + true + 4996;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;%(AdditionalDependencies) + true + true + true + true + UseLinkTimeCodeGeneration + false + + + $(IntDir)$(TargetName).lib + MachineX64 + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Debug/TrafficCounter.tlb + + + + + Disabled + ../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + commonheaders.h + Level3 + true + ProgramDatabase + CompileAsC + 4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;%(AdditionalDependencies) + true + true + false + + + $(IntDir)$(TargetName).lib + MachineX64 + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Debug/TrafficCounter.tlb + + + + + Disabled + ../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + commonheaders.h + Level3 + true + ProgramDatabase + CompileAsC + 4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;%(AdditionalDependencies) + true + true + false + + + $(IntDir)$(TargetName).lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Release/TrafficCounter.tlb + + + + + Full + OnlyExplicitInline + Size + true + ../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + commonheaders.h + Level3 + true + ProgramDatabase + 4996;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;%(AdditionalDependencies) + true + true + true + UseLinkTimeCodeGeneration + false + + + $(IntDir)$(TargetName).lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Release/TrafficCounter.tlb + + + + + Full + OnlyExplicitInline + Size + true + ../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;TRAFFICCOUNTER_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + commonheaders.h + Level3 + true + ProgramDatabase + 4996;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Msimg32.lib;%(AdditionalDependencies) + true + true + true + UseLinkTimeCodeGeneration + false + + + $(IntDir)$(TargetName).lib + MachineX64 + + + + + All + Default + + + All + + + All + + + %(PreprocessorDefinitions) + Create + %(PreprocessorDefinitions) + Create + %(PreprocessorDefinitions) + Create + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + Create + Create + %(PreprocessorDefinitions) + Create + %(PreprocessorDefinitions) + Create + %(PreprocessorDefinitions) + Create + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + Create + Create + All + + + All + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/TrafficCounter/TrafficCounter_10.vcxproj.filters b/plugins/TrafficCounter/TrafficCounter_10.vcxproj.filters new file mode 100644 index 0000000000..8cb96f67ad --- /dev/null +++ b/plugins/TrafficCounter/TrafficCounter_10.vcxproj.filters @@ -0,0 +1,64 @@ +п»ї + + + + {7248dd69-8a94-4e9f-81c4-1883723a61f6} + h;hpp;hxx;hm;inl + + + {7a03a86b-8068-47d0-bc10-07e824854944} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {379f9a87-c54b-4f64-ae10-cddbc3c96dbf} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Resource Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/plugins/TrafficCounter/commonheaders.c b/plugins/TrafficCounter/commonheaders.c new file mode 100644 index 0000000000..c9fe1b2686 --- /dev/null +++ b/plugins/TrafficCounter/commonheaders.c @@ -0,0 +1 @@ +#include "commonheaders.h" \ No newline at end of file diff --git a/plugins/TrafficCounter/commonheaders.h b/plugins/TrafficCounter/commonheaders.h new file mode 100644 index 0000000000..8939a53249 --- /dev/null +++ b/plugins/TrafficCounter/commonheaders.h @@ -0,0 +1,160 @@ +#ifndef commonheaders_h__ +#define commonheaders_h__ + +/* +Traffic Counter plugin for Miranda IM +Copyright 2007-2011 Mironych. + +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. +*/ + +#define MIRANDA_VER 0x0900 +#define MIRANDA_CUSTOM_LP +#define _USE_32BIT_TIME_T 1 + +// Standart includes +#include +#include +#include +#include +#include + +#include + +#include "resource.h" + +// Miranda SDK includes +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(push) +#pragma pack(1) +typedef struct +{ + BYTE Hour, Day, Month; + WORD Year; + DWORD Incoming, Outgoing; + WORD Time; +} HOURLYSTATS; +#pragma pack(pop) + +typedef struct tagTimer +{ + DWORD TimeAtStart; // Время в момент запуска таймера - в миллисекундах. + DWORD Timer; // Количество секунд со времени запуска таймера. +} TIMER; + +typedef struct +{ + char *name; // Имя аккаунта. + + TIMER Session; // Таймер текущей сессии (протокол в онлайне). + TIMER Total; // Таймер общий. + + DWORD TotalRecvTraffic, // Общий трафик протокола (за выбранный период) + TotalSentTraffic, + CurrentRecvTraffic, // Текущий трафик протокола (за сессию) + CurrentSentTraffic; + union + { + BYTE Flags; + struct + { + unsigned int Reserv0:1; // Активность потеряла смысл - статистика ведётся по всем аккаунтам. + unsigned int Visible:1; // = 1 - аккаунт будет показываться во фрейме счётчиков + unsigned int Enabled:1; // = 1 - аккаунт включен и не прячется + unsigned int State:1; // = 1 - аккаунт сейчас онлайн + unsigned int Reserv1:3; + }; + }; + + // Добавлено в версии 0.1.1.0. + DWORD NumberOfRecords; // Количество часов в общей статистике. + HOURLYSTATS *AllStatistics; // Полная статистика вместе со статистикой онлайна. + HANDLE hFile; // Файл с сохранённой статистикой данного протокола. + + DWORD StartIndex; // Номер записи в статистике, бывший актуальным на момент запуска. + DWORD StartIncoming; // Значение входящего трафика на момент запуска. + DWORD StartOutgoing; // Значение исходящего трафика на момент запуска. + + // 0.1.1.5. + DWORD Shift; // Номер записи в статистике старейшего выбранного аккаунта, + // дата которой соответствует началу статистики данного аккаунта. + + // 0.1.1.6 + TCHAR *tszAccountName; // Человеческое имя аккаунта для использования в графическом интерфейсе. +} PROTOLIST; + +//--------------------------------------------------------------------------------------------- +// Различные флаги +//--------------------------------------------------------------------------------------------- +union +{ + DWORD Flags; + struct + { + unsigned int NotifyBySize:1; //0 + unsigned int DrawCurrentTraffic:1; //1 + unsigned int DrawTotalTraffic:1; //2 + unsigned int DrawCurrentTimeCounter:1; //3 + unsigned int DrawProtoIcon:1; //4 + unsigned int Reserv0:1; //5 + unsigned int DrawProtoName:1; //6 + unsigned int DrawFrmAsSkin:1; //7 + unsigned int ShowSummary:1; //8 + unsigned int ShowTooltip:1; //9 + unsigned int ShowMainMenuItem:1; //10 + unsigned int ShowOverall:1; //11 + unsigned int Stat_Units:2; //12,13 + unsigned int Stat_Tab:3; //14,15,16 + unsigned int NotifyByTime:1; //17 + unsigned int Reserv2:1; //18 + unsigned int PeriodForShow:2; //19,20 + unsigned int FrameIsVisible:1; //21 + unsigned int Reserv1:1; //22 + unsigned int DrawTotalTimeCounter:1; //23 + }; +} unOptions; + +PROTOLIST *ProtoList; // Данные обо всех аккаунтах. +PROTOLIST OverallInfo; // Суммарные данные по видимым аккаунтам. +BYTE NumberOfAccounts; +WORD Stat_SelAcc; // Выбранные аккаунты в окне статистики +HWND TrafficHwnd; +DWORD mirandaVer; + +#include "misc.h" +#include "opttree.h" +#include "vars.h" +#include "statistics.h" +#include "TrafficCounter.h" + +#endif diff --git a/plugins/TrafficCounter/misc.c b/plugins/TrafficCounter/misc.c new file mode 100644 index 0000000000..6320117246 --- /dev/null +++ b/plugins/TrafficCounter/misc.c @@ -0,0 +1,303 @@ +/* +Traffic Counter plugin for Miranda IM +Copyright 2007-2011 Mironych. + +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 "commonheaders.h" + +/* Функция разбирает строку и возвращает список тегов и соответствующих им строк. +Аргументы: +InputString - строка для разбора; +RowItemsList - список найденных элементов. +Возвращаемое значение - количество элементов в списках. */ +WORD GetRowItems(TCHAR *InputString, RowItemInfo **RowItemsList) +{ + TCHAR *begin, *end; + WORD c = 0; + + // Ищем слева открывающую скобку. + begin = _tcschr(InputString, '{'); + // Если скобка найдена... + if (begin) + { + // Выделяем память под указатели + *RowItemsList = (RowItemInfo*)mir_alloc(sizeof(RowItemInfo)); + } + else return 0; + + do + { + // Сразу вслед за ней ищем закрывающую. + end = _tcschr(begin, '}'); + + // Выделяем память под указатели + *RowItemsList = (RowItemInfo*)mir_realloc(*RowItemsList, sizeof(RowItemInfo) * (c + 1)); + + // Разбираем тег. + _stscanf(begin + 1, _T("%c%d"), + &((*RowItemsList)[c].Alignment), + &((*RowItemsList)[c].Interval)); + + // Ищем далее открывающую скобку - это конец строки, соответствующей тегу. + begin = _tcschr(end, '{'); + + if (begin) + { + // Выделяем память под строку. + (*RowItemsList)[c].String = (TCHAR*)mir_alloc(sizeof(TCHAR) * (begin - end)); + // Копируем строку. + _tcsncpy((*RowItemsList)[c].String, end + 1, begin - end - 1); + (*RowItemsList)[c].String[begin - end - 1] = 0; + } + else + { + // Выделяем память под строку. + (*RowItemsList)[c].String = (TCHAR*)mir_alloc(sizeof(TCHAR) * _tcslen(end)); + // Копируем строку. + _tcsncpy((*RowItemsList)[c].String, end + 1, _tcslen(end)); + } + + c++; + } while (begin); + + return c; +} + +/* Функция возвращает количество дней в указанном месяце указанного года. */ +BYTE DaysInMonth(BYTE Month, WORD Year) +{ + switch (Month) + { + case 1: + case 3: + case 5: + case 7: + case 8: + case 10: + case 12: return 31; + case 4: + case 6: + case 9: + case 11: return 30; + case 2: return 28 + (BYTE)!((Year % 4) && ( (Year % 100) || !(Year % 400) )); + } + return 0; +} + +// Функция определяет день недели по дате +// 7 - ВС, 1 - ПН и т. д. +BYTE DayOfWeek(BYTE Day, BYTE Month, WORD Year) +{ + WORD a, y, m; + + a = (14 - Month) / 12; + y = Year - a; + m = Month + 12 * a - 2; + + a = (7000 + (Day + y + (y >> 2) - y / 100 + y / 400 + (31 * m) / 12)) % 7; + if (!a) a = 7; + + return a; +} + +/* +Аргументы: + Value - количество байт; + Unit - единицы измерения (0 - байты, 1 - килобайты, 2 - мегабайты, 3 - автоматически); + Buffer - адрес строки для записи результата; + Size - размер буфера. +Возвращаемое значение: требуемый размер буфера. +*/ +WORD GetFormattedTraffic(DWORD Value, BYTE Unit, TCHAR *Buffer, WORD Size) +{ + TCHAR Str1[32], szUnit[4] = {' ', 0}; + DWORD Divider; + NUMBERFMT nf = {0, 1, 3, _T(","), _T(" "), 0}; + TCHAR *Res; // Промежуточный результат. + WORD l; + + switch (Unit) + { + case 0: //bytes + Divider = 1; + nf.NumDigits = 0; + szUnit[0] = 0; + break; + case 1: // KB + Divider = 0x400; + nf.NumDigits = 2; + break; + case 2: // MB + Divider = 0x100000; + nf.NumDigits = 2; + break; + case 3: // Adaptive + nf.NumDigits = 2; + if (Value < 0x100000) { Divider = 0x400; szUnit[1] = 'K'; szUnit[2] = 'B'; } + else { Divider = 0x100000; szUnit[1] = 'M'; szUnit[2] = 'B'; } + break; + } + + mir_sntprintf(Str1, 32, _T("%d.%d"), Value / Divider, Value % Divider); + l = GetNumberFormat(LOCALE_USER_DEFAULT, 0, Str1, &nf, NULL, 0); + if (!l) return 0; + l += _tcslen(szUnit) + 1; + Res = (TCHAR*)malloc(l * sizeof(TCHAR)); + if (!Res) return 0; + GetNumberFormat(LOCALE_USER_DEFAULT, 0, Str1, &nf, Res, l); + _tcscat(Res, szUnit); + + if (Size && Buffer) + { + _tcscpy(Buffer, Res); + l = _tcslen(Buffer); + } + else + { + l = _tcslen(Res) + 1; + } + + free(Res); + return l; +} + +/* Преобразование интервала времени в его строковое представление +Аргументы: +Duration: интервал времени в секундах; +Format: строка формата; +Buffer: адрес буфера, куда функция помещает результат. +Size - размер буфера. */ +WORD GetDurationFormatM(DWORD Duration, TCHAR *Format, TCHAR *Buffer, WORD Size) +{ + DWORD q; + WORD TokenIndex, FormatIndex, Length; + TCHAR Token[256], // Аккумулятор. + *Res; // Промежуточный результат. + + Res = (TCHAR*)malloc(sizeof(TCHAR)); // Выделяем чуть-чуть памяти под результат, но это только начало. + SecureZeroMemory(Res, sizeof(TCHAR)); + + for (FormatIndex = 0; Format[FormatIndex];) + { + // Ищем токены. Считается, что токен - только буквы. + TokenIndex = 0; + q = _istalpha(Format[FormatIndex]); + // Копируем символы в аккумулятор до смены флага. + do + { + Token[TokenIndex++] = Format[FormatIndex++]; + } while (q == _istalpha(Format[FormatIndex])); + Token[TokenIndex] = 0; + + // Что получили в аккумуляторе? + if (!_tcscmp(Token, _T("d"))) + { + q = Duration / (60 * 60 * 24); + mir_sntprintf(Token, 256, _T("%d"), q); + Duration -= q * 60 * 60 * 24; + } + else + if (!_tcscmp(Token, _T("h"))) + { + q = Duration / (60 * 60); + mir_sntprintf(Token, 256, _T("%d"), q); + Duration -= q * 60 * 60; + } + else + if (!_tcscmp(Token, _T("hh"))) + { + q = Duration / (60 * 60); + mir_sntprintf(Token, 256, _T("%02d"), q); + Duration -= q * 60 * 60; + } + else + if (!_tcscmp(Token, _T("m"))) + { + q = Duration / 60; + mir_sntprintf(Token, 256, _T("%d"), q); + Duration -= q * 60; + } + else + if (!_tcscmp(Token, _T("mm"))) + { + q = Duration / 60; + mir_sntprintf(Token, 256, _T("%02d"), q); + Duration -= q * 60; + } + else + if (!_tcscmp(Token, _T("s"))) + { + q = Duration; + mir_sntprintf(Token, 256, _T("%d"), q); + Duration -= q; + } + else + if (!_tcscmp(Token, _T("ss"))) + { + q = Duration; + mir_sntprintf(Token, 256, _T("%02d"), q); + Duration -= q; + } + + // Добавим памяти, если нужно. + Length = _tcslen(Res) + _tcslen(Token) + 1; + Res = (TCHAR*)realloc(Res, Length * sizeof(TCHAR)); + _tcscat(Res, Token); + } + + if (Size && Buffer) + { + _tcsncpy(Buffer, Res, Size); + Length = _tcslen(Buffer); + } + else + { + Length = _tcslen(Res) + 1; + } + + free(Res); + return Length; +} + +/* Результат: +-1 - st1 < st2 + 0 - st1 = st2 ++1 - st1 > st2 +*/ +signed short int TimeCompare(SYSTEMTIME st1, SYSTEMTIME st2) +{ + signed short int a, b, c, d; + + a = st1.wYear - st2.wYear; + b = st1.wMonth - st2.wMonth; + c = st1.wDay - st2.wDay; + d = st1.wHour - st2.wHour; + + if (a < 0) return -1; + if (a > 0) return +1; + + if (b < 0) return -1; + if (b > 0) return +1; + + if (c < 0) return -1; + if (c > 0) return +1; + + if (d < 0) return -1; + if (d > 0) return +1; + + return 0; +} diff --git a/plugins/TrafficCounter/misc.h b/plugins/TrafficCounter/misc.h new file mode 100644 index 0000000000..e8ac6c10ea --- /dev/null +++ b/plugins/TrafficCounter/misc.h @@ -0,0 +1,32 @@ +typedef struct +{ + TCHAR Alignment; // Выравнивание. L - к левой границе, R - к правой. + WORD Interval; // Расстояние, на которое граница строки отстоит от левого края фрейма. + TCHAR *String; // Собственно строка. +} RowItemInfo; + +/* Функция разбирает строку и возвращает список тегов и соответствующих им строк. +Аргументы: +InputString - строка для разбора; +RowItemsList - список найденных элементов. +Возвращаемое значение - количество элементов в списках. */ +WORD GetRowItems(TCHAR *InputString, RowItemInfo **RowItemsList); + +/* Функция возвращает количество дней в указанном месяце указанного года. */ +BYTE DaysInMonth(BYTE Month, WORD Year); + +// Функция определяет день недели по дате +// 7 - ВС, 1 - ПН и т. д. +BYTE DayOfWeek(BYTE Day, BYTE Month, WORD Year); + +/* Аргументы: + Value - количество байт; + Unit - единицы измерения (0 - байты, 1 - килобайты, 2 - мегабайты, 3 - автоматически); + Buffer - адрес строки для записи результата; + Size - размер буфера. +Возвращаемое значение: требуемый размер буфера. */ +WORD GetFormattedTraffic(DWORD Value, BYTE Unit, TCHAR *Buffer, WORD Size); + +WORD GetDurationFormatM(DWORD Duration, TCHAR *Format, TCHAR *Buffer, WORD Size); + +signed short int TimeCompare(SYSTEMTIME st1, SYSTEMTIME st2); \ No newline at end of file diff --git a/plugins/TrafficCounter/opttree.c b/plugins/TrafficCounter/opttree.c new file mode 100644 index 0000000000..573a04cc8b --- /dev/null +++ b/plugins/TrafficCounter/opttree.c @@ -0,0 +1,416 @@ +/* + +Jabber Protocol Plugin for Miranda IM +Copyright ( C ) 2002-04 Santithorn Bunchua +Copyright ( C ) 2005-07 George Hazan +Copyright ( C ) 2007 Maxim Mluhov +Copyright ( C ) 2007 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. + +File name : $Source: $ +Revision : $Revision: $ +Last change on : $Date: $ +Last change by : $Author: $ + +*/ + +#include "commonheaders.h" + +HTREEITEM OptTree_FindNamedTreeItemAt(HWND hwndTree, HTREEITEM hItem, const TCHAR *name); +HTREEITEM OptTree_AddItem(HWND hwndTree, TCHAR *name, LPARAM lParam, int iconIndex); +extern OPTTREE_OPTION *pOptions; // Объявлено в модуле TrafficCounter.c. + +static void OptTree_TranslateItem(HWND hwndTree, HTREEITEM hItem) +{ + TCHAR buf[128]; + + TVITEM tvi = {0}; + tvi.mask = TVIF_HANDLE|TVIF_TEXT; + tvi.hItem = hItem; + tvi.pszText = buf; + tvi.cchTextMax = SIZEOF(buf); + SendMessage(hwndTree, TVM_GETITEM, 0, (LPARAM)&tvi); + // Проверим, надо ли переводить. + if ((tvi.lParam != -1) && (pOptions[tvi.lParam].dwFlag & OPTTREE_NOTRANSLATE)) return; + tvi.pszText = TranslateTS(tvi.pszText); + tvi.cchTextMax = lstrlen(tvi.pszText); + SendMessage(hwndTree, TVM_SETITEM, 0, (LPARAM)&tvi); +} + +void OptTree_Translate(HWND hwndTree) +{ + HTREEITEM hItem = TreeView_GetRoot(hwndTree); + while (hItem) + { + HTREEITEM hItemTmp = 0; + + OptTree_TranslateItem(hwndTree, hItem); + if (hItemTmp = TreeView_GetChild(hwndTree, hItem)) + { + hItem = hItemTmp; + } else + if (hItemTmp = TreeView_GetNextSibling(hwndTree, hItem)) + { + hItem = hItemTmp; + } else + { + while (1) + { + if (!(hItem = TreeView_GetParent(hwndTree, hItem))) break; + if (hItemTmp = TreeView_GetNextSibling(hwndTree, hItem)) + { + hItem = hItemTmp; + break; + } + } + } + } +} + +HTREEITEM OptTree_FindNamedTreeItemAt(HWND hwndTree, HTREEITEM hItem, const TCHAR *name) +{ + TVITEM tvi = {0}; + TCHAR str[MAX_PATH]; + + if (hItem) + tvi.hItem = TreeView_GetChild(hwndTree, hItem); + else + tvi.hItem = TreeView_GetRoot(hwndTree); + + if (!name) + return tvi.hItem; + + tvi.mask = TVIF_TEXT; + tvi.pszText = str; + tvi.cchTextMax = MAX_PATH; + + while (tvi.hItem) + { + TreeView_GetItem(hwndTree, &tvi); + + if (!lstrcmp(tvi.pszText, name)) + return tvi.hItem; + + tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); + } + return NULL; +} + +HTREEITEM OptTree_AddItem(HWND hwndTree, TCHAR *name, LPARAM lParam, int iconIndex) +{ + TCHAR itemName[1024]; + + TCHAR* sectionName; + int sectionLevel = 0; + + HTREEITEM hSection = NULL, result = NULL; + lstrcpy(itemName, name); + sectionName = itemName; + + while (sectionName) + { + // allow multi-level tree + TCHAR* pItemName = sectionName; + HTREEITEM hItem; + + if (sectionName = _tcschr(sectionName, '/')) + { + // one level deeper + *sectionName = 0; + sectionName++; + } + + hItem = OptTree_FindNamedTreeItemAt(hwndTree, hSection, pItemName); + if (!sectionName || !hItem) + { + if (!hItem) + { + TVINSERTSTRUCT tvis = {0}; + + tvis.hParent = hSection; + tvis.hInsertAfter = TVI_LAST;//TVI_SORT; + tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE; + tvis.item.pszText = pItemName; + tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED; + if (sectionName) + { + tvis.item.lParam = 0; + tvis.item.iImage = tvis.item.iSelectedImage = -1; + } else + { + tvis.item.lParam = lParam; + tvis.item.iImage = tvis.item.iSelectedImage = iconIndex; + tvis.item.mask |= TVIF_IMAGE|TVIF_SELECTEDIMAGE; + } + hItem = TreeView_InsertItem(hwndTree, &tvis); + if (!sectionName) + result = hItem; + } + } + sectionLevel++; + hSection = hItem; + } + + return result; +} + +BOOL OptTree_ProcessMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL *result, int idcTree, OPTTREE_OPTION *options, int optionCount) +{ + enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED }; + + HWND hwndTree = GetDlgItem(hwnd, idcTree); + switch (msg) + { + case WM_INITDIALOG: + { + int indx; + TCHAR itemName[1024]; + HIMAGELIST hImgLst; + + TreeView_SelectItem(hwndTree, NULL); + TreeView_DeleteAllItems(hwndTree); + + hImgLst = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR|ILC_COLOR32|ILC_MASK, 5, 1); + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA)); + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_TICK)); // check on + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_NOTICK)); // check off + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_TICK)); // radio on + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_NOTICK)); // radio on + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_GROUPOPEN)); + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_GROUPSHUT)); + TreeView_SetImageList(hwndTree, hImgLst, TVSIL_NORMAL); + + /* build options tree. based on code from IcoLib */ + for (indx = 0; indx < optionCount; indx++) + { + TCHAR* sectionName; + int sectionLevel = 0; + + HTREEITEM hSection = NULL; + if (options[indx].szOptionName) + lstrcpy(itemName, options[indx].szOptionName); + else + itemName[0] = 0; + + sectionName = itemName; + + while (sectionName) + { + // allow multi-level tree + TCHAR* pItemName = sectionName; + HTREEITEM hItem; + + if (sectionName = _tcschr(sectionName, '/')) + { + // one level deeper + *sectionName = 0; + sectionName++; + } + + hItem = OptTree_FindNamedTreeItemAt(hwndTree, hSection, pItemName); + //if (!sectionName || !hItem) + if ((!sectionName || !hItem) && !(options[indx].dwFlag & OPTTREE_INVISIBLE)) + { + if (!hItem) + { + TVINSERTSTRUCT tvis = {0}; + + tvis.hParent = hSection; + tvis.hInsertAfter = TVI_LAST;//TVI_SORT; + tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvis.item.pszText = pItemName; + tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED; + if (sectionName) + { + tvis.item.lParam = -1; + tvis.item.state |= TVIS_BOLD; + tvis.item.stateMask |= TVIS_BOLD; + tvis.item.iImage = tvis.item.iSelectedImage = IMG_GRPOPEN; + } else + { + tvis.item.lParam = indx; + if (options[indx].groupId == OPTTREE_CHECK) + { + tvis.item.iImage = tvis.item.iSelectedImage = IMG_NOCHECK; + } else + { + tvis.item.iImage = tvis.item.iSelectedImage = IMG_NORCHECK; + } + } + hItem = TreeView_InsertItem(hwndTree, &tvis); + if (!sectionName) + options[indx].hItem = hItem; + } + } + sectionLevel++; + hSection = hItem; + } + } + + OptTree_Translate(hwndTree); + ShowWindow(hwndTree, SW_SHOW); + TreeView_SelectItem(hwndTree, OptTree_FindNamedTreeItemAt(hwndTree, 0, NULL)); + break; + } + + case WM_DESTROY: + { + ImageList_Destroy(TreeView_GetImageList(hwndTree, TVSIL_NORMAL)); + break; + } + + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR)lparam; + if (lpnmhdr->idFrom != idcTree) break; + switch (lpnmhdr->code) + { + case NM_CLICK: + { + TVHITTESTINFO hti; + hti.pt.x=(short)LOWORD(GetMessagePos()); + hti.pt.y=(short)HIWORD(GetMessagePos()); + ScreenToClient(lpnmhdr->hwndFrom,&hti.pt); + if(TreeView_HitTest(lpnmhdr->hwndFrom,&hti)) + { + if(hti.flags&TVHT_ONITEMICON) + { + TVITEM tvi; + tvi.mask=TVIF_HANDLE|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem=hti.hItem; + TreeView_GetItem(lpnmhdr->hwndFrom,&tvi); + switch (tvi.iImage) + { + case IMG_GRPOPEN: + tvi.iImage = tvi.iSelectedImage = IMG_GRPCLOSED; + TreeView_Expand(lpnmhdr->hwndFrom, tvi.hItem, TVE_COLLAPSE); + break; + case IMG_GRPCLOSED: + tvi.iImage = tvi.iSelectedImage = IMG_GRPOPEN; + TreeView_Expand(lpnmhdr->hwndFrom, tvi.hItem, TVE_EXPAND); + break; + + case IMG_CHECK: + tvi.iImage = tvi.iSelectedImage = IMG_NOCHECK; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case IMG_NOCHECK: + tvi.iImage = tvi.iSelectedImage = IMG_CHECK; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case IMG_NORCHECK: + { + int i; + for (i = 0; i < optionCount; ++i) + { + if (options[i].groupId == options[tvi.lParam].groupId) + { + TVITEM tvi_tmp; + tvi_tmp.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi_tmp.hItem = options[i].hItem; + tvi_tmp.iImage = tvi_tmp.iSelectedImage = IMG_NORCHECK; + TreeView_SetItem(lpnmhdr->hwndFrom, &tvi_tmp); + } + } + tvi.iImage = tvi.iSelectedImage = IMG_RCHECK; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + } + } + TreeView_SetItem(lpnmhdr->hwndFrom,&tvi); + } + } + break; + } + + case TVN_ITEMEXPANDEDW: + { + LPNMTREEVIEWW lpnmtv = (LPNMTREEVIEWW)lparam; + TVITEM tvi; + tvi.mask=TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem = lpnmtv->itemNew.hItem; + tvi.iImage = tvi.iSelectedImage = + (lpnmtv->itemNew.state & TVIS_EXPANDED) ? IMG_GRPOPEN : IMG_GRPCLOSED; + SendMessageW(lpnmhdr->hwndFrom, TVM_SETITEMW, 0, (LPARAM)&tvi); + break; + } + + case TVN_ITEMEXPANDEDA: + { + LPNMTREEVIEWA lpnmtv = (LPNMTREEVIEWA)lparam; + TVITEM tvi; + tvi.mask=TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem = lpnmtv->itemNew.hItem; + tvi.iImage = tvi.iSelectedImage = + (lpnmtv->itemNew.state & TVIS_EXPANDED) ? IMG_GRPOPEN : IMG_GRPCLOSED; + SendMessageA(lpnmhdr->hwndFrom, TVM_SETITEMA, 0, (LPARAM)&tvi); + break; + } + } + break; + } + } + return FALSE; +} + +DWORD OptTree_GetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, char *szSettingName) +{ + enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED }; + + HWND hwndTree = GetDlgItem(hwnd, idcTree); + DWORD result = 0; + int i; + for (i = 0; i < optionCount; ++i) + { + if ((!options[i].szSettingName && !szSettingName) || + (options[i].szSettingName && szSettingName && !lstrcmpA(options[i].szSettingName, szSettingName))) + { + TVITEM tvi; + tvi.mask = TVIF_HANDLE|TVIF_IMAGE; + tvi.hItem = options[i].hItem; + TreeView_GetItem(hwndTree, &tvi); + if ((tvi.iImage == IMG_CHECK) || (tvi.iImage == IMG_RCHECK)) + result |= options[i].dwFlag; + } + } + return result; +} + +void OptTree_SetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, DWORD dwOptions, char *szSettingName) +{ + enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED }; + + HWND hwndTree = GetDlgItem(hwnd, idcTree); + int i; + for (i = 0; i < optionCount; ++i) + { + if ((!options[i].szSettingName && !szSettingName) || + (options[i].szSettingName && szSettingName && !lstrcmpA(options[i].szSettingName, szSettingName))) + { + TVITEM tvi; + tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem = options[i].hItem; + if (options[i].groupId == OPTTREE_CHECK) + { + tvi.iImage = tvi.iSelectedImage = (dwOptions & options[i].dwFlag) ? IMG_CHECK : IMG_NOCHECK; + } else + { + tvi.iImage = tvi.iSelectedImage = (dwOptions & options[i].dwFlag) ? IMG_RCHECK : IMG_NORCHECK; + } + TreeView_SetItem(hwndTree, &tvi); + } + } +} diff --git a/plugins/TrafficCounter/opttree.h b/plugins/TrafficCounter/opttree.h new file mode 100644 index 0000000000..968a0d28d7 --- /dev/null +++ b/plugins/TrafficCounter/opttree.h @@ -0,0 +1,54 @@ +/* + +Jabber Protocol Plugin for Miranda IM +Copyright ( C ) 2002-04 Santithorn Bunchua +Copyright ( C ) 2005-07 George Hazan +Copyright ( C ) 2007 Maxim Mluhov +Copyright ( C ) 2007 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. + +File name : $Source: $ +Revision : $Revision: $ +Last change on : $Date: $ +Last change by : $Author: $ + +*/ + +#ifndef __opttree_h__ +#define __opttree_h__ + +// Флаги +#define OPTTREE_CHECK 0 +#define OPTTREE_INVISIBLE 2 +#define OPTTREE_NOTRANSLATE 4 + +typedef struct { + int iconIndex; + TCHAR *szOptionName; + int groupId; + DWORD dwFlag; + HTREEITEM hItem; + char *szSettingName; +} OPTTREE_OPTION; + +BOOL OptTree_ProcessMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL *result, int idcTree, OPTTREE_OPTION *options, int optionCount); + +DWORD OptTree_GetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, char *szSettingName); +void OptTree_SetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, DWORD dwOptions, char *szSettingName); + +void OptTree_Translate(HWND hwndTree); + +#endif // __opttree_h__ diff --git a/plugins/TrafficCounter/res/network.ico b/plugins/TrafficCounter/res/network.ico new file mode 100644 index 0000000000..97c301be4d Binary files /dev/null and b/plugins/TrafficCounter/res/network.ico differ diff --git a/plugins/TrafficCounter/resource.h b/plugins/TrafficCounter/resource.h new file mode 100644 index 0000000000..63b8bdd055 --- /dev/null +++ b/plugins/TrafficCounter/resource.h @@ -0,0 +1,457 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resource.rc +// +#define IDC_AUTHICON 1 +#define IDC_NOTOALL 3 +#define IDC_APPLY 3 +#define IDI_MIRANDA 102 +#define IDD_OPT_TRAFFIC_POPUPS 103 +#define IDD_ABOUT 103 +#define IDI_SMS 103 +#define IDI_ONLINE 104 +#define IDI_OFFLINE 105 +#define IDD_CUSTOM_FONT 106 +#define IDD_OPT_FONTS 107 +#define IDD_OPT_GENMENU 108 +#define IDD_OPT_PROTOCOLORDER 109 +#define IDD_OPT_ICOLIB 110 +#define IDD_ICOLIB_IMPORT 111 +#define IDD_ADDED 115 +#define IDD_URLSEND 119 +#define IDD_URLRECV 120 +#define IDD_AUTHREQ 121 +#define IDD_DETAILS 125 +#define IDD_HISTORY 127 +#define IDI_AWAY 128 +#define IDI_FREE4CHAT 129 +#define IDI_INVISIBLE 130 +#define IDI_NA 131 +#define IDI_LOAD 132 +#define IDD_OPT_SOUND 134 +#define IDI_RECVMSG 136 +#define IDI_URL 138 +#define IDI_DND 158 +#define IDI_OCCUPIED 159 +#define IDI_USERDETAILS 160 +#define IDI_FINDUSER 161 +#define IDI_HELP 162 +#define IDI_OPTIONS 163 +#define IDI_MIRANDAWEBSITE 172 +#define IDI_RENAME 173 +#define IDI_HISTORY 174 +#define IDI_DELETE 175 +#define IDR_CONTEXT 180 +#define IDR_ICOLIB_CONTEXT 181 +#define IDC_DROP 183 +#define IDD_HISTORY_FIND 192 +#define IDI_SENDEMAIL 193 +#define IDD_FILERECV 194 +#define IDD_PROFILEMANAGER 197 +#define IDR_CLISTMENU 199 +#define IDI_BLANK 200 +#define IDD_FINDADD 201 +#define IDI_USERONLINE 201 +#define IDI_GROUPSHUT 202 +#define IDD_OPTIONS 203 +#define IDI_GROUPOPEN 203 +#define IDD_FILESEND 205 +#define IDI_NOTICK 205 +#define IDD_OPT_PLUGINS 206 +#define IDI_TICK 206 +#define IDD_OPT_ICONS 207 +#define IDI_FILE 207 +#define IDI_ADDCONTACT 210 +#define IDI_SMALLDOT 211 +#define IDI_FILLEDBLOB 212 +#define IDD_READAWAYMSG 213 +#define IDI_EMPTYBLOB 213 +#define IDD_OPT_IGNORE 214 +#define IDC_HYPERLINKHAND 214 +#define IDD_OPT_VISIBILITY 215 +#define IDC_DROPUSER 215 +#define IDD_SETAWAYMSG 216 +#define IDI_DETAILSLOGO 216 +#define IDD_OPT_AWAYMSG 217 +#define IDI_UNICODE 218 +#define IDI_ANSI 219 +#define IDD_INFO_SUMMARY 220 +#define IDI_LOADED 220 +#define IDD_INFO_CONTACT 221 +#define IDR_CREDITS 221 +#define IDI_NOTLOADED 221 +#define IDD_INFO_BACKGROUND 222 +#define IDD_INFO_NOTES 223 +#define IDD_ADDEMAIL 226 +#define IDD_ICONINDEX 227 +#define IDD_INFO_LOCATION 231 +#define IDD_INFO_WORK 232 +#define IDD_ADDPHONE 233 +#define IDD_INSTALLINI 235 +#define IDD_WARNINICHANGE 236 +#define IDD_INIIMPORTDONE 237 +#define IDB_SORTCOLUP 239 +#define IDB_SORTCOLDOWN 240 +#define IDD_OPT_TRAFFIC 248 +#define IDD_FILETRANSFERINFO 249 +#define IDD_OPT_FILETRANSFER 250 +#define IDD_FILEEXISTS 251 +#define IDD_DELETECONTACT 254 +#define IDD_DENYREASON 256 +#define IDD_ADDCONTACT 257 +#define IDD_OPT_CONTACT 261 +#define IDI_DOWNARROW 264 +#define IDD_OPT_IDLE 268 +#define IDD_PROFILE_SELECTION 269 +#define IDD_PROFILE_NEW 270 +#define IDI_TYPING 274 +#define IDD_UPDATE_NOTIFY 275 +#define IDD_OPT_UPDATENOTIFY 276 +#define IDI_GROUP_ICON 286 +#define IDI_UNINSTALL_ICON 287 +#define IDD_OPT_STATS 295 +#define IDI_ONTHEPHONE 1002 +#define IDC_MESSAGE 1002 +#define IDI_OUTTOLUNCH 1003 +#define IDC_AUTOCLOSE 1004 +#define IDC_FROM 1005 +#define IDC_AUTOMIN 1005 +#define IDC_DATE 1006 +#define IDC_MSG 1008 +#define IDC_NAME 1009 +#define IDC_NAMEVAL 1010 +#define IDC_ST_ENTERMSG 1013 +#define IDC_ST_ENTERURL 1014 +#define IDC_ENABLEUPNP 1015 +#define IDC_ABOUT 1032 +#define IDC_MYNOTES 1033 +#define IDC_URLS 1037 +#define IDC_REPLY 1039 +#define IDC_URL 1041 +#define IDC_FONTGROUP 1042 +#define IDC_COLOURLIST 1043 +#define IDC_STAT_RESTART 1044 +#define IDC_BTN_RESET 1045 +#define IDC_REASON 1046 +#define IDC_BTN_UNDO 1047 +#define IDC_EMAIL 1048 +#define IDC_NAMENICK 1049 +#define IDC_NAMEFIRST 1050 +#define IDC_NAMELAST 1051 +#define IDC_NICK 1053 +#define IDC_BTN_EXPORT 1054 +#define IDC_FONTLIST 1056 +#define IDC_CHOOSEFONT 1057 +#define IDC_GENDER 1060 +#define IDC_CITY 1061 +#define IDC_STATE 1062 +#define IDC_COUNTRY 1063 +#define IDC_AGE 1064 +#define IDC_ZIP 1064 +#define IDC_PHONE 1065 +#define IDC_STREET 1065 +#define IDC_COMPANY 1066 +#define IDC_LANGUAGE1 1066 +#define IDC_TIMEZONE 1067 +#define IDC_DEPARTMENT 1067 +#define IDC_LOCALTIME 1068 +#define IDC_DETAILS 1069 +#define IDC_POSITION 1069 +#define IDC_LANGUAGE2 1069 +#define IDC_ADD 1070 +#define IDC_LANGUAGE3 1070 +#define IDC_MOREOPTIONS 1071 +#define IDC_USERMENU 1071 +#define IDC_EDIT 1078 +#define IDC_LIST 1079 +#define IDC_HISTORY 1080 +#define IDC_MENUOBJECTS 1081 +#define IDC_MENUITEMS 1082 +#define IDC_NOTSUPPORTWARNING 1083 +#define IDC_INSERTSEPARATOR 1084 +#define IDC_GENMENU_SERVICE 1085 +#define IDC_GENMENU_CUSTOMNAME 1086 +#define IDC_GENMENU_SET 1087 +#define IDC_GENMENU_SET2 1088 +#define IDC_GENMENU_DEFAULT 1089 +#define IDC_BUILDTIME 1108 +#define IDC_CREDITSFILE 1109 +#define IDC_NUMBER 1113 +#define IDC_UIN 1123 +#define IDC_FINDWHAT 1131 +#define IDC_FIND 1132 +#define IDC_FILE 1133 +#define IDC_PROFILELIST 1134 +#define IDC_TABS 1141 +#define IDC_RESULTS 1142 +#define IDC_STATUS 1144 +#define IDC_CHANGE 1164 +#define IDC_PREVIEW 1165 +#define IDC_CHOOSE 1169 +#define IDC_TO 1170 +#define IDC_VERSION 1179 +#define IDC_ICONSET 1183 +#define IDC_BROWSE 1184 +#define IDC_PAGETREE 1186 +#define IDC_RETRIEVING 1193 +#define IDC_GETMORE 1200 +#define IDC_VISIBLEICON 1204 +#define IDC_INVISIBLEICON 1205 +#define IDC_FILEICON 1206 +#define IDC_ONLINEICON 1207 +#define IDC_FILENAMES 1208 +#define IDC_ALLICON 1208 +#define IDC_DONTREPLY 1209 +#define IDC_NONEICON 1209 +#define IDC_USEPREVIOUS 1210 +#define IDC_TYPINGICON 1210 +#define IDC_NODIALOG 1211 +#define IDC_USESPECIFIC 1212 +#define IDC_FILEDIR 1213 +#define IDC_ALLFILESPROGRESS 1217 +#define IDC_CURRENTSPEED 1219 +#define IDC_WHITERECT 1221 +#define IDC_ALLSPEED 1221 +#define IDC_CURRENTFILEPROGRESS 1222 +#define IDC_CURRENTFILEGROUP 1223 +#define IDC_FIRSTNAME 1224 +#define IDC_LASTNAME 1225 +#define IDC_CURRENTTRANSFERRED 1225 +#define IDC_DOBDAY 1226 +#define IDC_DOBMONTH 1227 +#define IDC_WEBPAGE 1228 +#define IDC_DOBYEAR 1228 +#define IDC_UPDATING 1231 +#define IDC_NAMEORDER 1234 +#define IDC_IMPORT 1241 +#define IDC_TOMAIN 1243 +#define IDC_TOPROTO 1244 +#define IDC_PROTOLIST 1245 +#define IDC_TODEFICON 1246 +#define IDC_IMPORTMULTI 1247 +#define IDC_BKGCOLOUR 1269 +#define IDC_FONTCOLOUR 1282 +#define IDC_INTERESTS 1305 +#define IDC_EMAILS 1306 +#define IDC_PAST 1307 +#define IDC_PHONES 1308 +#define IDC_SMS 1310 +#define IDC_AREA 1312 +#define IDC_UPDATE 1313 +#define IDC_ININAME 1333 +#define IDC_VIEWINI 1334 +#define IDC_SECURITYINFO 1335 +#define IDC_SETTINGNAME 1336 +#define IDC_NEWVALUE 1337 +#define IDC_WARNNOMORE 1338 +#define IDC_DELETE 1339 +#define IDC_RECYCLE 1340 +#define IDC_NEWNAME 1341 +#define IDC_MOVE 1342 +#define IDC_LEAVE 1343 +#define IDC_EXPERT 1346 +#define IDC_CATEGORYLIST 1366 +#define IDC_LOADICONS 1369 +#define IDC_STICONSGROUP 1371 +#define IDC_MSGICON 1375 +#define IDC_URLICON 1376 +#define IDC_STNOPAGE 1377 +#define IDC_STCHECKMARKS 1380 +#define IDC_MIRANDA 1388 +#define IDC_STATUSBAR 1389 +#define IDC_PROTOIDGROUP 1392 +#define IDC_BYPROTOID 1393 +#define IDC_PROTOID 1394 +#define IDC_EMAILGROUP 1395 +#define IDC_BYEMAIL 1396 +#define IDC_STNAMENICK 1397 +#define IDC_NAMEGROUP 1398 +#define IDC_BYNAME 1399 +#define IDC_STNAMEFIRST 1400 +#define IDC_STNAMELAST 1401 +#define IDC_ADVANCEDGROUP 1402 +#define IDC_BYADVANCED 1403 +#define IDC_ADVANCED 1404 +#define IDC_PROTOCOLORDER 1405 +#define IDC_TINYEXTENDEDGROUP 1406 +#define IDC_RESETPROTOCOLDATA 1407 +#define IDC_BYCUSTOM 1408 +#define IDC_PROTOCOLORDERWARNING 1409 +#define IDC_STSIMPLERIGHT 1440 +#define IDC_STATIC54 1453 +#define IDC_FILEDIRBROWSE 1475 +#define IDC_ALLFILESGROUP 1476 +#define IDC_SCANCMDLINEBROWSE 1476 +#define IDC_ALLTRANSFERRED 1477 +#define IDC_OPENFOLDER 1478 +#define IDC_OPENFILE 1479 +#define IDC_TOTALSIZE 1480 +#define IDC_AUTOACCEPT 1484 +#define IDC_SCANCMDLINE 1485 +#define IDC_WARNBEFOREOPENING 1488 +#define IDC_SCANDURINGDL 1489 +#define IDC_SCANAFTERDL 1490 +#define IDC_NOSCANNER 1491 +#define IDC_ST_CMDLINE 1492 +#define IDC_ST_CMDLINEHELP 1493 +#define IDC_PROPERTIES 1496 +#define IDC_RESUME 1497 +#define IDC_EXISTINGICON 1499 +#define IDC_RESUMEALL 1500 +#define IDC_OVERWRITE 1501 +#define IDC_OVERWRITEALL 1502 +#define IDC_SKIP 1503 +#define IDC_EXISTINGSIZE 1506 +#define IDC_EXISTINGDATE 1507 +#define IDC_EXISTINGTYPE 1508 +#define IDC_NEWICON 1509 +#define IDC_NEWSIZE 1510 +#define IDC_NEWDATE 1511 +#define IDC_NEWTYPE 1512 +#define IDC_SAVEAS 1513 +#define IDC_ASK 1516 +#define IDC_RENAME 1519 +#define IDC_VIRUSSCANNERGROUP 1520 +#define IDC_HIDE 1534 +#define IDC_TOPLINE 1535 +#define IDC_MAIL 1536 +#define IDC_DESCRIPTION 1538 +#define IDC_MYHANDLE 1540 +#define IDC_GROUP 1541 +#define IDC_ADDED 1542 +#define IDC_AUTH 1543 +#define IDC_DELETEHISTORY 1560 +#define IDC_AUTHREQ 1577 +#define IDC_AUTHGB 1578 +#define IDC_PROTOCOL 1580 +#define IDC_CONTRIBLINK 1586 +#define IDC_DEVS 1589 +#define IDC_LOGO 1591 +#define IDC_BUTTON_TSHOW 1597 +#define IDC_BUTTON_TSHOWHIDE 1598 +#define IDC_BUTTON_THIDE 1599 +#define IDC_CHECK1 1600 +#define IDC_DRAWKB 1601 +#define IDC_CHECK2 1604 +#define IDC_LAST_CLEAR 1609 +#define IDC_SAVETIMER 1612 +#define IDC_ESAVETIMER 1613 +#define IDC_BSHOWHIDE 1614 +#define IDC_NEED_RESTART 1615 +#define IDC_COLOR1 1617 +#define IDC_USESNAPPING 1618 +#define IDC_RESETCOLORS 1619 +#define IDC_COLOR2 1620 +#define IDC_DRAWCLEARDATE 1621 +#define IDC_NOTIFYSIZE 1622 +#define IDC_ENOTIFYSIZE 1623 +#define IDC_NOTIFYTIME 1624 +#define IDC_ENOTIFYTIME 1625 +#define IDC_TTRANSPARENT 1627 +#define IDC_TEST 1628 +#define IDC_TSTATIC 1633 +#define IDC_MAINTAB 1636 +#define IDC_IDLEONWINDOWS 1637 +#define IDC_POPUP_TIMEOUT 1638 +#define IDC_IDLEONMIRANDA 1638 +#define IDC_RADIO_FROMPOPUP 1639 +#define IDC_RADIO_CUSTOM 1640 +#define IDC_SELECT_PROTOCOLS 1641 +#define IDC_SCREENSAVER 1642 +#define IDC_LOCKED 1643 +#define IDC_IDLESHORT 1644 +#define IDC_COMBO_AUTO_CLEAR 1645 +#define IDC_IDLE1STTIME 1646 +#define IDC_IDLEPRIVATE 1649 +#define IDC_AASTATUS 1650 +#define IDC_AUTO_HIDE 1651 +#define IDC_AASHORTIDLE 1651 +#define IDC_CHECK3 1653 +#define IDC_CHECK_FIXED_HEIGHT 1655 +#define IDC_FORMAT 1656 +#define IDC_EDIT_DATEFORMAT 1657 +#define IDC_LINE_HEIGHT 1658 +#define IDC_CHECK_DATELINE 1659 +#define IDC_LOCATION 1659 +#define IDC_EDIT_ 1659 +#define IDC_SGROUP 1660 +#define IDC_COMBO_DATE_ALLIGN 1661 +#define IDC_SLOC 1661 +#define IDC_EDIT_COUNTER_FORMAT2 1661 +#define IDC_EDIT_COUNTER_FORMAT 1661 +#define IDC_EDIT_COUNTER_FORMAT3 1662 +#define IDC_EDIT_OVERALL_COUNTER_FORMAT 1662 +#define IDC_PROFILENAME 1673 +#define IDC_PROFILEDRIVERS 1674 +#define IDC_PLUGLIST 1676 +#define IDC_PLUGINLONGINFO 1677 +#define IDC_PLUGINAUTHOR 1679 +#define IDC_PLUGININFOFRAME 1680 +#define IDC_PLUGINCPYR 1681 +#define IDC_PLUGINURL 1682 +#define IDC_PLUGINPID 1683 +#define IDC_PLUGINEMAIL 1684 +#define IDC_IDLESPIN 1687 +#define IDC_NODBDRIVERS 1690 +#define IDC_IDLESTATUSLOCK 1691 +#define IDC_RESTART 1692 +#define IDC_TAB 1693 +#define IDC_IDLETERMINAL 1694 +#define IDC_ENABLESOUNDS 1695 +#define IDC_NEWVERSIONLABEL 1696 +#define IDC_CURRENTVERSION 1697 +#define IDC_DOWNLOAD 1699 +#define IDC_ENABLEUPDATES 1700 +#define IDC_ENABLEALPHA 1701 +#define IDC_RESETMENU 1702 +#define IDC_MODULES 1704 +#define IDC_STATIC_FILTERCAPTION 1705 +#define IDC_APPEARANCEOPTIONS 1715 +#define IDC_SPIN1 1716 +#define IDC_TOOLTIP_FORMAT 1718 +#define IDC_EDIT_TOOLTIP_FORMAT 1718 +#define IDC_TAB_STATS 1721 +#define IDC_COMBO1 1722 +#define IDC_COMBO_UNITS 1722 +#define IDC_LIST_DATA 1725 +#define IDC_STATIC_DNL 1726 +#define IDC_STATIC_UPL 1727 +#define IDC_STATIC_SUMM 1728 +#define IDC_BUTTON_CLEAR 1730 +#define IDC_EDIT_SPACE 21660 +#define IDC_EDIT_SPACE2 21661 +#define IDI_SEARCHALL 32548 +#define ID_ICQ_EXIT 40001 +#define IDM_COPY 40001 +#define ID_RESET 40002 +#define POPUP_HIDEEMPTYGROUPS 40003 +#define POPUP_NEWSUBGROUP 40004 +#define POPUP_HIDEOFFLINE 40005 +#define POPUP_GROUPHIDEOFFLINE 40006 +#define POPUP_HIDEOFFLINEROOT 40007 +#define POPUP_DISABLEGROUPS 40008 +#define IDC_SENDMESSAGE 40009 +#define IDM_COPYALL 40011 +#define IDM_SELECTALL 40012 +#define IDM_CLEAR 40013 +#define IDM_OPENNEW 40014 +#define IDM_OPENEXISTING 40015 +#define IDM_COPYLINK 40016 +#define POPUP_HIDEMIRANDA 40017 +#define ID_CANCELCHANGE 40018 +#define ID_TRAY_HIDE 40038 +#define ID_TRAY_EXIT 40040 +#define POPUP_NEWGROUP 40050 +#define POPUP_RENAMEGROUP 40052 +#define POPUP_DELETEGROUP 40053 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 297 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1731 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/TrafficCounter/resource.rc b/plugins/TrafficCounter/resource.rc new file mode 100644 index 0000000000..1b7687a641 --- /dev/null +++ b/plugins/TrafficCounter/resource.rc @@ -0,0 +1,233 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +#include "..\..\Include\statusmodes.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1251) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_UNINSTALL_ICON ICON "res\\network.ico" +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Russian (Russia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT_STATS DIALOGEX 0, 0, 305, 240 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + COMBOBOX IDC_COMBO_UNITS,243,69,62,90,CBS_DROPDOWNLIST | WS_TABSTOP + CONTROL "",IDC_TAB_STATS,"SysTabControl32",0x0,0,84,305,149 + LTEXT "Selected totals",IDC_STATIC,7,220,69,8,0,WS_EX_TRANSPARENT + LTEXT "Accounts",IDC_STATIC,5,4,30,8 + RTEXT "Units",IDC_STATIC,167,71,75,8 + LTEXT "0",IDC_STATIC_DNL,103,220,35,8,0,WS_EX_TRANSPARENT | WS_EX_RIGHT + LTEXT "0",IDC_STATIC_UPL,147,220,39,8,0,WS_EX_TRANSPARENT | WS_EX_RIGHT + LTEXT "0",IDC_STATIC_SUMM,195,220,39,8,0,WS_EX_TRANSPARENT | WS_EX_RIGHT + CONTROL "",IDC_LIST_DATA,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP,3,99,298,118 + PUSHBUTTON "Clear statistics",IDC_BUTTON_CLEAR,243,13,62,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPT_STATS, DIALOG + BEGIN + TOPMARGIN, 4 + BOTTOMMARGIN, 233 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Russian (Russia) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT_TRAFFIC_POPUPS DIALOG 0, 0, 313, 233 +STYLE DS_SETFONT | WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Notification",IDC_STATIC,4,5,302,104 + CONTROL "Notify me on every",IDC_NOTIFYSIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,15,86,10 + EDITTEXT IDC_ENOTIFYSIZE,96,13,29,14,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "kilobytes",IDC_STATIC,128,15,45,8 + CONTROL "Notify me on every",IDC_NOTIFYTIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,30,85,10 + EDITTEXT IDC_ENOTIFYTIME,96,28,29,14,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "minutes",IDC_STATIC,129,30,44,8 + LTEXT "Background colour:",IDC_STATIC,178,17,63,8 + CONTROL "",IDC_COLOR1,"ColourPicker",WS_TABSTOP,242,14,33,12 + LTEXT "Text colour:",IDC_STATIC,178,30,60,8 + CONTROL "",IDC_COLOR2,"ColourPicker",WS_TABSTOP,242,28,33,12 + PUSHBUTTON "Reset to default",IDC_RESETCOLORS,178,44,97,14 + GROUPBOX "Popup timeout",IDC_STATIC,10,62,110,41 + CONTROL "From PopUp plugin",IDC_RADIO_FROMPOPUP,"Button",BS_AUTORADIOBUTTON,14,73,101,10 + CONTROL "Custom",IDC_RADIO_CUSTOM,"Button",BS_AUTORADIOBUTTON,14,88,73,10 + EDITTEXT IDC_POPUP_TIMEOUT,90,85,24,14,ES_AUTOHSCROLL | ES_NUMBER + PUSHBUTTON "Test",IDC_TEST,251,93,50,11 +END + +IDD_OPT_TRAFFIC DIALOGEX 0, 0, 305, 245 +STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_COMBO_AUTO_CLEAR,259,3,42,88,CBS_DROPDOWNLIST | WS_TABSTOP + PUSHBUTTON "Show now",IDC_BSHOWHIDE,221,43,80,14 + LTEXT "Space between lines:",IDC_STATIC,190,25,70,8 + CONTROL "",IDC_APPEARANCEOPTIONS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | TVS_NOTOOLTIPS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,3,3,161,153 + EDITTEXT IDC_EDIT_SPACE,259,23,30,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_TABSTOP,287,25,9,12 + LTEXT "Counters format string:",IDC_STATIC,6,160,136,8 + EDITTEXT IDC_EDIT_COUNTER_FORMAT,3,168,298,38,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL + EDITTEXT IDC_EDIT_TOOLTIP_FORMAT,3,217,297,13,ES_MULTILINE | ES_AUTOHSCROLL + LTEXT "Tooltip format string:",IDC_STATIC,5,208,81,8 + LTEXT "Display traffic for current",IDC_LAST_CLEAR,177,6,81,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPT_TRAFFIC, DIALOG + BEGIN + BOTTOMMARGIN, 233 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include \r\n" + "#include \r\n" + "#include ""..\\..\\Include\\statusmodes.h""\r\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// +#include "version.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "Licensed under the terms of the GNU General Public License" + VALUE "CompanyName", " " + VALUE "FileDescription", "TrafficCounter" + VALUE "FileVersion", __VERSION_STRING + VALUE "InternalName", "TrafficCounter" + VALUE "LegalCopyright", "© 2002-2006 Ghost, © 2007-2012 Mironych" + VALUE "OriginalFilename", "TrafficCounter.dll" + VALUE "ProductName", "TrafficCounter" + VALUE "ProductVersion", __VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/TrafficCounter/statistics.c b/plugins/TrafficCounter/statistics.c new file mode 100644 index 0000000000..e202edd3fd --- /dev/null +++ b/plugins/TrafficCounter/statistics.c @@ -0,0 +1,751 @@ +/* +Traffic Counter plugin for Miranda IM +Copyright 2007-2011 Mironych. + +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. +*/ +/* ====================================================================================== +Здесь содержатся переменные и функции для работы со статистикой +Автор: Mironych +=======================================================================================*/ + +#include "commonheaders.h" +#include + +HWND hListAccs; + +BOOL CALLBACK DlgProcOptStatistics(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD i; + + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + // Создаём ListBox c перечнем аккаунтов. + hListAccs = CreateWindowEx(WS_EX_CLIENTEDGE, + _T("ListBox"), + NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | LBS_SORT | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | LBS_NOTIFY, + 2, 20, 246, 112, + hwndDlg, NULL, NULL, NULL); + SendMessage(hListAccs, WM_SETFONT, (WPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), 0); + for (i = NumberOfAccounts; i--; ) + { + // Готовим список аккаунтов + if (ProtoList[i].tszAccountName) + SendMessage(hListAccs, LB_ADDSTRING, 0, (LPARAM)ProtoList[i].tszAccountName); + } + for (i = NumberOfAccounts; i--; ) + SendMessage(hListAccs, LB_SETSEL, (WPARAM)0x01&(Stat_SelAcc>>i), (LPARAM)i); + // Готовим список единиц измерения + SendDlgItemMessage(hwndDlg, IDC_COMBO_UNITS, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Bytes")); + SendDlgItemMessage(hwndDlg, IDC_COMBO_UNITS, CB_INSERTSTRING, -1, (LPARAM)TranslateT("KB")); + SendDlgItemMessage(hwndDlg, IDC_COMBO_UNITS, CB_INSERTSTRING, -1, (LPARAM)TranslateT("MB")); + SendDlgItemMessage(hwndDlg, IDC_COMBO_UNITS, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Adaptive")); + SendDlgItemMessage(hwndDlg, IDC_COMBO_UNITS, CB_SETCURSEL, unOptions.Stat_Units, 0); + // Готовим закладки + { + TCITEM tci; + tci.mask = TCIF_TEXT; + tci.cchTextMax = 32; + tci.pszText = TranslateT("Hourly"); + SendDlgItemMessage(hwndDlg, IDC_TAB_STATS, TCM_INSERTITEM, 0, (LPARAM)&tci); + tci.pszText = TranslateT("Daily"); + SendDlgItemMessage(hwndDlg, IDC_TAB_STATS, TCM_INSERTITEM, 1, (LPARAM)&tci); + tci.pszText = TranslateT("Weekly"); + SendDlgItemMessage(hwndDlg, IDC_TAB_STATS, TCM_INSERTITEM, 2, (LPARAM)&tci); + tci.pszText = TranslateT("Monthly"); + SendDlgItemMessage(hwndDlg, IDC_TAB_STATS, TCM_INSERTITEM, 3, (LPARAM)&tci); + tci.pszText = TranslateT("Yearly"); + SendDlgItemMessage(hwndDlg, IDC_TAB_STATS, TCM_INSERTITEM, 4, (LPARAM)&tci); + SendDlgItemMessage(hwndDlg, IDC_TAB_STATS, TCM_SETCURSEL, unOptions.Stat_Tab, 0); + } + // Готовим ListView - колонки и стили + { + LVCOLUMN lvc ={0}; + + SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); +#ifdef UNICODE + SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_SETUNICODEFORMAT, 1, 0); +#else + SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_SETUNICODEFORMAT, 0, 0); +#endif + + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + lvc.cchTextMax = 32; + lvc.pszText = TranslateT("Period"); + lvc.cx = 135; + lvc.iSubItem = 0; + SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc); + lvc.fmt = LVCFMT_RIGHT; + lvc.pszText = TranslateT("Incoming"); + lvc.iSubItem = 1; + lvc.cx = 72; + SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_INSERTCOLUMN, 1, (LPARAM)&lvc); + lvc.pszText = TranslateT("Outgoing"); + lvc.iSubItem = 2; + lvc.cx = 72; + SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_INSERTCOLUMN, 2, (LPARAM)&lvc); + lvc.pszText = TranslateT("Sum"); + lvc.iSubItem = 3; + lvc.cx = 72; + SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_INSERTCOLUMN, 3, (LPARAM)&lvc); + lvc.pszText = TranslateT("Online"); + lvc.iSubItem = 4; + lvc.cx = 72; + SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_INSERTCOLUMN, 4, (LPARAM)&lvc); + } + Stat_Show(hwndDlg); + break; // WM_INITDIALOG + case WM_COMMAND: + if ((HWND)lParam == hListAccs) + { + DWORD SelItems[16]; + BYTE SelItemsCount; + if (HIWORD(wParam) == LBN_SELCHANGE) + { + SelItemsCount = SendMessage(hListAccs, LB_GETSELCOUNT, 0, 0); + SendMessage(hListAccs, + LB_GETSELITEMS, + SelItemsCount, + (LPARAM)SelItems); + for (Stat_SelAcc = i = 0; i < SelItemsCount; i++) + Stat_SelAcc |= 1 << SelItems[i]; + Stat_Show(hwndDlg); + } + } + switch (LOWORD(wParam)) + { + case IDC_COMBO_UNITS: + if (HIWORD(wParam) != CBN_SELCHANGE) break; + unOptions.Stat_Units = SendDlgItemMessage(hwndDlg, IDC_COMBO_UNITS, CB_GETCURSEL, 0, 0); + Stat_Show(hwndDlg); + break; + case IDC_BUTTON_CLEAR: + { + SYSTEMTIME stNow; + + if (IDOK != MessageBox(hwndDlg, + TranslateT("Now traffic statistics for selected accounts will be cleared.\nContinue?"), + _T("Traffic counter"), + MB_OKCANCEL | MB_ICONWARNING)) + break; + GetLocalTime(&stNow); + for (i = NumberOfAccounts; i--;) + if (0x01&(Stat_SelAcc>>i)) + { + SetFilePointer(ProtoList[i].hFile, sizeof(HOURLYSTATS), NULL, FILE_BEGIN); + SetEndOfFile(ProtoList[i].hFile); // Усекаем файл до одной записи. + ProtoList[i].NumberOfRecords = 1; + ProtoList[i].AllStatistics = (HOURLYSTATS*)mir_realloc(ProtoList[i].AllStatistics, sizeof(HOURLYSTATS)); + ProtoList[i].AllStatistics[0].Hour = stNow.wHour; + ProtoList[i].AllStatistics[0].Day = stNow.wDay; + ProtoList[i].AllStatistics[0].Month = stNow.wMonth; + ProtoList[i].AllStatistics[0].Year = stNow.wYear; + ProtoList[i].AllStatistics[0].Incoming = 0; + ProtoList[i].AllStatistics[0].Outgoing = 0; + ProtoList[i].StartIncoming = 0; + ProtoList[i].StartOutgoing = 0; + ProtoList[i].AllStatistics[0].Time = 0; + ProtoList[i].Total.TimeAtStart = GetTickCount(); + Stat_CheckStatistics(i); + } + Stat_Show(hwndDlg); + } + break; + } + break; // WM_COMMAND + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR)lParam; + + switch(lpnmhdr->idFrom) + { + case IDC_TAB_STATS: + if (lpnmhdr->code != TCN_SELCHANGE) break; + unOptions.Stat_Tab = SendDlgItemMessage(hwndDlg, IDC_TAB_STATS, TCM_GETCURSEL, 0, 0); + Stat_Show(hwndDlg); + break; + case IDC_LIST_DATA: + switch (lpnmhdr->code) + { + case LVN_GETDISPINFO: + { + NMLVDISPINFO* pdi = (NMLVDISPINFO*)lParam; + SYSTEMTIME st = {0}; + DWORD Index, Value; + double vartime; + TCHAR szBufW[64]; + BYTE EldestAcc; + + if (!(pdi->item.mask & LVIF_TEXT)) return 0; + + // Если нужна надпись. + if (!pdi->item.iSubItem) + { + EldestAcc = Stat_GetEldestAcc(Stat_SelAcc); + // Индекс применим только для самого старого аккаунта! + Index = Stat_GetStartIndex(EldestAcc, unOptions.Stat_Tab, pdi->item.iItem, &st); + switch (unOptions.Stat_Tab) + { + case 0: // Hourly + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, szBufW, 32); + mir_sntprintf(pdi->item.pszText, 32, _T("%s %02d:00 - %02d:59"), + szBufW, + ProtoList[EldestAcc].AllStatistics[Index].Hour, + ProtoList[EldestAcc].AllStatistics[Index].Hour); + break; + case 1: // Dayly + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pdi->item.pszText, 32); + break; + case 2: // Weekly + // Уходим к первому понедельнику слева. + SystemTimeToVariantTime(&st, &vartime); + vartime -= DayOfWeek(st.wDay, st.wMonth, st.wYear) - 1; + VariantTimeToSystemTime(vartime, &st); + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pdi->item.pszText, 32); + // Теперь к воскресенью. + SystemTimeToVariantTime(&st, &vartime); + vartime += 6; + VariantTimeToSystemTime(vartime, &st); + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, szBufW, 32); + mir_sntprintf(pdi->item.pszText, 32, _T("%s - %s"), pdi->item.pszText, szBufW); + break; + case 3: // Monthly + GetDateFormat(LOCALE_USER_DEFAULT, DATE_YEARMONTH, &st, NULL, pdi->item.pszText, 32); + break; + case 4: // Yearly + mir_sntprintf(pdi->item.pszText, 32, _T("%d"), st.wYear); + break; + } + return 0; + } + + Value = Stat_GetItemValue(Stat_SelAcc, unOptions.Stat_Tab, pdi->item.iItem, pdi->item.iSubItem); + + // Теперь можно записать в ListView циферки. + switch (pdi->item.iSubItem) + { + case 1: // Входящий + case 2: // Исходящий + case 3: // Сумма + GetFormattedTraffic(Value, unOptions.Stat_Units, pdi->item.pszText, 32); + break; + case 4: // Время + { + TCHAR *Fmt[5] = {_T("m:ss"), _T("h:mm:ss"), _T("h:mm:ss"), _T("d hh:mm:ss"), _T("d hh:mm:ss")}; + GetDurationFormatM(Value, Fmt[unOptions.Stat_Tab], pdi->item.pszText, 32); + } + break; + } + } + break; + + case NM_CLICK: + case LVN_ITEMCHANGED: + { + DWORD i, j = -1, dwTotalIncoming = 0, dwTotalOutgoing = 0; + + i = SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_GETSELECTEDCOUNT, 0, 0); + for ( ; i--;) + { + j = SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_GETNEXTITEM, j, LVNI_SELECTED); + dwTotalIncoming += Stat_GetItemValue(Stat_SelAcc, unOptions.Stat_Tab, j, 1); + dwTotalOutgoing += Stat_GetItemValue(Stat_SelAcc, unOptions.Stat_Tab, j, 2); + } + Stat_UpdateTotalTraffic(hwndDlg, dwTotalIncoming, dwTotalOutgoing); + } + break; + + case NM_CUSTOMDRAW: + { + LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam; + + switch (lplvcd->nmcd.dwDrawStage) + { + case CDDS_PREPAINT: // Перед началом рисования всего ListView. + SetWindowLong(hwndDlg, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW); + return TRUE; + case CDDS_ITEMPREPAINT: // Перед началом рисования строки. + { + COLORREF Color; + BYTE r, g, b; + + if (lplvcd->nmcd.dwItemSpec & 0x01) + { + Color = SendDlgItemMessage(hwndDlg, IDC_LIST_DATA, LVM_GETBKCOLOR, 0, 0); + r = GetRValue(Color); + g = GetGValue(Color); + b = GetBValue(Color); + r += r > 0x80 ? -40 : 40; + g += g > 0x80 ? -40 : 40; + b += b > 0x80 ? -40 : 40; + lplvcd->clrTextBk = RGB(r, g, b);; + } + SetWindowLong(hwndDlg, DWL_MSGRESULT, CDRF_NEWFONT); + return TRUE; + } + } + } + break; + } + break; + } + } + break; // WM_NOTIFY + } + return 0; +} + +/* +Функция читает статистику из файла для аккаунта с номером n. +*/ +void Stat_ReadFile(BYTE n) +{ + LARGE_INTEGER Size; + DWORD BytesRead; + TCHAR FileName[MAX_PATH], *pszPath; + SYSTEMTIME stNow, stLast = {0}; + + pszPath = Utils_ReplaceVarsT(_T("%miranda_userdata%\\statistics")); + CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)pszPath); + mir_sntprintf(FileName, MAX_PATH, _T("%s\\%S.stat"), pszPath, ProtoList[n].name); + mir_free(pszPath); + GetLocalTime(&stNow); + ProtoList[n].hFile = CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + GetFileSizeEx(ProtoList[n].hFile, &Size); + if (Size.QuadPart != 0) // Если файл со статистикой существует и имеет ненулевой размер... + { + // ...то читаем статистику из файла + ProtoList[n].NumberOfRecords = Size.QuadPart/sizeof(HOURLYSTATS); + ProtoList[n].AllStatistics = (HOURLYSTATS*)mir_alloc(sizeof(HOURLYSTATS)*ProtoList[n].NumberOfRecords); + ReadFile(ProtoList[n].hFile, &ProtoList[n].AllStatistics[0], sizeof(HOURLYSTATS)*ProtoList[n].NumberOfRecords, &BytesRead, NULL); + if (!BytesRead) + { + MessageBox(TrafficHwnd, TranslateT("Couldn't read statistics file"), _T("Traffic Counter"), MB_OK); + return; + } + } + else + { + // Необходимо создать новый файл. + ProtoList[n].NumberOfRecords = 1; + ProtoList[n].AllStatistics = (HOURLYSTATS*)mir_alloc(sizeof(HOURLYSTATS)); + ProtoList[n].AllStatistics[0].Hour = stNow.wHour; + ProtoList[n].AllStatistics[0].Day = stNow.wDay; + ProtoList[n].AllStatistics[0].Month = stNow.wMonth; + ProtoList[n].AllStatistics[0].Year = stNow.wYear; + ProtoList[n].AllStatistics[0].Incoming = + ProtoList[n].AllStatistics[0].Outgoing = + ProtoList[n].AllStatistics[0].Time = 0; + } + Stat_CheckStatistics(n); +} + +/* Функция готовит вывод в ListView статистики. +Аргументы: hwndDialog - хэндл окна диалога. */ +void Stat_Show(HWND hwndDialog) +{ + DWORD MaxRecords; + + // Нужно узнать количество записей. + MaxRecords = Stat_GetRecordsNumber(Stat_GetEldestAcc(Stat_SelAcc), unOptions.Stat_Tab); + // Установим такое же количество строк в ListView. + SendDlgItemMessage(hwndDialog, IDC_LIST_DATA, LVM_SETITEMCOUNT, MaxRecords, 0); + // Надо показать самые свежие записи. + SendDlgItemMessage(hwndDialog, IDC_LIST_DATA, LVM_ENSUREVISIBLE, (WPARAM)(MaxRecords - 1), 0); +} + +void Stat_UpdateTotalTraffic(HWND hwndDialog, DWORD Incoming, DWORD Outgoing) +{ + TCHAR tmp[32]; + + GetFormattedTraffic(Incoming, unOptions.Stat_Units, tmp, 32); + SetDlgItemText(hwndDialog, IDC_STATIC_DNL, tmp); + GetFormattedTraffic(Outgoing, unOptions.Stat_Units, tmp, 32); + SetDlgItemText(hwndDialog, IDC_STATIC_UPL, tmp); + GetFormattedTraffic(Incoming + Outgoing, unOptions.Stat_Units, tmp, 32); + SetDlgItemText(hwndDialog, IDC_STATIC_SUMM, tmp); +} + +/* +Функция сравнивает с текущим время последней записи в статистике для аккаунта с номером n. +Если они совпадают, ничего не происходит. +Если текущее время меньше времени последней записи (часы перевели назад), + количество записей уменьшается на соответствующее количество часов. +Если текущее время больше, в статистику включается необходимое количество пустых записей. +*/ +void Stat_CheckStatistics(BYTE n) +{ + SYSTEMTIME stNow, stLast = {0}; + HOURLYSTATS htTmp = {0}; + signed short int d;//, i; + DWORD q; + + stLast.wHour = ProtoList[n].AllStatistics[ProtoList[n].NumberOfRecords-1].Hour; + stLast.wDay = ProtoList[n].AllStatistics[ProtoList[n].NumberOfRecords-1].Day; + stLast.wMonth = ProtoList[n].AllStatistics[ProtoList[n].NumberOfRecords-1].Month; + stLast.wYear = ProtoList[n].AllStatistics[ProtoList[n].NumberOfRecords-1].Year; + + GetLocalTime(&stNow); + d = TimeCompare(stNow, stLast); + // Если текущее время совпадает со временем последней записи... + if (!d) + { + // ...сохраняем запись в файл и уходим. + SetFilePointer(ProtoList[n].hFile, 0-sizeof(HOURLYSTATS), NULL, FILE_END); + WriteFile(ProtoList[n].hFile, &ProtoList[n].AllStatistics[ProtoList[n].NumberOfRecords-1], sizeof(HOURLYSTATS), &q, NULL); + return; + } + + // Если часы перевели назад. + if (d < 0) + { + do + { + stLast.wHour--; + if (stLast.wHour == 0xFFFF) + { + stLast.wDay--; + if (!stLast.wDay) + { + stLast.wMonth--; + if (!stLast.wMonth) + { + stLast.wMonth = 12; + stLast.wYear--; + } + stLast.wDay = DaysInMonth(htTmp.Month, htTmp.Year); + } + } + + ProtoList[n].NumberOfRecords--; + } while (TimeCompare(stNow, stLast)); + return; + } + + if (d > 0) + { + // Сохраняем. + SetFilePointer(ProtoList[n].hFile, 0-sizeof(HOURLYSTATS), NULL, FILE_END); + WriteFile(ProtoList[n].hFile, &ProtoList[n].AllStatistics[ProtoList[n].NumberOfRecords-1], sizeof(HOURLYSTATS), &q, NULL); + + // Последняя запись из статистики понадобится для вычисления новых записей, поэтому копируем её (кроме трафика и времени). + memcpy(&htTmp, &ProtoList[n].AllStatistics[ProtoList[n].NumberOfRecords - 1], + sizeof(HOURLYSTATS) - 2 * sizeof(DWORD) - sizeof(WORD)); + // Счётчик времени каждый час должен начинать считать с нуля. + ProtoList[n].Total.TimeAtStart = GetTickCount() - stNow.wMilliseconds; + + do + { + ProtoList[n].AllStatistics = + (HOURLYSTATS*)mir_realloc(ProtoList[n].AllStatistics, sizeof(HOURLYSTATS) * ++ProtoList[n].NumberOfRecords); + + htTmp.Hour++; + if (htTmp.Hour > 23) + { + htTmp.Hour = 0; htTmp.Day++; + if (htTmp.Day > DaysInMonth(htTmp.Month, htTmp.Year)) + { + htTmp.Day = 1; htTmp.Month++; + if (htTmp.Month > 12) + { + htTmp.Month = 1; htTmp.Year++; + } + } + } + + stLast.wHour = htTmp.Hour; + stLast.wDay = htTmp.Day; + stLast.wMonth = htTmp.Month; + stLast.wYear = htTmp.Year; + + // Добавляем записи одновременно в ОЗУ и в файл. + WriteFile(ProtoList[n].hFile, &htTmp, sizeof(HOURLYSTATS), &q, NULL); + memcpy(&ProtoList[n].AllStatistics[ProtoList[n].NumberOfRecords - 1], &htTmp, sizeof(HOURLYSTATS)); + + } while (TimeCompare(stNow, stLast)); + } +} + +/* Функция возращает индекс первой записи в статистике, относящейся к выбранному интервалу. +При вычислении учитывается выбранный интервал и аккаунты. +Аргументы: +ItemNumber - номер строки в ListView (номер периода). +stReq - дата, соответствующая вычисленному индексу. +*/ +DWORD Stat_GetStartIndex(BYTE AccNum, BYTE Interval, DWORD ItemNumber, SYSTEMTIME *stReq) +{ + DWORD Left, Right, Probe; // Границы интервала для поиска (индексы статистики). + SYSTEMTIME stProbe = {0}; // Время тыка. + signed short int d = 1; + + if (!ItemNumber) + { + stReq->wHour = ProtoList[AccNum].AllStatistics[0].Hour; + stReq->wDay = ProtoList[AccNum].AllStatistics[0].Day; + stReq->wMonth = ProtoList[AccNum].AllStatistics[0].Month; + stReq->wYear = ProtoList[AccNum].AllStatistics[0].Year; + return 0; + } + + // Вычисляем время, соответствующее началу интервала. + for (Probe = 0, Left = 1; Left < ProtoList[AccNum].NumberOfRecords; Left++) + { + switch(Interval) + { + case STAT_INTERVAL_HOUR: + stReq->wHour = ProtoList[AccNum].AllStatistics[ItemNumber].Hour; + stReq->wDay = ProtoList[AccNum].AllStatistics[ItemNumber].Day; + stReq->wMonth = ProtoList[AccNum].AllStatistics[ItemNumber].Month; + stReq->wYear = ProtoList[AccNum].AllStatistics[ItemNumber].Year; + return ItemNumber; + break; + case STAT_INTERVAL_DAY: + if (ProtoList[AccNum].AllStatistics[Left].Day != ProtoList[AccNum].AllStatistics[Left - 1].Day) + Probe++; + break; + case STAT_INTERVAL_WEEK: + if ( !ProtoList[AccNum].AllStatistics[Left].Hour + && DayOfWeek(ProtoList[AccNum].AllStatistics[Left].Day, + ProtoList[AccNum].AllStatistics[Left].Month, + ProtoList[AccNum].AllStatistics[Left].Year) == 1) + Probe++; + break; + case STAT_INTERVAL_MONTH: + if (ProtoList[AccNum].AllStatistics[Left].Month != ProtoList[AccNum].AllStatistics[Left - 1].Month) + Probe++; + break; + case STAT_INTERVAL_YEAR: + if (ProtoList[AccNum].AllStatistics[Left].Year != ProtoList[AccNum].AllStatistics[Left - 1].Year) + Probe++; + break; + } + if (Probe == ItemNumber) break; + } + + stReq->wHour = ProtoList[AccNum].AllStatistics[Left].Hour; + stReq->wDay = ProtoList[AccNum].AllStatistics[Left].Day; + stReq->wMonth = ProtoList[AccNum].AllStatistics[Left].Month; + stReq->wYear = ProtoList[AccNum].AllStatistics[Left].Year; + + Left = 0; Right = ProtoList[AccNum].NumberOfRecords - 1; + + // Вычисляем индекс начала интервала. + while (TRUE) + { + if (Right - Left == 1) return Right; + Probe = (Left + Right) >> 1; + stProbe.wYear = ProtoList[AccNum].AllStatistics[Probe].Year; + stProbe.wMonth = ProtoList[AccNum].AllStatistics[Probe].Month; + stProbe.wDay = ProtoList[AccNum].AllStatistics[Probe].Day; + stProbe.wHour = ProtoList[AccNum].AllStatistics[Probe].Hour; + d = TimeCompare(*stReq, stProbe); + if (!d) break; + if (d < 0) Right = Probe; + if (d > 0) Left = Probe; + } + return Probe; +} + +/* Функция устанавливает величину сдвига для заданного аккаунта, +то есть номер записи в статистике старейшего из выбранных аккаунтов, +дата которой соответствует началу статистики указанного аккаунта. */ +void Stat_SetAccShift(BYTE AccNum, BYTE EldestAccount) +{ + DWORD Left, Right, Probe; // Границы интервала для поиска (индексы статистики). + SYSTEMTIME stReq = {0}, stProbe; + signed short int d = 1; + + if (AccNum == EldestAccount) + { + ProtoList[AccNum].Shift = 0; + return; + } + + stReq.wHour = ProtoList[AccNum].AllStatistics[0].Hour; + stReq.wDay = ProtoList[AccNum].AllStatistics[0].Day; + stReq.wMonth = ProtoList[AccNum].AllStatistics[0].Month; + stReq.wYear = ProtoList[AccNum].AllStatistics[0].Year; + + // Вычисляем индекс начала интервала. + Left = 0; Right = ProtoList[EldestAccount].NumberOfRecords - 1; + while (TRUE) + { + if (Right - Left == 1) + { + ProtoList[AccNum].Shift = Probe + d; + return; + } + Probe = (Left + Right) >> 1; + stProbe.wYear = ProtoList[EldestAccount].AllStatistics[Probe].Year; + stProbe.wMonth = ProtoList[EldestAccount].AllStatistics[Probe].Month; + stProbe.wDay = ProtoList[EldestAccount].AllStatistics[Probe].Day; + stProbe.wHour = ProtoList[EldestAccount].AllStatistics[Probe].Hour; + d = TimeCompare(stReq, stProbe); + if (!d) break; + if (d < 0) Right = Probe; + if (d > 0) Left = Probe; + } + ProtoList[AccNum].Shift = Probe; +} + +/* Функция вычисляет значение, соответствующее указанному подэлементу +указанной строки ListView. +Аргументы: +SelectedAccs - слово, в котором единичные биты соответствуют выбранным аккаунтам; +Interval - выбранный интервал; +ItemNum - номер строки в ListVew; +SubitemNum - номер колонки, определяет вид информации. */ +DWORD Stat_GetItemValue(WORD SelectedAccs, BYTE Interval, DWORD ItemNum, BYTE SubItemNum) +{ + DWORD Result = 0; + SYSTEMTIME st = {0}; + DWORD Index, IndexP, i; + signed long int IndexM; + BYTE a, EldestAcc; + + EldestAcc = Stat_GetEldestAcc(SelectedAccs); + Index = Stat_GetStartIndex(EldestAcc, Interval, ItemNum, &st); + + for (a = NumberOfAccounts; a--; ) + { + if (!((1 << a) & SelectedAccs)) continue; + Stat_SetAccShift(a, EldestAcc); + IndexM = Index - ProtoList[a].Shift; + IndexP = Index; + + for (i = 0; ; ) + { + if (IndexM >= 0) + switch (SubItemNum) + { + case 1: // Входящий + Result += ProtoList[a].AllStatistics[IndexM].Incoming; + break; + case 2: // Исходящий + Result += ProtoList[a].AllStatistics[IndexM].Outgoing; + break; + case 3: // Сумма + Result += ProtoList[a].AllStatistics[IndexM].Incoming + + ProtoList[a].AllStatistics[IndexM].Outgoing; + break; + case 4: // Время + Result += ProtoList[a].AllStatistics[IndexM].Time; + break; + } + + IndexM++; IndexP++; // Переходим к следующей записи. + if (IndexM == ProtoList[a].NumberOfRecords) break; + + // Когда остановиться? + switch (Interval) + { + case STAT_INTERVAL_HOUR: + i = 1; // Новый час начинается каждый час. + break; + case STAT_INTERVAL_DAY: + i = (0 == ProtoList[EldestAcc].AllStatistics[IndexP].Hour); + break; + case STAT_INTERVAL_WEEK: + i = (1 == DayOfWeek(ProtoList[EldestAcc].AllStatistics[IndexP].Day, + ProtoList[EldestAcc].AllStatistics[IndexP].Month, + ProtoList[EldestAcc].AllStatistics[IndexP].Year)) + && (0 == ProtoList[EldestAcc].AllStatistics[IndexP].Hour); + break; + case STAT_INTERVAL_MONTH: + i = (1 == ProtoList[EldestAcc].AllStatistics[IndexP].Day) + && (0 == ProtoList[EldestAcc].AllStatistics[IndexP].Hour); + break; + case STAT_INTERVAL_YEAR: + i = (1 == ProtoList[EldestAcc].AllStatistics[IndexP].Month) + && (1 == ProtoList[EldestAcc].AllStatistics[IndexP].Day) + && (0 == ProtoList[EldestAcc].AllStatistics[IndexP].Hour); + break; + } + + if (i) break; + } + } + + return Result; +} + +/* Функция возвращает количество записей в статистике для +заданного аккаунта и заданного интервала. */ +DWORD Stat_GetRecordsNumber(BYTE AccNum, BYTE Interval) +{ + DWORD Result, i; + + // Нужно узнать количество записей. + switch (Interval) + { + case STAT_INTERVAL_HOUR: + Result = ProtoList[AccNum].NumberOfRecords; // Для почасовой статистики совпадает. + break; + case STAT_INTERVAL_DAY: + for (Result = 1, i = ProtoList[AccNum].NumberOfRecords - 1; i--; ) + if (ProtoList[AccNum].AllStatistics[i].Day != ProtoList[AccNum].AllStatistics[i+1].Day) + Result++; + break; + case STAT_INTERVAL_WEEK: + for (Result = 1, i = ProtoList[AccNum].NumberOfRecords; i--; ) + if ( ProtoList[AccNum].AllStatistics[i].Hour == 23 + && DayOfWeek(ProtoList[AccNum].AllStatistics[i].Day, + ProtoList[AccNum].AllStatistics[i].Month, + ProtoList[AccNum].AllStatistics[i].Year) == 7) + Result++; + break; + case STAT_INTERVAL_MONTH: + for (Result = 1, i = ProtoList[AccNum].NumberOfRecords - 1; i--; ) + if (ProtoList[AccNum].AllStatistics[i].Month != ProtoList[AccNum].AllStatistics[i+1].Month) + Result++; + break; + case STAT_INTERVAL_YEAR: + for (Result = 1, i = ProtoList[AccNum].NumberOfRecords - 1; i--; ) + if (ProtoList[AccNum].AllStatistics[i].Year != ProtoList[AccNum].AllStatistics[i+1].Year) + Result++; + break; + } + + return Result; +} + +BYTE Stat_GetEldestAcc(WORD SelectedAccs) +{ + BYTE Result, i; + + // Узнаём номер аккаунта из числа выбранных, имеющего самую старую первую запись. + // (Это аккаунт с максимальным количеством записей.) + for (Result = i = 0; i < NumberOfAccounts; i++) + { + // Надо с чего-то начать поиск. + if ( 0x01 & (SelectedAccs >> i)) + { + Result = i; + break; + } + } + // Продолжаем поиск. + for (; ++i < NumberOfAccounts; ) + { + if ( 0x01 & (SelectedAccs >> i) && (ProtoList[i].NumberOfRecords > ProtoList[Result].NumberOfRecords) ) + Result = i; + } + + return Result; +} \ No newline at end of file diff --git a/plugins/TrafficCounter/statistics.h b/plugins/TrafficCounter/statistics.h new file mode 100644 index 0000000000..2fcff8520b --- /dev/null +++ b/plugins/TrafficCounter/statistics.h @@ -0,0 +1,45 @@ +#ifndef _statistics_h +#define _statistics_h + +/* +Traffic Counter plugin for Miranda IM +Copyright 2007-2011 Mironych. + +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. +*/ + +#define STAT_INTERVAL_HOUR 0 +#define STAT_INTERVAL_DAY 1 +#define STAT_INTERVAL_WEEK 2 +#define STAT_INTERVAL_MONTH 3 +#define STAT_INTERVAL_YEAR 4 + +#define STAT_UNITS_BYTES 0 +#define STAT_UNITS_KB 1 +#define STAT_UNITS_MB 2 +#define STAT_UNITS_ADAPTIVE 3 + +BOOL CALLBACK DlgProcOptStatistics(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +void Stat_ReadFile(BYTE); +void Stat_Show(HWND); +void Stat_UpdateTotalTraffic(HWND, DWORD, DWORD); +void Stat_CheckStatistics(BYTE); +DWORD Stat_GetStartIndex(BYTE AccNum, BYTE Interval, DWORD ItemNumber, SYSTEMTIME *st); +void Stat_SetAccShift(BYTE AccNum, BYTE EldestAccount); +DWORD Stat_GetItemValue(WORD SelectedAccs, BYTE Interval, DWORD ItemNum, BYTE SubitemNum); +DWORD Stat_GetRecordsNumber(BYTE AccNum, BYTE Interval); +BYTE Stat_GetEldestAcc(WORD SelectedAccs); + +#endif _statistics_h \ No newline at end of file diff --git a/plugins/TrafficCounter/vars.c b/plugins/TrafficCounter/vars.c new file mode 100644 index 0000000000..bc2cda965f --- /dev/null +++ b/plugins/TrafficCounter/vars.c @@ -0,0 +1,185 @@ +/* +Traffic Counter plugin for Miranda IM +Copyright 2007-2011 Mironych. + +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. +*/ +/* ====================================================================================== +Здесь содержатся функции для поддержки плагина Variables +Автор: Mironych +=======================================================================================*/ + +#include "commonheaders.h" + +static TCHAR* GetTraffic(ARGUMENTSINFO *ai) +{ + DWORD tmp, tmpsn = 0, tmprn = 0, tmpst = 0, tmprt = 0; + BYTE ed; + WORD l; + TCHAR *res; + + if (ai->argc != 5) return NULL; + + if (!_tcscmp(ai->targv[1], _T("overall"))) + { + tmpsn = OverallInfo.CurrentSentTraffic; + tmprn = OverallInfo.CurrentRecvTraffic; + tmpst = OverallInfo.TotalSentTraffic; + tmprt = OverallInfo.TotalRecvTraffic; + } + else + if (!_tcscmp(ai->targv[1], _T("summary"))) + { + for (ed = 0; ed < NumberOfAccounts; ed++) + if (ProtoList[ed].Visible) + { + tmpsn += ProtoList[ed].CurrentSentTraffic; + tmprn += ProtoList[ed].CurrentRecvTraffic; + tmpst += ProtoList[ed].TotalSentTraffic; + tmprt += ProtoList[ed].TotalRecvTraffic; + } + } + else + { // Ищем индекс протокола, переданного первым аргументом + for (tmp = ed = 0; ed < NumberOfAccounts; ed++) + { + TCHAR *buf; + if (!ProtoList[ed].name) continue; + buf = mir_a2t(ProtoList[ed].name); + if (!_tcscmp(buf, ai->targv[1])) + { + tmpsn = ProtoList[ed].CurrentSentTraffic; + tmprn = ProtoList[ed].CurrentRecvTraffic; + tmpst = ProtoList[ed].TotalSentTraffic; + tmprt = ProtoList[ed].TotalRecvTraffic; + tmp = 0xAA; // Признак того, что протокол был найден + } + mir_free(buf); + } + if (tmp != 0xAA) return NULL; + } + + if (!_tcscmp(ai->targv[2], _T("now"))) + { + if (!_tcscmp(ai->targv[3], _T("sent"))) tmp = tmpsn; + else + if (!_tcscmp(ai->targv[3], _T("received"))) tmp = tmprn; + else + if (!_tcscmp(ai->targv[3], _T("both"))) tmp = tmprn + tmpsn; + else return NULL; + } + else + if (!_tcscmp(ai->targv[2], _T("total"))) + { + if (!_tcscmp(ai->targv[3], _T("sent"))) tmp = tmpst; + else + if (!_tcscmp(ai->targv[3], _T("received"))) tmp = tmprt; + else + if (!_tcscmp(ai->targv[3], _T("both"))) tmp = tmprt + tmpst; + else return NULL; + } + else return NULL; + + if (!_tcscmp(ai->targv[4], _T("b"))) ed = 0; + else + if (!_tcscmp(ai->targv[4], _T("k"))) ed = 1; + else + if (!_tcscmp(ai->targv[4], _T("m"))) ed = 2; + else + if (!_tcscmp(ai->targv[4], _T("d"))) ed = 3; + else return NULL; + + // Получаем форматированную строку и возвращаем указатель на неё. + // Сначала узнаем размер буфера. + l = GetFormattedTraffic(tmp, ed, NULL, 0); + res = (TCHAR*)mir_alloc(l * sizeof(TCHAR)); + if (!res) return NULL; + if (GetFormattedTraffic(tmp, ed, res, l)) + return res; + + return NULL; +} + +static TCHAR* GetTime(ARGUMENTSINFO *ai) +{ + BYTE ed, flag; + TCHAR *res = NULL; + WORD l; + DWORD Duration; + + if (ai->argc != 4) return NULL; + + // Ищем индекс протокола, переданного первым аргументом + for (flag = ed = 0; ed < NumberOfAccounts; ed++) + { + TCHAR *buf; + if (!ProtoList[ed].name) continue; + buf = mir_a2t(ProtoList[ed].name); + if (!_tcscmp(buf, ai->targv[1])) + { + flag = 0xAA; + if (!_tcscmp(ai->targv[2], _T("now"))) + Duration = ProtoList[ed].Session.Timer; + else if (!_tcscmp(ai->targv[2], _T("total"))) + Duration = ProtoList[ed].Total.Timer; + else flag = 0; + break; + } + mir_free(buf); + } + if ( (flag != 0xAA) && !_tcscmp(ai->targv[1], _T("summary")) ) + { + flag = 0xAA; + if (!_tcscmp(ai->targv[2], _T("now"))) + Duration = OverallInfo.Session.Timer; + else if (!_tcscmp(ai->targv[2], _T("total"))) + Duration = OverallInfo.Total.Timer; + else flag = 0; + } + + if (flag != 0xAA) return NULL; + + // Получаем форматированную строку и возвращаем указатель на неё. + // Сначала узнаем размер буфера. + l = GetDurationFormatM(Duration, ai->targv[3], NULL, 0); + res = (TCHAR*)mir_alloc(l * sizeof(TCHAR)); + if (!res) return NULL; + GetDurationFormatM(Duration, ai->targv[3], res, l); + + return res; +} + +void RegisterVariablesTokens(void) +{ + TOKENREGISTER trs; + + if (!ServiceExists(MS_VARS_REGISTERTOKEN)) return; + + ZeroMemory(&trs, sizeof(trs)); + trs.cbSize = sizeof(TOKENREGISTER); + + // Функция, возвращающая трафик + trs.tszTokenString = _T("tc_GetTraffic"); + trs.parseFunctionT = GetTraffic; + trs.szHelpText = "Traffic counter\t(A,B,C,D)\tGet traffic counter value. A: OR overall OR summary; B: now OR total; C: sent OR received OR both; D: b - in bytes, k - in kilobytes, m - in megabytes, d - dynamic"; + trs.flags = TRF_TCHAR | TRF_PARSEFUNC | TRF_FUNCTION | TRF_FREEMEM; + trs.memType = TR_MEM_MIRANDA; + CallService(MS_VARS_REGISTERTOKEN, 0, (LPARAM)&trs); + // Функция, возвращающая время + trs.tszTokenString = _T("tc_GetTime"); + trs.parseFunctionT = GetTime; + trs.szHelpText = "Traffic counter\t(A,B,C)\tGet time counter value. A: OR summary; B: now OR total; C: format"; + CallService(MS_VARS_REGISTERTOKEN, 0, (LPARAM)&trs); +} diff --git a/plugins/TrafficCounter/vars.h b/plugins/TrafficCounter/vars.h new file mode 100644 index 0000000000..9c18990911 --- /dev/null +++ b/plugins/TrafficCounter/vars.h @@ -0,0 +1,9 @@ +#ifndef _vars_h +#define _vars_h + +//extern BYTE numProto; +extern BYTE NumberOfAccounts; +//extern PROTOLIST *ProtoList; +void RegisterVariablesTokens(void); + +#endif _vars_h \ No newline at end of file diff --git a/plugins/TrafficCounter/version.h b/plugins/TrafficCounter/version.h new file mode 100644 index 0000000000..d90dc2ec3e --- /dev/null +++ b/plugins/TrafficCounter/version.h @@ -0,0 +1,3 @@ +#define __FILEVERSION_STRING 0,1,1,8 +#define __VERSION_STRING "0.1.1.8" +#define __VERSION_DWORD 0x00010108 -- cgit v1.2.3