summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2023-01-02 21:10:29 +0300
committerdartraiden <wowemuh@gmail.com>2023-01-02 21:10:29 +0300
commit1979fd80424d16b2e489f9b57d01d9c7811d25a2 (patch)
tree960d42c5fe4a51f0fe2850bea91256e226bce221 /src/core
parentadfbbb217d4f4a05acf198755f219a5223d31c27 (diff)
Update copyrights
Diffstat (limited to 'src/core')
-rw-r--r--src/core/stdautoaway/src/autoaway.cpp2
-rw-r--r--src/core/stdautoaway/src/idle.cpp178
-rw-r--r--src/core/stdautoaway/src/main.cpp2
-rw-r--r--src/core/stdautoaway/src/options.cpp268
-rw-r--r--src/core/stdautoaway/src/stdafx.h2
-rw-r--r--src/core/stdautoaway/src/version.h2
-rw-r--r--src/core/stdaway/src/awaymsg.cpp2
-rw-r--r--src/core/stdaway/src/main.cpp2
-rw-r--r--src/core/stdaway/src/options.cpp280
-rw-r--r--src/core/stdaway/src/sendmsg.cpp2
-rw-r--r--src/core/stdaway/src/stdafx.h2
-rw-r--r--src/core/stdaway/src/version.h2
-rw-r--r--src/core/stdclist/src/clc.h2
-rw-r--r--src/core/stdclist/src/clcfonts.cpp2
-rw-r--r--src/core/stdclist/src/clcopts.cpp2
-rw-r--r--src/core/stdclist/src/clcpaint.cpp2
-rw-r--r--src/core/stdclist/src/clistmenus.cpp2
-rw-r--r--src/core/stdclist/src/clistopts.cpp2
-rw-r--r--src/core/stdclist/src/cluiopts.cpp2
-rw-r--r--src/core/stdclist/src/contact.cpp2
-rw-r--r--src/core/stdclist/src/init.cpp2
-rw-r--r--src/core/stdclist/src/stdafx.cxx2
-rw-r--r--src/core/stdclist/src/stdafx.h2
-rw-r--r--src/core/stdclist/src/version.h2
-rw-r--r--src/core/stdcrypt/src/encrypt.cpp2
-rw-r--r--src/core/stdcrypt/src/main.cpp2
-rw-r--r--src/core/stdcrypt/src/stdafx.h2
-rw-r--r--src/core/stdcrypt/src/stdcrypt.h2
-rw-r--r--src/core/stdcrypt/src/utils.cpp2
-rw-r--r--src/core/stdcrypt/src/version.h2
-rw-r--r--src/core/stdemail/src/email.cpp2
-rw-r--r--src/core/stdemail/src/main.cpp2
-rw-r--r--src/core/stdemail/src/stdafx.h2
-rw-r--r--src/core/stdemail/src/version.h2
-rw-r--r--src/core/stdfile/src/file.cpp2
-rw-r--r--src/core/stdfile/src/file.h2
-rw-r--r--src/core/stdfile/src/fileexistsdlg.cpp2
-rw-r--r--src/core/stdfile/src/fileopts.cpp2
-rw-r--r--src/core/stdfile/src/filerecvdlg.cpp2
-rw-r--r--src/core/stdfile/src/filesenddlg.cpp2
-rw-r--r--src/core/stdfile/src/filexferdlg.cpp1530
-rw-r--r--src/core/stdfile/src/ftmanager.cpp2
-rw-r--r--src/core/stdfile/src/main.cpp2
-rw-r--r--src/core/stdfile/src/stdafx.h2
-rw-r--r--src/core/stdfile/src/version.h2
-rw-r--r--src/core/stdmsg/src/chat_manager.cpp486
-rw-r--r--src/core/stdmsg/src/chat_window.cpp550
-rw-r--r--src/core/stdmsg/src/cmdlist.cpp2
-rw-r--r--src/core/stdmsg/src/cmdlist.h2
-rw-r--r--src/core/stdmsg/src/globals.cpp2
-rw-r--r--src/core/stdmsg/src/msgdialog.cpp2
-rw-r--r--src/core/stdmsg/src/msglog.cpp2
-rw-r--r--src/core/stdmsg/src/msgoptions.cpp2
-rw-r--r--src/core/stdmsg/src/msgs.cpp2
-rw-r--r--src/core/stdmsg/src/msgs.h2
-rw-r--r--src/core/stdmsg/src/msgtimedout.cpp2
-rw-r--r--src/core/stdmsg/src/srmm.cpp2
-rw-r--r--src/core/stdmsg/src/statusicon.cpp2
-rw-r--r--src/core/stdmsg/src/stdafx.cxx2
-rw-r--r--src/core/stdmsg/src/stdafx.h2
-rw-r--r--src/core/stdmsg/src/tabs.cpp1336
-rw-r--r--src/core/stdmsg/src/version.h2
-rw-r--r--src/core/stdpopup/src/stdafx.cxx34
-rw-r--r--src/core/stdpopup/src/version.h2
-rw-r--r--src/core/stduihist/src/history.cpp2
-rw-r--r--src/core/stduihist/src/main.cpp2
-rw-r--r--src/core/stduihist/src/stdafx.h2
-rw-r--r--src/core/stduihist/src/version.h2
-rw-r--r--src/core/stduserinfo/src/contactinfo.cpp2
-rw-r--r--src/core/stduserinfo/src/main.cpp2
-rw-r--r--src/core/stduserinfo/src/stdafx.h2
-rw-r--r--src/core/stduserinfo/src/stdinfo.cpp2
-rw-r--r--src/core/stduserinfo/src/userinfo.cpp2
-rw-r--r--src/core/stduserinfo/src/utils.h428
-rw-r--r--src/core/stduserinfo/src/version.h2
-rw-r--r--src/core/stduseronline/src/main.cpp2
-rw-r--r--src/core/stduseronline/src/stdafx.h2
-rw-r--r--src/core/stduseronline/src/useronline.cpp2
-rw-r--r--src/core/stduseronline/src/version.h2
79 files changed, 2615 insertions, 2615 deletions
diff --git a/src/core/stdautoaway/src/autoaway.cpp b/src/core/stdautoaway/src/autoaway.cpp
index f9a7fa8379..024487ed5a 100644
--- a/src/core/stdautoaway/src/autoaway.cpp
+++ b/src/core/stdautoaway/src/autoaway.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdautoaway/src/idle.cpp b/src/core/stdautoaway/src/idle.cpp
index aaabe0ddb2..b4faa31c4b 100644
--- a/src/core/stdautoaway/src/idle.cpp
+++ b/src/core/stdautoaway/src/idle.cpp
@@ -1,89 +1,89 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-static UINT_PTR g_hTimer;
-
-int IdleOptInit(WPARAM wParam, LPARAM);
-
-static int IdleObject_IsUserIdle()
-{
- if (g_plugin.bIdleMethod) {
- uint32_t dwTick = Miranda_GetIdle();
- return GetTickCount() - dwTick > (g_plugin.iIdleTime1st * 60 * 1000);
- }
-
- LASTINPUTINFO ii = { sizeof(ii) };
- if (GetLastInputInfo(&ii))
- return GetTickCount() - ii.dwTime > (g_plugin.iIdleTime1st * 60 * 1000);
-
- return FALSE;
-}
-
-static void CALLBACK IdleTimer(HWND, UINT, UINT_PTR idEvent, DWORD)
-{
- if (g_hTimer != idEvent)
- return;
-
- if (g_plugin.bIdleCheck && IdleObject_IsUserIdle())
- Idle_Enter(1);
-
- else if (g_plugin.bIdleOnSaver && IsScreenSaverRunning())
- Idle_Enter(2);
-
- else if (g_plugin.bIdleOnFullScr && IsFullScreen())
- Idle_Enter(3);
-
- else if (g_plugin.bIdleOnLock && IsWorkstationLocked())
- Idle_Enter(4);
-
- else if (g_plugin.bIdleOnTerminal && IsTerminalDisconnected())
- Idle_Enter(5);
-
- else // not idle
- Idle_Enter(-1);
-}
-
-void IdleObject_Create()
-{
- g_hTimer = SetTimer(nullptr, 0, 2000, IdleTimer);
-}
-
-void IdleObject_Destroy()
-{
- KillTimer(nullptr, g_hTimer);
-}
-
-void LoadIdleModule(void)
-{
- IdleObject_Create();
-
- HookEvent(ME_OPT_INITIALISE, IdleOptInit);
-}
-
-void UnloadIdleModule()
-{
- IdleObject_Destroy();
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+static UINT_PTR g_hTimer;
+
+int IdleOptInit(WPARAM wParam, LPARAM);
+
+static int IdleObject_IsUserIdle()
+{
+ if (g_plugin.bIdleMethod) {
+ uint32_t dwTick = Miranda_GetIdle();
+ return GetTickCount() - dwTick > (g_plugin.iIdleTime1st * 60 * 1000);
+ }
+
+ LASTINPUTINFO ii = { sizeof(ii) };
+ if (GetLastInputInfo(&ii))
+ return GetTickCount() - ii.dwTime > (g_plugin.iIdleTime1st * 60 * 1000);
+
+ return FALSE;
+}
+
+static void CALLBACK IdleTimer(HWND, UINT, UINT_PTR idEvent, DWORD)
+{
+ if (g_hTimer != idEvent)
+ return;
+
+ if (g_plugin.bIdleCheck && IdleObject_IsUserIdle())
+ Idle_Enter(1);
+
+ else if (g_plugin.bIdleOnSaver && IsScreenSaverRunning())
+ Idle_Enter(2);
+
+ else if (g_plugin.bIdleOnFullScr && IsFullScreen())
+ Idle_Enter(3);
+
+ else if (g_plugin.bIdleOnLock && IsWorkstationLocked())
+ Idle_Enter(4);
+
+ else if (g_plugin.bIdleOnTerminal && IsTerminalDisconnected())
+ Idle_Enter(5);
+
+ else // not idle
+ Idle_Enter(-1);
+}
+
+void IdleObject_Create()
+{
+ g_hTimer = SetTimer(nullptr, 0, 2000, IdleTimer);
+}
+
+void IdleObject_Destroy()
+{
+ KillTimer(nullptr, g_hTimer);
+}
+
+void LoadIdleModule(void)
+{
+ IdleObject_Create();
+
+ HookEvent(ME_OPT_INITIALISE, IdleOptInit);
+}
+
+void UnloadIdleModule()
+{
+ IdleObject_Destroy();
+}
diff --git a/src/core/stdautoaway/src/main.cpp b/src/core/stdautoaway/src/main.cpp
index 971fd166ff..1022f2a4d5 100644
--- a/src/core/stdautoaway/src/main.cpp
+++ b/src/core/stdautoaway/src/main.cpp
@@ -2,7 +2,7 @@
Standard auto away module for Miranda NG
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
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
diff --git a/src/core/stdautoaway/src/options.cpp b/src/core/stdautoaway/src/options.cpp
index 17a8f8381b..fed12a11f8 100644
--- a/src/core/stdautoaway/src/options.cpp
+++ b/src/core/stdautoaway/src/options.cpp
@@ -1,134 +1,134 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-static const uint16_t aa_Status[] = { ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND };
-
-int IdleGetStatusIndex(uint16_t status)
-{
- for (int j = 0; j < _countof(aa_Status); j++)
- if (aa_Status[j] == status)
- return j;
-
- return 0;
-}
-
-class COptionsDlg : public CDlgBase
-{
- CCtrlEdit edt1sttime;
- CCtrlSpin spinIdle;
- CCtrlCombo cmbAAStatus;
- CCtrlCheck chkShort, chkOnWindows, chkOnMiranda, chkScreenSaver, chkFullScreen, chkLocked;
- CCtrlCheck chkPrivate, chkStatusLock, chkTerminal, chkSoundsOff, chkShortIdle;
-
- void ShowHide()
- {
- BOOL bChecked = chkShort.GetState();
- chkOnWindows.Enable(bChecked);
- chkOnMiranda.Enable(bChecked);
- edt1sttime.Enable(bChecked);
-
- bChecked = chkShortIdle.GetState();
- cmbAAStatus.Enable(bChecked);
- chkStatusLock.Enable(bChecked);
- }
-
-public:
- COptionsDlg() :
- CDlgBase(g_plugin, IDD_OPT_IDLE),
- edt1sttime(this, IDC_IDLE1STTIME),
- spinIdle(this, IDC_IDLESPIN, 60, 1),
- cmbAAStatus(this, IDC_AASTATUS),
- chkShort(this, IDC_IDLESHORT),
- chkLocked(this, IDC_LOCKED),
- chkPrivate(this, IDC_IDLEPRIVATE),
- chkTerminal(this, IDC_IDLETERMINAL),
- chkOnWindows(this, IDC_IDLEONWINDOWS),
- chkSoundsOff(this, IDC_IDLESOUNDSOFF),
- chkOnMiranda(this, IDC_IDLEONMIRANDA),
- chkShortIdle(this, IDC_AASHORTIDLE),
- chkStatusLock(this, IDC_IDLESTATUSLOCK),
- chkFullScreen(this, IDC_FULLSCREEN),
- chkScreenSaver(this, IDC_SCREENSAVER)
- {
- CreateLink(chkShort, g_plugin.bIdleCheck);
- CreateLink(chkLocked, g_plugin.bIdleOnLock);
- CreateLink(chkPrivate, g_plugin.bIdlePrivate);
- CreateLink(chkTerminal, g_plugin.bIdleOnTerminal);
- CreateLink(chkShortIdle, g_plugin.bAAEnable);
- CreateLink(chkOnMiranda, g_plugin.bIdleMethod);
- CreateLink(chkSoundsOff, g_plugin.bIdleSoundsOff);
- CreateLink(chkStatusLock, g_plugin.bIdleStatusLock);
- CreateLink(chkFullScreen, g_plugin.bIdleOnFullScr);
- CreateLink(chkScreenSaver, g_plugin.bIdleOnSaver);
-
- chkShortIdle.OnChange = chkShort.OnChange = Callback(this, &COptionsDlg::onChange);
- }
-
- bool OnInitDialog() override
- {
- chkOnWindows.SetState(!g_plugin.bIdleMethod);
-
- spinIdle.SetPosition(g_plugin.iIdleTime1st);
-
- for (auto &it : aa_Status)
- cmbAAStatus.AddString(Clist_GetStatusModeDescription(it, 0));
- cmbAAStatus.SetCurSel(IdleGetStatusIndex(g_plugin.bAAStatus));
-
- ShowHide();
- return true;
- }
-
- bool OnApply() override
- {
- g_plugin.iIdleTime1st = spinIdle.GetPosition();
-
- int curSel = cmbAAStatus.GetCurSel();
- if (curSel != CB_ERR)
- g_plugin.bAAStatus = aa_Status[curSel];
-
- // destroy any current idle and reset settings.
- IdleObject_Destroy();
- IdleObject_Create();
- return true;
- }
-
- void onChange(CCtrlCheck*)
- {
- ShowHide();
- }
-};
-
-int IdleOptInit(WPARAM wParam, LPARAM)
-{
- OPTIONSDIALOGPAGE odp = {};
- odp.position = 100000000;
- odp.szGroup.a = LPGEN("Status");
- odp.szTitle.a = LPGEN("Idle");
- odp.flags = ODPF_BOLDGROUPS;
- odp.pDialog = new COptionsDlg();
- g_plugin.addOptions(wParam, &odp);
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+static const uint16_t aa_Status[] = { ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND };
+
+int IdleGetStatusIndex(uint16_t status)
+{
+ for (int j = 0; j < _countof(aa_Status); j++)
+ if (aa_Status[j] == status)
+ return j;
+
+ return 0;
+}
+
+class COptionsDlg : public CDlgBase
+{
+ CCtrlEdit edt1sttime;
+ CCtrlSpin spinIdle;
+ CCtrlCombo cmbAAStatus;
+ CCtrlCheck chkShort, chkOnWindows, chkOnMiranda, chkScreenSaver, chkFullScreen, chkLocked;
+ CCtrlCheck chkPrivate, chkStatusLock, chkTerminal, chkSoundsOff, chkShortIdle;
+
+ void ShowHide()
+ {
+ BOOL bChecked = chkShort.GetState();
+ chkOnWindows.Enable(bChecked);
+ chkOnMiranda.Enable(bChecked);
+ edt1sttime.Enable(bChecked);
+
+ bChecked = chkShortIdle.GetState();
+ cmbAAStatus.Enable(bChecked);
+ chkStatusLock.Enable(bChecked);
+ }
+
+public:
+ COptionsDlg() :
+ CDlgBase(g_plugin, IDD_OPT_IDLE),
+ edt1sttime(this, IDC_IDLE1STTIME),
+ spinIdle(this, IDC_IDLESPIN, 60, 1),
+ cmbAAStatus(this, IDC_AASTATUS),
+ chkShort(this, IDC_IDLESHORT),
+ chkLocked(this, IDC_LOCKED),
+ chkPrivate(this, IDC_IDLEPRIVATE),
+ chkTerminal(this, IDC_IDLETERMINAL),
+ chkOnWindows(this, IDC_IDLEONWINDOWS),
+ chkSoundsOff(this, IDC_IDLESOUNDSOFF),
+ chkOnMiranda(this, IDC_IDLEONMIRANDA),
+ chkShortIdle(this, IDC_AASHORTIDLE),
+ chkStatusLock(this, IDC_IDLESTATUSLOCK),
+ chkFullScreen(this, IDC_FULLSCREEN),
+ chkScreenSaver(this, IDC_SCREENSAVER)
+ {
+ CreateLink(chkShort, g_plugin.bIdleCheck);
+ CreateLink(chkLocked, g_plugin.bIdleOnLock);
+ CreateLink(chkPrivate, g_plugin.bIdlePrivate);
+ CreateLink(chkTerminal, g_plugin.bIdleOnTerminal);
+ CreateLink(chkShortIdle, g_plugin.bAAEnable);
+ CreateLink(chkOnMiranda, g_plugin.bIdleMethod);
+ CreateLink(chkSoundsOff, g_plugin.bIdleSoundsOff);
+ CreateLink(chkStatusLock, g_plugin.bIdleStatusLock);
+ CreateLink(chkFullScreen, g_plugin.bIdleOnFullScr);
+ CreateLink(chkScreenSaver, g_plugin.bIdleOnSaver);
+
+ chkShortIdle.OnChange = chkShort.OnChange = Callback(this, &COptionsDlg::onChange);
+ }
+
+ bool OnInitDialog() override
+ {
+ chkOnWindows.SetState(!g_plugin.bIdleMethod);
+
+ spinIdle.SetPosition(g_plugin.iIdleTime1st);
+
+ for (auto &it : aa_Status)
+ cmbAAStatus.AddString(Clist_GetStatusModeDescription(it, 0));
+ cmbAAStatus.SetCurSel(IdleGetStatusIndex(g_plugin.bAAStatus));
+
+ ShowHide();
+ return true;
+ }
+
+ bool OnApply() override
+ {
+ g_plugin.iIdleTime1st = spinIdle.GetPosition();
+
+ int curSel = cmbAAStatus.GetCurSel();
+ if (curSel != CB_ERR)
+ g_plugin.bAAStatus = aa_Status[curSel];
+
+ // destroy any current idle and reset settings.
+ IdleObject_Destroy();
+ IdleObject_Create();
+ return true;
+ }
+
+ void onChange(CCtrlCheck*)
+ {
+ ShowHide();
+ }
+};
+
+int IdleOptInit(WPARAM wParam, LPARAM)
+{
+ OPTIONSDIALOGPAGE odp = {};
+ odp.position = 100000000;
+ odp.szGroup.a = LPGEN("Status");
+ odp.szTitle.a = LPGEN("Idle");
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pDialog = new COptionsDlg();
+ g_plugin.addOptions(wParam, &odp);
+ return 0;
+}
diff --git a/src/core/stdautoaway/src/stdafx.h b/src/core/stdautoaway/src/stdafx.h
index be6446162a..aed3748da5 100644
--- a/src/core/stdautoaway/src/stdafx.h
+++ b/src/core/stdautoaway/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdautoaway/src/version.h b/src/core/stdautoaway/src/version.h
index 50fcd17758..e85f99715c 100644
--- a/src/core/stdautoaway/src/version.h
+++ b/src/core/stdautoaway/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for away state processing."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdAutoAway"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stdaway/src/awaymsg.cpp b/src/core/stdaway/src/awaymsg.cpp
index 94f097fbe1..391a61383e 100644
--- a/src/core/stdaway/src/awaymsg.cpp
+++ b/src/core/stdaway/src/awaymsg.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdaway/src/main.cpp b/src/core/stdaway/src/main.cpp
index 1dfab72a34..bf275c259a 100644
--- a/src/core/stdaway/src/main.cpp
+++ b/src/core/stdaway/src/main.cpp
@@ -2,7 +2,7 @@
Standard away message processing module for Miranda NG
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
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
diff --git a/src/core/stdaway/src/options.cpp b/src/core/stdaway/src/options.cpp
index 64943461d9..1287a623d3 100644
--- a/src/core/stdaway/src/options.cpp
+++ b/src/core/stdaway/src/options.cpp
@@ -1,140 +1,140 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-static const int statusModes[] =
-{
- ID_STATUS_OFFLINE, ID_STATUS_ONLINE, ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND,
- ID_STATUS_FREECHAT, ID_STATUS_INVISIBLE, ID_STATUS_IDLE
-};
-
-class CAwayMsgOptsDlg : public CDlgBase
-{
- struct
- {
- int ignore;
- int noDialog;
- int usePrevious;
- wchar_t msg[1024];
- }
- m_info[_countof(statusModes)];
-
- int oldPage = -1;
-
- CCtrlEdit etdMsg;
- CCtrlCombo cmbStatus;
- CCtrlCheck chkDontReply, chkUsePrev, chkUseSpecific, chkNoDialog;
-
-public:
- CAwayMsgOptsDlg() :
- CDlgBase(g_plugin, IDD_OPT_AWAYMSG),
- etdMsg(this, IDC_MSG),
- cmbStatus(this, IDC_STATUS),
- chkUsePrev(this, IDC_USEPREVIOUS),
- chkNoDialog(this, IDC_NODIALOG),
- chkDontReply(this, IDC_DONTREPLY),
- chkUseSpecific(this, IDC_USESPECIFIC)
- {
- chkUsePrev.OnChange = chkDontReply.OnChange = chkUseSpecific.OnChange = Callback(this, &CAwayMsgOptsDlg::onSelChange_Status);
- cmbStatus.OnSelChanged = Callback(this, &CAwayMsgOptsDlg::onSelChange_Status);
- }
-
- bool OnInitDialog() override
- {
- for (auto &it : statusModes) {
- if (!(protoModeMsgFlags & Proto_Status2Flag(it)))
- continue;
-
- int j = cmbStatus.AddString(Clist_GetStatusModeDescription(it, 0), it);
- m_info[j].ignore = g_plugin.GetStatusModeByte(it, "Ignore");
- m_info[j].noDialog = g_plugin.GetStatusModeByte(it, "NoDlg", true);
- m_info[j].usePrevious = g_plugin.GetStatusModeByte(it, "UsePrev");
-
- DBVARIANT dbv;
- if (g_plugin.getWString(StatusModeToDbSetting(it, "Default"), &dbv))
- if (g_plugin.getWString(StatusModeToDbSetting(it, "Msg"), &dbv))
- dbv.pwszVal = mir_wstrdup(GetDefaultMessage(it));
- mir_wstrcpy(m_info[j].msg, dbv.pwszVal);
- mir_free(dbv.pwszVal);
- }
-
- cmbStatus.SetCurSel(0);
- onSelChange_Status(0);
- return true;
- }
-
- bool OnApply() override
- {
- onSelChange_Status(0);
-
- for (int i = cmbStatus.GetCount() - 1; i >= 0; i--) {
- int status = cmbStatus.GetItemData(i);
- g_plugin.SetStatusModeByte(status, "Ignore", (uint8_t)m_info[i].ignore);
- g_plugin.SetStatusModeByte(status, "NoDlg", (uint8_t)m_info[i].noDialog);
- g_plugin.SetStatusModeByte(status, "UsePrev", (uint8_t)m_info[i].usePrevious);
- g_plugin.setWString(StatusModeToDbSetting(status, "Default"), m_info[i].msg);
- }
- return true;
- }
-
- void onSelChange_Status(CCtrlCombo*)
- {
- if (oldPage != -1) {
- m_info[oldPage].ignore = chkDontReply.GetState();
- m_info[oldPage].noDialog = chkNoDialog.GetState();
- m_info[oldPage].usePrevious = chkUsePrev.GetState();
- etdMsg.GetText(m_info[oldPage].msg, _countof(m_info[oldPage].msg));
- }
-
- int i = cmbStatus.GetCurSel();
- chkDontReply.SetState(i < 0 ? 0 : m_info[i].ignore);
- chkNoDialog.SetState(i < 0 ? 0 : m_info[i].noDialog);
- chkUsePrev.SetState(i < 0 ? 0 : m_info[i].usePrevious);
- chkUseSpecific.SetState(i < 0 ? 0 : !m_info[i].usePrevious);
-
- etdMsg.SetText(i < 0 ? L"" : m_info[i].msg);
-
- chkNoDialog.Enable(i < 0 ? 0 : !m_info[i].ignore);
- chkUsePrev.Enable(i < 0 ? 0 : !m_info[i].ignore);
- chkUseSpecific.Enable(i < 0 ? 0 : !m_info[i].ignore);
- etdMsg.Enable(i < 0 ? 0 : !(m_info[i].ignore || m_info[i].usePrevious));
- oldPage = i;
- }
-};
-
-int AwayMsgOptInitialise(WPARAM wParam, LPARAM)
-{
- if (protoModeMsgFlags == 0)
- return 0;
-
- OPTIONSDIALOGPAGE odp = {};
- odp.flags = ODPF_BOLDGROUPS;
- odp.position = 870000000;
- odp.szTitle.a = LPGEN("Status messages");
- odp.szGroup.a = LPGEN("Status");
- odp.pDialog = new CAwayMsgOptsDlg();
- g_plugin.addOptions(wParam, &odp);
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+static const int statusModes[] =
+{
+ ID_STATUS_OFFLINE, ID_STATUS_ONLINE, ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND,
+ ID_STATUS_FREECHAT, ID_STATUS_INVISIBLE, ID_STATUS_IDLE
+};
+
+class CAwayMsgOptsDlg : public CDlgBase
+{
+ struct
+ {
+ int ignore;
+ int noDialog;
+ int usePrevious;
+ wchar_t msg[1024];
+ }
+ m_info[_countof(statusModes)];
+
+ int oldPage = -1;
+
+ CCtrlEdit etdMsg;
+ CCtrlCombo cmbStatus;
+ CCtrlCheck chkDontReply, chkUsePrev, chkUseSpecific, chkNoDialog;
+
+public:
+ CAwayMsgOptsDlg() :
+ CDlgBase(g_plugin, IDD_OPT_AWAYMSG),
+ etdMsg(this, IDC_MSG),
+ cmbStatus(this, IDC_STATUS),
+ chkUsePrev(this, IDC_USEPREVIOUS),
+ chkNoDialog(this, IDC_NODIALOG),
+ chkDontReply(this, IDC_DONTREPLY),
+ chkUseSpecific(this, IDC_USESPECIFIC)
+ {
+ chkUsePrev.OnChange = chkDontReply.OnChange = chkUseSpecific.OnChange = Callback(this, &CAwayMsgOptsDlg::onSelChange_Status);
+ cmbStatus.OnSelChanged = Callback(this, &CAwayMsgOptsDlg::onSelChange_Status);
+ }
+
+ bool OnInitDialog() override
+ {
+ for (auto &it : statusModes) {
+ if (!(protoModeMsgFlags & Proto_Status2Flag(it)))
+ continue;
+
+ int j = cmbStatus.AddString(Clist_GetStatusModeDescription(it, 0), it);
+ m_info[j].ignore = g_plugin.GetStatusModeByte(it, "Ignore");
+ m_info[j].noDialog = g_plugin.GetStatusModeByte(it, "NoDlg", true);
+ m_info[j].usePrevious = g_plugin.GetStatusModeByte(it, "UsePrev");
+
+ DBVARIANT dbv;
+ if (g_plugin.getWString(StatusModeToDbSetting(it, "Default"), &dbv))
+ if (g_plugin.getWString(StatusModeToDbSetting(it, "Msg"), &dbv))
+ dbv.pwszVal = mir_wstrdup(GetDefaultMessage(it));
+ mir_wstrcpy(m_info[j].msg, dbv.pwszVal);
+ mir_free(dbv.pwszVal);
+ }
+
+ cmbStatus.SetCurSel(0);
+ onSelChange_Status(0);
+ return true;
+ }
+
+ bool OnApply() override
+ {
+ onSelChange_Status(0);
+
+ for (int i = cmbStatus.GetCount() - 1; i >= 0; i--) {
+ int status = cmbStatus.GetItemData(i);
+ g_plugin.SetStatusModeByte(status, "Ignore", (uint8_t)m_info[i].ignore);
+ g_plugin.SetStatusModeByte(status, "NoDlg", (uint8_t)m_info[i].noDialog);
+ g_plugin.SetStatusModeByte(status, "UsePrev", (uint8_t)m_info[i].usePrevious);
+ g_plugin.setWString(StatusModeToDbSetting(status, "Default"), m_info[i].msg);
+ }
+ return true;
+ }
+
+ void onSelChange_Status(CCtrlCombo*)
+ {
+ if (oldPage != -1) {
+ m_info[oldPage].ignore = chkDontReply.GetState();
+ m_info[oldPage].noDialog = chkNoDialog.GetState();
+ m_info[oldPage].usePrevious = chkUsePrev.GetState();
+ etdMsg.GetText(m_info[oldPage].msg, _countof(m_info[oldPage].msg));
+ }
+
+ int i = cmbStatus.GetCurSel();
+ chkDontReply.SetState(i < 0 ? 0 : m_info[i].ignore);
+ chkNoDialog.SetState(i < 0 ? 0 : m_info[i].noDialog);
+ chkUsePrev.SetState(i < 0 ? 0 : m_info[i].usePrevious);
+ chkUseSpecific.SetState(i < 0 ? 0 : !m_info[i].usePrevious);
+
+ etdMsg.SetText(i < 0 ? L"" : m_info[i].msg);
+
+ chkNoDialog.Enable(i < 0 ? 0 : !m_info[i].ignore);
+ chkUsePrev.Enable(i < 0 ? 0 : !m_info[i].ignore);
+ chkUseSpecific.Enable(i < 0 ? 0 : !m_info[i].ignore);
+ etdMsg.Enable(i < 0 ? 0 : !(m_info[i].ignore || m_info[i].usePrevious));
+ oldPage = i;
+ }
+};
+
+int AwayMsgOptInitialise(WPARAM wParam, LPARAM)
+{
+ if (protoModeMsgFlags == 0)
+ return 0;
+
+ OPTIONSDIALOGPAGE odp = {};
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.position = 870000000;
+ odp.szTitle.a = LPGEN("Status messages");
+ odp.szGroup.a = LPGEN("Status");
+ odp.pDialog = new CAwayMsgOptsDlg();
+ g_plugin.addOptions(wParam, &odp);
+ return 0;
+}
diff --git a/src/core/stdaway/src/sendmsg.cpp b/src/core/stdaway/src/sendmsg.cpp
index 1eaaac5cc4..dff644a928 100644
--- a/src/core/stdaway/src/sendmsg.cpp
+++ b/src/core/stdaway/src/sendmsg.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdaway/src/stdafx.h b/src/core/stdaway/src/stdafx.h
index 4cd3dd5b24..83d5a859c9 100644
--- a/src/core/stdaway/src/stdafx.h
+++ b/src/core/stdaway/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdaway/src/version.h b/src/core/stdaway/src/version.h
index 1cbc94e44c..03131a5179 100644
--- a/src/core/stdaway/src/version.h
+++ b/src/core/stdaway/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for the away messages processing."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdAway"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stdclist/src/clc.h b/src/core/stdclist/src/clc.h
index 9ecb9767af..c5a6581b38 100644
--- a/src/core/stdclist/src/clc.h
+++ b/src/core/stdclist/src/clc.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/clcfonts.cpp b/src/core/stdclist/src/clcfonts.cpp
index c5c4af1a9a..e435026332 100644
--- a/src/core/stdclist/src/clcfonts.cpp
+++ b/src/core/stdclist/src/clcfonts.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/clcopts.cpp b/src/core/stdclist/src/clcopts.cpp
index 688fba0c86..077cd80ca0 100644
--- a/src/core/stdclist/src/clcopts.cpp
+++ b/src/core/stdclist/src/clcopts.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/clcpaint.cpp b/src/core/stdclist/src/clcpaint.cpp
index 9bf6af7581..d2e59b1878 100644
--- a/src/core/stdclist/src/clcpaint.cpp
+++ b/src/core/stdclist/src/clcpaint.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/clistmenus.cpp b/src/core/stdclist/src/clistmenus.cpp
index 7d10154fde..57da5b4f22 100644
--- a/src/core/stdclist/src/clistmenus.cpp
+++ b/src/core/stdclist/src/clistmenus.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/clistopts.cpp b/src/core/stdclist/src/clistopts.cpp
index 29683b6506..3a6f435e24 100644
--- a/src/core/stdclist/src/clistopts.cpp
+++ b/src/core/stdclist/src/clistopts.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/cluiopts.cpp b/src/core/stdclist/src/cluiopts.cpp
index 785c0605b1..4816b59b7f 100644
--- a/src/core/stdclist/src/cluiopts.cpp
+++ b/src/core/stdclist/src/cluiopts.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/contact.cpp b/src/core/stdclist/src/contact.cpp
index daba1cdc61..cf9ba02cb7 100644
--- a/src/core/stdclist/src/contact.cpp
+++ b/src/core/stdclist/src/contact.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/init.cpp b/src/core/stdclist/src/init.cpp
index 3ca412c5f7..f379863284 100644
--- a/src/core/stdclist/src/init.cpp
+++ b/src/core/stdclist/src/init.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/stdafx.cxx b/src/core/stdclist/src/stdafx.cxx
index f64d25234b..ebbde0ade1 100644
--- a/src/core/stdclist/src/stdafx.cxx
+++ b/src/core/stdclist/src/stdafx.cxx
@@ -1,5 +1,5 @@
/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
diff --git a/src/core/stdclist/src/stdafx.h b/src/core/stdclist/src/stdafx.h
index d50af5e471..62b233fe55 100644
--- a/src/core/stdclist/src/stdafx.h
+++ b/src/core/stdclist/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdclist/src/version.h b/src/core/stdclist/src/version.h
index 1b178cd258..a652e79523 100644
--- a/src/core/stdclist/src/version.h
+++ b/src/core/stdclist/src/version.h
@@ -9,4 +9,4 @@
#define __DESCRIPTION "Core module for displaying contacts."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdClist"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stdcrypt/src/encrypt.cpp b/src/core/stdcrypt/src/encrypt.cpp
index e9689aa374..9d605848a2 100644
--- a/src/core/stdcrypt/src/encrypt.cpp
+++ b/src/core/stdcrypt/src/encrypt.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team,
+Copyright (C) 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdcrypt/src/main.cpp b/src/core/stdcrypt/src/main.cpp
index bc53c00f54..e1dc9218a6 100644
--- a/src/core/stdcrypt/src/main.cpp
+++ b/src/core/stdcrypt/src/main.cpp
@@ -1,7 +1,7 @@
/*
Standard encryption plugin for Miranda NG
-Copyright (C) 2012-22 George Hazan
+Copyright (C) 2012-23 George Hazan
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
diff --git a/src/core/stdcrypt/src/stdafx.h b/src/core/stdcrypt/src/stdafx.h
index 1ea23e6c16..4b6c1e7319 100644
--- a/src/core/stdcrypt/src/stdafx.h
+++ b/src/core/stdcrypt/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdcrypt/src/stdcrypt.h b/src/core/stdcrypt/src/stdcrypt.h
index 791e827d1a..3966a81631 100644
--- a/src/core/stdcrypt/src/stdcrypt.h
+++ b/src/core/stdcrypt/src/stdcrypt.h
@@ -1,7 +1,7 @@
/*
Standard encryption plugin for Miranda NG
-Copyright (C) 2012-22 George Hazan
+Copyright (C) 2012-23 George Hazan
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
diff --git a/src/core/stdcrypt/src/utils.cpp b/src/core/stdcrypt/src/utils.cpp
index fd5b3cff22..a3279e805e 100644
--- a/src/core/stdcrypt/src/utils.cpp
+++ b/src/core/stdcrypt/src/utils.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team,
+Copyright (C) 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdcrypt/src/version.h b/src/core/stdcrypt/src/version.h
index 6f6d4f9c96..30de347877 100644
--- a/src/core/stdcrypt/src/version.h
+++ b/src/core/stdcrypt/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for encryption."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdCrypt"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stdemail/src/email.cpp b/src/core/stdemail/src/email.cpp
index b6c68d672f..0f40657fff 100644
--- a/src/core/stdemail/src/email.cpp
+++ b/src/core/stdemail/src/email.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdemail/src/main.cpp b/src/core/stdemail/src/main.cpp
index 344e9501a9..19aaf95380 100644
--- a/src/core/stdemail/src/main.cpp
+++ b/src/core/stdemail/src/main.cpp
@@ -2,7 +2,7 @@
Standard e-mail urls launcher for Miranda NG
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
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
diff --git a/src/core/stdemail/src/stdafx.h b/src/core/stdemail/src/stdafx.h
index 8214c32bfe..4520b2f62f 100644
--- a/src/core/stdemail/src/stdafx.h
+++ b/src/core/stdemail/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdemail/src/version.h b/src/core/stdemail/src/version.h
index a158424f02..dd12d45a66 100644
--- a/src/core/stdemail/src/version.h
+++ b/src/core/stdemail/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for e-mail urls handling."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdEmail"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stdfile/src/file.cpp b/src/core/stdfile/src/file.cpp
index 8dcb922619..234f84404f 100644
--- a/src/core/stdfile/src/file.cpp
+++ b/src/core/stdfile/src/file.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdfile/src/file.h b/src/core/stdfile/src/file.h
index b89671ab8a..2bdddb04e5 100644
--- a/src/core/stdfile/src/file.h
+++ b/src/core/stdfile/src/file.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdfile/src/fileexistsdlg.cpp b/src/core/stdfile/src/fileexistsdlg.cpp
index bd715cfa24..c2e4f6dfa8 100644
--- a/src/core/stdfile/src/fileexistsdlg.cpp
+++ b/src/core/stdfile/src/fileexistsdlg.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdfile/src/fileopts.cpp b/src/core/stdfile/src/fileopts.cpp
index f5385174e1..f0d9e1bda2 100644
--- a/src/core/stdfile/src/fileopts.cpp
+++ b/src/core/stdfile/src/fileopts.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdfile/src/filerecvdlg.cpp b/src/core/stdfile/src/filerecvdlg.cpp
index 54aefe44c5..7a364e210e 100644
--- a/src/core/stdfile/src/filerecvdlg.cpp
+++ b/src/core/stdfile/src/filerecvdlg.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdfile/src/filesenddlg.cpp b/src/core/stdfile/src/filesenddlg.cpp
index 017725e89d..024cf68129 100644
--- a/src/core/stdfile/src/filesenddlg.cpp
+++ b/src/core/stdfile/src/filesenddlg.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdfile/src/filexferdlg.cpp b/src/core/stdfile/src/filexferdlg.cpp
index bcd6c16c54..32ef89ecf3 100644
--- a/src/core/stdfile/src/filexferdlg.cpp
+++ b/src/core/stdfile/src/filexferdlg.cpp
@@ -1,765 +1,765 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-#include <io.h>
-#include "file.h"
-
-static int CheckVirusScanned(HWND hwnd, FileDlgData *dat, int i)
-{
- if (dat->send) return 1;
- if (dat->fileVirusScanned == nullptr) return 0;
- if (dat->fileVirusScanned[i]) return 1;
- if (g_plugin.getByte("WarnBeforeOpening", 1) == 0) return 1;
-
- return IDYES == MessageBox(hwnd,
- TranslateT("This file has not yet been scanned for viruses. Are you certain you want to open it?"),
- TranslateT("File received"),
- MB_YESNO | MB_DEFBUTTON2);
-}
-
-#define M_VIRUSSCANDONE (WM_USER+100)
-struct virusscanthreadstartinfo
-{
- wchar_t *szFile;
- int returnCode;
- HWND hwndReply;
-};
-
-wchar_t* PFTS_StringToTchar(int flags, const wchar_t *s)
-{
- if (flags & PFTS_UTF)
- return mir_utf8decodeW((char*)s);
- if (flags & PFTS_UNICODE)
- return mir_wstrdup(s);
- return mir_a2u((char*)s);
-}
-
-int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS *ft, const wchar_t *s, wchar_t *r)
-{
- if (ft->flags & PFTS_UTF) {
- wchar_t *ts = mir_utf8decodeW((char*)s);
- int res = mir_wstrcmp(ts, r);
- mir_free(ts);
- return res;
- }
- if (ft->flags & PFTS_UNICODE)
- return mir_wstrcmp(s, r);
-
- wchar_t *ts = mir_a2u((char*)s);
- int res = mir_wstrcmp(ts, r);
- mir_free(ts);
- return res;
-}
-
-static void SetOpenFileButtonStyle(HWND hwndButton, int enabled)
-{
- EnableWindow(hwndButton, enabled);
-}
-
-void FillSendData(FileDlgData *dat, DBEVENTINFO &dbei)
-{
- dbei.szModule = Proto_GetBaseAccountName(dat->hContact);
- dbei.eventType = EVENTTYPE_FILE;
- dbei.flags = DBEF_SENT;
- dbei.timestamp = time(0);
- char *szFileNames = mir_utf8encodeW(dat->szFilenames), *szMsg = mir_utf8encodeW(dat->szMsg);
- dbei.flags |= DBEF_UTF;
-
- dbei.cbBlob = int(sizeof(uint32_t) + mir_strlen(szFileNames) + mir_strlen(szMsg) + 2);
- dbei.pBlob = (uint8_t*)mir_alloc(dbei.cbBlob);
- *(PDWORD)dbei.pBlob = 0;
- mir_strcpy((char*)dbei.pBlob + sizeof(uint32_t), szFileNames);
- mir_strcpy((char*)dbei.pBlob + sizeof(uint32_t) + mir_strlen(szFileNames) + 1, szMsg);
-
- mir_free(szFileNames), mir_free(szMsg);
-}
-
-static void __cdecl RunVirusScannerThread(virusscanthreadstartinfo *info)
-{
- DBVARIANT dbv;
- if (!g_plugin.getWString("ScanCmdLine", &dbv)) {
- if (dbv.pwszVal[0]) {
- STARTUPINFO si = { 0 };
- si.cb = sizeof(si);
- wchar_t *pszReplace = wcsstr(dbv.pwszVal, L"%f");
- wchar_t szCmdLine[768];
- if (pszReplace) {
- if (info->szFile[mir_wstrlen(info->szFile) - 1] == '\\')
- info->szFile[mir_wstrlen(info->szFile) - 1] = '\0';
- *pszReplace = 0;
- mir_snwprintf(szCmdLine, L"%s\"%s\"%s", dbv.pwszVal, info->szFile, pszReplace + 2);
- }
- else
- wcsncpy_s(szCmdLine, dbv.pwszVal, _TRUNCATE);
-
- PROCESS_INFORMATION pi;
- if (CreateProcess(nullptr, szCmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) {
- if (WaitForSingleObject(pi.hProcess, 3600 * 1000) == WAIT_OBJECT_0)
- PostMessage(info->hwndReply, M_VIRUSSCANDONE, info->returnCode, 0);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- }
- }
- db_free(&dbv);
- }
- mir_free(info->szFile);
- mir_free(info);
-}
-
-static void SetFilenameControls(HWND hwndDlg, FileDlgData *dat, PROTOFILETRANSFERSTATUS *fts)
-{
- wchar_t msg[MAX_PATH];
- wchar_t *fnbuf = nullptr, *fn = nullptr;
- SHFILEINFO shfi = {};
-
- if (fts->szCurrentFile.w) {
- fnbuf = mir_wstrdup(fts->szCurrentFile.w);
- if ((fn = wcsrchr(fnbuf, '\\')) == nullptr)
- fn = fnbuf;
- else fn++;
- }
-
- if (dat->hIcon) DestroyIcon(dat->hIcon); dat->hIcon = nullptr;
-
- if (fn && (fts->totalFiles > 1)) {
- mir_snwprintf(msg, L"%s: %s (%d %s %d)", Clist_GetContactDisplayName(fts->hContact), fn, fts->currentFileNumber + 1, TranslateT("of"), fts->totalFiles);
-
- SHGetFileInfo(fn, FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
- dat->hIcon = shfi.hIcon;
- }
- else if (fn) {
- mir_snwprintf(msg, L"%s: %s", Clist_GetContactDisplayName(fts->hContact), fn);
-
- SHGetFileInfo(fn, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
- dat->hIcon = shfi.hIcon;
- }
- else {
- mir_wstrncpy(msg, Clist_GetContactDisplayName(fts->hContact), _countof(msg));
- HICON hIcon = Skin_LoadIcon(SKINICON_OTHER_DOWNARROW);
- dat->hIcon = CopyIcon(hIcon);
- IcoLib_ReleaseIcon(hIcon, NULL);
- }
-
- mir_free(fnbuf);
-
- SendDlgItemMessage(hwndDlg, IDC_FILEICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->hIcon);
- SetDlgItemText(hwndDlg, IDC_CONTACTNAME, msg);
-}
-
-enum { FTS_TEXT, FTS_PROGRESS, FTS_OPEN };
-static void SetFtStatus(HWND hwndDlg, wchar_t *text, int mode)
-{
- SetDlgItemText(hwndDlg, IDC_STATUS, TranslateW(text));
- SetDlgItemText(hwndDlg, IDC_TRANSFERCOMPLETED, TranslateW(text));
-
- ShowWindow(GetDlgItem(hwndDlg, IDC_STATUS), (mode == FTS_TEXT) ? SW_SHOW : SW_HIDE);
- ShowWindow(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), (mode == FTS_PROGRESS) ? SW_SHOW : SW_HIDE);
- ShowWindow(GetDlgItem(hwndDlg, IDC_TRANSFERCOMPLETED), (mode == FTS_OPEN) ? SW_SHOW : SW_HIDE);
- ShowWindow(GetDlgItem(hwndDlg, IDC_FILEICON), (mode == FTS_OPEN) ? SW_SHOW : SW_HIDE);
-}
-
-static void HideProgressControls(HWND hwndDlg)
-{
- RECT rc;
- char buf[64];
-
- GetWindowRect(GetDlgItem(hwndDlg, IDC_ALLPRECENTS), &rc);
- MapWindowPoints(nullptr, hwndDlg, (LPPOINT)&rc, 2);
- SetWindowPos(hwndDlg, nullptr, 0, 0, 100, rc.bottom + 3, SWP_NOMOVE | SWP_NOZORDER);
- ShowWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), SW_HIDE);
- ShowWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), SW_HIDE);
-
- _strtime(buf);
- SetDlgItemTextA(hwndDlg, IDC_ALLPRECENTS, buf);
-
- PostMessage(GetParent(hwndDlg), WM_FT_RESIZE, 0, (LPARAM)hwndDlg);
-}
-
-static int FileTransferDlgResizer(HWND, LPARAM param, UTILRESIZECONTROL *urc)
-{
- auto *dat = (FileDlgData *)param;
-
- switch (urc->wId) {
- case IDC_CONTACTNAME:
- case IDC_STATUS:
- case IDC_ALLFILESPROGRESS:
- case IDC_TRANSFERCOMPLETED:
- return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
-
- case IDC_FRAME:
- return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
- case IDC_ALLPRECENTS:
- case IDCANCEL:
- case IDC_OPENFILE:
- case IDC_OPENFOLDER:
- return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP;
-
- case IDC_ALLTRANSFERRED:
- if (dat->waitingForAcceptance)
- return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
-
- urc->rcItem.right = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx) / 3;
- return RD_ANCHORX_CUSTOM | RD_ANCHORY_TOP;
-
- case IDC_ALLSPEED:
- if (dat->waitingForAcceptance)
- return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP;
-
- urc->rcItem.right = urc->rcItem.right - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx;
- urc->rcItem.left = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left) / 3;
- return RD_ANCHORX_CUSTOM | RD_ANCHORY_TOP;
- }
- return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
-}
-
-INT_PTR CALLBACK DlgProcFileTransfer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- FileDlgData *dat = (FileDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
- dat = (FileDlgData *)lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
- dat->hNotifyEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_RECVEVENT);
- dat->transferStatus.currentFileNumber = -1;
- if (dat->send) {
- if (db_mc_isMeta(dat->hContact))
- dat->hContact = db_mc_getMostOnline(dat->hContact);
- dat->fs = (HANDLE)ProtoChainSend(dat->hContact, PSS_FILE, (WPARAM)dat->szMsg, (LPARAM)dat->files);
- SetFtStatus(hwndDlg, LPGENW("Request sent, waiting for acceptance..."), FTS_TEXT);
- SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
- dat->waitingForAcceptance = 1;
- // hide "open" button since it may cause potential access violations...
- ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFILE), SW_HIDE);
- ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFOLDER), SW_HIDE);
- }
- else { //recv
- CreateDirectoryTreeW(dat->szSavePath);
- dat->fs = (HANDLE)ProtoChainSend(dat->hContact, PSS_FILEALLOW, (WPARAM)dat->fs, (LPARAM)dat->szSavePath);
- dat->transferStatus.szWorkingDir.w = mir_wstrdup(dat->szSavePath);
- if (!Contact::OnList(dat->hContact))
- dat->resumeBehaviour = FILERESUME_ASK;
- else
- dat->resumeBehaviour = g_plugin.getByte("IfExists", FILERESUME_ASK);
- SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT);
- }
-
- /* check we actually got an fs handle back from the protocol */
- if (!dat->fs) {
- SetFtStatus(hwndDlg, LPGENW("Unable to initiate transfer."), FTS_TEXT);
- dat->waitingForAcceptance = 0;
- }
- {
- LOGFONT lf;
- HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0);
- GetObject(hFont, sizeof(lf), &lf);
- lf.lfWeight = FW_BOLD;
- hFont = CreateFontIndirect(&lf);
- SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_SETFONT, (WPARAM)hFont, 0);
-
- SHFILEINFO shfi = {};
- SHGetFileInfo(L"", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
- dat->hIconFolder = shfi.hIcon;
- }
- dat->hIcon = nullptr;
- {
- char *szProto = Proto_GetBaseAccountName(dat->hContact);
- uint16_t status = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_ONLINE);
- SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)Skin_LoadProtoIcon(szProto, status));
- }
-
- SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0);
- SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, TRUE, 0);
-
- Button_SetSkin_IcoLib(hwndDlg, IDC_OPENFILE, SKINICON_OTHER_DOWNARROW, LPGEN("Open..."));
- SendDlgItemMessage(hwndDlg, IDC_OPENFILE, BUTTONSETASPUSHBTN, TRUE, 0);
-
- SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->hIconFolder);
- SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Open folder"), 0);
- SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONSETASFLATBTN, TRUE, 0);
-
- Button_SetSkin_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel"));
-
- SetDlgItemText(hwndDlg, IDC_CONTACTNAME, Clist_GetContactDisplayName(dat->hContact));
-
- if (!dat->waitingForAcceptance)
- SetTimer(hwndDlg, 1, 1000, nullptr);
- return TRUE;
-
- case WM_TIMER:
- memmove(dat->bytesRecvedHistory + 1, dat->bytesRecvedHistory, sizeof(dat->bytesRecvedHistory) - sizeof(dat->bytesRecvedHistory[0]));
- dat->bytesRecvedHistory[0] = dat->transferStatus.totalProgress;
- if (dat->bytesRecvedHistorySize < _countof(dat->bytesRecvedHistory))
- dat->bytesRecvedHistorySize++;
-
- wchar_t szSpeed[32], szTime[32], szDisplay[96];
- SYSTEMTIME st;
- ULARGE_INTEGER li;
- FILETIME ft;
-
- GetSensiblyFormattedSize((dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) / dat->bytesRecvedHistorySize, szSpeed, _countof(szSpeed), 0, 1, NULL);
- if (dat->bytesRecvedHistory[0] == dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1])
- mir_wstrcpy(szTime, L"??:??:??");
- else {
- li.QuadPart = 10000000ll * (dat->transferStatus.currentFileSize - dat->transferStatus.currentFileProgress) * dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]);
- ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart;
- FileTimeToSystemTime(&ft, &st);
- GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, _countof(szTime));
- }
- if (dat->bytesRecvedHistory[0] != dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) {
- li.QuadPart = 10000000ll * (dat->transferStatus.totalBytes - dat->transferStatus.totalProgress) * dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]);
- ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart;
- FileTimeToSystemTime(&ft, &st);
- GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, _countof(szTime));
- }
-
- mir_snwprintf(szDisplay, L"%s/%s (%s %s)", szSpeed, TranslateT("sec"), szTime, TranslateT("remaining"));
- SetDlgItemText(hwndDlg, IDC_ALLSPEED, szDisplay);
- break;
-
- case WM_MEASUREITEM:
- return Menu_MeasureItem(lParam);
-
- case WM_DRAWITEM:
- return Menu_DrawItem(lParam);
-
- case WM_FT_CLEANUP:
- if (!dat->fs) {
- PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
- DestroyWindow(hwndDlg);
- }
- break;
-
- case WM_COMMAND:
- if (!dat)
- break;
-
- if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact))
- break;
-
- switch (LOWORD(wParam)) {
- case IDOK:
- case IDCANCEL:
- PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
- DestroyWindow(hwndDlg);
- break;
-
- case IDC_CONTACT:
- {
- RECT rc;
- HMENU hMenu = Menu_BuildContactMenu(dat->hContact);
- GetWindowRect((HWND)lParam, &rc);
- TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL);
- DestroyMenu(hMenu);
- }
- break;
-
- case IDC_TRANSFERCOMPLETED:
- if (dat->transferStatus.currentFileNumber <= 1 && CheckVirusScanned(hwndDlg, dat, 0)) {
- ShellExecute(NULL, NULL, dat->files[0], NULL, NULL, SW_SHOW);
- break;
- }
-
- case IDC_OPENFOLDER:
- {
- wchar_t *path = dat->transferStatus.szWorkingDir.w;
- if (!path || !path[0]) {
- path = NEWWSTR_ALLOCA(dat->transferStatus.szCurrentFile.w);
- wchar_t *p = wcsrchr(path, '\\'); if (p) *p = 0;
- }
-
- if (path) ShellExecute(NULL, L"open", path, NULL, NULL, SW_SHOW);
- }
- break;
-
- case IDC_OPENFILE:
- wchar_t **files;
- if (dat->send) {
- if (dat->files == nullptr)
- files = dat->transferStatus.pszFiles.w;
- else
- files = dat->files;
- }
- else files = dat->files;
-
- HMENU hMenu = CreatePopupMenu();
- AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder"));
- AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
-
- if (files && *files) {
- int limit;
- wchar_t *pszFilename, *pszNewFileName;
-
- if (dat->send)
- limit = dat->transferStatus.totalFiles;
- else
- limit = dat->transferStatus.currentFileNumber;
-
- // Loop over all transfered files and add them to the menu
- for (int i = 0; i < limit; i++) {
- pszFilename = wcsrchr(files[i], '\\');
- if (pszFilename == nullptr)
- pszFilename = files[i];
- else
- pszFilename++;
-
- if (pszFilename) {
- size_t cbFileNameLen = mir_wstrlen(pszFilename);
-
- pszNewFileName = (wchar_t*)mir_alloc(cbFileNameLen * 2 * sizeof(wchar_t));
- wchar_t *p = pszNewFileName;
- for (size_t pszlen = 0; pszlen < cbFileNameLen; pszlen++) {
- *p++ = pszFilename[pszlen];
- if (pszFilename[pszlen] == '&')
- *p++ = '&';
- }
- *p = '\0';
- AppendMenu(hMenu, MF_STRING, i + 10, pszNewFileName);
- mir_free(pszNewFileName);
- }
- }
- }
-
- RECT rc;
- GetWindowRect((HWND)lParam, &rc);
- CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_CHECKED);
- int ret = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_RIGHTALIGN, rc.right, rc.bottom, 0, hwndDlg, nullptr);
- CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED);
- DestroyMenu(hMenu);
-
- if (ret == 1) {
- wchar_t *path = dat->transferStatus.szWorkingDir.w;
- if (!path || !path[0]) {
- path = NEWWSTR_ALLOCA(dat->transferStatus.szCurrentFile.w);
- wchar_t *p = wcsrchr(path, '\\');
- if (p)
- *p = 0;
- }
-
- if (path) ShellExecute(nullptr, L"open", path, nullptr, nullptr, SW_SHOW);
- }
- else if (ret && CheckVirusScanned(hwndDlg, dat, ret))
- ShellExecute(nullptr, nullptr, files[ret - 10], nullptr, nullptr, SW_SHOW);
- }
- break;
-
- case M_FILEEXISTSDLGREPLY:
- EnableWindow(hwndDlg, TRUE);
- {
- PROTOFILERESUME *pfr = (PROTOFILERESUME *)lParam;
- wchar_t *szOriginalFilename = (wchar_t *)wParam;
- char *szProto = Proto_GetBaseAccountName(dat->hContact);
-
- switch (pfr->action) {
- case FILERESUME_CANCEL:
- if (dat->fs) ProtoChainSend(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0);
- dat->fs = nullptr;
- mir_free(szOriginalFilename);
- if (pfr->szFilename) mir_free((char *)pfr->szFilename);
- mir_free(pfr);
- return 0;
- case FILERESUME_RESUMEALL:
- case FILERESUME_OVERWRITEALL:
- dat->resumeBehaviour = pfr->action;
- pfr->action &= ~FILERESUMEF_ALL;
- break;
- case FILERESUME_RENAMEALL:
- pfr->action = FILERESUME_RENAME;
- {
- wchar_t *pszExtension, *pszFilename;
- if ((pszFilename = wcsrchr(szOriginalFilename, '\\')) == nullptr) pszFilename = szOriginalFilename;
- if ((pszExtension = wcsrchr(pszFilename + 1, '.')) == nullptr) pszExtension = pszFilename + mir_wstrlen(pszFilename);
- if (pfr->szFilename) mir_free((wchar_t *)pfr->szFilename);
- size_t size = (pszExtension - szOriginalFilename) + 21 + mir_wstrlen(pszExtension);
- pfr->szFilename = (wchar_t *)mir_alloc(sizeof(wchar_t) * size);
- for (int i = 1;; i++) {
- mir_snwprintf((wchar_t *)pfr->szFilename, size, L"%.*s (%u)%s", pszExtension - szOriginalFilename, szOriginalFilename, i, pszExtension);
- if (_waccess(pfr->szFilename, 0) != 0)
- break;
- }
- }
- break;
- }
- mir_free(szOriginalFilename);
- CallProtoService(szProto, PS_FILERESUME, (WPARAM)dat->fs, (LPARAM)pfr);
- delete pfr;
- }
- break;
-
- case HM_RECVEVENT:
- {
- ACKDATA *ack = (ACKDATA *)lParam;
- if (ack->hProcess != dat->fs) break;
- if (ack->type != ACKTYPE_FILE) break;
- if (ack->hContact != dat->hContact) break;
-
- if (dat->waitingForAcceptance) {
- SetTimer(hwndDlg, 1, 1000, nullptr);
- dat->waitingForAcceptance = 0;
- }
-
- switch (ack->result) {
- case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENW("Decision sent"), FTS_TEXT); break;
- case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENW("Connecting..."), FTS_TEXT); break;
- case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENW("Connecting to proxy..."), FTS_TEXT); break;
- case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENW("Connected"), FTS_TEXT); break;
- case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT); break;
- case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENW("Initializing..."), FTS_TEXT); break;
- case ACKRESULT_NEXTFILE:
- SetFtStatus(hwndDlg, LPGENW("Moving to next file..."), FTS_TEXT);
- SetDlgItemTextA(hwndDlg, IDC_FILENAME, "");
- if (dat->transferStatus.currentFileNumber == 1 && dat->transferStatus.totalFiles > 1 && !dat->send)
- SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
- if (dat->transferStatus.currentFileNumber != -1 && dat->files && !dat->send && g_plugin.getByte("UseScanner", VIRUSSCAN_DISABLE) == VIRUSSCAN_DURINGDL) {
- if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber]) & FILE_ATTRIBUTE_DIRECTORY)
- PostMessage(hwndDlg, M_VIRUSSCANDONE, dat->transferStatus.currentFileNumber, 0);
- else {
- virusscanthreadstartinfo *vstsi = (virusscanthreadstartinfo *)mir_alloc(sizeof(virusscanthreadstartinfo));
- vstsi->hwndReply = hwndDlg;
- vstsi->szFile = mir_wstrdup(dat->files[dat->transferStatus.currentFileNumber]);
- vstsi->returnCode = dat->transferStatus.currentFileNumber;
- mir_forkThread<virusscanthreadstartinfo>(RunVirusScannerThread, vstsi);
- }
- }
- break;
-
- case ACKRESULT_FILERESUME:
- UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS *)ack->lParam);
- {
- PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus;
- SetFilenameControls(hwndDlg, dat, fts);
- if (_waccess(fts->szCurrentFile.w, 0))
- break;
-
- SetFtStatus(hwndDlg, LPGENW("File already exists"), FTS_TEXT);
- if (dat->resumeBehaviour == FILERESUME_ASK) {
- TDlgProcFileExistsParam param = { hwndDlg, fts };
- ShowWindow(hwndDlg, SW_SHOWNORMAL);
- CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILEEXISTS), hwndDlg, DlgProcFileExists, (LPARAM)&param);
- EnableWindow(hwndDlg, FALSE);
- }
- else {
- PROTOFILERESUME *pfr = new PROTOFILERESUME();
- pfr->action = dat->resumeBehaviour;
- pfr->szFilename = nullptr;
- PostMessage(hwndDlg, M_FILEEXISTSDLGREPLY, (WPARAM)mir_wstrdup(fts->szCurrentFile.w), (LPARAM)pfr);
- }
- }
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1);
- return TRUE;
-
- case ACKRESULT_DATA:
- {
- PROTOFILETRANSFERSTATUS *fts = (PROTOFILETRANSFERSTATUS *)ack->lParam;
- wchar_t str[64], str2[64], szSizeDone[32], szSizeTotal[32];//, *contactName;
-
- if (dat->fileVirusScanned == nullptr)
- dat->fileVirusScanned = (int *)mir_calloc(sizeof(int) * fts->totalFiles);
-
- // This needs to be here - otherwise we get holes in the files array
- if (!dat->send) {
- if (dat->files == nullptr)
- dat->files = (wchar_t **)mir_calloc((fts->totalFiles + 1) * sizeof(wchar_t *));
- if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == nullptr)
- dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->szCurrentFile.w);
- }
-
- /* HACK: for 0.3.3, limit updates to around 1.1 ack per second */
- if (fts->totalProgress != fts->totalBytes && GetTickCount() < (dat->dwTicks + 650))
- break; // the last update was less than a second ago!
- dat->dwTicks = GetTickCount();
-
- // Update local transfer status with data from protocol
- UpdateProtoFileTransferStatus(&dat->transferStatus, fts);
- fts = &dat->transferStatus;
-
- bool firstTime = false;
- if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0) {
- SetFtStatus(hwndDlg, (fts->flags & PFTS_SENDING) ? LPGENW("Sending...") : LPGENW("Receiving..."), FTS_PROGRESS);
- SetFilenameControls(hwndDlg, dat, fts);
- firstTime = true;
- }
-
- const unsigned long lastPos = SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_GETPOS, 0, 0);
- const unsigned long nextPos = fts->totalBytes ? (100ll * fts->totalProgress / fts->totalBytes) : 0;
- if (lastPos != nextPos || firstTime) {
- SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0);
- mir_snwprintf(str, L"%u%%", nextPos);
- SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str);
- }
-
- int units;
- GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, _countof(szSizeTotal), 0, 1, &units);
- GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, _countof(szSizeDone), units, 0, NULL);
- mir_snwprintf(str, L"%s/%s", szSizeDone, szSizeTotal);
- str2[0] = 0;
- GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, _countof(str2));
- if (mir_wstrcmp(str, str2))
- SetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str);
- }
- break;
-
- case ACKRESULT_SUCCESS:
- case ACKRESULT_FAILED:
- case ACKRESULT_DENIED:
- HideProgressControls(hwndDlg);
- KillTimer(hwndDlg, 1);
- if (!dat->send)
- SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
- SetDlgItemText(hwndDlg, IDCANCEL, TranslateT("Close"));
- if (dat->hNotifyEvent)
- UnhookEvent(dat->hNotifyEvent);
- dat->hNotifyEvent = nullptr;
-
- if (ack->result == ACKRESULT_DENIED) {
- dat->fs = nullptr; /* protocol will free structure */
- Skin_PlaySound("FileDenied");
- SetFtStatus(hwndDlg, LPGENW("File transfer denied"), FTS_TEXT);
- }
- else if (ack->result == ACKRESULT_FAILED) {
- dat->fs = nullptr; /* protocol will free structure */
- Skin_PlaySound("FileFailed");
- SetFtStatus(hwndDlg, LPGENW("File transfer failed"), FTS_TEXT);
- }
- else {
- Skin_PlaySound("FileDone");
- if (dat->send) {
- dat->fs = nullptr; /* protocol will free structure */
- SetFtStatus(hwndDlg, LPGENW("Transfer completed."), FTS_TEXT);
-
- DBEVENTINFO dbei = {};
- FillSendData(dat, dbei);
- db_event_add(dat->hContact, &dbei);
- if (dbei.pBlob)
- mir_free(dbei.pBlob);
- dat->files = nullptr; //protocol library frees this
- }
- else {
- SetFtStatus(hwndDlg,
- (dat->transferStatus.totalFiles == 1) ?
- LPGENW("Transfer completed, open file.") :
- LPGENW("Transfer completed, open folder."),
- FTS_OPEN);
-
- int useScanner = g_plugin.getByte("UseScanner", VIRUSSCAN_DISABLE);
- if (useScanner != VIRUSSCAN_DISABLE) {
- auto *vstsi = (virusscanthreadstartinfo *)mir_alloc(sizeof(virusscanthreadstartinfo));
- vstsi->hwndReply = hwndDlg;
- if (useScanner == VIRUSSCAN_DURINGDL) {
- vstsi->returnCode = dat->transferStatus.currentFileNumber;
- if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber]) & FILE_ATTRIBUTE_DIRECTORY) {
- PostMessage(hwndDlg, M_VIRUSSCANDONE, vstsi->returnCode, 0);
- mir_free(vstsi);
- vstsi = nullptr;
- }
- else vstsi->szFile = mir_wstrdup(dat->files[dat->transferStatus.currentFileNumber]);
- }
- else {
- vstsi->szFile = mir_wstrdup(dat->transferStatus.szWorkingDir.w);
- vstsi->returnCode = -1;
- }
- SetFtStatus(hwndDlg, LPGENW("Scanning for viruses..."), FTS_TEXT);
- if (vstsi)
- mir_forkThread<virusscanthreadstartinfo>(RunVirusScannerThread, vstsi);
- }
- else dat->fs = nullptr; /* protocol will free structure */
-
- dat->transferStatus.currentFileNumber = dat->transferStatus.totalFiles;
- }
- }
-
- PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg);
- break;
- }
- }
- break;
-
- case M_VIRUSSCANDONE:
- {
- int done = 1;
- if ((int)wParam == -1) {
- for (int i = 0; i < dat->transferStatus.totalFiles; i++)
- dat->fileVirusScanned[i] = 1;
- }
- else {
- dat->fileVirusScanned[wParam] = 1;
- for (int i = 0; i < dat->transferStatus.totalFiles; i++)
- if (!dat->fileVirusScanned[i]) {
- done = 0;
- break;
- }
- }
- if (done) {
- dat->fs = nullptr; /* protocol will free structure */
- SetFtStatus(hwndDlg, LPGENW("Transfer and virus scan complete"), FTS_TEXT);
- }
- }
- break;
-
- case WM_SIZE:
- Utils_ResizeDialog(hwndDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_FILETRANSFERINFO), FileTransferDlgResizer, LPARAM(dat));
-
- RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
- RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
- RedrawWindow(GetDlgItem(hwndDlg, IDC_CONTACTNAME), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
- RedrawWindow(GetDlgItem(hwndDlg, IDC_STATUS), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
- break;
-
- case WM_DESTROY:
- KillTimer(hwndDlg, 1);
-
- HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0);
- DeleteObject(hFont);
-
- Button_FreeIcon_IcoLib(hwndDlg, IDC_CONTACT);
- Button_FreeIcon_IcoLib(hwndDlg, IDC_OPENFILE);
- Button_FreeIcon_IcoLib(hwndDlg, IDCANCEL);
-
- delete dat;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
- break;
- }
- return FALSE;
-}
-
-FileDlgData::~FileDlgData()
-{
- if (fs)
- ProtoChainSend(hContact, PSS_FILECANCEL, (WPARAM)fs, 0);
- if (hPreshutdownEvent)
- UnhookEvent(hPreshutdownEvent);
- if (hNotifyEvent)
- UnhookEvent(hNotifyEvent);
-
- FreeProtoFileTransferStatus(&transferStatus);
- FreeFilesMatrix(&files);
-
- mir_free(fileVirusScanned);
- if (hIcon)
- DestroyIcon(hIcon);
- if (hIconFolder)
- DestroyIcon(hIconFolder);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+#include <io.h>
+#include "file.h"
+
+static int CheckVirusScanned(HWND hwnd, FileDlgData *dat, int i)
+{
+ if (dat->send) return 1;
+ if (dat->fileVirusScanned == nullptr) return 0;
+ if (dat->fileVirusScanned[i]) return 1;
+ if (g_plugin.getByte("WarnBeforeOpening", 1) == 0) return 1;
+
+ return IDYES == MessageBox(hwnd,
+ TranslateT("This file has not yet been scanned for viruses. Are you certain you want to open it?"),
+ TranslateT("File received"),
+ MB_YESNO | MB_DEFBUTTON2);
+}
+
+#define M_VIRUSSCANDONE (WM_USER+100)
+struct virusscanthreadstartinfo
+{
+ wchar_t *szFile;
+ int returnCode;
+ HWND hwndReply;
+};
+
+wchar_t* PFTS_StringToTchar(int flags, const wchar_t *s)
+{
+ if (flags & PFTS_UTF)
+ return mir_utf8decodeW((char*)s);
+ if (flags & PFTS_UNICODE)
+ return mir_wstrdup(s);
+ return mir_a2u((char*)s);
+}
+
+int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS *ft, const wchar_t *s, wchar_t *r)
+{
+ if (ft->flags & PFTS_UTF) {
+ wchar_t *ts = mir_utf8decodeW((char*)s);
+ int res = mir_wstrcmp(ts, r);
+ mir_free(ts);
+ return res;
+ }
+ if (ft->flags & PFTS_UNICODE)
+ return mir_wstrcmp(s, r);
+
+ wchar_t *ts = mir_a2u((char*)s);
+ int res = mir_wstrcmp(ts, r);
+ mir_free(ts);
+ return res;
+}
+
+static void SetOpenFileButtonStyle(HWND hwndButton, int enabled)
+{
+ EnableWindow(hwndButton, enabled);
+}
+
+void FillSendData(FileDlgData *dat, DBEVENTINFO &dbei)
+{
+ dbei.szModule = Proto_GetBaseAccountName(dat->hContact);
+ dbei.eventType = EVENTTYPE_FILE;
+ dbei.flags = DBEF_SENT;
+ dbei.timestamp = time(0);
+ char *szFileNames = mir_utf8encodeW(dat->szFilenames), *szMsg = mir_utf8encodeW(dat->szMsg);
+ dbei.flags |= DBEF_UTF;
+
+ dbei.cbBlob = int(sizeof(uint32_t) + mir_strlen(szFileNames) + mir_strlen(szMsg) + 2);
+ dbei.pBlob = (uint8_t*)mir_alloc(dbei.cbBlob);
+ *(PDWORD)dbei.pBlob = 0;
+ mir_strcpy((char*)dbei.pBlob + sizeof(uint32_t), szFileNames);
+ mir_strcpy((char*)dbei.pBlob + sizeof(uint32_t) + mir_strlen(szFileNames) + 1, szMsg);
+
+ mir_free(szFileNames), mir_free(szMsg);
+}
+
+static void __cdecl RunVirusScannerThread(virusscanthreadstartinfo *info)
+{
+ DBVARIANT dbv;
+ if (!g_plugin.getWString("ScanCmdLine", &dbv)) {
+ if (dbv.pwszVal[0]) {
+ STARTUPINFO si = { 0 };
+ si.cb = sizeof(si);
+ wchar_t *pszReplace = wcsstr(dbv.pwszVal, L"%f");
+ wchar_t szCmdLine[768];
+ if (pszReplace) {
+ if (info->szFile[mir_wstrlen(info->szFile) - 1] == '\\')
+ info->szFile[mir_wstrlen(info->szFile) - 1] = '\0';
+ *pszReplace = 0;
+ mir_snwprintf(szCmdLine, L"%s\"%s\"%s", dbv.pwszVal, info->szFile, pszReplace + 2);
+ }
+ else
+ wcsncpy_s(szCmdLine, dbv.pwszVal, _TRUNCATE);
+
+ PROCESS_INFORMATION pi;
+ if (CreateProcess(nullptr, szCmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) {
+ if (WaitForSingleObject(pi.hProcess, 3600 * 1000) == WAIT_OBJECT_0)
+ PostMessage(info->hwndReply, M_VIRUSSCANDONE, info->returnCode, 0);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ }
+ db_free(&dbv);
+ }
+ mir_free(info->szFile);
+ mir_free(info);
+}
+
+static void SetFilenameControls(HWND hwndDlg, FileDlgData *dat, PROTOFILETRANSFERSTATUS *fts)
+{
+ wchar_t msg[MAX_PATH];
+ wchar_t *fnbuf = nullptr, *fn = nullptr;
+ SHFILEINFO shfi = {};
+
+ if (fts->szCurrentFile.w) {
+ fnbuf = mir_wstrdup(fts->szCurrentFile.w);
+ if ((fn = wcsrchr(fnbuf, '\\')) == nullptr)
+ fn = fnbuf;
+ else fn++;
+ }
+
+ if (dat->hIcon) DestroyIcon(dat->hIcon); dat->hIcon = nullptr;
+
+ if (fn && (fts->totalFiles > 1)) {
+ mir_snwprintf(msg, L"%s: %s (%d %s %d)", Clist_GetContactDisplayName(fts->hContact), fn, fts->currentFileNumber + 1, TranslateT("of"), fts->totalFiles);
+
+ SHGetFileInfo(fn, FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
+ dat->hIcon = shfi.hIcon;
+ }
+ else if (fn) {
+ mir_snwprintf(msg, L"%s: %s", Clist_GetContactDisplayName(fts->hContact), fn);
+
+ SHGetFileInfo(fn, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
+ dat->hIcon = shfi.hIcon;
+ }
+ else {
+ mir_wstrncpy(msg, Clist_GetContactDisplayName(fts->hContact), _countof(msg));
+ HICON hIcon = Skin_LoadIcon(SKINICON_OTHER_DOWNARROW);
+ dat->hIcon = CopyIcon(hIcon);
+ IcoLib_ReleaseIcon(hIcon, NULL);
+ }
+
+ mir_free(fnbuf);
+
+ SendDlgItemMessage(hwndDlg, IDC_FILEICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->hIcon);
+ SetDlgItemText(hwndDlg, IDC_CONTACTNAME, msg);
+}
+
+enum { FTS_TEXT, FTS_PROGRESS, FTS_OPEN };
+static void SetFtStatus(HWND hwndDlg, wchar_t *text, int mode)
+{
+ SetDlgItemText(hwndDlg, IDC_STATUS, TranslateW(text));
+ SetDlgItemText(hwndDlg, IDC_TRANSFERCOMPLETED, TranslateW(text));
+
+ ShowWindow(GetDlgItem(hwndDlg, IDC_STATUS), (mode == FTS_TEXT) ? SW_SHOW : SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), (mode == FTS_PROGRESS) ? SW_SHOW : SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_TRANSFERCOMPLETED), (mode == FTS_OPEN) ? SW_SHOW : SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_FILEICON), (mode == FTS_OPEN) ? SW_SHOW : SW_HIDE);
+}
+
+static void HideProgressControls(HWND hwndDlg)
+{
+ RECT rc;
+ char buf[64];
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_ALLPRECENTS), &rc);
+ MapWindowPoints(nullptr, hwndDlg, (LPPOINT)&rc, 2);
+ SetWindowPos(hwndDlg, nullptr, 0, 0, 100, rc.bottom + 3, SWP_NOMOVE | SWP_NOZORDER);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), SW_HIDE);
+
+ _strtime(buf);
+ SetDlgItemTextA(hwndDlg, IDC_ALLPRECENTS, buf);
+
+ PostMessage(GetParent(hwndDlg), WM_FT_RESIZE, 0, (LPARAM)hwndDlg);
+}
+
+static int FileTransferDlgResizer(HWND, LPARAM param, UTILRESIZECONTROL *urc)
+{
+ auto *dat = (FileDlgData *)param;
+
+ switch (urc->wId) {
+ case IDC_CONTACTNAME:
+ case IDC_STATUS:
+ case IDC_ALLFILESPROGRESS:
+ case IDC_TRANSFERCOMPLETED:
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
+
+ case IDC_FRAME:
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
+ case IDC_ALLPRECENTS:
+ case IDCANCEL:
+ case IDC_OPENFILE:
+ case IDC_OPENFOLDER:
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP;
+
+ case IDC_ALLTRANSFERRED:
+ if (dat->waitingForAcceptance)
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
+
+ urc->rcItem.right = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx) / 3;
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_TOP;
+
+ case IDC_ALLSPEED:
+ if (dat->waitingForAcceptance)
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP;
+
+ urc->rcItem.right = urc->rcItem.right - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx;
+ urc->rcItem.left = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left) / 3;
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_TOP;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+}
+
+INT_PTR CALLBACK DlgProcFileTransfer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ FileDlgData *dat = (FileDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ dat = (FileDlgData *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ dat->hNotifyEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_RECVEVENT);
+ dat->transferStatus.currentFileNumber = -1;
+ if (dat->send) {
+ if (db_mc_isMeta(dat->hContact))
+ dat->hContact = db_mc_getMostOnline(dat->hContact);
+ dat->fs = (HANDLE)ProtoChainSend(dat->hContact, PSS_FILE, (WPARAM)dat->szMsg, (LPARAM)dat->files);
+ SetFtStatus(hwndDlg, LPGENW("Request sent, waiting for acceptance..."), FTS_TEXT);
+ SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
+ dat->waitingForAcceptance = 1;
+ // hide "open" button since it may cause potential access violations...
+ ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFILE), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFOLDER), SW_HIDE);
+ }
+ else { //recv
+ CreateDirectoryTreeW(dat->szSavePath);
+ dat->fs = (HANDLE)ProtoChainSend(dat->hContact, PSS_FILEALLOW, (WPARAM)dat->fs, (LPARAM)dat->szSavePath);
+ dat->transferStatus.szWorkingDir.w = mir_wstrdup(dat->szSavePath);
+ if (!Contact::OnList(dat->hContact))
+ dat->resumeBehaviour = FILERESUME_ASK;
+ else
+ dat->resumeBehaviour = g_plugin.getByte("IfExists", FILERESUME_ASK);
+ SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT);
+ }
+
+ /* check we actually got an fs handle back from the protocol */
+ if (!dat->fs) {
+ SetFtStatus(hwndDlg, LPGENW("Unable to initiate transfer."), FTS_TEXT);
+ dat->waitingForAcceptance = 0;
+ }
+ {
+ LOGFONT lf;
+ HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0);
+ GetObject(hFont, sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ hFont = CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_SETFONT, (WPARAM)hFont, 0);
+
+ SHFILEINFO shfi = {};
+ SHGetFileInfo(L"", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
+ dat->hIconFolder = shfi.hIcon;
+ }
+ dat->hIcon = nullptr;
+ {
+ char *szProto = Proto_GetBaseAccountName(dat->hContact);
+ uint16_t status = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_ONLINE);
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)Skin_LoadProtoIcon(szProto, status));
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, TRUE, 0);
+
+ Button_SetSkin_IcoLib(hwndDlg, IDC_OPENFILE, SKINICON_OTHER_DOWNARROW, LPGEN("Open..."));
+ SendDlgItemMessage(hwndDlg, IDC_OPENFILE, BUTTONSETASPUSHBTN, TRUE, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->hIconFolder);
+ SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Open folder"), 0);
+ SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONSETASFLATBTN, TRUE, 0);
+
+ Button_SetSkin_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel"));
+
+ SetDlgItemText(hwndDlg, IDC_CONTACTNAME, Clist_GetContactDisplayName(dat->hContact));
+
+ if (!dat->waitingForAcceptance)
+ SetTimer(hwndDlg, 1, 1000, nullptr);
+ return TRUE;
+
+ case WM_TIMER:
+ memmove(dat->bytesRecvedHistory + 1, dat->bytesRecvedHistory, sizeof(dat->bytesRecvedHistory) - sizeof(dat->bytesRecvedHistory[0]));
+ dat->bytesRecvedHistory[0] = dat->transferStatus.totalProgress;
+ if (dat->bytesRecvedHistorySize < _countof(dat->bytesRecvedHistory))
+ dat->bytesRecvedHistorySize++;
+
+ wchar_t szSpeed[32], szTime[32], szDisplay[96];
+ SYSTEMTIME st;
+ ULARGE_INTEGER li;
+ FILETIME ft;
+
+ GetSensiblyFormattedSize((dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) / dat->bytesRecvedHistorySize, szSpeed, _countof(szSpeed), 0, 1, NULL);
+ if (dat->bytesRecvedHistory[0] == dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1])
+ mir_wstrcpy(szTime, L"??:??:??");
+ else {
+ li.QuadPart = 10000000ll * (dat->transferStatus.currentFileSize - dat->transferStatus.currentFileProgress) * dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]);
+ ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart;
+ FileTimeToSystemTime(&ft, &st);
+ GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, _countof(szTime));
+ }
+ if (dat->bytesRecvedHistory[0] != dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) {
+ li.QuadPart = 10000000ll * (dat->transferStatus.totalBytes - dat->transferStatus.totalProgress) * dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]);
+ ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart;
+ FileTimeToSystemTime(&ft, &st);
+ GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, _countof(szTime));
+ }
+
+ mir_snwprintf(szDisplay, L"%s/%s (%s %s)", szSpeed, TranslateT("sec"), szTime, TranslateT("remaining"));
+ SetDlgItemText(hwndDlg, IDC_ALLSPEED, szDisplay);
+ break;
+
+ case WM_MEASUREITEM:
+ return Menu_MeasureItem(lParam);
+
+ case WM_DRAWITEM:
+ return Menu_DrawItem(lParam);
+
+ case WM_FT_CLEANUP:
+ if (!dat->fs) {
+ PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
+ DestroyWindow(hwndDlg);
+ }
+ break;
+
+ case WM_COMMAND:
+ if (!dat)
+ break;
+
+ if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact))
+ break;
+
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ case IDCANCEL:
+ PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_CONTACT:
+ {
+ RECT rc;
+ HMENU hMenu = Menu_BuildContactMenu(dat->hContact);
+ GetWindowRect((HWND)lParam, &rc);
+ TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ }
+ break;
+
+ case IDC_TRANSFERCOMPLETED:
+ if (dat->transferStatus.currentFileNumber <= 1 && CheckVirusScanned(hwndDlg, dat, 0)) {
+ ShellExecute(NULL, NULL, dat->files[0], NULL, NULL, SW_SHOW);
+ break;
+ }
+
+ case IDC_OPENFOLDER:
+ {
+ wchar_t *path = dat->transferStatus.szWorkingDir.w;
+ if (!path || !path[0]) {
+ path = NEWWSTR_ALLOCA(dat->transferStatus.szCurrentFile.w);
+ wchar_t *p = wcsrchr(path, '\\'); if (p) *p = 0;
+ }
+
+ if (path) ShellExecute(NULL, L"open", path, NULL, NULL, SW_SHOW);
+ }
+ break;
+
+ case IDC_OPENFILE:
+ wchar_t **files;
+ if (dat->send) {
+ if (dat->files == nullptr)
+ files = dat->transferStatus.pszFiles.w;
+ else
+ files = dat->files;
+ }
+ else files = dat->files;
+
+ HMENU hMenu = CreatePopupMenu();
+ AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder"));
+ AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
+
+ if (files && *files) {
+ int limit;
+ wchar_t *pszFilename, *pszNewFileName;
+
+ if (dat->send)
+ limit = dat->transferStatus.totalFiles;
+ else
+ limit = dat->transferStatus.currentFileNumber;
+
+ // Loop over all transfered files and add them to the menu
+ for (int i = 0; i < limit; i++) {
+ pszFilename = wcsrchr(files[i], '\\');
+ if (pszFilename == nullptr)
+ pszFilename = files[i];
+ else
+ pszFilename++;
+
+ if (pszFilename) {
+ size_t cbFileNameLen = mir_wstrlen(pszFilename);
+
+ pszNewFileName = (wchar_t*)mir_alloc(cbFileNameLen * 2 * sizeof(wchar_t));
+ wchar_t *p = pszNewFileName;
+ for (size_t pszlen = 0; pszlen < cbFileNameLen; pszlen++) {
+ *p++ = pszFilename[pszlen];
+ if (pszFilename[pszlen] == '&')
+ *p++ = '&';
+ }
+ *p = '\0';
+ AppendMenu(hMenu, MF_STRING, i + 10, pszNewFileName);
+ mir_free(pszNewFileName);
+ }
+ }
+ }
+
+ RECT rc;
+ GetWindowRect((HWND)lParam, &rc);
+ CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_CHECKED);
+ int ret = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_RIGHTALIGN, rc.right, rc.bottom, 0, hwndDlg, nullptr);
+ CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED);
+ DestroyMenu(hMenu);
+
+ if (ret == 1) {
+ wchar_t *path = dat->transferStatus.szWorkingDir.w;
+ if (!path || !path[0]) {
+ path = NEWWSTR_ALLOCA(dat->transferStatus.szCurrentFile.w);
+ wchar_t *p = wcsrchr(path, '\\');
+ if (p)
+ *p = 0;
+ }
+
+ if (path) ShellExecute(nullptr, L"open", path, nullptr, nullptr, SW_SHOW);
+ }
+ else if (ret && CheckVirusScanned(hwndDlg, dat, ret))
+ ShellExecute(nullptr, nullptr, files[ret - 10], nullptr, nullptr, SW_SHOW);
+ }
+ break;
+
+ case M_FILEEXISTSDLGREPLY:
+ EnableWindow(hwndDlg, TRUE);
+ {
+ PROTOFILERESUME *pfr = (PROTOFILERESUME *)lParam;
+ wchar_t *szOriginalFilename = (wchar_t *)wParam;
+ char *szProto = Proto_GetBaseAccountName(dat->hContact);
+
+ switch (pfr->action) {
+ case FILERESUME_CANCEL:
+ if (dat->fs) ProtoChainSend(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0);
+ dat->fs = nullptr;
+ mir_free(szOriginalFilename);
+ if (pfr->szFilename) mir_free((char *)pfr->szFilename);
+ mir_free(pfr);
+ return 0;
+ case FILERESUME_RESUMEALL:
+ case FILERESUME_OVERWRITEALL:
+ dat->resumeBehaviour = pfr->action;
+ pfr->action &= ~FILERESUMEF_ALL;
+ break;
+ case FILERESUME_RENAMEALL:
+ pfr->action = FILERESUME_RENAME;
+ {
+ wchar_t *pszExtension, *pszFilename;
+ if ((pszFilename = wcsrchr(szOriginalFilename, '\\')) == nullptr) pszFilename = szOriginalFilename;
+ if ((pszExtension = wcsrchr(pszFilename + 1, '.')) == nullptr) pszExtension = pszFilename + mir_wstrlen(pszFilename);
+ if (pfr->szFilename) mir_free((wchar_t *)pfr->szFilename);
+ size_t size = (pszExtension - szOriginalFilename) + 21 + mir_wstrlen(pszExtension);
+ pfr->szFilename = (wchar_t *)mir_alloc(sizeof(wchar_t) * size);
+ for (int i = 1;; i++) {
+ mir_snwprintf((wchar_t *)pfr->szFilename, size, L"%.*s (%u)%s", pszExtension - szOriginalFilename, szOriginalFilename, i, pszExtension);
+ if (_waccess(pfr->szFilename, 0) != 0)
+ break;
+ }
+ }
+ break;
+ }
+ mir_free(szOriginalFilename);
+ CallProtoService(szProto, PS_FILERESUME, (WPARAM)dat->fs, (LPARAM)pfr);
+ delete pfr;
+ }
+ break;
+
+ case HM_RECVEVENT:
+ {
+ ACKDATA *ack = (ACKDATA *)lParam;
+ if (ack->hProcess != dat->fs) break;
+ if (ack->type != ACKTYPE_FILE) break;
+ if (ack->hContact != dat->hContact) break;
+
+ if (dat->waitingForAcceptance) {
+ SetTimer(hwndDlg, 1, 1000, nullptr);
+ dat->waitingForAcceptance = 0;
+ }
+
+ switch (ack->result) {
+ case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENW("Decision sent"), FTS_TEXT); break;
+ case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENW("Connecting..."), FTS_TEXT); break;
+ case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENW("Connecting to proxy..."), FTS_TEXT); break;
+ case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENW("Connected"), FTS_TEXT); break;
+ case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT); break;
+ case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENW("Initializing..."), FTS_TEXT); break;
+ case ACKRESULT_NEXTFILE:
+ SetFtStatus(hwndDlg, LPGENW("Moving to next file..."), FTS_TEXT);
+ SetDlgItemTextA(hwndDlg, IDC_FILENAME, "");
+ if (dat->transferStatus.currentFileNumber == 1 && dat->transferStatus.totalFiles > 1 && !dat->send)
+ SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
+ if (dat->transferStatus.currentFileNumber != -1 && dat->files && !dat->send && g_plugin.getByte("UseScanner", VIRUSSCAN_DISABLE) == VIRUSSCAN_DURINGDL) {
+ if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber]) & FILE_ATTRIBUTE_DIRECTORY)
+ PostMessage(hwndDlg, M_VIRUSSCANDONE, dat->transferStatus.currentFileNumber, 0);
+ else {
+ virusscanthreadstartinfo *vstsi = (virusscanthreadstartinfo *)mir_alloc(sizeof(virusscanthreadstartinfo));
+ vstsi->hwndReply = hwndDlg;
+ vstsi->szFile = mir_wstrdup(dat->files[dat->transferStatus.currentFileNumber]);
+ vstsi->returnCode = dat->transferStatus.currentFileNumber;
+ mir_forkThread<virusscanthreadstartinfo>(RunVirusScannerThread, vstsi);
+ }
+ }
+ break;
+
+ case ACKRESULT_FILERESUME:
+ UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS *)ack->lParam);
+ {
+ PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus;
+ SetFilenameControls(hwndDlg, dat, fts);
+ if (_waccess(fts->szCurrentFile.w, 0))
+ break;
+
+ SetFtStatus(hwndDlg, LPGENW("File already exists"), FTS_TEXT);
+ if (dat->resumeBehaviour == FILERESUME_ASK) {
+ TDlgProcFileExistsParam param = { hwndDlg, fts };
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILEEXISTS), hwndDlg, DlgProcFileExists, (LPARAM)&param);
+ EnableWindow(hwndDlg, FALSE);
+ }
+ else {
+ PROTOFILERESUME *pfr = new PROTOFILERESUME();
+ pfr->action = dat->resumeBehaviour;
+ pfr->szFilename = nullptr;
+ PostMessage(hwndDlg, M_FILEEXISTSDLGREPLY, (WPARAM)mir_wstrdup(fts->szCurrentFile.w), (LPARAM)pfr);
+ }
+ }
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1);
+ return TRUE;
+
+ case ACKRESULT_DATA:
+ {
+ PROTOFILETRANSFERSTATUS *fts = (PROTOFILETRANSFERSTATUS *)ack->lParam;
+ wchar_t str[64], str2[64], szSizeDone[32], szSizeTotal[32];//, *contactName;
+
+ if (dat->fileVirusScanned == nullptr)
+ dat->fileVirusScanned = (int *)mir_calloc(sizeof(int) * fts->totalFiles);
+
+ // This needs to be here - otherwise we get holes in the files array
+ if (!dat->send) {
+ if (dat->files == nullptr)
+ dat->files = (wchar_t **)mir_calloc((fts->totalFiles + 1) * sizeof(wchar_t *));
+ if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == nullptr)
+ dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->szCurrentFile.w);
+ }
+
+ /* HACK: for 0.3.3, limit updates to around 1.1 ack per second */
+ if (fts->totalProgress != fts->totalBytes && GetTickCount() < (dat->dwTicks + 650))
+ break; // the last update was less than a second ago!
+ dat->dwTicks = GetTickCount();
+
+ // Update local transfer status with data from protocol
+ UpdateProtoFileTransferStatus(&dat->transferStatus, fts);
+ fts = &dat->transferStatus;
+
+ bool firstTime = false;
+ if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0) {
+ SetFtStatus(hwndDlg, (fts->flags & PFTS_SENDING) ? LPGENW("Sending...") : LPGENW("Receiving..."), FTS_PROGRESS);
+ SetFilenameControls(hwndDlg, dat, fts);
+ firstTime = true;
+ }
+
+ const unsigned long lastPos = SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_GETPOS, 0, 0);
+ const unsigned long nextPos = fts->totalBytes ? (100ll * fts->totalProgress / fts->totalBytes) : 0;
+ if (lastPos != nextPos || firstTime) {
+ SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0);
+ mir_snwprintf(str, L"%u%%", nextPos);
+ SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str);
+ }
+
+ int units;
+ GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, _countof(szSizeTotal), 0, 1, &units);
+ GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, _countof(szSizeDone), units, 0, NULL);
+ mir_snwprintf(str, L"%s/%s", szSizeDone, szSizeTotal);
+ str2[0] = 0;
+ GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, _countof(str2));
+ if (mir_wstrcmp(str, str2))
+ SetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str);
+ }
+ break;
+
+ case ACKRESULT_SUCCESS:
+ case ACKRESULT_FAILED:
+ case ACKRESULT_DENIED:
+ HideProgressControls(hwndDlg);
+ KillTimer(hwndDlg, 1);
+ if (!dat->send)
+ SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
+ SetDlgItemText(hwndDlg, IDCANCEL, TranslateT("Close"));
+ if (dat->hNotifyEvent)
+ UnhookEvent(dat->hNotifyEvent);
+ dat->hNotifyEvent = nullptr;
+
+ if (ack->result == ACKRESULT_DENIED) {
+ dat->fs = nullptr; /* protocol will free structure */
+ Skin_PlaySound("FileDenied");
+ SetFtStatus(hwndDlg, LPGENW("File transfer denied"), FTS_TEXT);
+ }
+ else if (ack->result == ACKRESULT_FAILED) {
+ dat->fs = nullptr; /* protocol will free structure */
+ Skin_PlaySound("FileFailed");
+ SetFtStatus(hwndDlg, LPGENW("File transfer failed"), FTS_TEXT);
+ }
+ else {
+ Skin_PlaySound("FileDone");
+ if (dat->send) {
+ dat->fs = nullptr; /* protocol will free structure */
+ SetFtStatus(hwndDlg, LPGENW("Transfer completed."), FTS_TEXT);
+
+ DBEVENTINFO dbei = {};
+ FillSendData(dat, dbei);
+ db_event_add(dat->hContact, &dbei);
+ if (dbei.pBlob)
+ mir_free(dbei.pBlob);
+ dat->files = nullptr; //protocol library frees this
+ }
+ else {
+ SetFtStatus(hwndDlg,
+ (dat->transferStatus.totalFiles == 1) ?
+ LPGENW("Transfer completed, open file.") :
+ LPGENW("Transfer completed, open folder."),
+ FTS_OPEN);
+
+ int useScanner = g_plugin.getByte("UseScanner", VIRUSSCAN_DISABLE);
+ if (useScanner != VIRUSSCAN_DISABLE) {
+ auto *vstsi = (virusscanthreadstartinfo *)mir_alloc(sizeof(virusscanthreadstartinfo));
+ vstsi->hwndReply = hwndDlg;
+ if (useScanner == VIRUSSCAN_DURINGDL) {
+ vstsi->returnCode = dat->transferStatus.currentFileNumber;
+ if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber]) & FILE_ATTRIBUTE_DIRECTORY) {
+ PostMessage(hwndDlg, M_VIRUSSCANDONE, vstsi->returnCode, 0);
+ mir_free(vstsi);
+ vstsi = nullptr;
+ }
+ else vstsi->szFile = mir_wstrdup(dat->files[dat->transferStatus.currentFileNumber]);
+ }
+ else {
+ vstsi->szFile = mir_wstrdup(dat->transferStatus.szWorkingDir.w);
+ vstsi->returnCode = -1;
+ }
+ SetFtStatus(hwndDlg, LPGENW("Scanning for viruses..."), FTS_TEXT);
+ if (vstsi)
+ mir_forkThread<virusscanthreadstartinfo>(RunVirusScannerThread, vstsi);
+ }
+ else dat->fs = nullptr; /* protocol will free structure */
+
+ dat->transferStatus.currentFileNumber = dat->transferStatus.totalFiles;
+ }
+ }
+
+ PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg);
+ break;
+ }
+ }
+ break;
+
+ case M_VIRUSSCANDONE:
+ {
+ int done = 1;
+ if ((int)wParam == -1) {
+ for (int i = 0; i < dat->transferStatus.totalFiles; i++)
+ dat->fileVirusScanned[i] = 1;
+ }
+ else {
+ dat->fileVirusScanned[wParam] = 1;
+ for (int i = 0; i < dat->transferStatus.totalFiles; i++)
+ if (!dat->fileVirusScanned[i]) {
+ done = 0;
+ break;
+ }
+ }
+ if (done) {
+ dat->fs = nullptr; /* protocol will free structure */
+ SetFtStatus(hwndDlg, LPGENW("Transfer and virus scan complete"), FTS_TEXT);
+ }
+ }
+ break;
+
+ case WM_SIZE:
+ Utils_ResizeDialog(hwndDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_FILETRANSFERINFO), FileTransferDlgResizer, LPARAM(dat));
+
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_CONTACTNAME), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_STATUS), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
+ break;
+
+ case WM_DESTROY:
+ KillTimer(hwndDlg, 1);
+
+ HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0);
+ DeleteObject(hFont);
+
+ Button_FreeIcon_IcoLib(hwndDlg, IDC_CONTACT);
+ Button_FreeIcon_IcoLib(hwndDlg, IDC_OPENFILE);
+ Button_FreeIcon_IcoLib(hwndDlg, IDCANCEL);
+
+ delete dat;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ break;
+ }
+ return FALSE;
+}
+
+FileDlgData::~FileDlgData()
+{
+ if (fs)
+ ProtoChainSend(hContact, PSS_FILECANCEL, (WPARAM)fs, 0);
+ if (hPreshutdownEvent)
+ UnhookEvent(hPreshutdownEvent);
+ if (hNotifyEvent)
+ UnhookEvent(hNotifyEvent);
+
+ FreeProtoFileTransferStatus(&transferStatus);
+ FreeFilesMatrix(&files);
+
+ mir_free(fileVirusScanned);
+ if (hIcon)
+ DestroyIcon(hIcon);
+ if (hIconFolder)
+ DestroyIcon(hIconFolder);
+}
diff --git a/src/core/stdfile/src/ftmanager.cpp b/src/core/stdfile/src/ftmanager.cpp
index 20206908be..56b0a168a7 100644
--- a/src/core/stdfile/src/ftmanager.cpp
+++ b/src/core/stdfile/src/ftmanager.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdfile/src/main.cpp b/src/core/stdfile/src/main.cpp
index 275c58cf44..3797ea1e49 100644
--- a/src/core/stdfile/src/main.cpp
+++ b/src/core/stdfile/src/main.cpp
@@ -2,7 +2,7 @@
Standard file transfers' plugin for Miranda NG
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
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
diff --git a/src/core/stdfile/src/stdafx.h b/src/core/stdfile/src/stdafx.h
index b732c1278c..775d957d38 100644
--- a/src/core/stdfile/src/stdafx.h
+++ b/src/core/stdfile/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdfile/src/version.h b/src/core/stdfile/src/version.h
index 777678748d..2099819477 100644
--- a/src/core/stdfile/src/version.h
+++ b/src/core/stdfile/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for sending/receiving files."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdFile"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stdmsg/src/chat_manager.cpp b/src/core/stdmsg/src/chat_manager.cpp
index b72f53acd7..b461b91703 100644
--- a/src/core/stdmsg/src/chat_manager.cpp
+++ b/src/core/stdmsg/src/chat_manager.cpp
@@ -1,243 +1,243 @@
-/*
-Chat module plugin for Miranda IM
-
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-pfnDoTrayIcon oldDoTrayIcon;
-pfnDoPopup oldDoPopup;
-
-SESSION_INFO* SM_GetPrevWindow(SESSION_INFO *si)
-{
- int i = g_chatApi.arSessions.indexOf(si);
- if (i == -1)
- return nullptr;
-
- for (i--; i >= 0; i--) {
- SESSION_INFO *p = g_chatApi.arSessions[i];
- if (p->pDlg)
- return p;
- }
-
- return nullptr;
-}
-
-SESSION_INFO* SM_GetNextWindow(SESSION_INFO *si)
-{
- int i = g_chatApi.arSessions.indexOf(si);
- if (i == -1)
- return nullptr;
-
- for (i++; i < g_chatApi.arSessions.getCount(); i++) {
- SESSION_INFO *p = g_chatApi.arSessions[i];
- if (p->pDlg)
- return p;
- }
-
- return nullptr;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-HMENU g_hMenu = nullptr;
-
-GlobalLogSettings g_Settings;
-
-static MODULEINFO* MM_CreateModule()
-{
- return new MODULEINFO();
-}
-
-static void OnReplaceSession(SESSION_INFO *si)
-{
- if (si->pDlg)
- RedrawWindow(GetDlgItem(si->pDlg->GetHwnd(), IDC_SRMM_NICKLIST), nullptr, nullptr, RDW_INVALIDATE);
-}
-
-static void OnFlashHighlight(SESSION_INFO *si, int bInactive)
-{
- if (!bInactive || si->pDlg == nullptr)
- return;
-
- if (g_Settings.bTabsEnable)
- g_pTabDialog->SetMessageHighlight(si->pDlg);
- else if (Chat::bFlashWindowHighlight)
- si->pDlg->StartFlash();
-}
-
-static void OnFlashWindow(SESSION_INFO *si, int bInactive)
-{
- if (!bInactive || si->pDlg == nullptr)
- return;
-
- if (g_Settings.bTabsEnable)
- g_pTabDialog->SetTabHighlight(si->pDlg);
- else if (Chat::bFlashWindow)
- si->pDlg->StartFlash();
-}
-
-static BOOL DoTrayIcon(SESSION_INFO *si, GCEVENT *gce)
-{
- if (gce->iType & g_Settings.dwTrayIconFlags)
- return oldDoTrayIcon(si, gce);
- return TRUE;
-}
-
-static BOOL DoPopup(SESSION_INFO *si, GCEVENT *gce)
-{
- if (gce->iType & g_Settings.dwPopupFlags)
- return oldDoPopup(si, gce);
- return TRUE;
-}
-
-static void OnLoadSettings()
-{
- g_Settings.iX = db_get_dw(0, CHAT_MODULE, "roomx", -1);
- g_Settings.iY = db_get_dw(0, CHAT_MODULE, "roomy", -1);
-
- g_Settings.bTabsEnable = db_get_b(0, CHAT_MODULE, "Tabs", 1) != 0;
- g_Settings.bTabsAtBottom = db_get_b(0, CHAT_MODULE, "TabBottom", 0) != 0;
- g_Settings.bTabCloseOnDblClick = db_get_b(0, CHAT_MODULE, "TabCloseOnDblClick", 0) != 0;
- g_Settings.bAddColonToAutoComplete = db_get_b(0, CHAT_MODULE, "AddColonToAutoComplete", 1) != 0;
-
- g_Settings.iSplitterX = db_get_w(0, CHAT_MODULE, "SplitterX", 105);
- if (g_Settings.iSplitterX <= 50)
- g_Settings.iSplitterX = 105;
- g_Settings.iSplitterY = db_get_w(0, CHAT_MODULE, "SplitterY", 90);
- if (g_Settings.iSplitterY <= 65)
- g_Settings.iSplitterY = 90;
-}
-
-static void RegisterFonts()
-{
- ColourIDW colourid = {};
- strncpy(colourid.dbSettingsGroup, CHAT_MODULE, sizeof(colourid.dbSettingsGroup));
- wcsncpy(colourid.group, LPGENW("Message sessions") L"/" LPGENW("Chat module"), _countof(colourid.group));
-
- strncpy(colourid.setting, "ColorLogBG", _countof(colourid.setting));
- wcsncpy(colourid.name, LPGENW("Group chat log background"), _countof(colourid.name));
- colourid.defcolour = GetSysColor(COLOR_WINDOW);
- g_plugin.addColor(&colourid);
-
- strncpy(colourid.setting, "ColorMessageBG", _countof(colourid.setting));
- wcsncpy(colourid.name, LPGENW("Message background"), _countof(colourid.name));
- colourid.defcolour = GetSysColor(COLOR_WINDOW);
- g_plugin.addColor(&colourid);
-
- strncpy(colourid.setting, "ColorNicklistBG", _countof(colourid.setting));
- wcsncpy(colourid.name, LPGENW("Nick list background"), _countof(colourid.name));
- colourid.defcolour = GetSysColor(COLOR_WINDOW);
- g_plugin.addColor(&colourid);
-
- strncpy(colourid.setting, "ColorNicklistLines", _countof(colourid.setting));
- wcsncpy(colourid.name, LPGENW("Nick list lines"), _countof(colourid.name));
- colourid.defcolour = GetSysColor(COLOR_INACTIVEBORDER);
- g_plugin.addColor(&colourid);
-
- strncpy(colourid.setting, "ColorNicklistSelectedBG", _countof(colourid.setting));
- wcsncpy(colourid.name, LPGENW("Nick list background (selected)"), _countof(colourid.name));
- colourid.defcolour = GetSysColor(COLOR_HIGHLIGHT);
- g_plugin.addColor(&colourid);
-}
-
-static void ShowRoom(SESSION_INFO *si)
-{
- if (!si)
- return;
-
- // Do we need to create a window?
- if (si->pDlg == nullptr) {
- CTabbedWindow *pContainer = GetContainer();
- if (g_Settings.bTabsEnable) {
- pContainer->AddPage(si);
- PostMessage(pContainer->GetHwnd(), WM_SIZE, 0, 0);
- }
- else {
- CMsgDialog *pDlg = pContainer->m_pEmbed = new CMsgDialog(pContainer, si);
- pContainer->Create();
- pDlg->SetParent(pContainer->GetHwnd());
- pDlg->Create();
- pContainer->Show();
- pContainer->FixTabIcons(pDlg);
- PostMessage(pContainer->GetHwnd(), WM_SIZE, 0, 0);
- }
-
- if (si->iType != GCW_SERVER)
- si->pDlg->UpdateNickList();
- else
- si->pDlg->UpdateTitle();
- si->pDlg->UpdateStatusBar();
- }
- else if (g_Settings.bTabsEnable && g_pTabDialog)
- g_pTabDialog->m_tab.ActivatePage(g_pTabDialog->m_tab.GetDlgIndex(si->pDlg));
-
- SetWindowLongPtr(si->pDlg->GetHwnd(), GWL_EXSTYLE, GetWindowLongPtr(si->pDlg->GetHwnd(), GWL_EXSTYLE) | WS_EX_APPWINDOW);
-
- if (IsIconic(si->pDlg->GetHwnd()))
- si->pDlg->Show(SW_NORMAL);
- si->pDlg->Show(SW_SHOW);
- SetForegroundWindow(si->pDlg->GetHwnd());
-}
-
-int OnCheckPlugins(WPARAM, LPARAM)
-{
- g_plugin.bSmileyInstalled = ServiceExists(MS_SMILEYADD_REPLACESMILEYS);
- return 0;
-}
-
-void Load_ChatModule()
-{
- AddIcons();
- RegisterFonts();
-
- CHAT_MANAGER_INITDATA data = { &g_Settings, sizeof(MODULEINFO), sizeof(SESSION_INFO), LPGENW("Message sessions") L"/" LPGENW("Chat module"), FONTMODE_USE, &g_plugin };
- Chat_CustomizeApi(&data);
-
- g_chatApi.MM_CreateModule = MM_CreateModule;
- g_chatApi.OnReplaceSession = OnReplaceSession;
-
- g_chatApi.OnLoadSettings = OnLoadSettings;
- g_chatApi.OnFlashWindow = OnFlashWindow;
- g_chatApi.OnFlashHighlight = OnFlashHighlight;
- g_chatApi.ShowRoom = ShowRoom;
-
- Srmm_CreateHotkey(LPGEN("Messaging"), LPGEN("Send message"));
-
- oldDoPopup = g_chatApi.DoPopup; g_chatApi.DoPopup = DoPopup;
- oldDoTrayIcon = g_chatApi.DoTrayIcon; g_chatApi.DoTrayIcon = DoTrayIcon;
- g_chatApi.ReloadSettings();
-
- g_hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_MENU));
-
- HookEvent(ME_SYSTEM_MODULELOAD, OnCheckPlugins);
-}
-
-void Unload_ChatModule()
-{
- db_set_w(0, CHAT_MODULE, "SplitterX", (uint16_t)g_Settings.iSplitterX);
- db_set_w(0, CHAT_MODULE, "SplitterY", (uint16_t)g_Settings.iSplitterY);
- db_set_dw(0, CHAT_MODULE, "roomx", g_Settings.iX);
- db_set_dw(0, CHAT_MODULE, "roomy", g_Settings.iY);
- db_set_dw(0, CHAT_MODULE, "roomwidth", g_Settings.iWidth);
- db_set_dw(0, CHAT_MODULE, "roomheight", g_Settings.iHeight);
-
- DestroyMenu(g_hMenu);
-}
+/*
+Chat module plugin for Miranda IM
+
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+pfnDoTrayIcon oldDoTrayIcon;
+pfnDoPopup oldDoPopup;
+
+SESSION_INFO* SM_GetPrevWindow(SESSION_INFO *si)
+{
+ int i = g_chatApi.arSessions.indexOf(si);
+ if (i == -1)
+ return nullptr;
+
+ for (i--; i >= 0; i--) {
+ SESSION_INFO *p = g_chatApi.arSessions[i];
+ if (p->pDlg)
+ return p;
+ }
+
+ return nullptr;
+}
+
+SESSION_INFO* SM_GetNextWindow(SESSION_INFO *si)
+{
+ int i = g_chatApi.arSessions.indexOf(si);
+ if (i == -1)
+ return nullptr;
+
+ for (i++; i < g_chatApi.arSessions.getCount(); i++) {
+ SESSION_INFO *p = g_chatApi.arSessions[i];
+ if (p->pDlg)
+ return p;
+ }
+
+ return nullptr;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+HMENU g_hMenu = nullptr;
+
+GlobalLogSettings g_Settings;
+
+static MODULEINFO* MM_CreateModule()
+{
+ return new MODULEINFO();
+}
+
+static void OnReplaceSession(SESSION_INFO *si)
+{
+ if (si->pDlg)
+ RedrawWindow(GetDlgItem(si->pDlg->GetHwnd(), IDC_SRMM_NICKLIST), nullptr, nullptr, RDW_INVALIDATE);
+}
+
+static void OnFlashHighlight(SESSION_INFO *si, int bInactive)
+{
+ if (!bInactive || si->pDlg == nullptr)
+ return;
+
+ if (g_Settings.bTabsEnable)
+ g_pTabDialog->SetMessageHighlight(si->pDlg);
+ else if (Chat::bFlashWindowHighlight)
+ si->pDlg->StartFlash();
+}
+
+static void OnFlashWindow(SESSION_INFO *si, int bInactive)
+{
+ if (!bInactive || si->pDlg == nullptr)
+ return;
+
+ if (g_Settings.bTabsEnable)
+ g_pTabDialog->SetTabHighlight(si->pDlg);
+ else if (Chat::bFlashWindow)
+ si->pDlg->StartFlash();
+}
+
+static BOOL DoTrayIcon(SESSION_INFO *si, GCEVENT *gce)
+{
+ if (gce->iType & g_Settings.dwTrayIconFlags)
+ return oldDoTrayIcon(si, gce);
+ return TRUE;
+}
+
+static BOOL DoPopup(SESSION_INFO *si, GCEVENT *gce)
+{
+ if (gce->iType & g_Settings.dwPopupFlags)
+ return oldDoPopup(si, gce);
+ return TRUE;
+}
+
+static void OnLoadSettings()
+{
+ g_Settings.iX = db_get_dw(0, CHAT_MODULE, "roomx", -1);
+ g_Settings.iY = db_get_dw(0, CHAT_MODULE, "roomy", -1);
+
+ g_Settings.bTabsEnable = db_get_b(0, CHAT_MODULE, "Tabs", 1) != 0;
+ g_Settings.bTabsAtBottom = db_get_b(0, CHAT_MODULE, "TabBottom", 0) != 0;
+ g_Settings.bTabCloseOnDblClick = db_get_b(0, CHAT_MODULE, "TabCloseOnDblClick", 0) != 0;
+ g_Settings.bAddColonToAutoComplete = db_get_b(0, CHAT_MODULE, "AddColonToAutoComplete", 1) != 0;
+
+ g_Settings.iSplitterX = db_get_w(0, CHAT_MODULE, "SplitterX", 105);
+ if (g_Settings.iSplitterX <= 50)
+ g_Settings.iSplitterX = 105;
+ g_Settings.iSplitterY = db_get_w(0, CHAT_MODULE, "SplitterY", 90);
+ if (g_Settings.iSplitterY <= 65)
+ g_Settings.iSplitterY = 90;
+}
+
+static void RegisterFonts()
+{
+ ColourIDW colourid = {};
+ strncpy(colourid.dbSettingsGroup, CHAT_MODULE, sizeof(colourid.dbSettingsGroup));
+ wcsncpy(colourid.group, LPGENW("Message sessions") L"/" LPGENW("Chat module"), _countof(colourid.group));
+
+ strncpy(colourid.setting, "ColorLogBG", _countof(colourid.setting));
+ wcsncpy(colourid.name, LPGENW("Group chat log background"), _countof(colourid.name));
+ colourid.defcolour = GetSysColor(COLOR_WINDOW);
+ g_plugin.addColor(&colourid);
+
+ strncpy(colourid.setting, "ColorMessageBG", _countof(colourid.setting));
+ wcsncpy(colourid.name, LPGENW("Message background"), _countof(colourid.name));
+ colourid.defcolour = GetSysColor(COLOR_WINDOW);
+ g_plugin.addColor(&colourid);
+
+ strncpy(colourid.setting, "ColorNicklistBG", _countof(colourid.setting));
+ wcsncpy(colourid.name, LPGENW("Nick list background"), _countof(colourid.name));
+ colourid.defcolour = GetSysColor(COLOR_WINDOW);
+ g_plugin.addColor(&colourid);
+
+ strncpy(colourid.setting, "ColorNicklistLines", _countof(colourid.setting));
+ wcsncpy(colourid.name, LPGENW("Nick list lines"), _countof(colourid.name));
+ colourid.defcolour = GetSysColor(COLOR_INACTIVEBORDER);
+ g_plugin.addColor(&colourid);
+
+ strncpy(colourid.setting, "ColorNicklistSelectedBG", _countof(colourid.setting));
+ wcsncpy(colourid.name, LPGENW("Nick list background (selected)"), _countof(colourid.name));
+ colourid.defcolour = GetSysColor(COLOR_HIGHLIGHT);
+ g_plugin.addColor(&colourid);
+}
+
+static void ShowRoom(SESSION_INFO *si)
+{
+ if (!si)
+ return;
+
+ // Do we need to create a window?
+ if (si->pDlg == nullptr) {
+ CTabbedWindow *pContainer = GetContainer();
+ if (g_Settings.bTabsEnable) {
+ pContainer->AddPage(si);
+ PostMessage(pContainer->GetHwnd(), WM_SIZE, 0, 0);
+ }
+ else {
+ CMsgDialog *pDlg = pContainer->m_pEmbed = new CMsgDialog(pContainer, si);
+ pContainer->Create();
+ pDlg->SetParent(pContainer->GetHwnd());
+ pDlg->Create();
+ pContainer->Show();
+ pContainer->FixTabIcons(pDlg);
+ PostMessage(pContainer->GetHwnd(), WM_SIZE, 0, 0);
+ }
+
+ if (si->iType != GCW_SERVER)
+ si->pDlg->UpdateNickList();
+ else
+ si->pDlg->UpdateTitle();
+ si->pDlg->UpdateStatusBar();
+ }
+ else if (g_Settings.bTabsEnable && g_pTabDialog)
+ g_pTabDialog->m_tab.ActivatePage(g_pTabDialog->m_tab.GetDlgIndex(si->pDlg));
+
+ SetWindowLongPtr(si->pDlg->GetHwnd(), GWL_EXSTYLE, GetWindowLongPtr(si->pDlg->GetHwnd(), GWL_EXSTYLE) | WS_EX_APPWINDOW);
+
+ if (IsIconic(si->pDlg->GetHwnd()))
+ si->pDlg->Show(SW_NORMAL);
+ si->pDlg->Show(SW_SHOW);
+ SetForegroundWindow(si->pDlg->GetHwnd());
+}
+
+int OnCheckPlugins(WPARAM, LPARAM)
+{
+ g_plugin.bSmileyInstalled = ServiceExists(MS_SMILEYADD_REPLACESMILEYS);
+ return 0;
+}
+
+void Load_ChatModule()
+{
+ AddIcons();
+ RegisterFonts();
+
+ CHAT_MANAGER_INITDATA data = { &g_Settings, sizeof(MODULEINFO), sizeof(SESSION_INFO), LPGENW("Message sessions") L"/" LPGENW("Chat module"), FONTMODE_USE, &g_plugin };
+ Chat_CustomizeApi(&data);
+
+ g_chatApi.MM_CreateModule = MM_CreateModule;
+ g_chatApi.OnReplaceSession = OnReplaceSession;
+
+ g_chatApi.OnLoadSettings = OnLoadSettings;
+ g_chatApi.OnFlashWindow = OnFlashWindow;
+ g_chatApi.OnFlashHighlight = OnFlashHighlight;
+ g_chatApi.ShowRoom = ShowRoom;
+
+ Srmm_CreateHotkey(LPGEN("Messaging"), LPGEN("Send message"));
+
+ oldDoPopup = g_chatApi.DoPopup; g_chatApi.DoPopup = DoPopup;
+ oldDoTrayIcon = g_chatApi.DoTrayIcon; g_chatApi.DoTrayIcon = DoTrayIcon;
+ g_chatApi.ReloadSettings();
+
+ g_hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_MENU));
+
+ HookEvent(ME_SYSTEM_MODULELOAD, OnCheckPlugins);
+}
+
+void Unload_ChatModule()
+{
+ db_set_w(0, CHAT_MODULE, "SplitterX", (uint16_t)g_Settings.iSplitterX);
+ db_set_w(0, CHAT_MODULE, "SplitterY", (uint16_t)g_Settings.iSplitterY);
+ db_set_dw(0, CHAT_MODULE, "roomx", g_Settings.iX);
+ db_set_dw(0, CHAT_MODULE, "roomy", g_Settings.iY);
+ db_set_dw(0, CHAT_MODULE, "roomwidth", g_Settings.iWidth);
+ db_set_dw(0, CHAT_MODULE, "roomheight", g_Settings.iHeight);
+
+ DestroyMenu(g_hMenu);
+}
diff --git a/src/core/stdmsg/src/chat_window.cpp b/src/core/stdmsg/src/chat_window.cpp
index 52106ae755..8e1871dd4c 100644
--- a/src/core/stdmsg/src/chat_window.cpp
+++ b/src/core/stdmsg/src/chat_window.cpp
@@ -1,275 +1,275 @@
-/*
-Chat module plugin for Miranda IM
-
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CMsgDialog::LoadSettings()
-{
- m_clrInputBG = db_get_dw(0, CHAT_MODULE, "ColorMessageBG", GetSysColor(COLOR_WINDOW));
- LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, nullptr, &m_clrInputFG);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CMsgDialog::ShowFilterMenu()
-{
- HWND hwnd = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILTER), m_hwnd, FilterWndProc, (LPARAM)this);
- TranslateDialogDefault(hwnd);
-
- RECT rc;
- GetWindowRect(m_btnFilter.GetHwnd(), &rc);
- SetWindowPos(hwnd, HWND_TOP, rc.left - 85, (IsWindowVisible(m_btnFilter.GetHwnd()) || IsWindowVisible(m_btnBold.GetHwnd())) ? rc.top - 206 : rc.top - 186, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
-}
-
-void CMsgDialog::UpdateNickList()
-{
- int i = m_nickList.SendMsg(LB_GETTOPINDEX, 0, 0);
- m_nickList.SendMsg(LB_SETCOUNT, m_si->getUserList().getCount(), 0);
- m_nickList.SendMsg(LB_SETTOPINDEX, i, 0);
-
- UpdateTitle();
-}
-
-void CMsgDialog::UpdateOptions()
-{
- m_btnNickList.SendMsg(BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_plugin.getIcon(m_bNicklistEnabled ? IDI_NICKLIST2 : IDI_NICKLIST, FALSE));
- m_btnFilter.SendMsg(BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_plugin.getIcon(m_bFilterEnabled ? IDI_FILTER2 : IDI_FILTER, FALSE));
-
- HICON hIcon = ImageList_GetIcon(Clist_GetImageList(), GetImageId(), ILD_TRANSPARENT);
- SendMessage(m_pOwner->m_hwndStatus, SB_SETICON, 0, (LPARAM)hIcon);
- DestroyIcon(hIcon);
-
- Window_SetIcon_IcoLib(m_pOwner->GetHwnd(), g_plugin.getIconHandle(IDI_CHANMGR));
-
- m_pLog->UpdateOptions();
-
- // nicklist
- int ih = Chat_GetTextPixelSize(L"AQGglo", g_Settings.UserListFont, FALSE);
- int ih2 = Chat_GetTextPixelSize(L"AQGglo", g_Settings.UserListHeadingsFont, FALSE);
- int height = db_get_b(0, CHAT_MODULE, "NicklistRowDist", 12);
- int font = ih > ih2 ? ih : ih2;
-
- // make sure we have space for icon!
- if (g_Settings.bShowContactStatus)
- font = font > 16 ? font : 16;
-
- m_nickList.SendMsg(LB_SETITEMHEIGHT, 0, height > font ? height : font);
- InvalidateRect(m_nickList.GetHwnd(), nullptr, TRUE);
-
- CSuper::UpdateOptions();
-}
-
-void CMsgDialog::UpdateStatusBar()
-{
- wchar_t *ptszDispName = m_si->pMI->ptszModDispName;
- int x = 12;
- x += Chat_GetTextPixelSize(ptszDispName, (HFONT)SendMessage(m_pOwner->m_hwndStatus, WM_GETFONT, 0, 0), TRUE);
- x += GetSystemMetrics(SM_CXSMICON);
- int iStatusbarParts[2] = { x, -1 };
- SendMessage(m_pOwner->m_hwndStatus, SB_SETPARTS, 2, (LPARAM)&iStatusbarParts);
-
- HICON hIcon = ImageList_GetIcon(Clist_GetImageList(), GetImageId(), ILD_TRANSPARENT);
- SendMessage(m_pOwner->m_hwndStatus, SB_SETICON, 0, (LPARAM)hIcon);
- DestroyIcon(hIcon);
-
- SendMessage(m_pOwner->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)ptszDispName);
- SendMessage(m_pOwner->m_hwndStatus, SB_SETTEXT, 1, (LPARAM)(m_si->ptszStatusbarText ? m_si->ptszStatusbarText : L""));
- SendMessage(m_pOwner->m_hwndStatus, SB_SETTIPTEXT, 1, (LPARAM)(m_si->ptszStatusbarText ? m_si->ptszStatusbarText : L""));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw)
-{
- auto *si = m_pDlg.m_si;
- if (lin == nullptr || si == nullptr)
- return;
-
- if (!bRedraw && si->iType == GCW_CHATROOM && m_pDlg.m_bFilterEnabled && (m_pDlg.m_iLogFilterFlags & lin->iType) == 0)
- return;
-
- LOGSTREAMDATA streamData;
- memset(&streamData, 0, sizeof(streamData));
- streamData.hwnd = m_rtf.GetHwnd();
- streamData.si = si;
- streamData.lin = lin;
- streamData.bStripFormat = FALSE;
-
- bool bFlag = false;
-
- EDITSTREAM stream = {};
- stream.pfnCallback = Srmm_LogStreamCallback;
- stream.dwCookie = (DWORD_PTR)& streamData;
-
- SCROLLINFO scroll;
- scroll.cbSize = sizeof(SCROLLINFO);
- scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
- GetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &scroll);
-
- POINT point = {};
- m_rtf.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&point);
-
- // do not scroll to bottom if there is a selection
- CHARRANGE oldsel, sel;
- m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldsel);
- if (oldsel.cpMax != oldsel.cpMin)
- m_rtf.SetDraw(false);
-
- //set the insertion point at the bottom
- sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
-
- // fix for the indent... must be a M$ bug
- if (sel.cpMax == 0)
- bRedraw = TRUE;
-
- // should the event(s) be appended to the current log
- WPARAM wp = bRedraw ? SF_RTF : SFF_SELECTION | SF_RTF;
-
- //get the number of pixels per logical inch
- if (bRedraw) {
- HDC hdc = GetDC(nullptr);
- g_chatApi.logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
- g_chatApi.logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
- ReleaseDC(nullptr, hdc);
- m_rtf.SetDraw(false);
- bFlag = true;
- }
-
- // stream in the event(s)
- streamData.lin = lin;
- streamData.bRedraw = bRedraw;
- m_rtf.SendMsg(EM_STREAMIN, wp, (LPARAM)&stream);
-
- // do smileys
- if (g_plugin.bSmileyInstalled && (bRedraw || (lin->ptszText && lin->iType != GC_EVENT_JOIN && lin->iType != GC_EVENT_NICK && lin->iType != GC_EVENT_ADDSTATUS && lin->iType != GC_EVENT_REMOVESTATUS))) {
- CHARRANGE newsel;
- newsel.cpMax = -1;
- newsel.cpMin = sel.cpMin;
- if (newsel.cpMin < 0)
- newsel.cpMin = 0;
-
- SMADD_RICHEDIT3 sm = {};
- sm.cbSize = sizeof(sm);
- sm.hwndRichEditControl = m_rtf.GetHwnd();
- sm.Protocolname = si->pszModule;
- sm.rangeToReplace = bRedraw ? nullptr : &newsel;
- sm.disableRedraw = TRUE;
- sm.hContact = si->hContact;
- CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm);
- }
-
- // scroll log to bottom if the log was previously scrolled to bottom, else restore old position
- if (bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax - scroll.nPage - 5 || scroll.nMax - scroll.nMin - scroll.nPage < 50)
- ScrollToBottom();
- else
- m_rtf.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&point);
-
- // do we need to restore the selection
- if (oldsel.cpMax != oldsel.cpMin) {
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldsel);
- m_rtf.SetDraw(true);
- InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
- }
-
- // need to invalidate the window
- if (bFlag) {
- sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
- m_rtf.SetDraw(true);
- InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-INT_PTR CALLBACK CMsgDialog::FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- static CMsgDialog *pDlg = nullptr;
- switch (uMsg) {
- case WM_INITDIALOG:
- pDlg = (CMsgDialog*)lParam;
- CheckDlgButton(hwndDlg, IDC_1, pDlg->m_iLogFilterFlags & GC_EVENT_ACTION ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_2, pDlg->m_iLogFilterFlags & GC_EVENT_MESSAGE ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_3, pDlg->m_iLogFilterFlags & GC_EVENT_NICK ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_4, pDlg->m_iLogFilterFlags & GC_EVENT_JOIN ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_5, pDlg->m_iLogFilterFlags & GC_EVENT_PART ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_6, pDlg->m_iLogFilterFlags & GC_EVENT_TOPIC ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_7, pDlg->m_iLogFilterFlags & GC_EVENT_ADDSTATUS ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_8, pDlg->m_iLogFilterFlags & GC_EVENT_INFORMATION ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_9, pDlg->m_iLogFilterFlags & GC_EVENT_QUIT ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_10, pDlg->m_iLogFilterFlags & GC_EVENT_KICK ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_11, pDlg->m_iLogFilterFlags & GC_EVENT_NOTICE ? BST_CHECKED : BST_UNCHECKED);
- break;
-
- case WM_CTLCOLOREDIT:
- case WM_CTLCOLORSTATIC:
- SetTextColor((HDC)wParam, RGB(60, 60, 150));
- SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
- return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
-
- case WM_ACTIVATE:
- if (LOWORD(wParam) == WA_INACTIVE) {
- int iFlags = 0;
-
- if (IsDlgButtonChecked(hwndDlg, IDC_1) == BST_CHECKED)
- iFlags |= GC_EVENT_ACTION;
- if (IsDlgButtonChecked(hwndDlg, IDC_2) == BST_CHECKED)
- iFlags |= GC_EVENT_MESSAGE;
- if (IsDlgButtonChecked(hwndDlg, IDC_3) == BST_CHECKED)
- iFlags |= GC_EVENT_NICK;
- if (IsDlgButtonChecked(hwndDlg, IDC_4) == BST_CHECKED)
- iFlags |= GC_EVENT_JOIN;
- if (IsDlgButtonChecked(hwndDlg, IDC_5) == BST_CHECKED)
- iFlags |= GC_EVENT_PART;
- if (IsDlgButtonChecked(hwndDlg, IDC_6) == BST_CHECKED)
- iFlags |= GC_EVENT_TOPIC;
- if (IsDlgButtonChecked(hwndDlg, IDC_7) == BST_CHECKED)
- iFlags |= GC_EVENT_ADDSTATUS;
- if (IsDlgButtonChecked(hwndDlg, IDC_8) == BST_CHECKED)
- iFlags |= GC_EVENT_INFORMATION;
- if (IsDlgButtonChecked(hwndDlg, IDC_9) == BST_CHECKED)
- iFlags |= GC_EVENT_QUIT;
- if (IsDlgButtonChecked(hwndDlg, IDC_10) == BST_CHECKED)
- iFlags |= GC_EVENT_KICK;
- if (IsDlgButtonChecked(hwndDlg, IDC_11) == BST_CHECKED)
- iFlags |= GC_EVENT_NOTICE;
-
- if (iFlags & GC_EVENT_ADDSTATUS)
- iFlags |= GC_EVENT_REMOVESTATUS;
-
- pDlg->m_iLogFilterFlags = iFlags;
- if (pDlg->m_bFilterEnabled)
- pDlg->RedrawLog();
- PostMessage(hwndDlg, WM_CLOSE, 0, 0);
- }
- break;
-
- case WM_CLOSE:
- DestroyWindow(hwndDlg);
- break;
- }
-
- return FALSE;
-}
+/*
+Chat module plugin for Miranda IM
+
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CMsgDialog::LoadSettings()
+{
+ m_clrInputBG = db_get_dw(0, CHAT_MODULE, "ColorMessageBG", GetSysColor(COLOR_WINDOW));
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, nullptr, &m_clrInputFG);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CMsgDialog::ShowFilterMenu()
+{
+ HWND hwnd = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILTER), m_hwnd, FilterWndProc, (LPARAM)this);
+ TranslateDialogDefault(hwnd);
+
+ RECT rc;
+ GetWindowRect(m_btnFilter.GetHwnd(), &rc);
+ SetWindowPos(hwnd, HWND_TOP, rc.left - 85, (IsWindowVisible(m_btnFilter.GetHwnd()) || IsWindowVisible(m_btnBold.GetHwnd())) ? rc.top - 206 : rc.top - 186, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
+}
+
+void CMsgDialog::UpdateNickList()
+{
+ int i = m_nickList.SendMsg(LB_GETTOPINDEX, 0, 0);
+ m_nickList.SendMsg(LB_SETCOUNT, m_si->getUserList().getCount(), 0);
+ m_nickList.SendMsg(LB_SETTOPINDEX, i, 0);
+
+ UpdateTitle();
+}
+
+void CMsgDialog::UpdateOptions()
+{
+ m_btnNickList.SendMsg(BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_plugin.getIcon(m_bNicklistEnabled ? IDI_NICKLIST2 : IDI_NICKLIST, FALSE));
+ m_btnFilter.SendMsg(BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_plugin.getIcon(m_bFilterEnabled ? IDI_FILTER2 : IDI_FILTER, FALSE));
+
+ HICON hIcon = ImageList_GetIcon(Clist_GetImageList(), GetImageId(), ILD_TRANSPARENT);
+ SendMessage(m_pOwner->m_hwndStatus, SB_SETICON, 0, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ Window_SetIcon_IcoLib(m_pOwner->GetHwnd(), g_plugin.getIconHandle(IDI_CHANMGR));
+
+ m_pLog->UpdateOptions();
+
+ // nicklist
+ int ih = Chat_GetTextPixelSize(L"AQGglo", g_Settings.UserListFont, FALSE);
+ int ih2 = Chat_GetTextPixelSize(L"AQGglo", g_Settings.UserListHeadingsFont, FALSE);
+ int height = db_get_b(0, CHAT_MODULE, "NicklistRowDist", 12);
+ int font = ih > ih2 ? ih : ih2;
+
+ // make sure we have space for icon!
+ if (g_Settings.bShowContactStatus)
+ font = font > 16 ? font : 16;
+
+ m_nickList.SendMsg(LB_SETITEMHEIGHT, 0, height > font ? height : font);
+ InvalidateRect(m_nickList.GetHwnd(), nullptr, TRUE);
+
+ CSuper::UpdateOptions();
+}
+
+void CMsgDialog::UpdateStatusBar()
+{
+ wchar_t *ptszDispName = m_si->pMI->ptszModDispName;
+ int x = 12;
+ x += Chat_GetTextPixelSize(ptszDispName, (HFONT)SendMessage(m_pOwner->m_hwndStatus, WM_GETFONT, 0, 0), TRUE);
+ x += GetSystemMetrics(SM_CXSMICON);
+ int iStatusbarParts[2] = { x, -1 };
+ SendMessage(m_pOwner->m_hwndStatus, SB_SETPARTS, 2, (LPARAM)&iStatusbarParts);
+
+ HICON hIcon = ImageList_GetIcon(Clist_GetImageList(), GetImageId(), ILD_TRANSPARENT);
+ SendMessage(m_pOwner->m_hwndStatus, SB_SETICON, 0, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ SendMessage(m_pOwner->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)ptszDispName);
+ SendMessage(m_pOwner->m_hwndStatus, SB_SETTEXT, 1, (LPARAM)(m_si->ptszStatusbarText ? m_si->ptszStatusbarText : L""));
+ SendMessage(m_pOwner->m_hwndStatus, SB_SETTIPTEXT, 1, (LPARAM)(m_si->ptszStatusbarText ? m_si->ptszStatusbarText : L""));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw)
+{
+ auto *si = m_pDlg.m_si;
+ if (lin == nullptr || si == nullptr)
+ return;
+
+ if (!bRedraw && si->iType == GCW_CHATROOM && m_pDlg.m_bFilterEnabled && (m_pDlg.m_iLogFilterFlags & lin->iType) == 0)
+ return;
+
+ LOGSTREAMDATA streamData;
+ memset(&streamData, 0, sizeof(streamData));
+ streamData.hwnd = m_rtf.GetHwnd();
+ streamData.si = si;
+ streamData.lin = lin;
+ streamData.bStripFormat = FALSE;
+
+ bool bFlag = false;
+
+ EDITSTREAM stream = {};
+ stream.pfnCallback = Srmm_LogStreamCallback;
+ stream.dwCookie = (DWORD_PTR)& streamData;
+
+ SCROLLINFO scroll;
+ scroll.cbSize = sizeof(SCROLLINFO);
+ scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ GetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &scroll);
+
+ POINT point = {};
+ m_rtf.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&point);
+
+ // do not scroll to bottom if there is a selection
+ CHARRANGE oldsel, sel;
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldsel);
+ if (oldsel.cpMax != oldsel.cpMin)
+ m_rtf.SetDraw(false);
+
+ //set the insertion point at the bottom
+ sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+
+ // fix for the indent... must be a M$ bug
+ if (sel.cpMax == 0)
+ bRedraw = TRUE;
+
+ // should the event(s) be appended to the current log
+ WPARAM wp = bRedraw ? SF_RTF : SFF_SELECTION | SF_RTF;
+
+ //get the number of pixels per logical inch
+ if (bRedraw) {
+ HDC hdc = GetDC(nullptr);
+ g_chatApi.logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ g_chatApi.logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
+ ReleaseDC(nullptr, hdc);
+ m_rtf.SetDraw(false);
+ bFlag = true;
+ }
+
+ // stream in the event(s)
+ streamData.lin = lin;
+ streamData.bRedraw = bRedraw;
+ m_rtf.SendMsg(EM_STREAMIN, wp, (LPARAM)&stream);
+
+ // do smileys
+ if (g_plugin.bSmileyInstalled && (bRedraw || (lin->ptszText && lin->iType != GC_EVENT_JOIN && lin->iType != GC_EVENT_NICK && lin->iType != GC_EVENT_ADDSTATUS && lin->iType != GC_EVENT_REMOVESTATUS))) {
+ CHARRANGE newsel;
+ newsel.cpMax = -1;
+ newsel.cpMin = sel.cpMin;
+ if (newsel.cpMin < 0)
+ newsel.cpMin = 0;
+
+ SMADD_RICHEDIT3 sm = {};
+ sm.cbSize = sizeof(sm);
+ sm.hwndRichEditControl = m_rtf.GetHwnd();
+ sm.Protocolname = si->pszModule;
+ sm.rangeToReplace = bRedraw ? nullptr : &newsel;
+ sm.disableRedraw = TRUE;
+ sm.hContact = si->hContact;
+ CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm);
+ }
+
+ // scroll log to bottom if the log was previously scrolled to bottom, else restore old position
+ if (bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax - scroll.nPage - 5 || scroll.nMax - scroll.nMin - scroll.nPage < 50)
+ ScrollToBottom();
+ else
+ m_rtf.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&point);
+
+ // do we need to restore the selection
+ if (oldsel.cpMax != oldsel.cpMin) {
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldsel);
+ m_rtf.SetDraw(true);
+ InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
+ }
+
+ // need to invalidate the window
+ if (bFlag) {
+ sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ m_rtf.SetDraw(true);
+ InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR CALLBACK CMsgDialog::FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static CMsgDialog *pDlg = nullptr;
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ pDlg = (CMsgDialog*)lParam;
+ CheckDlgButton(hwndDlg, IDC_1, pDlg->m_iLogFilterFlags & GC_EVENT_ACTION ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_2, pDlg->m_iLogFilterFlags & GC_EVENT_MESSAGE ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_3, pDlg->m_iLogFilterFlags & GC_EVENT_NICK ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_4, pDlg->m_iLogFilterFlags & GC_EVENT_JOIN ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_5, pDlg->m_iLogFilterFlags & GC_EVENT_PART ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_6, pDlg->m_iLogFilterFlags & GC_EVENT_TOPIC ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_7, pDlg->m_iLogFilterFlags & GC_EVENT_ADDSTATUS ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_8, pDlg->m_iLogFilterFlags & GC_EVENT_INFORMATION ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_9, pDlg->m_iLogFilterFlags & GC_EVENT_QUIT ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_10, pDlg->m_iLogFilterFlags & GC_EVENT_KICK ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_11, pDlg->m_iLogFilterFlags & GC_EVENT_NOTICE ? BST_CHECKED : BST_UNCHECKED);
+ break;
+
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ SetTextColor((HDC)wParam, RGB(60, 60, 150));
+ SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
+ return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_INACTIVE) {
+ int iFlags = 0;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_1) == BST_CHECKED)
+ iFlags |= GC_EVENT_ACTION;
+ if (IsDlgButtonChecked(hwndDlg, IDC_2) == BST_CHECKED)
+ iFlags |= GC_EVENT_MESSAGE;
+ if (IsDlgButtonChecked(hwndDlg, IDC_3) == BST_CHECKED)
+ iFlags |= GC_EVENT_NICK;
+ if (IsDlgButtonChecked(hwndDlg, IDC_4) == BST_CHECKED)
+ iFlags |= GC_EVENT_JOIN;
+ if (IsDlgButtonChecked(hwndDlg, IDC_5) == BST_CHECKED)
+ iFlags |= GC_EVENT_PART;
+ if (IsDlgButtonChecked(hwndDlg, IDC_6) == BST_CHECKED)
+ iFlags |= GC_EVENT_TOPIC;
+ if (IsDlgButtonChecked(hwndDlg, IDC_7) == BST_CHECKED)
+ iFlags |= GC_EVENT_ADDSTATUS;
+ if (IsDlgButtonChecked(hwndDlg, IDC_8) == BST_CHECKED)
+ iFlags |= GC_EVENT_INFORMATION;
+ if (IsDlgButtonChecked(hwndDlg, IDC_9) == BST_CHECKED)
+ iFlags |= GC_EVENT_QUIT;
+ if (IsDlgButtonChecked(hwndDlg, IDC_10) == BST_CHECKED)
+ iFlags |= GC_EVENT_KICK;
+ if (IsDlgButtonChecked(hwndDlg, IDC_11) == BST_CHECKED)
+ iFlags |= GC_EVENT_NOTICE;
+
+ if (iFlags & GC_EVENT_ADDSTATUS)
+ iFlags |= GC_EVENT_REMOVESTATUS;
+
+ pDlg->m_iLogFilterFlags = iFlags;
+ if (pDlg->m_bFilterEnabled)
+ pDlg->RedrawLog();
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/src/core/stdmsg/src/cmdlist.cpp b/src/core/stdmsg/src/cmdlist.cpp
index beb669dcf5..1ace5b0545 100644
--- a/src/core/stdmsg/src/cmdlist.cpp
+++ b/src/core/stdmsg/src/cmdlist.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/cmdlist.h b/src/core/stdmsg/src/cmdlist.h
index bbe8c9b11b..fda5562689 100644
--- a/src/core/stdmsg/src/cmdlist.h
+++ b/src/core/stdmsg/src/cmdlist.h
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/globals.cpp b/src/core/stdmsg/src/globals.cpp
index de2ca11c6d..5d2b95cc46 100644
--- a/src/core/stdmsg/src/globals.cpp
+++ b/src/core/stdmsg/src/globals.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp
index 8e0c4ff3ed..359b308022 100644
--- a/src/core/stdmsg/src/msgdialog.cpp
+++ b/src/core/stdmsg/src/msgdialog.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/msglog.cpp b/src/core/stdmsg/src/msglog.cpp
index 8fb1f5edbd..791cd1b71e 100644
--- a/src/core/stdmsg/src/msglog.cpp
+++ b/src/core/stdmsg/src/msglog.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/msgoptions.cpp b/src/core/stdmsg/src/msgoptions.cpp
index 590afa2478..34dc8e044f 100644
--- a/src/core/stdmsg/src/msgoptions.cpp
+++ b/src/core/stdmsg/src/msgoptions.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/msgs.cpp b/src/core/stdmsg/src/msgs.cpp
index 95b209fd02..9f5be7be28 100644
--- a/src/core/stdmsg/src/msgs.cpp
+++ b/src/core/stdmsg/src/msgs.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/msgs.h b/src/core/stdmsg/src/msgs.h
index f21110e641..0e9f38dead 100644
--- a/src/core/stdmsg/src/msgs.h
+++ b/src/core/stdmsg/src/msgs.h
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/msgtimedout.cpp b/src/core/stdmsg/src/msgtimedout.cpp
index 19744fe695..828924580e 100644
--- a/src/core/stdmsg/src/msgtimedout.cpp
+++ b/src/core/stdmsg/src/msgtimedout.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/srmm.cpp b/src/core/stdmsg/src/srmm.cpp
index 69c350aad7..4485d40bb3 100644
--- a/src/core/stdmsg/src/srmm.cpp
+++ b/src/core/stdmsg/src/srmm.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/statusicon.cpp b/src/core/stdmsg/src/statusicon.cpp
index 4244f9037c..6255dc3e1e 100644
--- a/src/core/stdmsg/src/statusicon.cpp
+++ b/src/core/stdmsg/src/statusicon.cpp
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/stdafx.cxx b/src/core/stdmsg/src/stdafx.cxx
index 52ec2d6817..e23069a5b8 100644
--- a/src/core/stdmsg/src/stdafx.cxx
+++ b/src/core/stdmsg/src/stdafx.cxx
@@ -1,6 +1,6 @@
/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
diff --git a/src/core/stdmsg/src/stdafx.h b/src/core/stdmsg/src/stdafx.h
index a42feafac9..33d557a6a9 100644
--- a/src/core/stdmsg/src/stdafx.h
+++ b/src/core/stdmsg/src/stdafx.h
@@ -1,6 +1,6 @@
/*
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stdmsg/src/tabs.cpp b/src/core/stdmsg/src/tabs.cpp
index d60bec7634..402d1f2f0f 100644
--- a/src/core/stdmsg/src/tabs.cpp
+++ b/src/core/stdmsg/src/tabs.cpp
@@ -1,668 +1,668 @@
-/*
-
-Copyright 2000-12 Miranda IM, 2012-22 Miranda NG team,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-#include "statusicon.h"
-
-CTabbedWindow *g_pTabDialog = nullptr;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-CTabbedWindow* GetContainer()
-{
- if (g_Settings.bTabsEnable) {
- if (g_pTabDialog == nullptr) {
- g_pTabDialog = new CTabbedWindow();
- g_pTabDialog->Show();
- }
- return g_pTabDialog;
- }
-
- return new CTabbedWindow();
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static LRESULT CALLBACK TabSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CTabbedWindow *pOwner = (CTabbedWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
- TCHITTESTINFO tci = {};
-
- static bool bDragging = false;
- static int iBeginIndex = 0;
- switch (msg) {
- case WM_LBUTTONDOWN:
- tci.pt.x = (short)LOWORD(GetMessagePos());
- tci.pt.y = (short)HIWORD(GetMessagePos());
- if (DragDetect(hwnd, tci.pt) && TabCtrl_GetItemCount(hwnd) > 1) {
- tci.flags = TCHT_ONITEM;
- ScreenToClient(hwnd, &tci.pt);
- int idx = TabCtrl_HitTest(hwnd, &tci);
- if (idx != -1) {
- CMsgDialog *pDlg = (CMsgDialog*)pOwner->m_tab.GetNthPage(idx);
- if (pDlg) {
- bDragging = true;
- iBeginIndex = idx;
- ImageList_BeginDrag(Clist_GetImageList(), pDlg->GetImageId(), 8, 8);
- ImageList_DragEnter(hwnd, tci.pt.x, tci.pt.y);
- SetCapture(hwnd);
- }
- return TRUE;
- }
- }
- else pOwner->TabClicked();
- break;
-
- case WM_CAPTURECHANGED:
- bDragging = false;
- ImageList_DragLeave(hwnd);
- ImageList_EndDrag();
- break;
-
- case WM_MOUSEMOVE:
- if (bDragging) {
- tci.pt.x = (short)LOWORD(GetMessagePos());
- tci.pt.y = (short)HIWORD(GetMessagePos());
- ScreenToClient(hwnd, &tci.pt);
- ImageList_DragMove(tci.pt.x, tci.pt.y);
- }
- break;
-
- case WM_LBUTTONUP:
- if (bDragging && ReleaseCapture()) {
- tci.pt.x = (short)LOWORD(GetMessagePos());
- tci.pt.y = (short)HIWORD(GetMessagePos());
- tci.flags = TCHT_ONITEM;
- bDragging = false;
- ImageList_DragLeave(hwnd);
- ImageList_EndDrag();
-
- ScreenToClient(hwnd, &tci.pt);
- int idx = TabCtrl_HitTest(hwnd, &tci);
- if (idx != -1 && idx != iBeginIndex)
- pOwner->DropTab(idx, iBeginIndex);
- }
- break;
-
- case WM_LBUTTONDBLCLK:
- if (g_Settings.bTabCloseOnDblClick) {
- tci.pt.x = (short)LOWORD(GetMessagePos());
- tci.pt.y = (short)HIWORD(GetMessagePos());
- ScreenToClient(hwnd, &tci.pt);
-
- tci.flags = TCHT_ONITEM;
- int idx = TabCtrl_HitTest(hwnd, &tci);
- if (idx != -1) {
- CMsgDialog *pDlg = (CMsgDialog*)pOwner->m_tab.GetNthPage(idx);
- if (pDlg)
- pDlg->CloseTab();
- }
- }
- break;
-
- case WM_MBUTTONUP:
- tci.pt.x = (short)LOWORD(GetMessagePos());
- tci.pt.y = (short)HIWORD(GetMessagePos());
- tci.flags = TCHT_ONITEM;
-
- ScreenToClient(hwnd, &tci.pt);
- int idx = TabCtrl_HitTest(hwnd, &tci);
- if (idx != -1) {
- CMsgDialog *pDlg = (CMsgDialog*)pOwner->m_tab.GetNthPage(idx);
- if (pDlg)
- pDlg->CloseTab();
- }
- break;
- }
-
- return mir_callNextSubclass(hwnd, TabSubclassProc, msg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-CTabbedWindow::CTabbedWindow() :
- CDlgBase(g_plugin, IDD_CONTAINER),
- m_tab(this, IDC_TAB)
-{
- SetMinSize(450, 350);
-}
-
-bool CTabbedWindow::OnInitDialog()
-{
- SetWindowLongPtr(m_tab.GetHwnd(), GWLP_USERDATA, LPARAM(this));
- mir_subclassWindow(m_tab.GetHwnd(), ::TabSubclassProc);
-
- m_hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, nullptr, WS_CHILD | WS_VISIBLE | SBT_TOOLTIPS | SBARS_SIZEGRIP, 0, 0, 0, 0, m_hwnd, nullptr, g_plugin.getInst(), nullptr);
- SendMessage(m_hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0);
-
- RECT rc;
- GetWindowRect(m_hwndStatus, &rc);
- m_statusHeight = rc.bottom - rc.top;
-
- SetWindowPosition();
-
- if (!g_Settings.bTabsEnable) {
- m_tab.Hide();
- return false;
- }
-
- LONG_PTR mask = GetWindowLongPtr(m_tab.GetHwnd(), GWL_STYLE);
- if (g_Settings.bTabsAtBottom)
- mask |= TCS_BOTTOM;
- else
- mask &= ~TCS_BOTTOM;
- SetWindowLongPtr(m_tab.GetHwnd(), GWL_STYLE, mask);
-
- TabCtrl_SetMinTabWidth(m_tab.GetHwnd(), 80);
- TabCtrl_SetImageList(m_tab.GetHwnd(), Clist_GetImageList());
- return true;
-}
-
-void CTabbedWindow::OnDestroy()
-{
- DestroyWindow(m_hwndStatus); m_hwndStatus = nullptr;
-
- SaveWindowPosition(true);
-
- Utils_SaveWindowPosition(m_hwnd, g_plugin.bSavePerContact ? ((m_pEmbed == nullptr) ? 0 : m_pEmbed->m_hContact) : 0, CHAT_MODULE, "room");
-
- if (m_pEmbed == nullptr)
- g_pTabDialog = nullptr;
-}
-
-void CTabbedWindow::OnResize()
-{
- CDlgBase::OnResize();
-
- SendMessage(m_hwndStatus, WM_SIZE, 0, 0);
-
- if (m_pEmbed) {
- RECT rc;
- GetClientRect(m_tab.GetHwnd(), &rc);
- MoveWindow(m_pEmbed->GetHwnd(), 0, 0, rc.right - rc.left, rc.bottom - rc.top, FALSE);
- }
-
- SaveWindowPosition(false);
-}
-
-int CTabbedWindow::Resizer(UTILRESIZECONTROL *urc)
-{
- if (urc->wId == IDC_TAB) {
- urc->rcItem.top = 1;
- urc->rcItem.bottom = urc->dlgNewSize.cy - m_statusHeight - 1;
- return RD_ANCHORX_WIDTH | RD_ANCHORY_CUSTOM;
- }
-
- return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; // status bar
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-CTabbedWindow* CTabbedWindow::AddPage(MCONTACT hContact, wchar_t *pwszText, int iNoActivate)
-{
- CMsgDialog *pDlg = new CMsgDialog(this, hContact);
- pDlg->m_wszInitialText = pwszText;
- if (iNoActivate != -1)
- pDlg->m_bNoActivate = iNoActivate != 0;
-
- if (g_Settings.bTabsEnable) {
- m_tab.AddPage(Clist_GetContactDisplayName(hContact), nullptr, pDlg);
- FixTabIcons(pDlg);
-
- m_tab.ActivatePage(m_tab.GetCount() - 1);
- }
- else {
- m_pEmbed = pDlg;
- Create();
- pDlg->SetParent(m_hwnd);
- pDlg->Create();
- Show();
- }
-
- PostMessage(m_hwnd, WM_SIZE, 0, 0);
- return this;
-}
-
-void CTabbedWindow::AddPage(SESSION_INFO *si, int insertAt)
-{
- // does the tab already exist?
- int indexfound = (si->pDlg) ? m_tab.GetDlgIndex(si->pDlg) : -1;
- if (indexfound == -1) { // create a new tab
- wchar_t szTemp[30];
- mir_wstrncpy(szTemp, si->ptszName, 21);
- if (mir_wstrlen(si->ptszName) > 20)
- mir_wstrncpy(szTemp + 20, L"...", 4);
-
- if (!IsWindowVisible(m_hwnd))
- Show(SW_SHOW);
-
- CMsgDialog *pDlg = new CMsgDialog(this, si);
- pDlg->SetParent(m_hwnd);
- m_tab.AddPage(szTemp, nullptr, pDlg);
- m_tab.ActivatePage(m_tab.GetCount() - 1);
- FixTabIcons(pDlg);
- }
- else if (insertAt == -1)
- m_tab.ActivatePage(indexfound);
-}
-
-CMsgDialog* CTabbedWindow::CurrPage() const
-{
- return (m_pEmbed != nullptr) ? m_pEmbed : (CMsgDialog*)m_tab.GetActivePage();
-}
-
-void CTabbedWindow::DropTab(int begin, int end)
-{
- if (begin == end)
- return;
-
- m_tab.SwapPages(begin, end);
-
- CMsgDialog *pDlg = (CMsgDialog *)m_tab.GetNthPage(end);
- if (pDlg) {
- FixTabIcons(pDlg);
- m_tab.ActivatePage(end);
- }
-
- // fix the "fixed" positions
- int tabCount = m_tab.GetCount();
- for (int i = 0; i < tabCount; i++) {
- pDlg = (CMsgDialog *)m_tab.GetNthPage(i);
- if (pDlg == nullptr)
- continue;
-
- SESSION_INFO *si = pDlg->m_si;
- if (si && si->hContact && db_get_w(si->hContact, si->pszModule, "TabPosition", 0) != 0)
- db_set_w(si->hContact, si->pszModule, "TabPosition", i + 1);
- }
-}
-
-void CTabbedWindow::FixTabIcons(CMsgDialog *pDlg)
-{
- if (pDlg == nullptr)
- return;
-
- int image = pDlg->GetImageId();
-
- // if tabs are turned off, simply change the window's icon, otherwise set the tab's icon first
- if (m_pEmbed == nullptr) {
- int idx = m_tab.GetDlgIndex(pDlg);
- if (idx == -1)
- return;
-
- TCITEM tci = {};
- tci.mask = TCIF_IMAGE;
- TabCtrl_GetItem(m_tab.GetHwnd(), idx, &tci);
- if (tci.iImage != image) {
- tci.iImage = image;
- TabCtrl_SetItem(m_tab.GetHwnd(), idx, &tci);
- }
- }
-
- // set the container's icon only if we're processing the current page
- if (pDlg == CurrPage()) {
- Window_FreeIcon_IcoLib(m_hwnd);
- if (g_plugin.bUseStatusWinIcon)
- Window_SetProtoIcon_IcoLib(m_hwnd, pDlg->m_szProto, pDlg->m_wStatus);
- else if (pDlg->isChat())
- Window_SetIcon_IcoLib(m_hwnd, g_plugin.getIconHandle(IDI_CHANMGR));
- else
- Window_SetSkinIcon_IcoLib(m_hwnd, SKINICON_EVENT_MESSAGE);
- }
-}
-
-void CTabbedWindow::RemoveTab(CMsgDialog *pDlg)
-{
- int idx = m_tab.GetDlgIndex(pDlg);
- if (idx == -1)
- return;
-
- m_tab.RemovePage(idx);
- if (m_tab.GetCount() == 0)
- PostMessage(m_hwnd, WM_CLOSE, 0, 0);
- else {
- if (m_tab.GetNthPage(idx) == nullptr)
- idx--;
- m_tab.ActivatePage(idx);
- }
-}
-
-void CTabbedWindow::SaveWindowPosition(bool bUpdateSession)
-{
- WINDOWPLACEMENT wp = {};
- wp.length = sizeof(wp);
- GetWindowPlacement(m_hwnd, &wp);
-
- g_Settings.iX = wp.rcNormalPosition.left;
- g_Settings.iY = wp.rcNormalPosition.top;
- g_Settings.iWidth = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
- g_Settings.iHeight = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
-
- if (bUpdateSession) {
- iX = g_Settings.iX;
- iY = g_Settings.iY;
- iWidth = g_Settings.iWidth;
- iHeight = g_Settings.iHeight;
- }
-}
-
-void CTabbedWindow::SetMessageHighlight(CMsgDialog *pDlg)
-{
- if (m_tab.GetDlgIndex(pDlg) == -1)
- return;
-
- pDlg->m_si->wState |= GC_EVENT_HIGHLIGHT;
- FixTabIcons(pDlg);
- if (Chat::bFlashWindowHighlight && pDlg != m_tab.GetActivePage())
- pDlg->StartFlash();
-}
-
-void CTabbedWindow::SetTabHighlight(CMsgDialog *pDlg)
-{
- if (m_tab.GetDlgIndex(pDlg) == -1)
- return;
-
- FixTabIcons(pDlg);
- if (Chat::bFlashWindow && pDlg != m_tab.GetActivePage())
- pDlg->StartFlash();
-}
-
-void CTabbedWindow::SetWindowPosition()
-{
- if (m_pEmbed == nullptr) {
- Utils_RestoreWindowPosition(m_hwnd, 0, CHAT_MODULE, "room");
- return;
- }
-
- if (iX) {
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- GetWindowPlacement(m_hwnd, &wp);
-
- wp.rcNormalPosition.left = iX;
- wp.rcNormalPosition.top = iY;
- wp.rcNormalPosition.right = wp.rcNormalPosition.left + iWidth;
- wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + iHeight;
- wp.showCmd = SW_HIDE;
- SetWindowPlacement(m_hwnd, &wp);
- return;
- }
-
- int flag = m_pEmbed->m_bNoActivate ? RWPF_HIDDEN : 0;
- if (Utils_RestoreWindowPosition(m_hwnd, g_plugin.bSavePerContact ? m_pEmbed->m_hContact : 0, CHAT_MODULE, "room", flag)) {
- if (g_plugin.bSavePerContact) {
- if (Utils_RestoreWindowPosition(m_hwnd, 0, CHAT_MODULE, "room", flag | RWPF_NOMOVE))
- SetWindowPos(m_hwnd, nullptr, 0, 0, 550, 400, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);
- }
- else SetWindowPos(m_hwnd, nullptr, 0, 0, 550, 400, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);
- }
-
- if (!g_plugin.bSavePerContact && g_plugin.bCascade) {
- RECT rc, rcMax = {};
- CTabbedWindow *pMaxTab = nullptr;
-
- for (auto &it : g_arDialogs) {
- auto *pTab = it->m_pOwner;
- if (pTab == this)
- continue;
-
- GetWindowRect(pTab->GetHwnd(), &rc);
- if (rc.left > rcMax.left && rc.top > rcMax.top) {
- pMaxTab = pTab;
- rcMax = rc;
- }
- }
-
- if (pMaxTab) {
- m_windowWasCascaded = 1;
- int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
- SetWindowPos(m_hwnd, nullptr, rcMax.left + offset, rcMax.top + offset, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
- }
- }
-}
-
-void CTabbedWindow::SwitchNextTab()
-{
- int total = m_tab.GetCount();
- int i = TabCtrl_GetCurSel(m_tab.GetHwnd());
- if (i != -1 && total > 1) {
- if (i < total - 1)
- i++;
- else
- i = 0;
- m_tab.ActivatePage(i);
- TabClicked();
- }
-}
-
-void CTabbedWindow::SwitchPrevTab()
-{
- int total = m_tab.GetCount();
- int i = TabCtrl_GetCurSel(m_tab.GetHwnd());
- if (i != -1 && total >= 1) {
- if (i > 0)
- i--;
- else
- i = total - 1;
- m_tab.ActivatePage(i);
- TabClicked();
- }
-}
-
-void CTabbedWindow::SwitchTab(int iNewTab)
-{
- int total = m_tab.GetCount();
- int i = TabCtrl_GetCurSel(m_tab.GetHwnd());
- if (i != -1 && total != -1 && total != 1 && i != iNewTab && total > iNewTab) {
- m_tab.ActivatePage(iNewTab);
- TabClicked();
- }
-}
-
-void CTabbedWindow::TabClicked()
-{
- CMsgDialog *pDlg = (CMsgDialog*)m_tab.GetActivePage();
- if (pDlg == nullptr)
- return;
-
- SetFocus(pDlg->m_message.GetHwnd());
-
- SESSION_INFO *si = pDlg->m_si;
- if (si) {
- if (si->wState & STATE_TALK) {
- si->wState &= ~STATE_TALK;
- db_set_w(si->hContact, si->pszModule, "ApparentMode", 0);
- }
-
- if (si->wState & GC_EVENT_HIGHLIGHT) {
- si->wState &= ~GC_EVENT_HIGHLIGHT;
-
- if (g_clistApi.pfnGetEvent(si->hContact, 0))
- g_clistApi.pfnRemoveEvent(si->hContact, GC_FAKE_EVENT);
- }
-
- if (!si->pDlg) {
- g_chatApi.ShowRoom(si);
- SendMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0);
- }
- }
-
- FixTabIcons(pDlg);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-INT_PTR CTabbedWindow::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- RECT rc;
- int idx;
-
- switch (msg) {
- case WM_MOVE:
- SaveWindowPosition(false);
- break;
-
- case WM_ENTERSIZEMOVE:
- GetClientRect(m_hwnd, &rc);
- oldSizeX = rc.right - rc.left;
- oldSizeY = rc.bottom - rc.top;
- break;
-
- case WM_EXITSIZEMOVE:
- GetClientRect(m_hwnd, &rc);
- if (!((rc.right - rc.left) == oldSizeX && (rc.bottom - rc.top) == oldSizeY)) {
- CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
- if (pDlg != nullptr) {
- pDlg->m_pLog->ScrollToBottom();
- pDlg->Resize();
- }
- }
- break;
-
- case WM_DRAWITEM:
- {
- LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
- if (dis->hwndItem == m_hwndStatus) {
- CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
- if (pDlg != nullptr)
- DrawStatusIcons(pDlg->m_hContact, dis->hDC, dis->rcItem, 2);
- return TRUE;
- }
- }
- break;
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDOK) {
- CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
- if (pDlg != nullptr) {
- pDlg->m_btnOk.Click();
- return TRUE;
- }
- }
- break;
-
- case WM_ACTIVATE:
- if (LOWORD(wParam) == WA_INACTIVE)
- break;
-
- if (!m_pEmbed) {
- idx = TabCtrl_GetCurSel(m_tab.GetHwnd());
- if (idx != -1)
- m_tab.ActivatePage(idx);
- }
- else m_pEmbed->OnActivate();
- break;
-
- case WM_NOTIFY:
- if (((LPNMHDR)lParam)->hwndFrom == m_hwndStatus) {
- if (((LPNMHDR)lParam)->code == NM_CLICK || ((LPNMHDR)lParam)->code == NM_RCLICK) {
- NMMOUSE *nm = (NMMOUSE *)lParam;
- SendMessage(m_hwndStatus, SB_GETRECT, SendMessage(m_hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc);
- if (nm->pt.x >= rc.left) {
- CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
- if (pDlg != nullptr)
- CheckStatusIconClick(pDlg->m_hContact, m_hwndStatus, nm->pt, rc, 2, ((LPNMHDR)lParam)->code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0);
- }
- return TRUE;
- }
- }
-
- if (((LPNMHDR)lParam)->idFrom == IDC_TAB) {
- switch (((LPNMHDR)lParam)->code) {
- case TCN_SELCHANGE:
- m_tab.ActivatePage(TabCtrl_GetCurSel(m_tab.GetHwnd()));
- break;
-
- case NM_RCLICK:
- int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
- if (i == -1)
- break;
-
- TCHITTESTINFO tci = {};
- tci.pt.x = (short)LOWORD(GetMessagePos());
- tci.pt.y = (short)HIWORD(GetMessagePos());
- tci.flags = TCHT_ONITEM;
- ScreenToClient(GetDlgItem(m_hwnd, IDC_TAB), &tci.pt);
- if ((i = TabCtrl_HitTest(((LPNMHDR)lParam)->hwndFrom, &tci)) == -1)
- break;
-
- CMsgDialog *pDlg = (CMsgDialog*)m_tab.GetNthPage(i);
- SESSION_INFO *si = pDlg->m_si;
-
- ClientToScreen(GetDlgItem(m_hwnd, IDC_TAB), &tci.pt);
- HMENU hSubMenu = GetSubMenu(g_hMenu, 1);
- TranslateMenu(hSubMenu);
-
- if (si != nullptr) {
- uint16_t w = db_get_w(si->hContact, si->pszModule, "TabPosition", 0);
- if (w == 0)
- CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_UNCHECKED);
- else
- CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_CHECKED);
- }
- else CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_UNCHECKED);
-
- switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, tci.pt.x, tci.pt.y, 0, m_hwnd, nullptr)) {
- case ID_CLOSE:
- pDlg->CloseTab();
- break;
-
- case ID_LOCKPOSITION:
- if (si != nullptr) {
- if (!(GetMenuState(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND)&MF_CHECKED)) {
- if (si->hContact)
- db_set_w(si->hContact, si->pszModule, "TabPosition", (uint16_t)(i + 1));
- }
- else db_unset(si->hContact, si->pszModule, "TabPosition");
- }
- break;
-
- case ID_CLOSEOTHER:
- int tabCount = m_tab.GetCount();
- if (tabCount > 1) {
- while (tabCount--) {
- if (tabCount == i)
- continue;
-
- if (pDlg = (CMsgDialog*)m_tab.GetNthPage(tabCount))
- pDlg->CloseTab();
- }
- m_tab.ActivatePage(0);
- }
- break;
- }
- }
- }
- break;
- }
-
- return CDlgBase::DlgProc(msg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void UninitTabs()
-{
- if (g_pTabDialog != nullptr) {
- g_pTabDialog->Close();
- g_pTabDialog = nullptr;
- }
-}
+/*
+
+Copyright 2000-12 Miranda IM, 2012-23 Miranda NG team,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+#include "statusicon.h"
+
+CTabbedWindow *g_pTabDialog = nullptr;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+CTabbedWindow* GetContainer()
+{
+ if (g_Settings.bTabsEnable) {
+ if (g_pTabDialog == nullptr) {
+ g_pTabDialog = new CTabbedWindow();
+ g_pTabDialog->Show();
+ }
+ return g_pTabDialog;
+ }
+
+ return new CTabbedWindow();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static LRESULT CALLBACK TabSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CTabbedWindow *pOwner = (CTabbedWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ TCHITTESTINFO tci = {};
+
+ static bool bDragging = false;
+ static int iBeginIndex = 0;
+ switch (msg) {
+ case WM_LBUTTONDOWN:
+ tci.pt.x = (short)LOWORD(GetMessagePos());
+ tci.pt.y = (short)HIWORD(GetMessagePos());
+ if (DragDetect(hwnd, tci.pt) && TabCtrl_GetItemCount(hwnd) > 1) {
+ tci.flags = TCHT_ONITEM;
+ ScreenToClient(hwnd, &tci.pt);
+ int idx = TabCtrl_HitTest(hwnd, &tci);
+ if (idx != -1) {
+ CMsgDialog *pDlg = (CMsgDialog*)pOwner->m_tab.GetNthPage(idx);
+ if (pDlg) {
+ bDragging = true;
+ iBeginIndex = idx;
+ ImageList_BeginDrag(Clist_GetImageList(), pDlg->GetImageId(), 8, 8);
+ ImageList_DragEnter(hwnd, tci.pt.x, tci.pt.y);
+ SetCapture(hwnd);
+ }
+ return TRUE;
+ }
+ }
+ else pOwner->TabClicked();
+ break;
+
+ case WM_CAPTURECHANGED:
+ bDragging = false;
+ ImageList_DragLeave(hwnd);
+ ImageList_EndDrag();
+ break;
+
+ case WM_MOUSEMOVE:
+ if (bDragging) {
+ tci.pt.x = (short)LOWORD(GetMessagePos());
+ tci.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(hwnd, &tci.pt);
+ ImageList_DragMove(tci.pt.x, tci.pt.y);
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if (bDragging && ReleaseCapture()) {
+ tci.pt.x = (short)LOWORD(GetMessagePos());
+ tci.pt.y = (short)HIWORD(GetMessagePos());
+ tci.flags = TCHT_ONITEM;
+ bDragging = false;
+ ImageList_DragLeave(hwnd);
+ ImageList_EndDrag();
+
+ ScreenToClient(hwnd, &tci.pt);
+ int idx = TabCtrl_HitTest(hwnd, &tci);
+ if (idx != -1 && idx != iBeginIndex)
+ pOwner->DropTab(idx, iBeginIndex);
+ }
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ if (g_Settings.bTabCloseOnDblClick) {
+ tci.pt.x = (short)LOWORD(GetMessagePos());
+ tci.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(hwnd, &tci.pt);
+
+ tci.flags = TCHT_ONITEM;
+ int idx = TabCtrl_HitTest(hwnd, &tci);
+ if (idx != -1) {
+ CMsgDialog *pDlg = (CMsgDialog*)pOwner->m_tab.GetNthPage(idx);
+ if (pDlg)
+ pDlg->CloseTab();
+ }
+ }
+ break;
+
+ case WM_MBUTTONUP:
+ tci.pt.x = (short)LOWORD(GetMessagePos());
+ tci.pt.y = (short)HIWORD(GetMessagePos());
+ tci.flags = TCHT_ONITEM;
+
+ ScreenToClient(hwnd, &tci.pt);
+ int idx = TabCtrl_HitTest(hwnd, &tci);
+ if (idx != -1) {
+ CMsgDialog *pDlg = (CMsgDialog*)pOwner->m_tab.GetNthPage(idx);
+ if (pDlg)
+ pDlg->CloseTab();
+ }
+ break;
+ }
+
+ return mir_callNextSubclass(hwnd, TabSubclassProc, msg, wParam, lParam);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+CTabbedWindow::CTabbedWindow() :
+ CDlgBase(g_plugin, IDD_CONTAINER),
+ m_tab(this, IDC_TAB)
+{
+ SetMinSize(450, 350);
+}
+
+bool CTabbedWindow::OnInitDialog()
+{
+ SetWindowLongPtr(m_tab.GetHwnd(), GWLP_USERDATA, LPARAM(this));
+ mir_subclassWindow(m_tab.GetHwnd(), ::TabSubclassProc);
+
+ m_hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, nullptr, WS_CHILD | WS_VISIBLE | SBT_TOOLTIPS | SBARS_SIZEGRIP, 0, 0, 0, 0, m_hwnd, nullptr, g_plugin.getInst(), nullptr);
+ SendMessage(m_hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0);
+
+ RECT rc;
+ GetWindowRect(m_hwndStatus, &rc);
+ m_statusHeight = rc.bottom - rc.top;
+
+ SetWindowPosition();
+
+ if (!g_Settings.bTabsEnable) {
+ m_tab.Hide();
+ return false;
+ }
+
+ LONG_PTR mask = GetWindowLongPtr(m_tab.GetHwnd(), GWL_STYLE);
+ if (g_Settings.bTabsAtBottom)
+ mask |= TCS_BOTTOM;
+ else
+ mask &= ~TCS_BOTTOM;
+ SetWindowLongPtr(m_tab.GetHwnd(), GWL_STYLE, mask);
+
+ TabCtrl_SetMinTabWidth(m_tab.GetHwnd(), 80);
+ TabCtrl_SetImageList(m_tab.GetHwnd(), Clist_GetImageList());
+ return true;
+}
+
+void CTabbedWindow::OnDestroy()
+{
+ DestroyWindow(m_hwndStatus); m_hwndStatus = nullptr;
+
+ SaveWindowPosition(true);
+
+ Utils_SaveWindowPosition(m_hwnd, g_plugin.bSavePerContact ? ((m_pEmbed == nullptr) ? 0 : m_pEmbed->m_hContact) : 0, CHAT_MODULE, "room");
+
+ if (m_pEmbed == nullptr)
+ g_pTabDialog = nullptr;
+}
+
+void CTabbedWindow::OnResize()
+{
+ CDlgBase::OnResize();
+
+ SendMessage(m_hwndStatus, WM_SIZE, 0, 0);
+
+ if (m_pEmbed) {
+ RECT rc;
+ GetClientRect(m_tab.GetHwnd(), &rc);
+ MoveWindow(m_pEmbed->GetHwnd(), 0, 0, rc.right - rc.left, rc.bottom - rc.top, FALSE);
+ }
+
+ SaveWindowPosition(false);
+}
+
+int CTabbedWindow::Resizer(UTILRESIZECONTROL *urc)
+{
+ if (urc->wId == IDC_TAB) {
+ urc->rcItem.top = 1;
+ urc->rcItem.bottom = urc->dlgNewSize.cy - m_statusHeight - 1;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_CUSTOM;
+ }
+
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; // status bar
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+CTabbedWindow* CTabbedWindow::AddPage(MCONTACT hContact, wchar_t *pwszText, int iNoActivate)
+{
+ CMsgDialog *pDlg = new CMsgDialog(this, hContact);
+ pDlg->m_wszInitialText = pwszText;
+ if (iNoActivate != -1)
+ pDlg->m_bNoActivate = iNoActivate != 0;
+
+ if (g_Settings.bTabsEnable) {
+ m_tab.AddPage(Clist_GetContactDisplayName(hContact), nullptr, pDlg);
+ FixTabIcons(pDlg);
+
+ m_tab.ActivatePage(m_tab.GetCount() - 1);
+ }
+ else {
+ m_pEmbed = pDlg;
+ Create();
+ pDlg->SetParent(m_hwnd);
+ pDlg->Create();
+ Show();
+ }
+
+ PostMessage(m_hwnd, WM_SIZE, 0, 0);
+ return this;
+}
+
+void CTabbedWindow::AddPage(SESSION_INFO *si, int insertAt)
+{
+ // does the tab already exist?
+ int indexfound = (si->pDlg) ? m_tab.GetDlgIndex(si->pDlg) : -1;
+ if (indexfound == -1) { // create a new tab
+ wchar_t szTemp[30];
+ mir_wstrncpy(szTemp, si->ptszName, 21);
+ if (mir_wstrlen(si->ptszName) > 20)
+ mir_wstrncpy(szTemp + 20, L"...", 4);
+
+ if (!IsWindowVisible(m_hwnd))
+ Show(SW_SHOW);
+
+ CMsgDialog *pDlg = new CMsgDialog(this, si);
+ pDlg->SetParent(m_hwnd);
+ m_tab.AddPage(szTemp, nullptr, pDlg);
+ m_tab.ActivatePage(m_tab.GetCount() - 1);
+ FixTabIcons(pDlg);
+ }
+ else if (insertAt == -1)
+ m_tab.ActivatePage(indexfound);
+}
+
+CMsgDialog* CTabbedWindow::CurrPage() const
+{
+ return (m_pEmbed != nullptr) ? m_pEmbed : (CMsgDialog*)m_tab.GetActivePage();
+}
+
+void CTabbedWindow::DropTab(int begin, int end)
+{
+ if (begin == end)
+ return;
+
+ m_tab.SwapPages(begin, end);
+
+ CMsgDialog *pDlg = (CMsgDialog *)m_tab.GetNthPage(end);
+ if (pDlg) {
+ FixTabIcons(pDlg);
+ m_tab.ActivatePage(end);
+ }
+
+ // fix the "fixed" positions
+ int tabCount = m_tab.GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ pDlg = (CMsgDialog *)m_tab.GetNthPage(i);
+ if (pDlg == nullptr)
+ continue;
+
+ SESSION_INFO *si = pDlg->m_si;
+ if (si && si->hContact && db_get_w(si->hContact, si->pszModule, "TabPosition", 0) != 0)
+ db_set_w(si->hContact, si->pszModule, "TabPosition", i + 1);
+ }
+}
+
+void CTabbedWindow::FixTabIcons(CMsgDialog *pDlg)
+{
+ if (pDlg == nullptr)
+ return;
+
+ int image = pDlg->GetImageId();
+
+ // if tabs are turned off, simply change the window's icon, otherwise set the tab's icon first
+ if (m_pEmbed == nullptr) {
+ int idx = m_tab.GetDlgIndex(pDlg);
+ if (idx == -1)
+ return;
+
+ TCITEM tci = {};
+ tci.mask = TCIF_IMAGE;
+ TabCtrl_GetItem(m_tab.GetHwnd(), idx, &tci);
+ if (tci.iImage != image) {
+ tci.iImage = image;
+ TabCtrl_SetItem(m_tab.GetHwnd(), idx, &tci);
+ }
+ }
+
+ // set the container's icon only if we're processing the current page
+ if (pDlg == CurrPage()) {
+ Window_FreeIcon_IcoLib(m_hwnd);
+ if (g_plugin.bUseStatusWinIcon)
+ Window_SetProtoIcon_IcoLib(m_hwnd, pDlg->m_szProto, pDlg->m_wStatus);
+ else if (pDlg->isChat())
+ Window_SetIcon_IcoLib(m_hwnd, g_plugin.getIconHandle(IDI_CHANMGR));
+ else
+ Window_SetSkinIcon_IcoLib(m_hwnd, SKINICON_EVENT_MESSAGE);
+ }
+}
+
+void CTabbedWindow::RemoveTab(CMsgDialog *pDlg)
+{
+ int idx = m_tab.GetDlgIndex(pDlg);
+ if (idx == -1)
+ return;
+
+ m_tab.RemovePage(idx);
+ if (m_tab.GetCount() == 0)
+ PostMessage(m_hwnd, WM_CLOSE, 0, 0);
+ else {
+ if (m_tab.GetNthPage(idx) == nullptr)
+ idx--;
+ m_tab.ActivatePage(idx);
+ }
+}
+
+void CTabbedWindow::SaveWindowPosition(bool bUpdateSession)
+{
+ WINDOWPLACEMENT wp = {};
+ wp.length = sizeof(wp);
+ GetWindowPlacement(m_hwnd, &wp);
+
+ g_Settings.iX = wp.rcNormalPosition.left;
+ g_Settings.iY = wp.rcNormalPosition.top;
+ g_Settings.iWidth = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
+ g_Settings.iHeight = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
+
+ if (bUpdateSession) {
+ iX = g_Settings.iX;
+ iY = g_Settings.iY;
+ iWidth = g_Settings.iWidth;
+ iHeight = g_Settings.iHeight;
+ }
+}
+
+void CTabbedWindow::SetMessageHighlight(CMsgDialog *pDlg)
+{
+ if (m_tab.GetDlgIndex(pDlg) == -1)
+ return;
+
+ pDlg->m_si->wState |= GC_EVENT_HIGHLIGHT;
+ FixTabIcons(pDlg);
+ if (Chat::bFlashWindowHighlight && pDlg != m_tab.GetActivePage())
+ pDlg->StartFlash();
+}
+
+void CTabbedWindow::SetTabHighlight(CMsgDialog *pDlg)
+{
+ if (m_tab.GetDlgIndex(pDlg) == -1)
+ return;
+
+ FixTabIcons(pDlg);
+ if (Chat::bFlashWindow && pDlg != m_tab.GetActivePage())
+ pDlg->StartFlash();
+}
+
+void CTabbedWindow::SetWindowPosition()
+{
+ if (m_pEmbed == nullptr) {
+ Utils_RestoreWindowPosition(m_hwnd, 0, CHAT_MODULE, "room");
+ return;
+ }
+
+ if (iX) {
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(m_hwnd, &wp);
+
+ wp.rcNormalPosition.left = iX;
+ wp.rcNormalPosition.top = iY;
+ wp.rcNormalPosition.right = wp.rcNormalPosition.left + iWidth;
+ wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + iHeight;
+ wp.showCmd = SW_HIDE;
+ SetWindowPlacement(m_hwnd, &wp);
+ return;
+ }
+
+ int flag = m_pEmbed->m_bNoActivate ? RWPF_HIDDEN : 0;
+ if (Utils_RestoreWindowPosition(m_hwnd, g_plugin.bSavePerContact ? m_pEmbed->m_hContact : 0, CHAT_MODULE, "room", flag)) {
+ if (g_plugin.bSavePerContact) {
+ if (Utils_RestoreWindowPosition(m_hwnd, 0, CHAT_MODULE, "room", flag | RWPF_NOMOVE))
+ SetWindowPos(m_hwnd, nullptr, 0, 0, 550, 400, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);
+ }
+ else SetWindowPos(m_hwnd, nullptr, 0, 0, 550, 400, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);
+ }
+
+ if (!g_plugin.bSavePerContact && g_plugin.bCascade) {
+ RECT rc, rcMax = {};
+ CTabbedWindow *pMaxTab = nullptr;
+
+ for (auto &it : g_arDialogs) {
+ auto *pTab = it->m_pOwner;
+ if (pTab == this)
+ continue;
+
+ GetWindowRect(pTab->GetHwnd(), &rc);
+ if (rc.left > rcMax.left && rc.top > rcMax.top) {
+ pMaxTab = pTab;
+ rcMax = rc;
+ }
+ }
+
+ if (pMaxTab) {
+ m_windowWasCascaded = 1;
+ int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
+ SetWindowPos(m_hwnd, nullptr, rcMax.left + offset, rcMax.top + offset, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
+ }
+ }
+}
+
+void CTabbedWindow::SwitchNextTab()
+{
+ int total = m_tab.GetCount();
+ int i = TabCtrl_GetCurSel(m_tab.GetHwnd());
+ if (i != -1 && total > 1) {
+ if (i < total - 1)
+ i++;
+ else
+ i = 0;
+ m_tab.ActivatePage(i);
+ TabClicked();
+ }
+}
+
+void CTabbedWindow::SwitchPrevTab()
+{
+ int total = m_tab.GetCount();
+ int i = TabCtrl_GetCurSel(m_tab.GetHwnd());
+ if (i != -1 && total >= 1) {
+ if (i > 0)
+ i--;
+ else
+ i = total - 1;
+ m_tab.ActivatePage(i);
+ TabClicked();
+ }
+}
+
+void CTabbedWindow::SwitchTab(int iNewTab)
+{
+ int total = m_tab.GetCount();
+ int i = TabCtrl_GetCurSel(m_tab.GetHwnd());
+ if (i != -1 && total != -1 && total != 1 && i != iNewTab && total > iNewTab) {
+ m_tab.ActivatePage(iNewTab);
+ TabClicked();
+ }
+}
+
+void CTabbedWindow::TabClicked()
+{
+ CMsgDialog *pDlg = (CMsgDialog*)m_tab.GetActivePage();
+ if (pDlg == nullptr)
+ return;
+
+ SetFocus(pDlg->m_message.GetHwnd());
+
+ SESSION_INFO *si = pDlg->m_si;
+ if (si) {
+ if (si->wState & STATE_TALK) {
+ si->wState &= ~STATE_TALK;
+ db_set_w(si->hContact, si->pszModule, "ApparentMode", 0);
+ }
+
+ if (si->wState & GC_EVENT_HIGHLIGHT) {
+ si->wState &= ~GC_EVENT_HIGHLIGHT;
+
+ if (g_clistApi.pfnGetEvent(si->hContact, 0))
+ g_clistApi.pfnRemoveEvent(si->hContact, GC_FAKE_EVENT);
+ }
+
+ if (!si->pDlg) {
+ g_chatApi.ShowRoom(si);
+ SendMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0);
+ }
+ }
+
+ FixTabIcons(pDlg);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR CTabbedWindow::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ RECT rc;
+ int idx;
+
+ switch (msg) {
+ case WM_MOVE:
+ SaveWindowPosition(false);
+ break;
+
+ case WM_ENTERSIZEMOVE:
+ GetClientRect(m_hwnd, &rc);
+ oldSizeX = rc.right - rc.left;
+ oldSizeY = rc.bottom - rc.top;
+ break;
+
+ case WM_EXITSIZEMOVE:
+ GetClientRect(m_hwnd, &rc);
+ if (!((rc.right - rc.left) == oldSizeX && (rc.bottom - rc.top) == oldSizeY)) {
+ CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
+ if (pDlg != nullptr) {
+ pDlg->m_pLog->ScrollToBottom();
+ pDlg->Resize();
+ }
+ }
+ break;
+
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
+ if (dis->hwndItem == m_hwndStatus) {
+ CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
+ if (pDlg != nullptr)
+ DrawStatusIcons(pDlg->m_hContact, dis->hDC, dis->rcItem, 2);
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK) {
+ CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
+ if (pDlg != nullptr) {
+ pDlg->m_btnOk.Click();
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_INACTIVE)
+ break;
+
+ if (!m_pEmbed) {
+ idx = TabCtrl_GetCurSel(m_tab.GetHwnd());
+ if (idx != -1)
+ m_tab.ActivatePage(idx);
+ }
+ else m_pEmbed->OnActivate();
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->hwndFrom == m_hwndStatus) {
+ if (((LPNMHDR)lParam)->code == NM_CLICK || ((LPNMHDR)lParam)->code == NM_RCLICK) {
+ NMMOUSE *nm = (NMMOUSE *)lParam;
+ SendMessage(m_hwndStatus, SB_GETRECT, SendMessage(m_hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc);
+ if (nm->pt.x >= rc.left) {
+ CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
+ if (pDlg != nullptr)
+ CheckStatusIconClick(pDlg->m_hContact, m_hwndStatus, nm->pt, rc, 2, ((LPNMHDR)lParam)->code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0);
+ }
+ return TRUE;
+ }
+ }
+
+ if (((LPNMHDR)lParam)->idFrom == IDC_TAB) {
+ switch (((LPNMHDR)lParam)->code) {
+ case TCN_SELCHANGE:
+ m_tab.ActivatePage(TabCtrl_GetCurSel(m_tab.GetHwnd()));
+ break;
+
+ case NM_RCLICK:
+ int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
+ if (i == -1)
+ break;
+
+ TCHITTESTINFO tci = {};
+ tci.pt.x = (short)LOWORD(GetMessagePos());
+ tci.pt.y = (short)HIWORD(GetMessagePos());
+ tci.flags = TCHT_ONITEM;
+ ScreenToClient(GetDlgItem(m_hwnd, IDC_TAB), &tci.pt);
+ if ((i = TabCtrl_HitTest(((LPNMHDR)lParam)->hwndFrom, &tci)) == -1)
+ break;
+
+ CMsgDialog *pDlg = (CMsgDialog*)m_tab.GetNthPage(i);
+ SESSION_INFO *si = pDlg->m_si;
+
+ ClientToScreen(GetDlgItem(m_hwnd, IDC_TAB), &tci.pt);
+ HMENU hSubMenu = GetSubMenu(g_hMenu, 1);
+ TranslateMenu(hSubMenu);
+
+ if (si != nullptr) {
+ uint16_t w = db_get_w(si->hContact, si->pszModule, "TabPosition", 0);
+ if (w == 0)
+ CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_UNCHECKED);
+ else
+ CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_CHECKED);
+ }
+ else CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_UNCHECKED);
+
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, tci.pt.x, tci.pt.y, 0, m_hwnd, nullptr)) {
+ case ID_CLOSE:
+ pDlg->CloseTab();
+ break;
+
+ case ID_LOCKPOSITION:
+ if (si != nullptr) {
+ if (!(GetMenuState(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND)&MF_CHECKED)) {
+ if (si->hContact)
+ db_set_w(si->hContact, si->pszModule, "TabPosition", (uint16_t)(i + 1));
+ }
+ else db_unset(si->hContact, si->pszModule, "TabPosition");
+ }
+ break;
+
+ case ID_CLOSEOTHER:
+ int tabCount = m_tab.GetCount();
+ if (tabCount > 1) {
+ while (tabCount--) {
+ if (tabCount == i)
+ continue;
+
+ if (pDlg = (CMsgDialog*)m_tab.GetNthPage(tabCount))
+ pDlg->CloseTab();
+ }
+ m_tab.ActivatePage(0);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ return CDlgBase::DlgProc(msg, wParam, lParam);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void UninitTabs()
+{
+ if (g_pTabDialog != nullptr) {
+ g_pTabDialog->Close();
+ g_pTabDialog = nullptr;
+ }
+}
diff --git a/src/core/stdmsg/src/version.h b/src/core/stdmsg/src/version.h
index 80b240e521..c2573ed98b 100644
--- a/src/core/stdmsg/src/version.h
+++ b/src/core/stdmsg/src/version.h
@@ -9,4 +9,4 @@
#define __DESCRIPTION "Core module for send/receive instant messages."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdMsg"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stdpopup/src/stdafx.cxx b/src/core/stdpopup/src/stdafx.cxx
index 1ab0efee94..ebbde0ade1 100644
--- a/src/core/stdpopup/src/stdafx.cxx
+++ b/src/core/stdpopup/src/stdafx.cxx
@@ -1,18 +1,18 @@
-/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-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 version 2
-of the License.
-
-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, see <http://www.gnu.org/licenses/>.
-*/
-
+/*
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+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 version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
#include "stdafx.h" \ No newline at end of file
diff --git a/src/core/stdpopup/src/version.h b/src/core/stdpopup/src/version.h
index 2ffc660f71..16d5b005cd 100644
--- a/src/core/stdpopup/src/version.h
+++ b/src/core/stdpopup/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for popups."
#define __AUTHOR "Scott Ellis, Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdPopup"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stduihist/src/history.cpp b/src/core/stduihist/src/history.cpp
index 56c3aba8a5..ae92875fab 100644
--- a/src/core/stduihist/src/history.cpp
+++ b/src/core/stduihist/src/history.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stduihist/src/main.cpp b/src/core/stduihist/src/main.cpp
index 1911bd9792..1be11d7ac3 100644
--- a/src/core/stduihist/src/main.cpp
+++ b/src/core/stduihist/src/main.cpp
@@ -2,7 +2,7 @@
Standard ugly history viewer for Miranda NG
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
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
diff --git a/src/core/stduihist/src/stdafx.h b/src/core/stduihist/src/stdafx.h
index 9817742ad3..aae29d451d 100644
--- a/src/core/stduihist/src/stdafx.h
+++ b/src/core/stduihist/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stduihist/src/version.h b/src/core/stduihist/src/version.h
index 62eda51681..ee7cceff2a 100644
--- a/src/core/stduihist/src/version.h
+++ b/src/core/stduihist/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for built-in history viewer."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdUIHist"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stduserinfo/src/contactinfo.cpp b/src/core/stduserinfo/src/contactinfo.cpp
index a19783e4df..7adec4c09b 100644
--- a/src/core/stduserinfo/src/contactinfo.cpp
+++ b/src/core/stduserinfo/src/contactinfo.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stduserinfo/src/main.cpp b/src/core/stduserinfo/src/main.cpp
index 5334c9727f..9bd9b6f7be 100644
--- a/src/core/stduserinfo/src/main.cpp
+++ b/src/core/stduserinfo/src/main.cpp
@@ -2,7 +2,7 @@
Standard User Info plugin for Miranda NG
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
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
diff --git a/src/core/stduserinfo/src/stdafx.h b/src/core/stduserinfo/src/stdafx.h
index 76b456e716..ca5412f200 100644
--- a/src/core/stduserinfo/src/stdafx.h
+++ b/src/core/stduserinfo/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stduserinfo/src/stdinfo.cpp b/src/core/stduserinfo/src/stdinfo.cpp
index 5acec2d245..ca3b2edd20 100644
--- a/src/core/stduserinfo/src/stdinfo.cpp
+++ b/src/core/stduserinfo/src/stdinfo.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stduserinfo/src/userinfo.cpp b/src/core/stduserinfo/src/userinfo.cpp
index 9448d5c96f..30792d9244 100644
--- a/src/core/stduserinfo/src/userinfo.cpp
+++ b/src/core/stduserinfo/src/userinfo.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stduserinfo/src/utils.h b/src/core/stduserinfo/src/utils.h
index cb766c47ae..9ceb33b61d 100644
--- a/src/core/stduserinfo/src/utils.h
+++ b/src/core/stduserinfo/src/utils.h
@@ -1,214 +1,214 @@
-/*
-
-Standard User Info plugin for Miranda NG
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-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.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#define SVS_NORMAL 0
-#define SVS_GENDER 1
-#define SVS_ZEROISUNSPEC 2
-#define SVS_IP 3
-#define SVS_COUNTRY 4
-#define SVS_MONTH 5
-#define SVS_SIGNED 6
-#define SVS_TIMEZONE 7
-#define SVS_MARITAL 8
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct DataItem
-{
- const char *szSetting;
- int idCtrl, special;
-};
-
-template <size_t _Size>
-bool IsEmptyValue(MCONTACT hContact, DataItem(&buffer)[_Size], const char *szModule = nullptr)
-{
- if (szModule == nullptr)
- szModule = Proto_GetBaseAccountName(hContact);
-
- DBVARIANT dbv;
- for (auto &it : buffer) {
- if (db_get_s(hContact, szModule, it.szSetting, &dbv, 0) != 0)
- continue;
-
- db_free(&dbv);
- return false;
- }
-
- return true;
-}
-
-template <size_t _Size>
-void SetValue(HWND hwndDlg, MCONTACT hContact, DataItem(&buffer)[_Size], const char *szModule = nullptr)
-{
- if (szModule == nullptr)
- szModule = Proto_GetBaseAccountName(hContact);
-
- for (auto &it : buffer) {
- char *pstr = nullptr;
- wchar_t *pwstr = nullptr, wstr[80];
-
- DBVARIANT dbv = { DBVT_DELETED };
-
- bool unspecified;
- if (szModule == nullptr)
- unspecified = true;
- else
- unspecified = db_get_s(hContact, szModule, it.szSetting, &dbv, 0) != 0;
-
- if (!unspecified) {
- switch (dbv.type) {
- case DBVT_BYTE:
- if (it.special == SVS_GENDER) {
- if (dbv.cVal == 'M') pwstr = TranslateT("Male");
- else if (dbv.cVal == 'F') pwstr = TranslateT("Female");
- else unspecified = 1;
- }
- else if (it.special == SVS_MONTH) {
- if (dbv.bVal > 0 && dbv.bVal <= 12) {
- pwstr = wstr;
- GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME1 - 1 + dbv.bVal, wstr, _countof(wstr));
- }
- else unspecified = 1;
- }
- else if (it.special == SVS_TIMEZONE) {
- if (dbv.cVal == -100) unspecified = 1;
- else {
- pwstr = wstr;
- mir_snwprintf(wstr, dbv.cVal ? L"UTC%+d:%02d" : L"UTC", -dbv.cVal / 2, (dbv.cVal & 1) * 30);
- }
- }
- else if (it.special == SVS_MARITAL) {
- switch (dbv.cVal) {
- case 0:
- pwstr = TranslateT("<not specified>");
- break;
- case 10:
- pwstr = TranslateT("Single");
- break;
- case 11:
- pwstr = TranslateT("Close relationships");
- break;
- case 12:
- pwstr = TranslateT("Engaged");
- break;
- case 20:
- pwstr = TranslateT("Married");
- break;
- case 30:
- pwstr = TranslateT("Divorced");
- break;
- case 31:
- pwstr = TranslateT("Separated");
- break;
- case 40:
- pwstr = TranslateT("Widowed");
- break;
- case 50:
- pwstr = TranslateT("Actively searching");
- break;
- case 60:
- pwstr = TranslateT("In love");
- break;
- case 70:
- pwstr = TranslateT("It's complicated");
- break;
- case 80:
- pwstr = TranslateT("In a civil union");
- break;
- default:
- unspecified = 1;
- }
- }
- else {
- unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.bVal == 0);
- pwstr = _itow(it.special == SVS_SIGNED ? dbv.cVal : dbv.bVal, wstr, 10);
- }
- break;
-
- case DBVT_WORD:
- if (it.special == SVS_COUNTRY) {
- uint16_t wSave = dbv.wVal;
- if (wSave == (uint16_t)-1) {
- char szSettingName[100];
- mir_snprintf(szSettingName, "%sName", it.szSetting);
- if (!db_get_ws(hContact, szModule, szSettingName, &dbv)) {
- pwstr = dbv.pwszVal;
- unspecified = false;
- break;
- }
- }
-
- pwstr = TranslateW(_A2T((char *)CallService(MS_UTILS_GETCOUNTRYBYNUMBER, wSave, 0)));
- unspecified = pwstr == nullptr;
- }
- else {
- unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.wVal == 0);
- pwstr = _itow(it.special == SVS_SIGNED ? dbv.sVal : dbv.wVal, wstr, 10);
- }
- break;
-
- case DBVT_DWORD:
- unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.dVal == 0);
- if (it.special == SVS_IP) {
- struct in_addr ia;
- ia.S_un.S_addr = htonl(dbv.dVal);
- mir_wstrncpy(wstr, _A2T(inet_ntoa(ia)), _countof(wstr));
- pwstr = wstr;
- if (dbv.dVal == 0)
- unspecified = 1;
- }
- else pwstr = _itow(it.special == SVS_SIGNED ? dbv.lVal : dbv.dVal, wstr, 10);
- break;
-
- case DBVT_ASCIIZ:
- unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.pszVal[0] == '\0');
- pstr = dbv.pszVal;
- break;
-
- case DBVT_UTF8:
- unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.pszVal[0] == '\0');
- if (!unspecified) {
- SetDlgItemTextW(hwndDlg, it.idCtrl, TranslateW(ptrW(mir_utf8decodeW(dbv.pszVal))));
- goto LBL_Exit;
- }
-
- mir_utf8decode(dbv.pszVal, &pwstr);
- break;
-
- default:
- pwstr = wstr;
- mir_wstrcpy(wstr, L"???");
- break;
- }
- }
-
- if (unspecified)
- SetDlgItemText(hwndDlg, it.idCtrl, TranslateT("<not specified>"));
- else if (pwstr != nullptr)
- SetDlgItemText(hwndDlg, it.idCtrl, pwstr);
- else
- SetDlgItemTextA(hwndDlg, it.idCtrl, pstr);
-
-LBL_Exit:
- EnableWindow(GetDlgItem(hwndDlg, it.idCtrl), !unspecified);
- db_free(&dbv);
- }
-}
+/*
+
+Standard User Info plugin for Miranda NG
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+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.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#define SVS_NORMAL 0
+#define SVS_GENDER 1
+#define SVS_ZEROISUNSPEC 2
+#define SVS_IP 3
+#define SVS_COUNTRY 4
+#define SVS_MONTH 5
+#define SVS_SIGNED 6
+#define SVS_TIMEZONE 7
+#define SVS_MARITAL 8
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct DataItem
+{
+ const char *szSetting;
+ int idCtrl, special;
+};
+
+template <size_t _Size>
+bool IsEmptyValue(MCONTACT hContact, DataItem(&buffer)[_Size], const char *szModule = nullptr)
+{
+ if (szModule == nullptr)
+ szModule = Proto_GetBaseAccountName(hContact);
+
+ DBVARIANT dbv;
+ for (auto &it : buffer) {
+ if (db_get_s(hContact, szModule, it.szSetting, &dbv, 0) != 0)
+ continue;
+
+ db_free(&dbv);
+ return false;
+ }
+
+ return true;
+}
+
+template <size_t _Size>
+void SetValue(HWND hwndDlg, MCONTACT hContact, DataItem(&buffer)[_Size], const char *szModule = nullptr)
+{
+ if (szModule == nullptr)
+ szModule = Proto_GetBaseAccountName(hContact);
+
+ for (auto &it : buffer) {
+ char *pstr = nullptr;
+ wchar_t *pwstr = nullptr, wstr[80];
+
+ DBVARIANT dbv = { DBVT_DELETED };
+
+ bool unspecified;
+ if (szModule == nullptr)
+ unspecified = true;
+ else
+ unspecified = db_get_s(hContact, szModule, it.szSetting, &dbv, 0) != 0;
+
+ if (!unspecified) {
+ switch (dbv.type) {
+ case DBVT_BYTE:
+ if (it.special == SVS_GENDER) {
+ if (dbv.cVal == 'M') pwstr = TranslateT("Male");
+ else if (dbv.cVal == 'F') pwstr = TranslateT("Female");
+ else unspecified = 1;
+ }
+ else if (it.special == SVS_MONTH) {
+ if (dbv.bVal > 0 && dbv.bVal <= 12) {
+ pwstr = wstr;
+ GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME1 - 1 + dbv.bVal, wstr, _countof(wstr));
+ }
+ else unspecified = 1;
+ }
+ else if (it.special == SVS_TIMEZONE) {
+ if (dbv.cVal == -100) unspecified = 1;
+ else {
+ pwstr = wstr;
+ mir_snwprintf(wstr, dbv.cVal ? L"UTC%+d:%02d" : L"UTC", -dbv.cVal / 2, (dbv.cVal & 1) * 30);
+ }
+ }
+ else if (it.special == SVS_MARITAL) {
+ switch (dbv.cVal) {
+ case 0:
+ pwstr = TranslateT("<not specified>");
+ break;
+ case 10:
+ pwstr = TranslateT("Single");
+ break;
+ case 11:
+ pwstr = TranslateT("Close relationships");
+ break;
+ case 12:
+ pwstr = TranslateT("Engaged");
+ break;
+ case 20:
+ pwstr = TranslateT("Married");
+ break;
+ case 30:
+ pwstr = TranslateT("Divorced");
+ break;
+ case 31:
+ pwstr = TranslateT("Separated");
+ break;
+ case 40:
+ pwstr = TranslateT("Widowed");
+ break;
+ case 50:
+ pwstr = TranslateT("Actively searching");
+ break;
+ case 60:
+ pwstr = TranslateT("In love");
+ break;
+ case 70:
+ pwstr = TranslateT("It's complicated");
+ break;
+ case 80:
+ pwstr = TranslateT("In a civil union");
+ break;
+ default:
+ unspecified = 1;
+ }
+ }
+ else {
+ unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.bVal == 0);
+ pwstr = _itow(it.special == SVS_SIGNED ? dbv.cVal : dbv.bVal, wstr, 10);
+ }
+ break;
+
+ case DBVT_WORD:
+ if (it.special == SVS_COUNTRY) {
+ uint16_t wSave = dbv.wVal;
+ if (wSave == (uint16_t)-1) {
+ char szSettingName[100];
+ mir_snprintf(szSettingName, "%sName", it.szSetting);
+ if (!db_get_ws(hContact, szModule, szSettingName, &dbv)) {
+ pwstr = dbv.pwszVal;
+ unspecified = false;
+ break;
+ }
+ }
+
+ pwstr = TranslateW(_A2T((char *)CallService(MS_UTILS_GETCOUNTRYBYNUMBER, wSave, 0)));
+ unspecified = pwstr == nullptr;
+ }
+ else {
+ unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.wVal == 0);
+ pwstr = _itow(it.special == SVS_SIGNED ? dbv.sVal : dbv.wVal, wstr, 10);
+ }
+ break;
+
+ case DBVT_DWORD:
+ unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.dVal == 0);
+ if (it.special == SVS_IP) {
+ struct in_addr ia;
+ ia.S_un.S_addr = htonl(dbv.dVal);
+ mir_wstrncpy(wstr, _A2T(inet_ntoa(ia)), _countof(wstr));
+ pwstr = wstr;
+ if (dbv.dVal == 0)
+ unspecified = 1;
+ }
+ else pwstr = _itow(it.special == SVS_SIGNED ? dbv.lVal : dbv.dVal, wstr, 10);
+ break;
+
+ case DBVT_ASCIIZ:
+ unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.pszVal[0] == '\0');
+ pstr = dbv.pszVal;
+ break;
+
+ case DBVT_UTF8:
+ unspecified = (it.special == SVS_ZEROISUNSPEC && dbv.pszVal[0] == '\0');
+ if (!unspecified) {
+ SetDlgItemTextW(hwndDlg, it.idCtrl, TranslateW(ptrW(mir_utf8decodeW(dbv.pszVal))));
+ goto LBL_Exit;
+ }
+
+ mir_utf8decode(dbv.pszVal, &pwstr);
+ break;
+
+ default:
+ pwstr = wstr;
+ mir_wstrcpy(wstr, L"???");
+ break;
+ }
+ }
+
+ if (unspecified)
+ SetDlgItemText(hwndDlg, it.idCtrl, TranslateT("<not specified>"));
+ else if (pwstr != nullptr)
+ SetDlgItemText(hwndDlg, it.idCtrl, pwstr);
+ else
+ SetDlgItemTextA(hwndDlg, it.idCtrl, pstr);
+
+LBL_Exit:
+ EnableWindow(GetDlgItem(hwndDlg, it.idCtrl), !unspecified);
+ db_free(&dbv);
+ }
+}
diff --git a/src/core/stduserinfo/src/version.h b/src/core/stduserinfo/src/version.h
index 1a68b614db..441fd0cdef 100644
--- a/src/core/stduserinfo/src/version.h
+++ b/src/core/stduserinfo/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for providing user information."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdUserInfo"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stduseronline/src/main.cpp b/src/core/stduseronline/src/main.cpp
index 255a954e35..da3e0c5cd8 100644
--- a/src/core/stduseronline/src/main.cpp
+++ b/src/core/stduseronline/src/main.cpp
@@ -2,7 +2,7 @@
Standard user online monitor for Miranda NG
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
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
diff --git a/src/core/stduseronline/src/stdafx.h b/src/core/stduseronline/src/stdafx.h
index a34a26fd31..1f069e243c 100644
--- a/src/core/stduseronline/src/stdafx.h
+++ b/src/core/stduseronline/src/stdafx.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stduseronline/src/useronline.cpp b/src/core/stduseronline/src/useronline.cpp
index 3b1520a0a6..be50bf3165 100644
--- a/src/core/stduseronline/src/useronline.cpp
+++ b/src/core/stduseronline/src/useronline.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/core/stduseronline/src/version.h b/src/core/stduseronline/src/version.h
index 3edec197fb..ec2b47a6f8 100644
--- a/src/core/stduseronline/src/version.h
+++ b/src/core/stduseronline/src/version.h
@@ -8,4 +8,4 @@
#define __DESCRIPTION "Core module for user-is-online event processing."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/StdUserOnline"
-#define __COPYRIGHT "© 2012-22 Miranda NG team"
+#define __COPYRIGHT "© 2012-23 Miranda NG team"