From 3b4342ead0909ee9f5d515db932272f901708a3a Mon Sep 17 00:00:00 2001 From: Vlad Mironov Date: Thu, 21 Feb 2013 15:59:28 +0000 Subject: =?UTF-8?q?=D1=81-plus-plusification?= 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@3671 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/TrafficCounter/.cproject | 194 ++- plugins/TrafficCounter/.project | 3 +- plugins/TrafficCounter/src/TrafficCounter.c | 1716 ------------------------ plugins/TrafficCounter/src/TrafficCounter.cpp | 1724 +++++++++++++++++++++++++ plugins/TrafficCounter/src/commonheaders.c | 1 - plugins/TrafficCounter/src/commonheaders.cpp | 1 + plugins/TrafficCounter/src/commonheaders.h | 11 +- plugins/TrafficCounter/src/misc.c | 303 ----- plugins/TrafficCounter/src/misc.cpp | 303 +++++ plugins/TrafficCounter/src/opttree.c | 410 ------ plugins/TrafficCounter/src/opttree.cpp | 410 ++++++ plugins/TrafficCounter/src/statistics.c | 751 ----------- plugins/TrafficCounter/src/statistics.cpp | 756 +++++++++++ plugins/TrafficCounter/src/vars.c | 185 --- plugins/TrafficCounter/src/vars.cpp | 188 +++ 15 files changed, 3469 insertions(+), 3487 deletions(-) delete mode 100644 plugins/TrafficCounter/src/TrafficCounter.c create mode 100644 plugins/TrafficCounter/src/TrafficCounter.cpp delete mode 100644 plugins/TrafficCounter/src/commonheaders.c create mode 100644 plugins/TrafficCounter/src/commonheaders.cpp delete mode 100644 plugins/TrafficCounter/src/misc.c create mode 100644 plugins/TrafficCounter/src/misc.cpp delete mode 100644 plugins/TrafficCounter/src/opttree.c create mode 100644 plugins/TrafficCounter/src/opttree.cpp delete mode 100644 plugins/TrafficCounter/src/statistics.c create mode 100644 plugins/TrafficCounter/src/statistics.cpp delete mode 100644 plugins/TrafficCounter/src/vars.c create mode 100644 plugins/TrafficCounter/src/vars.cpp (limited to 'plugins/TrafficCounter') diff --git a/plugins/TrafficCounter/.cproject b/plugins/TrafficCounter/.cproject index 0f799a8a7d..1ed51ff4fd 100644 --- a/plugins/TrafficCounter/.cproject +++ b/plugins/TrafficCounter/.cproject @@ -1,12 +1,12 @@ - - + + - - + + @@ -16,65 +16,66 @@ - - - - - - - - - + + - - + + @@ -84,101 +85,72 @@ - - - - - - - - - - - + - - + - + + diff --git a/plugins/TrafficCounter/.project b/plugins/TrafficCounter/.project index 9662d3935a..ebb10d548f 100644 --- a/plugins/TrafficCounter/.project +++ b/plugins/TrafficCounter/.project @@ -27,7 +27,7 @@ org.eclipse.cdt.make.core.buildLocation - ${workspace_loc:/tcounter/Debug} + ${workspace_loc:/TrafficCounter/Release} org.eclipse.cdt.make.core.contents @@ -64,6 +64,7 @@ org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature org.eclipse.cdt.managedbuilder.core.managedBuildNature org.eclipse.cdt.managedbuilder.core.ScannerConfigNature diff --git a/plugins/TrafficCounter/src/TrafficCounter.c b/plugins/TrafficCounter/src/TrafficCounter.c deleted file mode 100644 index a423804e64..0000000000 --- a/plugins/TrafficCounter/src/TrafficCounter.c +++ /dev/null @@ -1,1716 +0,0 @@ -/* -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" -#include "m_tipper.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); - - -PLUGININFOEX pluginInfoEx = -{ - sizeof(PLUGININFOEX), - "Traffic Counter", - 0, // Начиная с версии ядра 0.92.1.0 поле с версией не используется. - "Adding traffic and time counters.", - "Ghost, Mironych", - "", - "© 2002-2006 Ghost, © 2007-2012 Mironych", - "", - UNICODE_AWARE, - {0x82181510, 0x5dfa, 0x49d7, { 0xb4, 0x69, 0x33, 0x87, 0x1e, 0x2a, 0xe8, 0xb5}} // {82181510-5DFA-49d7-B469-33871E2AE8B5} -}; - -__declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) -{ - mirandaVer = mirandaVersion; - return &pluginInfoEx; -} - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - hInst = hinstDLL; - DisableThreadLibraryCalls(hInst); - - 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 = db_get_dw(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, 0x0882); - Stat_SelAcc = db_get_w(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_STAT_ACC_OPT, 0x01); - - //settings for notification - Traffic_PopupBkColor = db_get_dw(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_BKCOLOR,RGB(200,255,200)); - Traffic_PopupFontColor = db_get_dw(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_FONTCOLOR,RGB(0,0,0)); - // - Traffic_Notify_time_value = db_get_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_TIME_VALUE,10); - // - Traffic_Notify_size_value = db_get_w(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_SIZE_VALUE,100); - // - //popup timeout - Traffic_PopupTimeoutDefault = db_get_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_DEFAULT,1); - Traffic_PopupTimeoutValue = db_get_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_VALUE,5); - - // Формат счётчика для каждого активного протокола - if (db_get_ts(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_COUNTER_FORMAT, &dbv) == 0) - { - if(lstrlen(dbv.ptszVal) > 0) - lstrcpyn(Traffic_CounterFormat, dbv.ptszVal, SIZEOF(Traffic_CounterFormat)); - // - db_free(&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 (db_get_ts(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_TOOLTIP_FORMAT, &dbv) == 0) - { - if(lstrlen(dbv.ptszVal) > 0) - lstrcpyn(Traffic_TooltipFormat, dbv.ptszVal, SIZEOF(Traffic_TooltipFormat)); - // - db_free(&dbv); - } - else //defaults here - { - _tcscpy(Traffic_TooltipFormat, _T("Traffic Counter")); - } - - Traffic_AdditionSpace = db_get_b(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_ADDITION_SPACE, 0); - - // Счётчик времени онлайна - OverallInfo.Total.Timer = db_get_dw(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 INT_PTR 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 INT_PTR 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 = db_get_b(NULL, "ModernSettings", "UseKeyColor", 1); - KeyColor = db_get_dw(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; - 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; - - // Сохраняем счётчик времени онлайна - db_set_dw(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; - db_set_b(NULL, ProtoList[i].name, SETTINGS_PROTO_FLAGS, ProtoList[i].Flags); - } - - //settings for notification - db_set_dw(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_BKCOLOR,Traffic_PopupBkColor); - db_set_dw(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_FONTCOLOR,Traffic_PopupFontColor); - // - db_set_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_TIME_VALUE,Traffic_Notify_time_value); - // - db_set_w(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_SIZE_VALUE,Traffic_Notify_size_value); - // - //popup timeout - db_set_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_DEFAULT,Traffic_PopupTimeoutDefault); - db_set_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_VALUE,Traffic_PopupTimeoutValue); - // - // Формат счётчиков - db_set_ts(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_COUNTER_FORMAT, Traffic_CounterFormat); - - db_set_ts(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_TOOLTIP_FORMAT, Traffic_TooltipFormat); - - db_set_b(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_ADDITION_SPACE, Traffic_AdditionSpace); - // Сохраняем флаги - db_set_dw(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, unOptions.Flags); - db_set_w(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")) - && !db_get_b(NULL, "ModernData", "DisableEngine", 0) - && db_get_b(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 ( !db_get_b(NULL, "ModernData", "DisableEngine", 0) - && db_get_b(NULL, "ModernData", "EnableLayering", 1) - && ServiceExists(MS_SKINENG_INVALIDATEFRAMEIMAGE)) - CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE, (WPARAM)TrafficHwnd, 0); - else - { - HDC hdc = GetDC(hwnd); - PaintTrafficCounterWindow(hwnd, hdc); - ReleaseDC(hwnd, hdc); - } - } - break; - - case WM_ERASEBKGND: - return 1; - - case WM_LBUTTONDOWN : - if (db_get_b(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); - - CallService(MS_TIPPER_SHOWTIPW, (WPARAM)TooltipText, (LPARAM)&ti); - - TooltipShowing = TRUE; - mir_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_PTR 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); - db_set_dw(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, unOptions.Flags); - // - return 0; -} - -void Traffic_AddMainMenuItem(void) -{ - CLISTMENUITEM mi = { sizeof(mi) }; - mi.position = -0x7FFFFFFF; - mi.flags = 0; - mi.hIcon = NULL; - mi.pszName = LPGEN("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); - _tcsncpy(ppd.lptzContactName, TranslateT("Traffic counter notification"), MAX_CONTACTNAME); - // - mir_sntprintf(ppd.lptzText, MAX_SECONDLINE, TranslateT("%d kilobytes sent"), - notify_send_size = OverallInfo.CurrentSentTraffic >> 10); - // - ppd.colorBack = Traffic_PopupBkColor; - ppd.colorText = Traffic_PopupFontColor; - ppd.PluginWindowProc = NULL; - ppd.iSeconds = (Traffic_PopupTimeoutDefault ? 0 : Traffic_PopupTimeoutValue); - PUAddPopUpT(&ppd); -} - -void NotifyOnRecv(void) -{ - POPUPDATAT ppd; - - ZeroMemory(&ppd, sizeof(ppd)); - ppd.lchContact = NULL; - ppd.lchIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); - _tcsncpy(ppd.lptzContactName, TranslateT("Traffic counter notification"),MAX_CONTACTNAME); - // - mir_sntprintf(ppd.lptzText, MAX_SECONDLINE, TranslateT("%d kilobytes received"), - notify_recv_size = OverallInfo.CurrentRecvTraffic >> 10); - // - ppd.colorBack = Traffic_PopupBkColor; - ppd.colorText = Traffic_PopupFontColor; - ppd.PluginWindowProc = NULL; - ppd.iSeconds = (Traffic_PopupTimeoutDefault ? 0 : Traffic_PopupTimeoutValue); - PUAddPopUpT(&ppd); -} - -void CreateProtocolList(void) -{ - int i; - PROTOACCOUNT **acc; - // - ProtoEnumAccounts(&NumberOfAccounts,&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 = db_get_b(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 = db_get_b(NULL, "ModernSettings", "UseKeyColor", 1); - KeyColor = db_get_dw(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/src/TrafficCounter.cpp b/plugins/TrafficCounter/src/TrafficCounter.cpp new file mode 100644 index 0000000000..8a9611328e --- /dev/null +++ b/plugins/TrafficCounter/src/TrafficCounter.cpp @@ -0,0 +1,1724 @@ +/* +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" +#include "m_tipper.h" + +/*-------------------------------------------------------------------------------------------------------------------*/ +//GLOBAL +/*-------------------------------------------------------------------------------------------------------------------*/ +uTCFLAGS unOptions; +PROTOLIST *ProtoList; // Данные обо всех аккаунтах. +PROTOLIST OverallInfo; // Суммарные данные по видимым аккаунтам. +int NumberOfAccounts; +extern WORD Stat_SelAcc; +HWND TrafficHwnd; +DWORD mirandaVer; + +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); + + +PLUGININFOEX pluginInfoEx = +{ + sizeof(PLUGININFOEX), + "Traffic Counter", + 0, // Начиная с версии ядра 0.92.1.0 поле с версией не используется. + "Adding traffic and time counters.", + "Ghost, Mironych", + "", + "© 2002-2006 Ghost, © 2007-2012 Mironych", + "", + UNICODE_AWARE, + {0x82181510, 0x5dfa, 0x49d7, { 0xb4, 0x69, 0x33, 0x87, 0x1e, 0x2a, 0xe8, 0xb5}} // {82181510-5DFA-49d7-B469-33871E2AE8B5} +}; + +extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) +{ + mirandaVer = mirandaVersion; + return &pluginInfoEx; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + hInst = hinstDLL; + DisableThreadLibraryCalls(hInst); + + return TRUE; +} + +extern "C" 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; +} + +extern "C" 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 = db_get_dw(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, 0x0882); + Stat_SelAcc = db_get_w(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_STAT_ACC_OPT, 0x01); + + //settings for notification + Traffic_PopupBkColor = db_get_dw(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_BKCOLOR,RGB(200,255,200)); + Traffic_PopupFontColor = db_get_dw(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_FONTCOLOR,RGB(0,0,0)); + // + Traffic_Notify_time_value = db_get_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_TIME_VALUE,10); + // + Traffic_Notify_size_value = db_get_w(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_SIZE_VALUE,100); + // + //popup timeout + Traffic_PopupTimeoutDefault = db_get_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_DEFAULT,1); + Traffic_PopupTimeoutValue = db_get_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_VALUE,5); + + // Формат счётчика для каждого активного протокола + if (db_get_ts(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_COUNTER_FORMAT, &dbv) == 0) + { + if(lstrlen(dbv.ptszVal) > 0) + lstrcpyn(Traffic_CounterFormat, dbv.ptszVal, SIZEOF(Traffic_CounterFormat)); + // + db_free(&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 (db_get_ts(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_TOOLTIP_FORMAT, &dbv) == 0) + { + if(lstrlen(dbv.ptszVal) > 0) + lstrcpyn(Traffic_TooltipFormat, dbv.ptszVal, SIZEOF(Traffic_TooltipFormat)); + // + db_free(&dbv); + } + else //defaults here + { + _tcscpy(Traffic_TooltipFormat, _T("Traffic Counter")); + } + + Traffic_AdditionSpace = db_get_b(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_ADDITION_SPACE, 0); + + // Счётчик времени онлайна + OverallInfo.Total.Timer = db_get_dw(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 INT_PTR 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 INT_PTR 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 = db_get_b(NULL, "ModernSettings", "UseKeyColor", 1); + KeyColor = db_get_dw(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; + 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; + + // Сохраняем счётчик времени онлайна + db_set_dw(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; + db_set_b(NULL, ProtoList[i].name, SETTINGS_PROTO_FLAGS, ProtoList[i].Flags); + } + + //settings for notification + db_set_dw(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_BKCOLOR,Traffic_PopupBkColor); + db_set_dw(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_FONTCOLOR,Traffic_PopupFontColor); + // + db_set_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_TIME_VALUE,Traffic_Notify_time_value); + // + db_set_w(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_NOTIFY_SIZE_VALUE,Traffic_Notify_size_value); + // + //popup timeout + db_set_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_DEFAULT,Traffic_PopupTimeoutDefault); + db_set_b(NULL,TRAFFIC_SETTINGS_GROUP,SETTINGS_POPUP_TIMEOUT_VALUE,Traffic_PopupTimeoutValue); + // + // Формат счётчиков + db_set_ts(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_COUNTER_FORMAT, Traffic_CounterFormat); + + db_set_ts(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_TOOLTIP_FORMAT, Traffic_TooltipFormat); + + db_set_b(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_ADDITION_SPACE, Traffic_AdditionSpace); + // Сохраняем флаги + db_set_dw(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, unOptions.Flags); + db_set_w(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")) + && !db_get_b(NULL, "ModernData", "DisableEngine", 0) + && db_get_b(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); + } + mir_free(buf); + 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 ( !db_get_b(NULL, "ModernData", "DisableEngine", 0) + && db_get_b(NULL, "ModernData", "EnableLayering", 1) + && ServiceExists(MS_SKINENG_INVALIDATEFRAMEIMAGE)) + CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE, (WPARAM)TrafficHwnd, 0); + else + { + HDC hdc = GetDC(hwnd); + PaintTrafficCounterWindow(hwnd, hdc); + ReleaseDC(hwnd, hdc); + } + } + break; + + case WM_ERASEBKGND: + return 1; + + case WM_LBUTTONDOWN : + if (db_get_b(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); + + CallService(MS_TIPPER_SHOWTIPW, (WPARAM)TooltipText, (LPARAM)&ti); + + TooltipShowing = TRUE; + mir_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_PTR 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); + db_set_dw(NULL, TRAFFIC_SETTINGS_GROUP, SETTINGS_WHAT_DRAW, unOptions.Flags); + // + return 0; +} + +void Traffic_AddMainMenuItem(void) +{ + CLISTMENUITEM mi = { sizeof(mi) }; + mi.position = -0x7FFFFFFF; + mi.flags = 0; + mi.hIcon = NULL; + mi.pszName = LPGEN("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); + _tcsncpy(ppd.lptzContactName, TranslateT("Traffic counter notification"), MAX_CONTACTNAME); + // + mir_sntprintf(ppd.lptzText, MAX_SECONDLINE, TranslateT("%d kilobytes sent"), + notify_send_size = OverallInfo.CurrentSentTraffic >> 10); + // + ppd.colorBack = Traffic_PopupBkColor; + ppd.colorText = Traffic_PopupFontColor; + ppd.PluginWindowProc = NULL; + ppd.iSeconds = (Traffic_PopupTimeoutDefault ? 0 : Traffic_PopupTimeoutValue); + PUAddPopUpT(&ppd); +} + +void NotifyOnRecv(void) +{ + POPUPDATAT ppd; + + ZeroMemory(&ppd, sizeof(ppd)); + ppd.lchContact = NULL; + ppd.lchIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + _tcsncpy(ppd.lptzContactName, TranslateT("Traffic counter notification"),MAX_CONTACTNAME); + // + mir_sntprintf(ppd.lptzText, MAX_SECONDLINE, TranslateT("%d kilobytes received"), + notify_recv_size = OverallInfo.CurrentRecvTraffic >> 10); + // + ppd.colorBack = Traffic_PopupBkColor; + ppd.colorText = Traffic_PopupFontColor; + ppd.PluginWindowProc = NULL; + ppd.iSeconds = (Traffic_PopupTimeoutDefault ? 0 : Traffic_PopupTimeoutValue); + PUAddPopUpT(&ppd); +} + +void CreateProtocolList(void) +{ + int i; + PROTOACCOUNT **acc; + // + ProtoEnumAccounts(&NumberOfAccounts,&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 = db_get_b(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 = db_get_b(NULL, "ModernSettings", "UseKeyColor", 1); + KeyColor = db_get_dw(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/src/commonheaders.c b/plugins/TrafficCounter/src/commonheaders.c deleted file mode 100644 index c9fe1b2686..0000000000 --- a/plugins/TrafficCounter/src/commonheaders.c +++ /dev/null @@ -1 +0,0 @@ -#include "commonheaders.h" \ No newline at end of file diff --git a/plugins/TrafficCounter/src/commonheaders.cpp b/plugins/TrafficCounter/src/commonheaders.cpp new file mode 100644 index 0000000000..14f99f7d71 --- /dev/null +++ b/plugins/TrafficCounter/src/commonheaders.cpp @@ -0,0 +1 @@ +#include "commonheaders.h" diff --git a/plugins/TrafficCounter/src/commonheaders.h b/plugins/TrafficCounter/src/commonheaders.h index bdc5974519..6b8a521308 100644 --- a/plugins/TrafficCounter/src/commonheaders.h +++ b/plugins/TrafficCounter/src/commonheaders.h @@ -115,7 +115,7 @@ typedef struct //--------------------------------------------------------------------------------------------- // Различные флаги //--------------------------------------------------------------------------------------------- -union +typedef union { DWORD Flags; struct @@ -141,14 +141,7 @@ union unsigned int Reserv1:1; //22 unsigned int DrawTotalTimeCounter:1; //23 }; -} unOptions; - -PROTOLIST *ProtoList; // Данные обо всех аккаунтах. -PROTOLIST OverallInfo; // Суммарные данные по видимым аккаунтам. -int NumberOfAccounts; -WORD Stat_SelAcc; // Выбранные аккаунты в окне статистики -HWND TrafficHwnd; -DWORD mirandaVer; +} uTCFLAGS; #include "misc.h" #include "opttree.h" diff --git a/plugins/TrafficCounter/src/misc.c b/plugins/TrafficCounter/src/misc.c deleted file mode 100644 index 6320117246..0000000000 --- a/plugins/TrafficCounter/src/misc.c +++ /dev/null @@ -1,303 +0,0 @@ -/* -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/src/misc.cpp b/plugins/TrafficCounter/src/misc.cpp new file mode 100644 index 0000000000..6320117246 --- /dev/null +++ b/plugins/TrafficCounter/src/misc.cpp @@ -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/src/opttree.c b/plugins/TrafficCounter/src/opttree.c deleted file mode 100644 index 05502ee78e..0000000000 --- a/plugins/TrafficCounter/src/opttree.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - -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. -*/ - -#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/src/opttree.cpp b/plugins/TrafficCounter/src/opttree.cpp new file mode 100644 index 0000000000..05502ee78e --- /dev/null +++ b/plugins/TrafficCounter/src/opttree.cpp @@ -0,0 +1,410 @@ +/* + +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. +*/ + +#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/src/statistics.c b/plugins/TrafficCounter/src/statistics.c deleted file mode 100644 index 03e30f2e90..0000000000 --- a/plugins/TrafficCounter/src/statistics.c +++ /dev/null @@ -1,751 +0,0 @@ -/* -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; - -INT_PTR 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?"), - TranslateT("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, DWLP_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, DWLP_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"), TranslateT("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/src/statistics.cpp b/plugins/TrafficCounter/src/statistics.cpp new file mode 100644 index 0000000000..859ecb40a9 --- /dev/null +++ b/plugins/TrafficCounter/src/statistics.cpp @@ -0,0 +1,756 @@ +/* +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 + +extern HWND TrafficHwnd; +extern PROTOLIST *ProtoList; +extern uTCFLAGS unOptions; +WORD Stat_SelAcc; // Выбранные аккаунты в окне статистики + +HWND hListAccs; + +INT_PTR 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?"), + TranslateT("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, DWLP_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, DWLP_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"), TranslateT("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; +} diff --git a/plugins/TrafficCounter/src/vars.c b/plugins/TrafficCounter/src/vars.c deleted file mode 100644 index bc2cda965f..0000000000 --- a/plugins/TrafficCounter/src/vars.c +++ /dev/null @@ -1,185 +0,0 @@ -/* -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/src/vars.cpp b/plugins/TrafficCounter/src/vars.cpp new file mode 100644 index 0000000000..bca68d5569 --- /dev/null +++ b/plugins/TrafficCounter/src/vars.cpp @@ -0,0 +1,188 @@ +/* +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" + +extern PROTOLIST *ProtoList; +extern PROTOLIST OverallInfo; + +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); +} -- cgit v1.2.3