diff options
author | George Hazan <ghazan@miranda.im> | 2021-11-07 12:05:31 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2021-11-07 12:05:49 +0300 |
commit | 27dab93c710a72ed363b5e0a543827b210ea71af (patch) | |
tree | fec437c914def6d356b2568efb2d44707b1351b9 /src | |
parent | 66940037defd069b5c6676969b889b60a8ed8fd0 (diff) |
let's separate modules for Windows from common ones
Diffstat (limited to 'src')
-rw-r--r-- | src/mir_core/mir_core.vcxproj | 165 | ||||
-rw-r--r-- | src/mir_core/mir_core.vcxproj.filters | 202 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlBase.cpp (renamed from src/mir_core/src/CCtrlBase.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlButton.cpp (renamed from src/mir_core/src/CCtrlButton.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlCheck.cpp (renamed from src/mir_core/src/CCtrlCheck.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlClc.cpp (renamed from src/mir_core/src/CCtrlClc.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlColor.cpp (renamed from src/mir_core/src/CCtrlColor.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlCombo.cpp (renamed from src/mir_core/src/CCtrlCombo.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlData.cpp (renamed from src/mir_core/src/CCtrlData.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlEdit.cpp (renamed from src/mir_core/src/CCtrlEdit.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlHyperlink.cpp (renamed from src/mir_core/src/CCtrlHyperlink.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlLabel.cpp (renamed from src/mir_core/src/CCtrlLabel.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlListBox.cpp (renamed from src/mir_core/src/CCtrlListBox.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlListView.cpp (renamed from src/mir_core/src/CCtrlListView.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlMButton.cpp (renamed from src/mir_core/src/CCtrlMButton.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlPages.cpp (renamed from src/mir_core/src/CCtrlPages.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlRichEdit.cpp (renamed from src/mir_core/src/CCtrlRichEdit.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlSlider.cpp (renamed from src/mir_core/src/CCtrlSlider.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlSpin.cpp (renamed from src/mir_core/src/CCtrlSpin.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlTreeOpts.cpp (renamed from src/mir_core/src/CCtrlTreeOpts.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CCtrlTreeView.cpp (renamed from src/mir_core/src/CCtrlTreeView.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CDbLink.cpp (renamed from src/mir_core/src/CDbLink.cpp) | 184 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CDlgBase.cpp (renamed from src/mir_core/src/CDlgBase.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CProgress.cpp (renamed from src/mir_core/src/CProgress.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CSplitter.cpp (renamed from src/mir_core/src/CSplitter.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/CTimer.cpp (renamed from src/mir_core/src/CTimer.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/cctrldate.cpp (renamed from src/mir_core/src/cctrldate.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/cmdline.cpp (renamed from src/mir_core/src/cmdline.cpp) | 154 | ||||
-rw-r--r-- | src/mir_core/src/Windows/colourpicker.cpp (renamed from src/mir_core/src/colourpicker.cpp) | 210 | ||||
-rw-r--r-- | src/mir_core/src/Windows/hyperlink.cpp (renamed from src/mir_core/src/hyperlink.cpp) | 554 | ||||
-rw-r--r-- | src/mir_core/src/Windows/icons.cpp (renamed from src/mir_core/src/icons.cpp) | 148 | ||||
-rw-r--r-- | src/mir_core/src/Windows/langpack.cpp (renamed from src/mir_core/src/langpack.cpp) | 1530 | ||||
-rw-r--r-- | src/mir_core/src/Windows/locks.cpp (renamed from src/mir_core/src/locks.cpp) | 2 | ||||
-rw-r--r-- | src/mir_core/src/Windows/miranda.cpp (renamed from src/mir_core/src/miranda.cpp) | 298 | ||||
-rw-r--r-- | src/mir_core/src/Windows/openurl.cpp (renamed from src/mir_core/src/openurl.cpp) | 152 | ||||
-rw-r--r-- | src/mir_core/src/Windows/path.cpp (renamed from src/mir_core/src/path.cpp) | 492 | ||||
-rw-r--r-- | src/mir_core/src/Windows/resizer.cpp (renamed from src/mir_core/src/resizer.cpp) | 302 | ||||
-rw-r--r-- | src/mir_core/src/Windows/subclass.cpp (renamed from src/mir_core/src/subclass.cpp) | 402 | ||||
-rw-r--r-- | src/mir_core/src/Windows/threads.cpp (renamed from src/mir_core/src/threads.cpp) | 800 | ||||
-rw-r--r-- | src/mir_core/src/Windows/timezones.cpp (renamed from src/mir_core/src/timezones.cpp) | 1184 | ||||
-rw-r--r-- | src/mir_core/src/Windows/windowlist.cpp (renamed from src/mir_core/src/windowlist.cpp) | 210 | ||||
-rw-r--r-- | src/mir_core/src/Windows/winutil.cpp (renamed from src/mir_core/src/winutil.cpp) | 236 | ||||
-rw-r--r-- | src/mir_core/src/Windows/winver.cpp (renamed from src/mir_core/src/winver.cpp) | 744 |
43 files changed, 4054 insertions, 3963 deletions
diff --git a/src/mir_core/mir_core.vcxproj b/src/mir_core/mir_core.vcxproj index 23e75824de..f0466fabab 100644 --- a/src/mir_core/mir_core.vcxproj +++ b/src/mir_core/mir_core.vcxproj @@ -42,67 +42,150 @@ <ItemGroup>
<ClCompile Include="src\binbuffer.cpp" />
<ClCompile Include="src\bitmaps.cpp" />
- <ClCompile Include="src\CCtrlBase.cpp" />
- <ClCompile Include="src\CCtrlButton.cpp" />
- <ClCompile Include="src\CCtrlCheck.cpp" />
- <ClCompile Include="src\CCtrlClc.cpp" />
- <ClCompile Include="src\CCtrlColor.cpp" />
- <ClCompile Include="src\CCtrlCombo.cpp" />
- <ClCompile Include="src\CCtrlData.cpp" />
- <ClCompile Include="src\cctrldate.cpp" />
- <ClCompile Include="src\CCtrlEdit.cpp" />
- <ClCompile Include="src\CCtrlHyperlink.cpp" />
- <ClCompile Include="src\CCtrlLabel.cpp" />
- <ClCompile Include="src\CCtrlListBox.cpp" />
- <ClCompile Include="src\CCtrlListView.cpp" />
- <ClCompile Include="src\CCtrlMButton.cpp" />
- <ClCompile Include="src\CCtrlPages.cpp" />
- <ClCompile Include="src\CCtrlRichEdit.cpp" />
- <ClCompile Include="src\CCtrlSlider.cpp" />
- <ClCompile Include="src\CCtrlSpin.cpp" />
- <ClCompile Include="src\CCtrlTreeOpts.cpp" />
- <ClCompile Include="src\CCtrlTreeView.cpp" />
- <ClCompile Include="src\CDbLink.cpp" />
- <ClCompile Include="src\CDlgBase.cpp" />
- <ClCompile Include="src\cmdline.cpp" />
- <ClCompile Include="src\colourpicker.cpp" />
- <ClCompile Include="src\CProgress.cpp" />
- <ClCompile Include="src\CSplitter.cpp" />
- <ClCompile Include="src\CTimer.cpp" />
<ClCompile Include="src\db.cpp" />
<ClCompile Include="src\http.cpp" />
- <ClCompile Include="src\hyperlink.cpp" />
- <ClCompile Include="src\icons.cpp" />
- <ClCompile Include="src\langpack.cpp" />
<ClCompile Include="src\lists.cpp" />
- <ClCompile Include="src\locks.cpp" />
<ClCompile Include="src\logger.cpp" />
<ClCompile Include="src\md5.cpp" />
<ClCompile Include="src\memory.cpp" />
- <ClCompile Include="src\miranda.cpp" />
<ClCompile Include="src\modules.cpp" />
<ClCompile Include="src\mstring.cpp" />
- <ClCompile Include="src\openurl.cpp" />
- <ClCompile Include="src\path.cpp" />
- <ClCompile Include="src\resizer.cpp" />
<ClCompile Include="src\sha1.cpp" />
<ClCompile Include="src\sha256.cpp" />
<ClCompile Include="src\stdafx.cxx">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="src\subclass.cpp" />
- <ClCompile Include="src\threads.cpp" />
- <ClCompile Include="src\timezones.cpp" />
<ClCompile Include="src\tinyxml2.cpp" />
<ClCompile Include="src\tinyxml2_utils.cpp" />
<ClCompile Include="src\utf.cpp" />
<ClCompile Include="src\utils.cpp" />
- <ClCompile Include="src\windowlist.cpp" />
- <ClCompile Include="src\winutil.cpp" />
- <ClCompile Include="src\winver.cpp" />
+ <ClCompile Include="src\Windows\CCtrlBase.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlButton.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlCheck.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlClc.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlColor.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlCombo.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlData.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\cctrldate.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlEdit.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlHyperlink.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlLabel.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlListBox.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlListView.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlMButton.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlPages.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlRichEdit.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlSlider.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlSpin.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlTreeOpts.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlTreeView.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CDbLink.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CDlgBase.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\cmdline.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\colourpicker.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CProgress.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CSplitter.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CTimer.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\hyperlink.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\icons.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\langpack.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\locks.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\miranda.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\openurl.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\path.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\resizer.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\subclass.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\threads.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\timezones.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\windowlist.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\winutil.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\winver.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
<ClInclude Include="src\miranda.h" />
<ClInclude Include="src\stdafx.h" />
<ClInclude Include="src\tinyxml2.h" />
+ <ClInclude Include="src\Windows\miranda.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="res\version.rc" />
diff --git a/src/mir_core/mir_core.vcxproj.filters b/src/mir_core/mir_core.vcxproj.filters index 2eba1c3237..92df544754 100644 --- a/src/mir_core/mir_core.vcxproj.filters +++ b/src/mir_core/mir_core.vcxproj.filters @@ -8,173 +8,173 @@ <ClCompile Include="src\bitmaps.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlBase.cpp">
+ <ClCompile Include="src\db.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlButton.cpp">
+ <ClCompile Include="src\http.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlCheck.cpp">
+ <ClCompile Include="src\lists.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlClc.cpp">
+ <ClCompile Include="src\logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlCombo.cpp">
+ <ClCompile Include="src\md5.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlData.cpp">
+ <ClCompile Include="src\memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\cctrldate.cpp">
+ <ClCompile Include="src\modules.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlEdit.cpp">
+ <ClCompile Include="src\mstring.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlHyperlink.cpp">
+ <ClCompile Include="src\sha1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlLabel.cpp">
+ <ClCompile Include="src\sha256.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlListBox.cpp">
+ <ClCompile Include="src\stdafx.cxx">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlListView.cpp">
+ <ClCompile Include="src\tinyxml2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlMButton.cpp">
+ <ClCompile Include="src\tinyxml2_utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlPages.cpp">
+ <ClCompile Include="src\utf.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlRichEdit.cpp">
+ <ClCompile Include="src\utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlSpin.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlBase.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlTreeView.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlButton.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CDbLink.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlCheck.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CDlgBase.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlClc.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\cmdline.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlColor.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\colourpicker.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlCombo.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CProgress.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlData.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CSplitter.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\cctrldate.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CTimer.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlEdit.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\db.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlHyperlink.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\http.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlLabel.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\hyperlink.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlListBox.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\icons.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlListView.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\langpack.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlMButton.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\lists.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlPages.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\locks.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlRichEdit.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\logger.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlSlider.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\md5.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlSpin.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\memory.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlTreeOpts.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\miranda.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlTreeView.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\modules.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CDbLink.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\mstring.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CDlgBase.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\openurl.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\cmdline.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\path.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\colourpicker.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\resizer.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CProgress.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\sha1.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CSplitter.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\sha256.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CTimer.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\stdafx.cxx">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\hyperlink.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\subclass.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\icons.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\threads.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\langpack.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\timezones.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\locks.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\tinyxml2.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\miranda.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\tinyxml2_utils.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\openurl.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\utf.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\path.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\utils.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\resizer.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\windowlist.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\subclass.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\winutil.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\threads.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\winver.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\timezones.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlTreeOpts.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\windowlist.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlColor.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\winutil.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlSlider.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\winver.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -187,6 +187,9 @@ <ClInclude Include="src\tinyxml2.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="src\Windows\miranda.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="res\version.rc">
@@ -197,4 +200,9 @@ <None Include="src\mir_core64.def" />
<None Include="src\mir_core.def" />
</ItemGroup>
+ <ItemGroup>
+ <Filter Include="Source Files\Windows">
+ <UniqueIdentifier>{af52c09e-568e-4948-95c9-120c030fd932}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
</Project>
\ No newline at end of file diff --git a/src/mir_core/src/CCtrlBase.cpp b/src/mir_core/src/Windows/CCtrlBase.cpp index aa684707e0..83afe7fea6 100644 --- a/src/mir_core/src/CCtrlBase.cpp +++ b/src/mir_core/src/Windows/CCtrlBase.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" static mir_cs csCtrl; diff --git a/src/mir_core/src/CCtrlButton.cpp b/src/mir_core/src/Windows/CCtrlButton.cpp index 75b25e477c..d86ba2e0ad 100644 --- a/src/mir_core/src/CCtrlButton.cpp +++ b/src/mir_core/src/Windows/CCtrlButton.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlButton diff --git a/src/mir_core/src/CCtrlCheck.cpp b/src/mir_core/src/Windows/CCtrlCheck.cpp index ce765274b4..0315e1601b 100644 --- a/src/mir_core/src/CCtrlCheck.cpp +++ b/src/mir_core/src/Windows/CCtrlCheck.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlCheck class diff --git a/src/mir_core/src/CCtrlClc.cpp b/src/mir_core/src/Windows/CCtrlClc.cpp index b5b439cdb7..9239d3d61a 100644 --- a/src/mir_core/src/CCtrlClc.cpp +++ b/src/mir_core/src/Windows/CCtrlClc.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlClc diff --git a/src/mir_core/src/CCtrlColor.cpp b/src/mir_core/src/Windows/CCtrlColor.cpp index 71e913b5b9..dcd841b213 100644 --- a/src/mir_core/src/CCtrlColor.cpp +++ b/src/mir_core/src/Windows/CCtrlColor.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlColor class diff --git a/src/mir_core/src/CCtrlCombo.cpp b/src/mir_core/src/Windows/CCtrlCombo.cpp index 4a67f14720..f481b1554d 100644 --- a/src/mir_core/src/CCtrlCombo.cpp +++ b/src/mir_core/src/Windows/CCtrlCombo.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlCombo class diff --git a/src/mir_core/src/CCtrlData.cpp b/src/mir_core/src/Windows/CCtrlData.cpp index 92c25a4c4d..7f228b159e 100644 --- a/src/mir_core/src/CCtrlData.cpp +++ b/src/mir_core/src/Windows/CCtrlData.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlData class diff --git a/src/mir_core/src/CCtrlEdit.cpp b/src/mir_core/src/Windows/CCtrlEdit.cpp index 3f60855843..4395af9419 100644 --- a/src/mir_core/src/CCtrlEdit.cpp +++ b/src/mir_core/src/Windows/CCtrlEdit.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlEdit class diff --git a/src/mir_core/src/CCtrlHyperlink.cpp b/src/mir_core/src/Windows/CCtrlHyperlink.cpp index 7a4bf2ab28..f63e87ed8e 100644 --- a/src/mir_core/src/CCtrlHyperlink.cpp +++ b/src/mir_core/src/Windows/CCtrlHyperlink.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlHyperlink diff --git a/src/mir_core/src/CCtrlLabel.cpp b/src/mir_core/src/Windows/CCtrlLabel.cpp index 2f95578aba..f4848592d5 100644 --- a/src/mir_core/src/CCtrlLabel.cpp +++ b/src/mir_core/src/Windows/CCtrlLabel.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlLabel diff --git a/src/mir_core/src/CCtrlListBox.cpp b/src/mir_core/src/Windows/CCtrlListBox.cpp index da75fefe19..71519a96ca 100644 --- a/src/mir_core/src/CCtrlListBox.cpp +++ b/src/mir_core/src/Windows/CCtrlListBox.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlListBox class diff --git a/src/mir_core/src/CCtrlListView.cpp b/src/mir_core/src/Windows/CCtrlListView.cpp index 5ac8f4d32e..23f780f170 100644 --- a/src/mir_core/src/CCtrlListView.cpp +++ b/src/mir_core/src/Windows/CCtrlListView.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlListView diff --git a/src/mir_core/src/CCtrlMButton.cpp b/src/mir_core/src/Windows/CCtrlMButton.cpp index 42f5fd3303..6ab2cb0efd 100644 --- a/src/mir_core/src/CCtrlMButton.cpp +++ b/src/mir_core/src/Windows/CCtrlMButton.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlMButton diff --git a/src/mir_core/src/CCtrlPages.cpp b/src/mir_core/src/Windows/CCtrlPages.cpp index 4ca7f1b16d..81ffdd008a 100644 --- a/src/mir_core/src/CCtrlPages.cpp +++ b/src/mir_core/src/Windows/CCtrlPages.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" static volatile long g_order = 1; diff --git a/src/mir_core/src/CCtrlRichEdit.cpp b/src/mir_core/src/Windows/CCtrlRichEdit.cpp index eec1a467c2..44d965a682 100644 --- a/src/mir_core/src/CCtrlRichEdit.cpp +++ b/src/mir_core/src/Windows/CCtrlRichEdit.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" #include <RichOle.h> diff --git a/src/mir_core/src/CCtrlSlider.cpp b/src/mir_core/src/Windows/CCtrlSlider.cpp index df42737d0b..4adbd45506 100644 --- a/src/mir_core/src/CCtrlSlider.cpp +++ b/src/mir_core/src/Windows/CCtrlSlider.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlSlider class diff --git a/src/mir_core/src/CCtrlSpin.cpp b/src/mir_core/src/Windows/CCtrlSpin.cpp index 9f452d6d6f..bf75a67c91 100644 --- a/src/mir_core/src/CCtrlSpin.cpp +++ b/src/mir_core/src/Windows/CCtrlSpin.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlSpin class diff --git a/src/mir_core/src/CCtrlTreeOpts.cpp b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp index 4c63a0042f..0867347106 100644 --- a/src/mir_core/src/CCtrlTreeOpts.cpp +++ b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_GRPOPEN, IMG_GRPCLOSED }; diff --git a/src/mir_core/src/CCtrlTreeView.cpp b/src/mir_core/src/Windows/CCtrlTreeView.cpp index 0522bfee03..08b4d57d7b 100644 --- a/src/mir_core/src/CCtrlTreeView.cpp +++ b/src/mir_core/src/Windows/CCtrlTreeView.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" int ImageList_AddIcon_IconLibLoaded(HIMAGELIST hIml, int iconId) { diff --git a/src/mir_core/src/CDbLink.cpp b/src/mir_core/src/Windows/CDbLink.cpp index e81c5e181a..4515e032f2 100644 --- a/src/mir_core/src/CDbLink.cpp +++ b/src/mir_core/src/Windows/CDbLink.cpp @@ -1,92 +1,92 @@ -/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-21 Miranda NG team
-
-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"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CDbLink class
-
-CDbLink::CDbLink(const char *szModule, const char *szSetting, BYTE type, DWORD iValue)
- : CDataLink(type)
-{
- m_szModule = mir_strdup(szModule);
- m_szSetting = mir_strdup(szSetting);
- m_iDefault = iValue;
- m_szDefault = nullptr;
- dbv.type = DBVT_DELETED;
-}
-
-CDbLink::CDbLink(const char *szModule, const char *szSetting, BYTE type, wchar_t *szValue)
- : CDataLink(type),
- m_iDefault(0)
-{
- m_szModule = mir_strdup(szModule);
- m_szSetting = mir_strdup(szSetting);
- m_szDefault = mir_wstrdup(szValue);
- dbv.type = DBVT_DELETED;
-}
-
-CDbLink::~CDbLink()
-{
- mir_free(m_szModule);
- mir_free(m_szSetting);
- mir_free(m_szDefault);
- if (dbv.type != DBVT_DELETED)
- db_free(&dbv);
-}
-
-DWORD CDbLink::LoadInt()
-{
- switch (m_type) {
- case DBVT_BYTE: return db_get_b(0, m_szModule, m_szSetting, m_iDefault);
- case DBVT_WORD: return db_get_w(0, m_szModule, m_szSetting, m_iDefault);
- case DBVT_DWORD: return db_get_dw(0, m_szModule, m_szSetting, m_iDefault);
- default: return m_iDefault;
- }
-}
-
-void CDbLink::SaveInt(DWORD value)
-{
- switch (m_type) {
- case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (BYTE)value); break;
- case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (WORD)value); break;
- case DBVT_DWORD: db_set_dw(0, m_szModule, m_szSetting, value); break;
- }
-}
-
-wchar_t* CDbLink::LoadText()
-{
- if (dbv.type != DBVT_DELETED) db_free(&dbv);
- if (!db_get_ws(0, m_szModule, m_szSetting, &dbv)) {
- if (dbv.type == DBVT_WCHAR)
- return dbv.pwszVal;
- return m_szDefault;
- }
-
- dbv.type = DBVT_DELETED;
- return m_szDefault;
-}
-
-void CDbLink::SaveText(wchar_t *value)
-{
- db_set_ws(0, m_szModule, m_szSetting, value);
-}
+/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 Miranda NG team + +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" + +///////////////////////////////////////////////////////////////////////////////////////// +// CDbLink class + +CDbLink::CDbLink(const char *szModule, const char *szSetting, BYTE type, DWORD iValue) + : CDataLink(type) +{ + m_szModule = mir_strdup(szModule); + m_szSetting = mir_strdup(szSetting); + m_iDefault = iValue; + m_szDefault = nullptr; + dbv.type = DBVT_DELETED; +} + +CDbLink::CDbLink(const char *szModule, const char *szSetting, BYTE type, wchar_t *szValue) + : CDataLink(type), + m_iDefault(0) +{ + m_szModule = mir_strdup(szModule); + m_szSetting = mir_strdup(szSetting); + m_szDefault = mir_wstrdup(szValue); + dbv.type = DBVT_DELETED; +} + +CDbLink::~CDbLink() +{ + mir_free(m_szModule); + mir_free(m_szSetting); + mir_free(m_szDefault); + if (dbv.type != DBVT_DELETED) + db_free(&dbv); +} + +DWORD CDbLink::LoadInt() +{ + switch (m_type) { + case DBVT_BYTE: return db_get_b(0, m_szModule, m_szSetting, m_iDefault); + case DBVT_WORD: return db_get_w(0, m_szModule, m_szSetting, m_iDefault); + case DBVT_DWORD: return db_get_dw(0, m_szModule, m_szSetting, m_iDefault); + default: return m_iDefault; + } +} + +void CDbLink::SaveInt(DWORD value) +{ + switch (m_type) { + case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (BYTE)value); break; + case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (WORD)value); break; + case DBVT_DWORD: db_set_dw(0, m_szModule, m_szSetting, value); break; + } +} + +wchar_t* CDbLink::LoadText() +{ + if (dbv.type != DBVT_DELETED) db_free(&dbv); + if (!db_get_ws(0, m_szModule, m_szSetting, &dbv)) { + if (dbv.type == DBVT_WCHAR) + return dbv.pwszVal; + return m_szDefault; + } + + dbv.type = DBVT_DELETED; + return m_szDefault; +} + +void CDbLink::SaveText(wchar_t *value) +{ + db_set_ws(0, m_szModule, m_szSetting, value); +} diff --git a/src/mir_core/src/CDlgBase.cpp b/src/mir_core/src/Windows/CDlgBase.cpp index f9f5f47a06..5949057fda 100644 --- a/src/mir_core/src/CDlgBase.cpp +++ b/src/mir_core/src/Windows/CDlgBase.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" static mir_cs csDialogs; diff --git a/src/mir_core/src/CProgress.cpp b/src/mir_core/src/Windows/CProgress.cpp index 3b745b10cd..acc4773aff 100644 --- a/src/mir_core/src/CProgress.cpp +++ b/src/mir_core/src/Windows/CProgress.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlProgress diff --git a/src/mir_core/src/CSplitter.cpp b/src/mir_core/src/Windows/CSplitter.cpp index 7ea0b538c9..24e406f999 100644 --- a/src/mir_core/src/CSplitter.cpp +++ b/src/mir_core/src/Windows/CSplitter.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CSplitter diff --git a/src/mir_core/src/CTimer.cpp b/src/mir_core/src/Windows/CTimer.cpp index dfaa83be0a..367c65249f 100644 --- a/src/mir_core/src/CTimer.cpp +++ b/src/mir_core/src/Windows/CTimer.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CTimer diff --git a/src/mir_core/src/cctrldate.cpp b/src/mir_core/src/Windows/cctrldate.cpp index 415c1571b2..809679aad3 100644 --- a/src/mir_core/src/cctrldate.cpp +++ b/src/mir_core/src/Windows/cctrldate.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdafx.h" +#include "../stdafx.h" ///////////////////////////////////////////////////////////////////////////////////////// // CCtrlDate class diff --git a/src/mir_core/src/cmdline.cpp b/src/mir_core/src/Windows/cmdline.cpp index 4dc74695c4..6aee0efe60 100644 --- a/src/mir_core/src/cmdline.cpp +++ b/src/mir_core/src/Windows/cmdline.cpp @@ -1,77 +1,77 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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"
-
-/* command line support */
-
-struct CmdLineParam
-{
- __inline CmdLineParam(const wchar_t *_name, const wchar_t *_value) :
- name(mir_wstrdup(_name)), value(mir_wstrdup(_value))
- {}
-
- ptrW name, value;
-};
-
-static int CompareParams(const CmdLineParam *p1, const CmdLineParam *p2)
-{
- return wcscmp(p1->name, p2->name);
-}
-
-static OBJLIST<CmdLineParam> arParams(5, CompareParams);
-
-MIR_CORE_DLL(void) CmdLine_Parse(const wchar_t *ptszCmdLine)
-{
- int nArgs = 0;
- wchar_t **pArgs = CommandLineToArgvW(ptszCmdLine, &nArgs);
- if (pArgs == nullptr)
- return;
-
- for (int i=0; i < nArgs; i++) {
- wchar_t *pOptionName = pArgs[i], *p;
-
- // not an option? skip it
- if (*pOptionName != '/' && *pOptionName != '-')
- continue;
-
- pOptionName++;
- if ((p = wcspbrk(pOptionName, L"=:")) == nullptr) { // no more text in string
- arParams.insert(new CmdLineParam(pOptionName, L""));
- break;
- }
-
- // parameter with value
- *p = 0;
- arParams.insert(new CmdLineParam(pOptionName, p+1));
- }
-
- LocalFree(pArgs);
-}
-
-MIR_CORE_DLL(const wchar_t*) CmdLine_GetOption(const wchar_t* ptszParameter)
-{
- CmdLineParam tmp(ptszParameter, nullptr);
- int idx = arParams.getIndex(&tmp);
- return (idx == -1) ? nullptr : arParams[idx].value.get();
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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" + +/* command line support */ + +struct CmdLineParam +{ + __inline CmdLineParam(const wchar_t *_name, const wchar_t *_value) : + name(mir_wstrdup(_name)), value(mir_wstrdup(_value)) + {} + + ptrW name, value; +}; + +static int CompareParams(const CmdLineParam *p1, const CmdLineParam *p2) +{ + return wcscmp(p1->name, p2->name); +} + +static OBJLIST<CmdLineParam> arParams(5, CompareParams); + +MIR_CORE_DLL(void) CmdLine_Parse(const wchar_t *ptszCmdLine) +{ + int nArgs = 0; + wchar_t **pArgs = CommandLineToArgvW(ptszCmdLine, &nArgs); + if (pArgs == nullptr) + return; + + for (int i=0; i < nArgs; i++) { + wchar_t *pOptionName = pArgs[i], *p; + + // not an option? skip it + if (*pOptionName != '/' && *pOptionName != '-') + continue; + + pOptionName++; + if ((p = wcspbrk(pOptionName, L"=:")) == nullptr) { // no more text in string + arParams.insert(new CmdLineParam(pOptionName, L"")); + break; + } + + // parameter with value + *p = 0; + arParams.insert(new CmdLineParam(pOptionName, p+1)); + } + + LocalFree(pArgs); +} + +MIR_CORE_DLL(const wchar_t*) CmdLine_GetOption(const wchar_t* ptszParameter) +{ + CmdLineParam tmp(ptszParameter, nullptr); + int idx = arParams.getIndex(&tmp); + return (idx == -1) ? nullptr : arParams[idx].value.get(); +} diff --git a/src/mir_core/src/colourpicker.cpp b/src/mir_core/src/Windows/colourpicker.cpp index 181eadd894..464c29abc5 100644 --- a/src/mir_core/src/colourpicker.cpp +++ b/src/mir_core/src/Windows/colourpicker.cpp @@ -1,105 +1,105 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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 LRESULT CALLBACK ColourPickerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- switch (message) {
- case WM_CREATE:
- SetWindowLongPtr(hwnd, 0, 0);
- SetWindowLongPtr(hwnd, sizeof(COLORREF), 0);
- break;
-
- case CPM_SETDEFAULTCOLOUR:
- SetWindowLongPtr(hwnd, sizeof(COLORREF), lParam);
- break;
-
- case CPM_GETDEFAULTCOLOUR:
- return GetWindowLongPtr(hwnd, sizeof(COLORREF));
-
- case CPM_SETCOLOUR:
- SetWindowLongPtr(hwnd, 0, lParam);
- InvalidateRect(hwnd, nullptr, FALSE);
- break;
-
- case CPM_GETCOLOUR:
- return GetWindowLongPtr(hwnd, 0);
-
- case WM_LBUTTONUP:
- {
- COLORREF custColours[16] = { 0 };
- custColours[0] = GetWindowLongPtr(hwnd, sizeof(COLORREF));
-
- CHOOSECOLOR cc = { 0 };
- cc.lStructSize = sizeof(CHOOSECOLOR);
- cc.hwndOwner = hwnd;
- cc.hInstance = (HWND)g_hInst;
- cc.rgbResult = GetWindowLongPtr(hwnd, 0);
- cc.lpCustColors = custColours;
- cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
- if (ChooseColor(&cc)) {
- SetWindowLongPtr(hwnd, 0, cc.rgbResult);
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), CPN_COLOURCHANGED), (LPARAM)hwnd);
- InvalidateRect(hwnd, nullptr, FALSE);
- }
- }
- break;
-
- case WM_ENABLE:
- InvalidateRect(hwnd, nullptr, FALSE);
- break;
-
- case WM_NCPAINT:
- case WM_PAINT:
- PAINTSTRUCT ps;
- HDC hdc1 = BeginPaint(hwnd, &ps);
-
- RECT rc;
- GetClientRect(hwnd, &rc);
- DrawEdge(hdc1, &rc, EDGE_ETCHED, BF_RECT);
- InflateRect(&rc, -2, -2);
-
- HBRUSH hBrush = (IsWindowEnabled(hwnd)) ? CreateSolidBrush(GetWindowLongPtr(hwnd, 0)) : CreateHatchBrush(HS_BDIAGONAL, GetSysColor(COLOR_GRAYTEXT));
- SetBkColor(hdc1, GetSysColor(COLOR_BTNFACE));
- FillRect(hdc1, &rc, hBrush);
- DeleteObject(hBrush);
-
- EndPaint(hwnd, &ps);
- break;
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-void InitColourPicker(void)
-{
- WNDCLASS wcl = { 0 };
- wcl.lpfnWndProc = ColourPickerWndProc;
- wcl.cbWndExtra = sizeof(COLORREF) * 2;
- wcl.hInstance = g_hInst;
- wcl.lpszClassName = _T(WNDCLASS_COLOURPICKER);
- wcl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
- wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
- RegisterClass(&wcl);
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 LRESULT CALLBACK ColourPickerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_CREATE: + SetWindowLongPtr(hwnd, 0, 0); + SetWindowLongPtr(hwnd, sizeof(COLORREF), 0); + break; + + case CPM_SETDEFAULTCOLOUR: + SetWindowLongPtr(hwnd, sizeof(COLORREF), lParam); + break; + + case CPM_GETDEFAULTCOLOUR: + return GetWindowLongPtr(hwnd, sizeof(COLORREF)); + + case CPM_SETCOLOUR: + SetWindowLongPtr(hwnd, 0, lParam); + InvalidateRect(hwnd, nullptr, FALSE); + break; + + case CPM_GETCOLOUR: + return GetWindowLongPtr(hwnd, 0); + + case WM_LBUTTONUP: + { + COLORREF custColours[16] = { 0 }; + custColours[0] = GetWindowLongPtr(hwnd, sizeof(COLORREF)); + + CHOOSECOLOR cc = { 0 }; + cc.lStructSize = sizeof(CHOOSECOLOR); + cc.hwndOwner = hwnd; + cc.hInstance = (HWND)g_hInst; + cc.rgbResult = GetWindowLongPtr(hwnd, 0); + cc.lpCustColors = custColours; + cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT; + if (ChooseColor(&cc)) { + SetWindowLongPtr(hwnd, 0, cc.rgbResult); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), CPN_COLOURCHANGED), (LPARAM)hwnd); + InvalidateRect(hwnd, nullptr, FALSE); + } + } + break; + + case WM_ENABLE: + InvalidateRect(hwnd, nullptr, FALSE); + break; + + case WM_NCPAINT: + case WM_PAINT: + PAINTSTRUCT ps; + HDC hdc1 = BeginPaint(hwnd, &ps); + + RECT rc; + GetClientRect(hwnd, &rc); + DrawEdge(hdc1, &rc, EDGE_ETCHED, BF_RECT); + InflateRect(&rc, -2, -2); + + HBRUSH hBrush = (IsWindowEnabled(hwnd)) ? CreateSolidBrush(GetWindowLongPtr(hwnd, 0)) : CreateHatchBrush(HS_BDIAGONAL, GetSysColor(COLOR_GRAYTEXT)); + SetBkColor(hdc1, GetSysColor(COLOR_BTNFACE)); + FillRect(hdc1, &rc, hBrush); + DeleteObject(hBrush); + + EndPaint(hwnd, &ps); + break; + } + return DefWindowProc(hwnd, message, wParam, lParam); +} + +void InitColourPicker(void) +{ + WNDCLASS wcl = { 0 }; + wcl.lpfnWndProc = ColourPickerWndProc; + wcl.cbWndExtra = sizeof(COLORREF) * 2; + wcl.hInstance = g_hInst; + wcl.lpszClassName = _T(WNDCLASS_COLOURPICKER); + wcl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; + RegisterClass(&wcl); +} diff --git a/src/mir_core/src/hyperlink.cpp b/src/mir_core/src/Windows/hyperlink.cpp index 12aa157522..65ce93c54a 100644 --- a/src/mir_core/src/hyperlink.cpp +++ b/src/mir_core/src/Windows/hyperlink.cpp @@ -1,277 +1,277 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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"
-
-struct HyperlinkWndData
-{
- HFONT hEnableFont, hDisableFont;
- RECT rcText;
- COLORREF enableColor, disableColor, focusColor;
- BYTE flags; /* see HLKF_* */
-};
-
-/* flags */
-#define HLKF_HASENABLECOLOR 0x1 /* dat->enableColor is not system default */
-#define HLKF_HASDISABLECOLOR 0x2 /* dat->disableColor is not system default */
-
-/* internal messages */
-#define HLK_MEASURETEXT (WM_USER+1)
-#define HLK_INVALIDATE (WM_USER+2)
-
-static LRESULT CALLBACK HyperlinkWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- HyperlinkWndData *dat = (HyperlinkWndData*)GetWindowLongPtr(hwnd, 0);
-
- HDC hdc;
- RECT rc;
- POINT pt;
- HFONT hFont;
- LOGFONT lf;
- HCURSOR hCursor;
- COLORREF prevColor;
-
- switch (msg) {
- case WM_NCCREATE:
- dat = (struct HyperlinkWndData*)mir_calloc(sizeof(struct HyperlinkWndData));
- if (dat == nullptr)
- return FALSE; /* fail creation */
- SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); /* always succeeds */
- /* fall thru */
-
- case WM_SYSCOLORCHANGE:
- if (!(dat->flags&HLKF_HASENABLECOLOR)) {
- if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) dat->enableColor = RGB(0, 0, 255);
- else dat->enableColor = GetSysColor(COLOR_HOTLIGHT);
- dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
- }
- if (!(dat->flags&HLKF_HASDISABLECOLOR))
- dat->disableColor = GetSysColor(COLOR_GRAYTEXT);
- break;
-
- case WM_SETFOCUS:
- case WM_KILLFOCUS:
- RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE);
- break;
-
- case WM_MOUSEACTIVATE:
- SetFocus(hwnd);
- return MA_ACTIVATE;
-
- case WM_GETDLGCODE:
- if (lParam) {
- MSG *pMsg = (MSG *)lParam;
- if (pMsg->message == WM_KEYDOWN) {
- if (pMsg->wParam == VK_TAB)
- return 0;
- if (pMsg->wParam == VK_ESCAPE)
- return 0;
- }
- else if (pMsg->message == WM_CHAR) {
- if (pMsg->wParam == '\t')
- return 0;
- if (pMsg->wParam == 27)
- return 0;
- }
- }
- return DLGC_WANTMESSAGE;
-
- case WM_KEYDOWN:
- switch (wParam) {
- case VK_SPACE:
- case VK_RETURN:
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
- break;
- }
- return 0;
-
- case WM_LBUTTONDOWN:
- POINTSTOPOINT(pt, MAKEPOINTS(lParam));
- if (!PtInRect(&dat->rcText, pt)) break;
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
- return 0;
-
- case WM_SETFONT:
- if ((HFONT)wParam == nullptr) { /* use default system color */
- dat->hEnableFont = dat->hDisableFont = nullptr;
- return 0;
- }
- if (GetObject((HFONT)wParam, sizeof(lf), &lf)) {
- lf.lfUnderline = 1;
- hFont = CreateFontIndirect(&lf);
- if (hFont != nullptr) {
- dat->hEnableFont = hFont;
- dat->hDisableFont = (HFONT)wParam;
- if (LOWORD(lParam)) SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
- SendMessage(hwnd, HLK_MEASURETEXT, 0, 0);
- }
- }
- return 0;
-
- case WM_ERASEBKGND:
- return TRUE;
-
- case WM_ENABLE:
- case HLK_INVALIDATE:
- if (GetWindowRect(hwnd, &rc)) {
- pt.x = rc.left;
- pt.y = rc.top;
-
- HWND hwndParent = GetParent(hwnd);
- if (hwndParent == nullptr)
- hwndParent = hwnd;
- if (!ScreenToClient(hwndParent, &pt))
- break;
-
- rc.right = pt.x + (rc.right - rc.left);
- rc.bottom = pt.y + (rc.bottom - rc.top);
- rc.left = pt.x;
- rc.top = pt.y;
- InvalidateRect(hwndParent, &rc, TRUE);
- }
- return 0;
-
- case WM_GETFONT:
- return (LRESULT)dat->hDisableFont;
-
- case WM_CREATE:
- case HLK_MEASURETEXT:
- wchar_t szText[256];
- if (!GetWindowText(hwnd, szText, _countof(szText))) return 0;
- lParam = (LPARAM)szText;
- /* fall thru */
-
- case WM_SETTEXT:
- hdc = GetDC(hwnd);
- if (hdc == nullptr) /* text change failed */
- return 0;
- else {
- BOOL fMeasured = FALSE;
- HFONT hPrevFont = nullptr;
- if (dat->hEnableFont != nullptr) hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
- if (dat->hEnableFont == nullptr || hPrevFont != nullptr) { /* select failed? */
- SIZE textSize;
- if (GetTextExtentPoint32(hdc, (wchar_t*)lParam, (int)mir_wstrlen((wchar_t*)lParam), &textSize)) {
- if (GetClientRect(hwnd, &rc)) {
- dat->rcText.top = 0;
- dat->rcText.bottom = dat->rcText.top + textSize.cy;
- LONG style = GetWindowLongPtr(hwnd, GWL_STYLE);
- if (style & SS_CENTER) dat->rcText.left = (rc.right - textSize.cx) / 2;
- else if (style & SS_RIGHT) dat->rcText.left = rc.right - textSize.cx;
- else dat->rcText.left = 0;
- dat->rcText.right = dat->rcText.left + textSize.cx;
- fMeasured = TRUE;
- }
- }
- }
- if (dat->hEnableFont != nullptr && hPrevFont != nullptr)
- SelectObject(hdc, hPrevFont);
- ReleaseDC(hwnd, hdc);
- if (!fMeasured) /* text change failed */
- return 0;
-
- SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
- }
- break;
-
- case WM_SETCURSOR:
- if (!GetCursorPos(&pt)) return FALSE;
- if (!ScreenToClient(hwnd, &pt)) return FALSE;
- if (PtInRect(&dat->rcText, pt)) {
- hCursor = (HCURSOR)GetClassLongPtr(hwnd, GCLP_HCURSOR);
- if (hCursor == nullptr)
- hCursor = LoadCursor(nullptr, IDC_HAND); /* Win2000+ */
- }
- else hCursor = LoadCursor(nullptr, IDC_ARROW);
- SetCursor(hCursor);
- return TRUE;
-
- case HLK_SETENABLECOLOUR:
- prevColor = dat->enableColor;
- dat->enableColor = (COLORREF)wParam;
- dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
- dat->flags |= HLKF_HASENABLECOLOR;
- return (LRESULT)prevColor;
-
- case HLK_SETDISABLECOLOUR:
- prevColor = dat->disableColor;
- dat->disableColor = (COLORREF)wParam;
- dat->flags |= HLKF_HASDISABLECOLOR;
- return (LRESULT)prevColor;
-
- case WM_NCPAINT:
- return 0;
-
- case WM_PAINT:
- PAINTSTRUCT ps;
- hdc = BeginPaint(hwnd, &ps);
- if (hdc != nullptr) {
- HFONT hPrevFont;
- COLORREF textColor;
- if (IsWindowEnabled(hwnd)) {
- hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
- textColor = (GetFocus() == hwnd) ? dat->focusColor : dat->enableColor;
- }
- else {
- hPrevFont = (HFONT)SelectObject(hdc, dat->hDisableFont);
- textColor = dat->disableColor;
- }
- if (GetClientRect(hwnd, &rc) && GetWindowText(hwnd, szText, _countof(szText))) {
- BOOL fSmoothing;
- UINT fSmoothingType;
- SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fSmoothing, 0);
- SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &fSmoothingType, 0);
- if (fSmoothing && fSmoothingType == FE_FONTSMOOTHINGCLEARTYPE)
- DrawThemeParentBackground(hwnd, hdc, &rc);
- SetBkMode(hdc, TRANSPARENT);
- SetTextColor(hdc, textColor);
- UINT alignFlag = (GetWindowLongPtr(hwnd, GWL_STYLE) & (SS_CENTER | SS_RIGHT | SS_LEFT));
- DrawText(hdc, szText, -1, &rc, alignFlag | DT_NOPREFIX | DT_SINGLELINE | DT_TOP);
- }
- if (hPrevFont != nullptr) SelectObject(hdc, hPrevFont);
- EndPaint(hwnd, &ps);
- }
- return 0;
-
- case WM_NCDESTROY:
- if (dat->hEnableFont != nullptr) DeleteObject(dat->hEnableFont);
- mir_free(dat);
- break;
- }
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-void InitHyperlink(void)
-{
- g_hCursorNS = LoadCursor(nullptr, IDC_SIZENS);
- g_hCursorWE = LoadCursor(nullptr, IDC_SIZEWE);
-
- WNDCLASS wcl = { 0 };
- wcl.lpfnWndProc = HyperlinkWndProc;
- wcl.cbWndExtra = sizeof(struct HyperlinkWndData*);
- wcl.hInstance = g_hInst;
- wcl.lpszClassName = WNDCLASS_HYPERLINK;
- wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_PARENTDC;
- RegisterClass(&wcl); /* automatically unregistered on exit */
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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" + +struct HyperlinkWndData +{ + HFONT hEnableFont, hDisableFont; + RECT rcText; + COLORREF enableColor, disableColor, focusColor; + BYTE flags; /* see HLKF_* */ +}; + +/* flags */ +#define HLKF_HASENABLECOLOR 0x1 /* dat->enableColor is not system default */ +#define HLKF_HASDISABLECOLOR 0x2 /* dat->disableColor is not system default */ + +/* internal messages */ +#define HLK_MEASURETEXT (WM_USER+1) +#define HLK_INVALIDATE (WM_USER+2) + +static LRESULT CALLBACK HyperlinkWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HyperlinkWndData *dat = (HyperlinkWndData*)GetWindowLongPtr(hwnd, 0); + + HDC hdc; + RECT rc; + POINT pt; + HFONT hFont; + LOGFONT lf; + HCURSOR hCursor; + COLORREF prevColor; + + switch (msg) { + case WM_NCCREATE: + dat = (struct HyperlinkWndData*)mir_calloc(sizeof(struct HyperlinkWndData)); + if (dat == nullptr) + return FALSE; /* fail creation */ + SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); /* always succeeds */ + /* fall thru */ + + case WM_SYSCOLORCHANGE: + if (!(dat->flags&HLKF_HASENABLECOLOR)) { + if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) dat->enableColor = RGB(0, 0, 255); + else dat->enableColor = GetSysColor(COLOR_HOTLIGHT); + dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2); + } + if (!(dat->flags&HLKF_HASDISABLECOLOR)) + dat->disableColor = GetSysColor(COLOR_GRAYTEXT); + break; + + case WM_SETFOCUS: + case WM_KILLFOCUS: + RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE); + break; + + case WM_MOUSEACTIVATE: + SetFocus(hwnd); + return MA_ACTIVATE; + + case WM_GETDLGCODE: + if (lParam) { + MSG *pMsg = (MSG *)lParam; + if (pMsg->message == WM_KEYDOWN) { + if (pMsg->wParam == VK_TAB) + return 0; + if (pMsg->wParam == VK_ESCAPE) + return 0; + } + else if (pMsg->message == WM_CHAR) { + if (pMsg->wParam == '\t') + return 0; + if (pMsg->wParam == 27) + return 0; + } + } + return DLGC_WANTMESSAGE; + + case WM_KEYDOWN: + switch (wParam) { + case VK_SPACE: + case VK_RETURN: + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd); + break; + } + return 0; + + case WM_LBUTTONDOWN: + POINTSTOPOINT(pt, MAKEPOINTS(lParam)); + if (!PtInRect(&dat->rcText, pt)) break; + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd); + return 0; + + case WM_SETFONT: + if ((HFONT)wParam == nullptr) { /* use default system color */ + dat->hEnableFont = dat->hDisableFont = nullptr; + return 0; + } + if (GetObject((HFONT)wParam, sizeof(lf), &lf)) { + lf.lfUnderline = 1; + hFont = CreateFontIndirect(&lf); + if (hFont != nullptr) { + dat->hEnableFont = hFont; + dat->hDisableFont = (HFONT)wParam; + if (LOWORD(lParam)) SendMessage(hwnd, HLK_INVALIDATE, 0, 0); + SendMessage(hwnd, HLK_MEASURETEXT, 0, 0); + } + } + return 0; + + case WM_ERASEBKGND: + return TRUE; + + case WM_ENABLE: + case HLK_INVALIDATE: + if (GetWindowRect(hwnd, &rc)) { + pt.x = rc.left; + pt.y = rc.top; + + HWND hwndParent = GetParent(hwnd); + if (hwndParent == nullptr) + hwndParent = hwnd; + if (!ScreenToClient(hwndParent, &pt)) + break; + + rc.right = pt.x + (rc.right - rc.left); + rc.bottom = pt.y + (rc.bottom - rc.top); + rc.left = pt.x; + rc.top = pt.y; + InvalidateRect(hwndParent, &rc, TRUE); + } + return 0; + + case WM_GETFONT: + return (LRESULT)dat->hDisableFont; + + case WM_CREATE: + case HLK_MEASURETEXT: + wchar_t szText[256]; + if (!GetWindowText(hwnd, szText, _countof(szText))) return 0; + lParam = (LPARAM)szText; + /* fall thru */ + + case WM_SETTEXT: + hdc = GetDC(hwnd); + if (hdc == nullptr) /* text change failed */ + return 0; + else { + BOOL fMeasured = FALSE; + HFONT hPrevFont = nullptr; + if (dat->hEnableFont != nullptr) hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont); + if (dat->hEnableFont == nullptr || hPrevFont != nullptr) { /* select failed? */ + SIZE textSize; + if (GetTextExtentPoint32(hdc, (wchar_t*)lParam, (int)mir_wstrlen((wchar_t*)lParam), &textSize)) { + if (GetClientRect(hwnd, &rc)) { + dat->rcText.top = 0; + dat->rcText.bottom = dat->rcText.top + textSize.cy; + LONG style = GetWindowLongPtr(hwnd, GWL_STYLE); + if (style & SS_CENTER) dat->rcText.left = (rc.right - textSize.cx) / 2; + else if (style & SS_RIGHT) dat->rcText.left = rc.right - textSize.cx; + else dat->rcText.left = 0; + dat->rcText.right = dat->rcText.left + textSize.cx; + fMeasured = TRUE; + } + } + } + if (dat->hEnableFont != nullptr && hPrevFont != nullptr) + SelectObject(hdc, hPrevFont); + ReleaseDC(hwnd, hdc); + if (!fMeasured) /* text change failed */ + return 0; + + SendMessage(hwnd, HLK_INVALIDATE, 0, 0); + } + break; + + case WM_SETCURSOR: + if (!GetCursorPos(&pt)) return FALSE; + if (!ScreenToClient(hwnd, &pt)) return FALSE; + if (PtInRect(&dat->rcText, pt)) { + hCursor = (HCURSOR)GetClassLongPtr(hwnd, GCLP_HCURSOR); + if (hCursor == nullptr) + hCursor = LoadCursor(nullptr, IDC_HAND); /* Win2000+ */ + } + else hCursor = LoadCursor(nullptr, IDC_ARROW); + SetCursor(hCursor); + return TRUE; + + case HLK_SETENABLECOLOUR: + prevColor = dat->enableColor; + dat->enableColor = (COLORREF)wParam; + dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2); + dat->flags |= HLKF_HASENABLECOLOR; + return (LRESULT)prevColor; + + case HLK_SETDISABLECOLOUR: + prevColor = dat->disableColor; + dat->disableColor = (COLORREF)wParam; + dat->flags |= HLKF_HASDISABLECOLOR; + return (LRESULT)prevColor; + + case WM_NCPAINT: + return 0; + + case WM_PAINT: + PAINTSTRUCT ps; + hdc = BeginPaint(hwnd, &ps); + if (hdc != nullptr) { + HFONT hPrevFont; + COLORREF textColor; + if (IsWindowEnabled(hwnd)) { + hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont); + textColor = (GetFocus() == hwnd) ? dat->focusColor : dat->enableColor; + } + else { + hPrevFont = (HFONT)SelectObject(hdc, dat->hDisableFont); + textColor = dat->disableColor; + } + if (GetClientRect(hwnd, &rc) && GetWindowText(hwnd, szText, _countof(szText))) { + BOOL fSmoothing; + UINT fSmoothingType; + SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fSmoothing, 0); + SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &fSmoothingType, 0); + if (fSmoothing && fSmoothingType == FE_FONTSMOOTHINGCLEARTYPE) + DrawThemeParentBackground(hwnd, hdc, &rc); + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, textColor); + UINT alignFlag = (GetWindowLongPtr(hwnd, GWL_STYLE) & (SS_CENTER | SS_RIGHT | SS_LEFT)); + DrawText(hdc, szText, -1, &rc, alignFlag | DT_NOPREFIX | DT_SINGLELINE | DT_TOP); + } + if (hPrevFont != nullptr) SelectObject(hdc, hPrevFont); + EndPaint(hwnd, &ps); + } + return 0; + + case WM_NCDESTROY: + if (dat->hEnableFont != nullptr) DeleteObject(dat->hEnableFont); + mir_free(dat); + break; + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void InitHyperlink(void) +{ + g_hCursorNS = LoadCursor(nullptr, IDC_SIZENS); + g_hCursorWE = LoadCursor(nullptr, IDC_SIZEWE); + + WNDCLASS wcl = { 0 }; + wcl.lpfnWndProc = HyperlinkWndProc; + wcl.cbWndExtra = sizeof(struct HyperlinkWndData*); + wcl.hInstance = g_hInst; + wcl.lpszClassName = WNDCLASS_HYPERLINK; + wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_PARENTDC; + RegisterClass(&wcl); /* automatically unregistered on exit */ +} diff --git a/src/mir_core/src/icons.cpp b/src/mir_core/src/Windows/icons.cpp index 12ff1f5caf..b187f7ba0c 100644 --- a/src/mir_core/src/icons.cpp +++ b/src/mir_core/src/Windows/icons.cpp @@ -1,74 +1,74 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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"
-
-MIR_CORE_DLL(void) Icon_Register(HINSTANCE hInst, const char *szSection, IconItem *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
-{
- wchar_t szFile[MAX_PATH];
- GetModuleFileName(hInst, szFile, MAX_PATH);
-
- SKINICONDESC sid = {};
- sid.defaultFile.w = szFile;
- sid.section.a = (char*)szSection;
- sid.flags = SIDF_PATH_UNICODE;
-
- for (unsigned i = 0; i < iCount; i++) {
- char szSetting[100];
- if (prefix) {
- mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
- sid.pszName = szSetting;
- }
- else sid.pszName = pIcons[i].szName;
-
- sid.cx = sid.cy = pIcons[i].size;
- sid.description.a = pIcons[i].szDescr;
- sid.iDefaultIndex = -pIcons[i].defIconID;
- pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
- }
-}
-
-MIR_CORE_DLL(void) Icon_RegisterT(HINSTANCE hInst, const wchar_t *szSection, IconItemT *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
-{
- wchar_t szFile[MAX_PATH];
- GetModuleFileName(hInst, szFile, MAX_PATH);
-
- SKINICONDESC sid = {};
- sid.defaultFile.w = szFile;
- sid.section.w = (wchar_t*)szSection;
- sid.flags = SIDF_ALL_UNICODE;
-
- for (unsigned i = 0; i < iCount; i++) {
- char szSetting[100];
- if (prefix) {
- mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
- sid.pszName = szSetting;
- }
- else sid.pszName = pIcons[i].szName;
-
- sid.cx = sid.cy = pIcons[i].size;
- sid.description.w = pIcons[i].tszDescr;
- sid.iDefaultIndex = -pIcons[i].defIconID;
- pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
- }
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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" + +MIR_CORE_DLL(void) Icon_Register(HINSTANCE hInst, const char *szSection, IconItem *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin) +{ + wchar_t szFile[MAX_PATH]; + GetModuleFileName(hInst, szFile, MAX_PATH); + + SKINICONDESC sid = {}; + sid.defaultFile.w = szFile; + sid.section.a = (char*)szSection; + sid.flags = SIDF_PATH_UNICODE; + + for (unsigned i = 0; i < iCount; i++) { + char szSetting[100]; + if (prefix) { + mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName); + sid.pszName = szSetting; + } + else sid.pszName = pIcons[i].szName; + + sid.cx = sid.cy = pIcons[i].size; + sid.description.a = pIcons[i].szDescr; + sid.iDefaultIndex = -pIcons[i].defIconID; + pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin); + } +} + +MIR_CORE_DLL(void) Icon_RegisterT(HINSTANCE hInst, const wchar_t *szSection, IconItemT *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin) +{ + wchar_t szFile[MAX_PATH]; + GetModuleFileName(hInst, szFile, MAX_PATH); + + SKINICONDESC sid = {}; + sid.defaultFile.w = szFile; + sid.section.w = (wchar_t*)szSection; + sid.flags = SIDF_ALL_UNICODE; + + for (unsigned i = 0; i < iCount; i++) { + char szSetting[100]; + if (prefix) { + mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName); + sid.pszName = szSetting; + } + else sid.pszName = pIcons[i].szName; + + sid.cx = sid.cy = pIcons[i].size; + sid.description.w = pIcons[i].tszDescr; + sid.iDefaultIndex = -pIcons[i].defIconID; + pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin); + } +} diff --git a/src/mir_core/src/langpack.cpp b/src/mir_core/src/Windows/langpack.cpp index c16ebc878f..f877a7ca5f 100644 --- a/src/mir_core/src/langpack.cpp +++ b/src/mir_core/src/Windows/langpack.cpp @@ -1,765 +1,765 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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 "../../mir_app/src/langpack.h"
-
-#define LANGPACK_BUF_SIZE 4000
-
-static int CompareMuuids(const MUUID *p1, const MUUID *p2)
-{
- return memcmp(p1, p2, sizeof(MUUID));
-}
-
-static LIST<MUUID> lMuuids(10, CompareMuuids);
-static MUUID *pCurrentMuuid = nullptr;
-static HANDLE hevChanged = nullptr;
-
-static BOOL bModuleInitialized = FALSE;
-
-struct LangPackEntry
-{
- DWORD englishHash;
- char *szLocal;
- char *utfLocal;
- wchar_t *wszLocal;
- MUUID *pMuuid;
- LangPackEntry* pNext; // for langpack items with the same hash value
-};
-
-static LANGPACK_INFO langPack;
-static wchar_t g_tszRoot[MAX_PATH];
-
-static LangPackEntry *g_pEntries;
-static int g_entryCount, g_entriesAlloced;
-
-static int IsEmpty(const char *str)
-{
- for (int i = 0; str[i]; i++)
- if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n')
- return 0;
-
- return 1;
-}
-
-static int ConvertBackslashes(char *str, UINT fileCp)
-{
- int shift = 0;
- char *pstr;
- for (pstr = str; *pstr; pstr = CharNextExA(fileCp, pstr, 0)) {
- if (*pstr == '\\') {
- shift++;
- switch (pstr[1]) {
- case 'n': *pstr = '\n'; break;
- case 't': *pstr = '\t'; break;
- case 'r': *pstr = '\r'; break;
- case 's': *pstr = ' '; break;
- default: *pstr = pstr[1]; break;
- }
- memmove(pstr + 1, pstr + 2, strlen(pstr + 2) + 1);
- }
- }
- return shift;
-}
-
-#ifdef _DEBUG
-//#pragma optimize("gt", on)
-#endif
-
-// MurmurHash2
-MIR_CORE_DLL(unsigned int) mir_hash(const void * key, unsigned int len)
-{
- // 'm' and 'r' are mixing constants generated offline.
- // They're not really 'magic', they just happen to work well.
- const unsigned int m = 0x5bd1e995;
- const int r = 24;
-
- // Initialize the hash to a 'random' value
- unsigned int h = len;
-
- // Mix 4 bytes at a time into the hash
- const unsigned char *data = (const unsigned char*)key;
-
- while (len >= 4) {
- unsigned int k = *(unsigned int*)data;
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- // Handle the last few bytes of the input array
- switch (len) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0];
- h *= m;
- }
-
- // Do a few final mixes of the hash to ensure the last few
- // bytes are well-incorporated.
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
-
-static unsigned int __fastcall hashstrW(const char *key)
-{
- if (key == nullptr) return 0;
- const unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
- char *buf = (char*)alloca(len + 1);
- for (unsigned i = 0; i <= len; ++i)
- buf[i] = key[i << 1];
- return mir_hash(buf, len);
-}
-
-static const MUUID* GetMuid(HPLUGIN pPlugin)
-{
- if (!pPlugin)
- return nullptr;
-
- __try {
- return &pPlugin->getInfo().uuid;
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- return nullptr;
- }
-}
-
-static int SortLangPackHashesProc(LangPackEntry *arg1, LangPackEntry *arg2)
-{
- if (arg1->englishHash < arg2->englishHash) return -1;
- if (arg1->englishHash > arg2->englishHash) return 1;
-
- return (arg1->pMuuid < arg2->pMuuid) ? -1 : 1;
-}
-
-static void swapBytes(void *p, size_t iSize)
-{
- char *head = (char*)p; // here
- char *tail = head + iSize - 1;
-
- for (; tail > head; --tail, ++head) {
- char temp = *head;
- *head = *tail;
- *tail = temp;
- }
-}
-
-static bool EnterMuuid(const char *p, MUUID &result)
-{
- if (*p++ != '{')
- return false;
-
- BYTE *d = (BYTE*)&result;
-
- for (int nBytes = 0; *p && nBytes < 24; p++) {
- if (*p == '-')
- continue;
-
- if (*p == '}')
- break;
-
- if (!isxdigit(*p))
- return false;
-
- if (!isxdigit(p[1]))
- return false;
-
- int c = 0;
- if (sscanf(p, "%2x", &c) != 1)
- return false;
-
- *d++ = (BYTE)c;
- nBytes++;
- p++;
- }
-
- if (*p != '}')
- return false;
-
- swapBytes(&result.a, sizeof(result.a));
- swapBytes(&result.b, sizeof(result.b));
- swapBytes(&result.c, sizeof(result.c));
- return true;
-}
-
-static void LoadLangPackFile(FILE *fp, char *line)
-{
- while (!feof(fp)) {
- if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
- break;
-
- if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
- continue;
-
- rtrim(line);
-
- if (line[0] == '#') {
- strlwr(line);
-
- if (!memcmp(line + 1, "include", 7)) {
- wchar_t tszFileName[MAX_PATH];
- wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
- if (p)
- *p = 0;
- mir_snwprintf(tszFileName, L"%s\\%S", langPack.tszFullPath, ltrim(line + 9));
- if (p)
- *p = '\\';
-
- FILE *fpNew = _wfopen(tszFileName, L"r");
- if (fpNew) {
- line[0] = 0;
- fgets(line, LANGPACK_BUF_SIZE, fpNew);
-
- if (strlen(line) >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
- fseek(fpNew, 3, SEEK_SET);
- else
- fseek(fpNew, 0, SEEK_SET);
-
- LoadLangPackFile(fpNew, line);
- fclose(fpNew);
- }
- }
- else if (!memcmp(line + 1, "muuid", 5)) {
- MUUID t;
- if (!EnterMuuid(line + 7, t))
- continue;
-
- MUUID *pNew = (MUUID*)mir_alloc(sizeof(MUUID));
- memcpy(pNew, &t, sizeof(t));
- lMuuids.insert(pNew);
- pCurrentMuuid = pNew;
- }
-
- continue;
- }
-
- char cFirst = line[0];
-
- ConvertBackslashes(line, CP_UTF8);
-
- size_t cbLen = strlen(line) - 1;
- if (cFirst == '[' && line[cbLen] == ']') {
- if (g_entryCount && g_pEntries[g_entryCount-1].wszLocal == nullptr)
- g_entryCount--;
-
- char *pszLine = line + 1;
- line[cbLen] = '\0';
- if (++g_entryCount > g_entriesAlloced) {
- g_entriesAlloced += 128;
- g_pEntries = (LangPackEntry*)mir_realloc(g_pEntries, sizeof(LangPackEntry)*g_entriesAlloced);
- }
-
- LangPackEntry *E = &g_pEntries[g_entryCount - 1];
- E->englishHash = mir_hashstr(pszLine);
- E->szLocal = E->utfLocal = nullptr;
- E->wszLocal = nullptr;
- E->pMuuid = pCurrentMuuid;
- E->pNext = nullptr;
- continue;
- }
-
- if (!g_entryCount)
- continue;
-
- LangPackEntry *E = &g_pEntries[g_entryCount - 1];
- int iNeeded = MultiByteToWideChar(CP_UTF8, 0, line, -1, nullptr, 0), iOldLen;
- if (E->wszLocal == nullptr) {
- iOldLen = 0;
- E->wszLocal = (wchar_t *)mir_alloc((iNeeded + 1) * sizeof(wchar_t));
- MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal, iNeeded);
- }
- else {
- iOldLen = (int)wcslen(E->wszLocal);
- E->wszLocal = (wchar_t*)mir_realloc(E->wszLocal, (sizeof(wchar_t)* (iOldLen + iNeeded + 2)));
- E->wszLocal[iOldLen++] = '\n';
- }
- MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal + iOldLen, iNeeded);
- }
-}
-
-static int LoadLangDescr(LANGPACK_INFO &lpinfo, FILE *fp, char *line, int &startOfLine)
-{
- char szLanguage[64]; szLanguage[0] = 0;
- CMStringA szAuthors;
-
- lpinfo.codepage = CP_ACP;
- lpinfo.flags = 0;
- lpinfo.tszLanguage[0] = 0;
-
- fgets(line, LANGPACK_BUF_SIZE, fp);
- size_t lineLen = strlen(line);
- if (lineLen >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
- memmove(line, line + 3, lineLen - 2);
-
- lrtrim(line);
- if (mir_strcmp(line, "Miranda Language Pack Version 1"))
- return 2;
-
- // headers
- while (!feof(fp)) {
- startOfLine = ftell(fp);
- if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
- break;
-
- lrtrim(line);
- if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
- continue;
-
- if (line[0] == '[' || line[0] == '#')
- break;
-
- char *pszColon = strchr(line, ':');
- if (pszColon == nullptr)
- return 3;
-
- *pszColon++ = 0;
- if (!mir_strcmp(line, "Language")) {
- strncpy_s(szLanguage, pszColon, _TRUNCATE);
- lrtrim(szLanguage);
- }
- else if (!mir_strcmp(line, "Last-Modified-Using")) {
- lpinfo.szLastModifiedUsing = pszColon;
- lpinfo.szLastModifiedUsing.Trim();
- }
- else if (!mir_strcmp(line, "Authors")) {
- if (!szAuthors.IsEmpty())
- szAuthors.AppendChar(' ');
- szAuthors.Append(lrtrim(pszColon));
- }
- else if (!mir_strcmp(line, "Locale")) {
- char szBuf[20], *stopped;
-
- lrtrim(pszColon + 1);
- USHORT langID = (USHORT)strtol(pszColon, &stopped, 16);
- lpinfo.Locale = MAKELCID(langID, 0);
- GetLocaleInfoA(lpinfo.Locale, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10);
- szBuf[5] = 0; // codepages have max. 5 digits
- lpinfo.codepage = atoi(szBuf);
- }
- }
-
- lpinfo.szAuthors = szAuthors;
-
- ptrW buf(mir_utf8decodeW(szLanguage));
- if (buf)
- wcsncpy_s(lpinfo.tszLanguage, buf, _TRUNCATE);
- else if (lpinfo.Locale != 0)
- GetLocaleInfo(lpinfo.Locale, LOCALE_SENGLANGUAGE, lpinfo.tszLanguage, _countof(lpinfo.tszLanguage));
-
- if (!lpinfo.tszLanguage[0]) {
- wchar_t *p = wcschr(lpinfo.tszFileName, '_');
- wcsncpy_s(lpinfo.tszLanguage, ((p != nullptr) ? (p + 1) : lpinfo.tszFileName), _TRUNCATE);
- p = wcsrchr(lpinfo.tszLanguage, '.');
- if (p != nullptr) *p = '\0';
- }
- return 0;
-}
-
-MIR_CORE_DLL(int) LoadLangPack(const wchar_t *ptszLangPack)
-{
- if (ptszLangPack == nullptr || !mir_wstrcmpi(ptszLangPack, L""))
- return 1;
-
- // ensure that a lang's name is a full file name
- wchar_t tszFullPath[MAX_PATH];
- if (!PathIsAbsoluteW(ptszLangPack))
- mir_snwprintf(tszFullPath, L"%s\\%s", g_tszRoot, ptszLangPack);
- else
- wcsncpy_s(tszFullPath, ptszLangPack, _TRUNCATE);
-
- // this lang is already loaded? nothing to do then
- if (!mir_wstrcmp(tszFullPath, langPack.tszFullPath))
- return 0;
-
- // ok... loading a new langpack. remove the old one if needed
- if (g_entryCount)
- UnloadLangPackModule();
-
- langPack.Locale = 0;
- langPack.codepage = CP_ACP;
- langPack.flags = 0;
-
- // exists & not a directory?
- DWORD dwAttrib = GetFileAttributes(tszFullPath);
- if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
- return 3;
-
- // copy the full file name and extract a file name from it
- wcsncpy_s(langPack.tszFullPath, tszFullPath, _TRUNCATE);
- wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
- wcsncpy_s(langPack.tszFileName, (p == nullptr) ? tszFullPath : p + 1, _TRUNCATE);
- CharLower(langPack.tszFileName);
-
- FILE *fp = _wfopen(tszFullPath, L"rt");
- if (fp == nullptr)
- return 1;
-
- char line[LANGPACK_BUF_SIZE] = "";
- int startOfLine = 0;
- if (LoadLangDescr(langPack, fp, line, startOfLine)) {
- fclose(fp);
- return 1;
- }
-
- // body
- fseek(fp, startOfLine, SEEK_SET);
-
- LoadLangPackFile(fp, line);
- fclose(fp);
- pCurrentMuuid = nullptr;
-
- qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
- return 0;
-}
-
-MIR_CORE_DLL(int) LoadLangPackDescr(const wchar_t *ptszLangPack, LANGPACK_INFO *lpInfo)
-{
- if (lpInfo == nullptr)
- return 1;
-
- wcsncpy_s(lpInfo->tszFullPath, ptszLangPack, _TRUNCATE);
- wchar_t *p = wcsrchr(lpInfo->tszFullPath, '\\');
- wcsncpy_s(lpInfo->tszFileName, (p == nullptr) ? ptszLangPack : p+1, _TRUNCATE);
- CharLower(lpInfo->tszFileName);
-
- FILE *fp = _wfopen(ptszLangPack, L"rt");
- if (fp == nullptr)
- return 1;
-
- char line[LANGPACK_BUF_SIZE] = "";
- int startOfLine = 0;
- int res = LoadLangDescr(*lpInfo, fp, line, startOfLine);
- fclose(fp);
- return res;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static int SortLangPackHashesProc2(LangPackEntry *arg1, LangPackEntry *arg2)
-{
- if (arg1->englishHash < arg2->englishHash) return -1;
- if (arg1->englishHash > arg2->englishHash) return 1;
- return 0;
-}
-
-char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W)
-{
- if (g_entryCount == 0 || szEnglish == nullptr)
- return (char*)szEnglish;
-
- LangPackEntry key, *entry;
- key.englishHash = (W == 1) ? hashstrW(szEnglish) : mir_hashstr(szEnglish);
- entry = (LangPackEntry*)bsearch(&key, g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc2);
- if (entry == nullptr)
- return (char*)szEnglish;
-
- // try to find the exact match, otherwise the first entry will be returned
- if (pUuid) {
- for (LangPackEntry *p = entry->pNext; p != nullptr; p = p->pNext) {
- if (*p->pMuuid == *pUuid) {
- entry = p;
- break;
- }
- }
- }
-
- switch (W) {
- case 0:
- if (entry->szLocal == nullptr && entry->wszLocal != nullptr)
- entry->szLocal = mir_u2a_cp(entry->wszLocal, langPack.codepage);
- return entry->szLocal;
-
- case 1:
- return (char*)entry->wszLocal;
-
- case 2:
- if (entry->utfLocal == nullptr && entry->wszLocal != nullptr)
- entry->utfLocal = mir_utf8encodeW(entry->wszLocal);
- return entry->utfLocal;
- }
-
- return nullptr;
-}
-
-MIR_CORE_DLL(int) Langpack_GetDefaultCodePage()
-{
- return langPack.codepage;
-}
-
-MIR_CORE_DLL(int) Langpack_GetDefaultLocale()
-{
- return (langPack.Locale == 0) ? LOCALE_USER_DEFAULT : langPack.Locale;
-}
-
-MIR_CORE_DLL(wchar_t*) Langpack_PcharToTchar(const char *pszStr)
-{
- if (pszStr == nullptr)
- return nullptr;
-
- int len = (int)strlen(pszStr);
- wchar_t *result = (wchar_t*)alloca((len + 1)*sizeof(wchar_t));
- MultiByteToWideChar(Langpack_GetDefaultCodePage(), 0, pszStr, -1, result, len);
- result[len] = 0;
- return mir_wstrdup(TranslateW_LP(result));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(char*) TranslateA_LP(const char *str, HPLUGIN pPlugin)
-{
- return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 0);
-}
-
-MIR_CORE_DLL(char*) TranslateU_LP(const char *str, HPLUGIN pPlugin)
-{
- return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 2);
-}
-
-MIR_CORE_DLL(wchar_t*) TranslateW_LP(const wchar_t *str, HPLUGIN pPlugin)
-{
- return (wchar_t*)LangPackTranslateString(GetMuid(pPlugin), (LPCSTR)str, 1);
-}
-
-MIR_CORE_DLL(void) TranslateMenu_LP(HMENU hMenu, HPLUGIN pPlugin)
-{
- const MUUID *uuid = &pPlugin->getInfo().uuid;
-
- MENUITEMINFO mii = { 0 };
- mii.cbSize = sizeof(mii);
-
- for (int i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) {
- wchar_t str[256];
- mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
- mii.dwTypeData = (wchar_t*)str;
- mii.cch = _countof(str);
- GetMenuItemInfo(hMenu, i, TRUE, &mii);
-
- if (mii.cch && mii.dwTypeData) {
- wchar_t *result = (wchar_t*)LangPackTranslateString(uuid, (const char*)mii.dwTypeData, TRUE);
- if (result != mii.dwTypeData) {
- mii.dwTypeData = result;
- mii.fMask = MIIM_TYPE;
- SetMenuItemInfo(hMenu, i, TRUE, &mii);
- }
- }
-
- if (mii.hSubMenu != nullptr)
- TranslateMenu_LP(mii.hSubMenu, pPlugin);
- }
-}
-
-static void TranslateWindow(const MUUID *pUuid, HWND hwnd)
-{
- wchar_t title[2048];
- GetWindowText(hwnd, title, _countof(title));
-
- wchar_t *result = (wchar_t*)LangPackTranslateString(pUuid, (const char*)title, TRUE);
- if (result != title)
- SetWindowText(hwnd, result);
-}
-
-static BOOL CALLBACK TranslateDialogEnumProc(HWND hwnd, LPARAM lParam)
-{
- HPLUGIN pPlugin = (HPLUGIN)lParam;
- const MUUID *uuid = GetMuid(pPlugin);
-
- wchar_t szClass[32];
- GetClassName(hwnd, szClass, _countof(szClass));
- if (!mir_wstrcmpi(szClass, L"static") || !mir_wstrcmpi(szClass, L"hyperlink") || !mir_wstrcmpi(szClass, L"button") || !mir_wstrcmpi(szClass, L"MButtonClass") || !mir_wstrcmpi(szClass, L"MHeaderbarCtrl"))
- TranslateWindow(uuid, hwnd);
- else if (!mir_wstrcmpi(szClass, L"edit")) {
- if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY)
- TranslateWindow(uuid, hwnd);
- }
- return TRUE;
-}
-
-MIR_CORE_DLL(void) TranslateDialog_LP(HWND hDlg, HPLUGIN pPlugin)
-{
- TranslateWindow(GetMuid(pPlugin), hDlg);
- EnumChildWindows(hDlg, TranslateDialogEnumProc, (LPARAM)pPlugin);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) Langpack_SortDuplicates(void)
-{
- if (g_entryCount == 0)
- return;
-
- LangPackEntry *s = g_pEntries + 1, *d = s, *pLast = g_pEntries;
- DWORD dwSavedHash = g_pEntries->englishHash;
- bool bSortNeeded = false;
-
- for (int i = 1; i < g_entryCount; i++, s++) {
- if (s->englishHash != dwSavedHash) {
- pLast = d;
- if (s != d)
- *d++ = *s;
- else
- d++;
- dwSavedHash = s->englishHash;
- }
- else {
- bSortNeeded = true;
- LangPackEntry *p = (LangPackEntry*)mir_alloc(sizeof(LangPackEntry));
- *p = *s;
- pLast->pNext = p; pLast = p;
- }
- }
-
- if (bSortNeeded) {
- g_entryCount = (int)(d - g_pEntries);
- qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void GetDefaultLang()
-{
- // calculate the langpacks' root
- PathToAbsoluteW(L"\\Languages", g_tszRoot);
- if (_waccess(g_tszRoot, 0) != 0) // directory Languages exists
- PathToAbsoluteW(L".", g_tszRoot);
-
- // look into mirandaboot.ini
- wchar_t tszLangName[256];
- Profile_GetSetting(L"Language/DefaultLanguage", tszLangName);
- if (tszLangName[0]) {
- if (!mir_wstrcmpi(tszLangName, L"default")) {
- db_set_ws(0, "Langpack", "Current", L"default");
- return;
- }
- if (!LoadLangPack(tszLangName)) {
- db_set_ws(0, "Langpack", "Current", tszLangName);
- return;
- }
- }
-
- // try to load langpack that matches UserDefaultUILanguage
- wchar_t tszPath[MAX_PATH];
- if (GetLocaleInfo(MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT), LOCALE_SENGLANGUAGE, tszLangName, _countof(tszLangName))) {
- mir_snwprintf(tszPath, L"langpack_%s.txt", wcslwr(tszLangName));
- if (!LoadLangPack(tszPath)) {
- db_set_ws(0, "Langpack", "Current", tszPath);
- return;
- }
- }
-
- // finally try to load first file
- mir_snwprintf(tszPath, L"%s\\langpack_*.txt", g_tszRoot);
-
- WIN32_FIND_DATA fd;
- HANDLE hFind = FindFirstFile(tszPath, &fd);
- if (hFind != INVALID_HANDLE_VALUE) {
- do {
- /* search first langpack that could be loaded */
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- continue;
-
- if (!LoadLangPack(fd.cFileName)) {
- db_set_ws(0, "Langpack", "Current", fd.cFileName);
- break;
- }
- } while (FindNextFile(hFind, &fd));
- FindClose(hFind);
- }
- else db_set_ws(0, "Langpack", "Current", L"default");
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) ReloadLangpack(wchar_t *pszStr)
-{
- if (pszStr == nullptr)
- pszStr = NEWWSTR_ALLOCA(langPack.tszFileName);
-
- UnloadLangPackModule();
- LoadLangPack(pszStr);
- Langpack_SortDuplicates();
-
- NotifyEventHooks(hevChanged, 0, 0);
-}
-
-static INT_PTR srvReloadLangpack(WPARAM, LPARAM lParam)
-{
- ReloadLangpack((wchar_t*)lParam);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) LoadLangPackModule(void)
-{
- bModuleInitialized = TRUE;
- hevChanged = CreateHookableEvent(ME_LANGPACK_CHANGED);
- CreateServiceFunction(MS_LANGPACK_RELOAD, srvReloadLangpack);
- GetDefaultLang();
- return 0;
-}
-
-void UnloadLangPackModule()
-{
- if (!bModuleInitialized) return;
-
- for (auto &it : lMuuids)
- mir_free(it);
- lMuuids.destroy();
-
- LangPackEntry *p = g_pEntries;
- for (int i = 0; i < g_entryCount; i++, p++) {
- if (p->pNext != nullptr) {
- for (LangPackEntry *p1 = p->pNext; p1 != nullptr;) {
- LangPackEntry *p2 = p1; p1 = p1->pNext;
- mir_free(p2->szLocal);
- mir_free(p2->wszLocal);
- mir_free(p2);
- }
- }
-
- mir_free(p->szLocal);
- mir_free(p->wszLocal);
- }
-
- if (g_entryCount) {
- mir_free(g_pEntries);
- g_pEntries = nullptr;
- g_entryCount = g_entriesAlloced = 0;
- }
-
- langPack.tszFileName[0] = langPack.tszFullPath[0] = 0;
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 "../../../mir_app/src/langpack.h" + +#define LANGPACK_BUF_SIZE 4000 + +static int CompareMuuids(const MUUID *p1, const MUUID *p2) +{ + return memcmp(p1, p2, sizeof(MUUID)); +} + +static LIST<MUUID> lMuuids(10, CompareMuuids); +static MUUID *pCurrentMuuid = nullptr; +static HANDLE hevChanged = nullptr; + +static BOOL bModuleInitialized = FALSE; + +struct LangPackEntry +{ + DWORD englishHash; + char *szLocal; + char *utfLocal; + wchar_t *wszLocal; + MUUID *pMuuid; + LangPackEntry* pNext; // for langpack items with the same hash value +}; + +static LANGPACK_INFO langPack; +static wchar_t g_tszRoot[MAX_PATH]; + +static LangPackEntry *g_pEntries; +static int g_entryCount, g_entriesAlloced; + +static int IsEmpty(const char *str) +{ + for (int i = 0; str[i]; i++) + if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n') + return 0; + + return 1; +} + +static int ConvertBackslashes(char *str, UINT fileCp) +{ + int shift = 0; + char *pstr; + for (pstr = str; *pstr; pstr = CharNextExA(fileCp, pstr, 0)) { + if (*pstr == '\\') { + shift++; + switch (pstr[1]) { + case 'n': *pstr = '\n'; break; + case 't': *pstr = '\t'; break; + case 'r': *pstr = '\r'; break; + case 's': *pstr = ' '; break; + default: *pstr = pstr[1]; break; + } + memmove(pstr + 1, pstr + 2, strlen(pstr + 2) + 1); + } + } + return shift; +} + +#ifdef _DEBUG +//#pragma optimize("gt", on) +#endif + +// MurmurHash2 +MIR_CORE_DLL(unsigned int) mir_hash(const void * key, unsigned int len) +{ + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + const unsigned int m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + unsigned int h = len; + + // Mix 4 bytes at a time into the hash + const unsigned char *data = (const unsigned char*)key; + + while (len >= 4) { + unsigned int k = *(unsigned int*)data; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + // Handle the last few bytes of the input array + switch (len) { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + } + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} + +static unsigned int __fastcall hashstrW(const char *key) +{ + if (key == nullptr) return 0; + const unsigned int len = (unsigned int)wcslen((const wchar_t*)key); + char *buf = (char*)alloca(len + 1); + for (unsigned i = 0; i <= len; ++i) + buf[i] = key[i << 1]; + return mir_hash(buf, len); +} + +static const MUUID* GetMuid(HPLUGIN pPlugin) +{ + if (!pPlugin) + return nullptr; + + __try { + return &pPlugin->getInfo().uuid; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return nullptr; + } +} + +static int SortLangPackHashesProc(LangPackEntry *arg1, LangPackEntry *arg2) +{ + if (arg1->englishHash < arg2->englishHash) return -1; + if (arg1->englishHash > arg2->englishHash) return 1; + + return (arg1->pMuuid < arg2->pMuuid) ? -1 : 1; +} + +static void swapBytes(void *p, size_t iSize) +{ + char *head = (char*)p; // here + char *tail = head + iSize - 1; + + for (; tail > head; --tail, ++head) { + char temp = *head; + *head = *tail; + *tail = temp; + } +} + +static bool EnterMuuid(const char *p, MUUID &result) +{ + if (*p++ != '{') + return false; + + BYTE *d = (BYTE*)&result; + + for (int nBytes = 0; *p && nBytes < 24; p++) { + if (*p == '-') + continue; + + if (*p == '}') + break; + + if (!isxdigit(*p)) + return false; + + if (!isxdigit(p[1])) + return false; + + int c = 0; + if (sscanf(p, "%2x", &c) != 1) + return false; + + *d++ = (BYTE)c; + nBytes++; + p++; + } + + if (*p != '}') + return false; + + swapBytes(&result.a, sizeof(result.a)); + swapBytes(&result.b, sizeof(result.b)); + swapBytes(&result.c, sizeof(result.c)); + return true; +} + +static void LoadLangPackFile(FILE *fp, char *line) +{ + while (!feof(fp)) { + if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr) + break; + + if (IsEmpty(line) || line[0] == ';' || line[0] == 0) + continue; + + rtrim(line); + + if (line[0] == '#') { + strlwr(line); + + if (!memcmp(line + 1, "include", 7)) { + wchar_t tszFileName[MAX_PATH]; + wchar_t *p = wcsrchr(langPack.tszFullPath, '\\'); + if (p) + *p = 0; + mir_snwprintf(tszFileName, L"%s\\%S", langPack.tszFullPath, ltrim(line + 9)); + if (p) + *p = '\\'; + + FILE *fpNew = _wfopen(tszFileName, L"r"); + if (fpNew) { + line[0] = 0; + fgets(line, LANGPACK_BUF_SIZE, fpNew); + + if (strlen(line) >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf') + fseek(fpNew, 3, SEEK_SET); + else + fseek(fpNew, 0, SEEK_SET); + + LoadLangPackFile(fpNew, line); + fclose(fpNew); + } + } + else if (!memcmp(line + 1, "muuid", 5)) { + MUUID t; + if (!EnterMuuid(line + 7, t)) + continue; + + MUUID *pNew = (MUUID*)mir_alloc(sizeof(MUUID)); + memcpy(pNew, &t, sizeof(t)); + lMuuids.insert(pNew); + pCurrentMuuid = pNew; + } + + continue; + } + + char cFirst = line[0]; + + ConvertBackslashes(line, CP_UTF8); + + size_t cbLen = strlen(line) - 1; + if (cFirst == '[' && line[cbLen] == ']') { + if (g_entryCount && g_pEntries[g_entryCount-1].wszLocal == nullptr) + g_entryCount--; + + char *pszLine = line + 1; + line[cbLen] = '\0'; + if (++g_entryCount > g_entriesAlloced) { + g_entriesAlloced += 128; + g_pEntries = (LangPackEntry*)mir_realloc(g_pEntries, sizeof(LangPackEntry)*g_entriesAlloced); + } + + LangPackEntry *E = &g_pEntries[g_entryCount - 1]; + E->englishHash = mir_hashstr(pszLine); + E->szLocal = E->utfLocal = nullptr; + E->wszLocal = nullptr; + E->pMuuid = pCurrentMuuid; + E->pNext = nullptr; + continue; + } + + if (!g_entryCount) + continue; + + LangPackEntry *E = &g_pEntries[g_entryCount - 1]; + int iNeeded = MultiByteToWideChar(CP_UTF8, 0, line, -1, nullptr, 0), iOldLen; + if (E->wszLocal == nullptr) { + iOldLen = 0; + E->wszLocal = (wchar_t *)mir_alloc((iNeeded + 1) * sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal, iNeeded); + } + else { + iOldLen = (int)wcslen(E->wszLocal); + E->wszLocal = (wchar_t*)mir_realloc(E->wszLocal, (sizeof(wchar_t)* (iOldLen + iNeeded + 2))); + E->wszLocal[iOldLen++] = '\n'; + } + MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal + iOldLen, iNeeded); + } +} + +static int LoadLangDescr(LANGPACK_INFO &lpinfo, FILE *fp, char *line, int &startOfLine) +{ + char szLanguage[64]; szLanguage[0] = 0; + CMStringA szAuthors; + + lpinfo.codepage = CP_ACP; + lpinfo.flags = 0; + lpinfo.tszLanguage[0] = 0; + + fgets(line, LANGPACK_BUF_SIZE, fp); + size_t lineLen = strlen(line); + if (lineLen >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf') + memmove(line, line + 3, lineLen - 2); + + lrtrim(line); + if (mir_strcmp(line, "Miranda Language Pack Version 1")) + return 2; + + // headers + while (!feof(fp)) { + startOfLine = ftell(fp); + if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr) + break; + + lrtrim(line); + if (IsEmpty(line) || line[0] == ';' || line[0] == 0) + continue; + + if (line[0] == '[' || line[0] == '#') + break; + + char *pszColon = strchr(line, ':'); + if (pszColon == nullptr) + return 3; + + *pszColon++ = 0; + if (!mir_strcmp(line, "Language")) { + strncpy_s(szLanguage, pszColon, _TRUNCATE); + lrtrim(szLanguage); + } + else if (!mir_strcmp(line, "Last-Modified-Using")) { + lpinfo.szLastModifiedUsing = pszColon; + lpinfo.szLastModifiedUsing.Trim(); + } + else if (!mir_strcmp(line, "Authors")) { + if (!szAuthors.IsEmpty()) + szAuthors.AppendChar(' '); + szAuthors.Append(lrtrim(pszColon)); + } + else if (!mir_strcmp(line, "Locale")) { + char szBuf[20], *stopped; + + lrtrim(pszColon + 1); + USHORT langID = (USHORT)strtol(pszColon, &stopped, 16); + lpinfo.Locale = MAKELCID(langID, 0); + GetLocaleInfoA(lpinfo.Locale, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10); + szBuf[5] = 0; // codepages have max. 5 digits + lpinfo.codepage = atoi(szBuf); + } + } + + lpinfo.szAuthors = szAuthors; + + ptrW buf(mir_utf8decodeW(szLanguage)); + if (buf) + wcsncpy_s(lpinfo.tszLanguage, buf, _TRUNCATE); + else if (lpinfo.Locale != 0) + GetLocaleInfo(lpinfo.Locale, LOCALE_SENGLANGUAGE, lpinfo.tszLanguage, _countof(lpinfo.tszLanguage)); + + if (!lpinfo.tszLanguage[0]) { + wchar_t *p = wcschr(lpinfo.tszFileName, '_'); + wcsncpy_s(lpinfo.tszLanguage, ((p != nullptr) ? (p + 1) : lpinfo.tszFileName), _TRUNCATE); + p = wcsrchr(lpinfo.tszLanguage, '.'); + if (p != nullptr) *p = '\0'; + } + return 0; +} + +MIR_CORE_DLL(int) LoadLangPack(const wchar_t *ptszLangPack) +{ + if (ptszLangPack == nullptr || !mir_wstrcmpi(ptszLangPack, L"")) + return 1; + + // ensure that a lang's name is a full file name + wchar_t tszFullPath[MAX_PATH]; + if (!PathIsAbsoluteW(ptszLangPack)) + mir_snwprintf(tszFullPath, L"%s\\%s", g_tszRoot, ptszLangPack); + else + wcsncpy_s(tszFullPath, ptszLangPack, _TRUNCATE); + + // this lang is already loaded? nothing to do then + if (!mir_wstrcmp(tszFullPath, langPack.tszFullPath)) + return 0; + + // ok... loading a new langpack. remove the old one if needed + if (g_entryCount) + UnloadLangPackModule(); + + langPack.Locale = 0; + langPack.codepage = CP_ACP; + langPack.flags = 0; + + // exists & not a directory? + DWORD dwAttrib = GetFileAttributes(tszFullPath); + if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) + return 3; + + // copy the full file name and extract a file name from it + wcsncpy_s(langPack.tszFullPath, tszFullPath, _TRUNCATE); + wchar_t *p = wcsrchr(langPack.tszFullPath, '\\'); + wcsncpy_s(langPack.tszFileName, (p == nullptr) ? tszFullPath : p + 1, _TRUNCATE); + CharLower(langPack.tszFileName); + + FILE *fp = _wfopen(tszFullPath, L"rt"); + if (fp == nullptr) + return 1; + + char line[LANGPACK_BUF_SIZE] = ""; + int startOfLine = 0; + if (LoadLangDescr(langPack, fp, line, startOfLine)) { + fclose(fp); + return 1; + } + + // body + fseek(fp, startOfLine, SEEK_SET); + + LoadLangPackFile(fp, line); + fclose(fp); + pCurrentMuuid = nullptr; + + qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc); + return 0; +} + +MIR_CORE_DLL(int) LoadLangPackDescr(const wchar_t *ptszLangPack, LANGPACK_INFO *lpInfo) +{ + if (lpInfo == nullptr) + return 1; + + wcsncpy_s(lpInfo->tszFullPath, ptszLangPack, _TRUNCATE); + wchar_t *p = wcsrchr(lpInfo->tszFullPath, '\\'); + wcsncpy_s(lpInfo->tszFileName, (p == nullptr) ? ptszLangPack : p+1, _TRUNCATE); + CharLower(lpInfo->tszFileName); + + FILE *fp = _wfopen(ptszLangPack, L"rt"); + if (fp == nullptr) + return 1; + + char line[LANGPACK_BUF_SIZE] = ""; + int startOfLine = 0; + int res = LoadLangDescr(*lpInfo, fp, line, startOfLine); + fclose(fp); + return res; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static int SortLangPackHashesProc2(LangPackEntry *arg1, LangPackEntry *arg2) +{ + if (arg1->englishHash < arg2->englishHash) return -1; + if (arg1->englishHash > arg2->englishHash) return 1; + return 0; +} + +char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W) +{ + if (g_entryCount == 0 || szEnglish == nullptr) + return (char*)szEnglish; + + LangPackEntry key, *entry; + key.englishHash = (W == 1) ? hashstrW(szEnglish) : mir_hashstr(szEnglish); + entry = (LangPackEntry*)bsearch(&key, g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc2); + if (entry == nullptr) + return (char*)szEnglish; + + // try to find the exact match, otherwise the first entry will be returned + if (pUuid) { + for (LangPackEntry *p = entry->pNext; p != nullptr; p = p->pNext) { + if (*p->pMuuid == *pUuid) { + entry = p; + break; + } + } + } + + switch (W) { + case 0: + if (entry->szLocal == nullptr && entry->wszLocal != nullptr) + entry->szLocal = mir_u2a_cp(entry->wszLocal, langPack.codepage); + return entry->szLocal; + + case 1: + return (char*)entry->wszLocal; + + case 2: + if (entry->utfLocal == nullptr && entry->wszLocal != nullptr) + entry->utfLocal = mir_utf8encodeW(entry->wszLocal); + return entry->utfLocal; + } + + return nullptr; +} + +MIR_CORE_DLL(int) Langpack_GetDefaultCodePage() +{ + return langPack.codepage; +} + +MIR_CORE_DLL(int) Langpack_GetDefaultLocale() +{ + return (langPack.Locale == 0) ? LOCALE_USER_DEFAULT : langPack.Locale; +} + +MIR_CORE_DLL(wchar_t*) Langpack_PcharToTchar(const char *pszStr) +{ + if (pszStr == nullptr) + return nullptr; + + int len = (int)strlen(pszStr); + wchar_t *result = (wchar_t*)alloca((len + 1)*sizeof(wchar_t)); + MultiByteToWideChar(Langpack_GetDefaultCodePage(), 0, pszStr, -1, result, len); + result[len] = 0; + return mir_wstrdup(TranslateW_LP(result)); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(char*) TranslateA_LP(const char *str, HPLUGIN pPlugin) +{ + return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 0); +} + +MIR_CORE_DLL(char*) TranslateU_LP(const char *str, HPLUGIN pPlugin) +{ + return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 2); +} + +MIR_CORE_DLL(wchar_t*) TranslateW_LP(const wchar_t *str, HPLUGIN pPlugin) +{ + return (wchar_t*)LangPackTranslateString(GetMuid(pPlugin), (LPCSTR)str, 1); +} + +MIR_CORE_DLL(void) TranslateMenu_LP(HMENU hMenu, HPLUGIN pPlugin) +{ + const MUUID *uuid = &pPlugin->getInfo().uuid; + + MENUITEMINFO mii = { 0 }; + mii.cbSize = sizeof(mii); + + for (int i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) { + wchar_t str[256]; + mii.fMask = MIIM_TYPE | MIIM_SUBMENU; + mii.dwTypeData = (wchar_t*)str; + mii.cch = _countof(str); + GetMenuItemInfo(hMenu, i, TRUE, &mii); + + if (mii.cch && mii.dwTypeData) { + wchar_t *result = (wchar_t*)LangPackTranslateString(uuid, (const char*)mii.dwTypeData, TRUE); + if (result != mii.dwTypeData) { + mii.dwTypeData = result; + mii.fMask = MIIM_TYPE; + SetMenuItemInfo(hMenu, i, TRUE, &mii); + } + } + + if (mii.hSubMenu != nullptr) + TranslateMenu_LP(mii.hSubMenu, pPlugin); + } +} + +static void TranslateWindow(const MUUID *pUuid, HWND hwnd) +{ + wchar_t title[2048]; + GetWindowText(hwnd, title, _countof(title)); + + wchar_t *result = (wchar_t*)LangPackTranslateString(pUuid, (const char*)title, TRUE); + if (result != title) + SetWindowText(hwnd, result); +} + +static BOOL CALLBACK TranslateDialogEnumProc(HWND hwnd, LPARAM lParam) +{ + HPLUGIN pPlugin = (HPLUGIN)lParam; + const MUUID *uuid = GetMuid(pPlugin); + + wchar_t szClass[32]; + GetClassName(hwnd, szClass, _countof(szClass)); + if (!mir_wstrcmpi(szClass, L"static") || !mir_wstrcmpi(szClass, L"hyperlink") || !mir_wstrcmpi(szClass, L"button") || !mir_wstrcmpi(szClass, L"MButtonClass") || !mir_wstrcmpi(szClass, L"MHeaderbarCtrl")) + TranslateWindow(uuid, hwnd); + else if (!mir_wstrcmpi(szClass, L"edit")) { + if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY) + TranslateWindow(uuid, hwnd); + } + return TRUE; +} + +MIR_CORE_DLL(void) TranslateDialog_LP(HWND hDlg, HPLUGIN pPlugin) +{ + TranslateWindow(GetMuid(pPlugin), hDlg); + EnumChildWindows(hDlg, TranslateDialogEnumProc, (LPARAM)pPlugin); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(void) Langpack_SortDuplicates(void) +{ + if (g_entryCount == 0) + return; + + LangPackEntry *s = g_pEntries + 1, *d = s, *pLast = g_pEntries; + DWORD dwSavedHash = g_pEntries->englishHash; + bool bSortNeeded = false; + + for (int i = 1; i < g_entryCount; i++, s++) { + if (s->englishHash != dwSavedHash) { + pLast = d; + if (s != d) + *d++ = *s; + else + d++; + dwSavedHash = s->englishHash; + } + else { + bSortNeeded = true; + LangPackEntry *p = (LangPackEntry*)mir_alloc(sizeof(LangPackEntry)); + *p = *s; + pLast->pNext = p; pLast = p; + } + } + + if (bSortNeeded) { + g_entryCount = (int)(d - g_pEntries); + qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void GetDefaultLang() +{ + // calculate the langpacks' root + PathToAbsoluteW(L"\\Languages", g_tszRoot); + if (_waccess(g_tszRoot, 0) != 0) // directory Languages exists + PathToAbsoluteW(L".", g_tszRoot); + + // look into mirandaboot.ini + wchar_t tszLangName[256]; + Profile_GetSetting(L"Language/DefaultLanguage", tszLangName); + if (tszLangName[0]) { + if (!mir_wstrcmpi(tszLangName, L"default")) { + db_set_ws(0, "Langpack", "Current", L"default"); + return; + } + if (!LoadLangPack(tszLangName)) { + db_set_ws(0, "Langpack", "Current", tszLangName); + return; + } + } + + // try to load langpack that matches UserDefaultUILanguage + wchar_t tszPath[MAX_PATH]; + if (GetLocaleInfo(MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT), LOCALE_SENGLANGUAGE, tszLangName, _countof(tszLangName))) { + mir_snwprintf(tszPath, L"langpack_%s.txt", wcslwr(tszLangName)); + if (!LoadLangPack(tszPath)) { + db_set_ws(0, "Langpack", "Current", tszPath); + return; + } + } + + // finally try to load first file + mir_snwprintf(tszPath, L"%s\\langpack_*.txt", g_tszRoot); + + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(tszPath, &fd); + if (hFind != INVALID_HANDLE_VALUE) { + do { + /* search first langpack that could be loaded */ + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + if (!LoadLangPack(fd.cFileName)) { + db_set_ws(0, "Langpack", "Current", fd.cFileName); + break; + } + } while (FindNextFile(hFind, &fd)); + FindClose(hFind); + } + else db_set_ws(0, "Langpack", "Current", L"default"); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(void) ReloadLangpack(wchar_t *pszStr) +{ + if (pszStr == nullptr) + pszStr = NEWWSTR_ALLOCA(langPack.tszFileName); + + UnloadLangPackModule(); + LoadLangPack(pszStr); + Langpack_SortDuplicates(); + + NotifyEventHooks(hevChanged, 0, 0); +} + +static INT_PTR srvReloadLangpack(WPARAM, LPARAM lParam) +{ + ReloadLangpack((wchar_t*)lParam); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) LoadLangPackModule(void) +{ + bModuleInitialized = TRUE; + hevChanged = CreateHookableEvent(ME_LANGPACK_CHANGED); + CreateServiceFunction(MS_LANGPACK_RELOAD, srvReloadLangpack); + GetDefaultLang(); + return 0; +} + +void UnloadLangPackModule() +{ + if (!bModuleInitialized) return; + + for (auto &it : lMuuids) + mir_free(it); + lMuuids.destroy(); + + LangPackEntry *p = g_pEntries; + for (int i = 0; i < g_entryCount; i++, p++) { + if (p->pNext != nullptr) { + for (LangPackEntry *p1 = p->pNext; p1 != nullptr;) { + LangPackEntry *p2 = p1; p1 = p1->pNext; + mir_free(p2->szLocal); + mir_free(p2->wszLocal); + mir_free(p2); + } + } + + mir_free(p->szLocal); + mir_free(p->wszLocal); + } + + if (g_entryCount) { + mir_free(g_pEntries); + g_pEntries = nullptr; + g_entryCount = g_entriesAlloced = 0; + } + + langPack.tszFileName[0] = langPack.tszFullPath[0] = 0; +} diff --git a/src/mir_core/src/locks.cpp b/src/mir_core/src/Windows/locks.cpp index 2855974dea..809926f2b9 100644 --- a/src/mir_core/src/locks.cpp +++ b/src/mir_core/src/Windows/locks.cpp @@ -22,7 +22,7 @@ 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 "../stdafx.h" mir_cs::mir_cs() { diff --git a/src/mir_core/src/miranda.cpp b/src/mir_core/src/Windows/miranda.cpp index 9a0915e53c..ba7ac7bf96 100644 --- a/src/mir_core/src/miranda.cpp +++ b/src/mir_core/src/Windows/miranda.cpp @@ -1,149 +1,149 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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"
-
-HWND hAPCWindow = nullptr;
-
-int InitPathUtils(void);
-void RecalculateTime(void);
-
-void CheckLogs();
-void InitLogs();
-void UninitLogs();
-
-void InitColourPicker();
-void InitHyperlink();
-void InitTimeZones();
-void InitWinver();
-
-HINSTANCE g_hInst = nullptr;
-
-HCURSOR g_hCursorNS, g_hCursorWE;
-HANDLE hThreadQueueEmpty;
-DWORD mir_tls = 0;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static INT_PTR RestartMiranda(WPARAM wParam, LPARAM lParam)
-{
- wchar_t mirandaPath[MAX_PATH], cmdLine[MAX_PATH];
- if (lParam)
- wcsncpy_s(mirandaPath, (const wchar_t*)lParam, _TRUNCATE);
- else
- GetModuleFileName(nullptr, mirandaPath, _countof(mirandaPath));
-
- if (wParam) {
- VARSW profilename(L"%miranda_profilename%");
- mir_snwprintf(cmdLine, L"\"%s\" /restart:%d /profile=%s", mirandaPath, GetCurrentProcessId(), (wchar_t*)profilename);
- }
- else mir_snwprintf(cmdLine, L"\"%s\" /restart:%d", mirandaPath, GetCurrentProcessId());
-
- CallService("CloseAction", 0, 0);
-
- PROCESS_INFORMATION pi;
- STARTUPINFO startupInfo = { 0 };
- startupInfo.cb = sizeof(startupInfo);
- CreateProcess(mirandaPath, cmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupInfo, &pi);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// module init
-
-static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- if (msg == WM_USER+1) {
- PAPCFUNC pFunc = (PAPCFUNC)wParam;
- pFunc((ULONG_PTR)lParam);
- return 0;
- }
-
- if (msg == WM_TIMER)
- CheckLogs();
-
- if (msg == WM_TIMECHANGE)
- RecalculateTime();
-
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-static void LoadCoreModule(void)
-{
- INITCOMMONCONTROLSEX icce = {0};
- icce.dwSize = sizeof(icce);
- icce.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES;
- InitCommonControlsEx(&icce);
-
- hAPCWindow = CreateWindowEx(0, L"ComboLBox", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
- SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW);
- DestroyWindow(hAPCWindow);
-
- hAPCWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
- SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc);
- SetTimer(hAPCWindow, 1, 1000, nullptr);
- hThreadQueueEmpty = CreateEvent(nullptr, TRUE, TRUE, nullptr);
-
- InitWinver();
- InitPathUtils();
- InitLogs();
- InitColourPicker();
- InitHyperlink();
- InitTimeZones();
- InitialiseModularEngine();
-
- CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda);
-
- pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036");
-}
-
-MIR_CORE_DLL(void) UnloadCoreModule(void)
-{
- DestroyWindow(hAPCWindow);
- CloseHandle(hThreadQueueEmpty);
- TlsFree(mir_tls);
-
- DestroyModularEngine();
- UninitLogs();
- UnloadLangPackModule();
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// entry point
-
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
-{
- if (fdwReason == DLL_PROCESS_ATTACH) {
- g_hInst = hinstDLL;
- mir_tls = TlsAlloc();
- LoadCoreModule();
- }
- else if (fdwReason == DLL_THREAD_DETACH) {
- HANDLE hEvent = TlsGetValue(mir_tls);
- if (hEvent)
- CloseHandle(hEvent);
- }
- return TRUE;
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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" + +HWND hAPCWindow = nullptr; + +int InitPathUtils(void); +void RecalculateTime(void); + +void CheckLogs(); +void InitLogs(); +void UninitLogs(); + +void InitColourPicker(); +void InitHyperlink(); +void InitTimeZones(); +void InitWinver(); + +HINSTANCE g_hInst = nullptr; + +HCURSOR g_hCursorNS, g_hCursorWE; +HANDLE hThreadQueueEmpty; +DWORD mir_tls = 0; + +///////////////////////////////////////////////////////////////////////////////////////// + +static INT_PTR RestartMiranda(WPARAM wParam, LPARAM lParam) +{ + wchar_t mirandaPath[MAX_PATH], cmdLine[MAX_PATH]; + if (lParam) + wcsncpy_s(mirandaPath, (const wchar_t*)lParam, _TRUNCATE); + else + GetModuleFileName(nullptr, mirandaPath, _countof(mirandaPath)); + + if (wParam) { + VARSW profilename(L"%miranda_profilename%"); + mir_snwprintf(cmdLine, L"\"%s\" /restart:%d /profile=%s", mirandaPath, GetCurrentProcessId(), (wchar_t*)profilename); + } + else mir_snwprintf(cmdLine, L"\"%s\" /restart:%d", mirandaPath, GetCurrentProcessId()); + + CallService("CloseAction", 0, 0); + + PROCESS_INFORMATION pi; + STARTUPINFO startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + CreateProcess(mirandaPath, cmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupInfo, &pi); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// module init + +static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_USER+1) { + PAPCFUNC pFunc = (PAPCFUNC)wParam; + pFunc((ULONG_PTR)lParam); + return 0; + } + + if (msg == WM_TIMER) + CheckLogs(); + + if (msg == WM_TIMECHANGE) + RecalculateTime(); + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static void LoadCoreModule(void) +{ + INITCOMMONCONTROLSEX icce = {0}; + icce.dwSize = sizeof(icce); + icce.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES; + InitCommonControlsEx(&icce); + + hAPCWindow = CreateWindowEx(0, L"ComboLBox", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW); + DestroyWindow(hAPCWindow); + + hAPCWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc); + SetTimer(hAPCWindow, 1, 1000, nullptr); + hThreadQueueEmpty = CreateEvent(nullptr, TRUE, TRUE, nullptr); + + InitWinver(); + InitPathUtils(); + InitLogs(); + InitColourPicker(); + InitHyperlink(); + InitTimeZones(); + InitialiseModularEngine(); + + CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda); + + pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036"); +} + +MIR_CORE_DLL(void) UnloadCoreModule(void) +{ + DestroyWindow(hAPCWindow); + CloseHandle(hThreadQueueEmpty); + TlsFree(mir_tls); + + DestroyModularEngine(); + UninitLogs(); + UnloadLangPackModule(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// entry point + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID) +{ + if (fdwReason == DLL_PROCESS_ATTACH) { + g_hInst = hinstDLL; + mir_tls = TlsAlloc(); + LoadCoreModule(); + } + else if (fdwReason == DLL_THREAD_DETACH) { + HANDLE hEvent = TlsGetValue(mir_tls); + if (hEvent) + CloseHandle(hEvent); + } + return TRUE; +} diff --git a/src/mir_core/src/openurl.cpp b/src/mir_core/src/Windows/openurl.cpp index abc66f920b..40dc3ca54a 100644 --- a/src/mir_core/src/openurl.cpp +++ b/src/mir_core/src/Windows/openurl.cpp @@ -1,76 +1,76 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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 <ctype.h>
-
-struct TOpenUrlInfo
-{
- TOpenUrlInfo(wchar_t *_url, int _bNew) :
- szUrl(_url),
- newWindow(_bNew)
- {}
-
- ptrW szUrl;
- int newWindow;
-};
-
-static void __cdecl OpenURLThread(TOpenUrlInfo *hUrlInfo)
-{
- // wack a protocol on it
- CMStringW tszUrl;
- if ((isalpha(hUrlInfo->szUrl[0]) && hUrlInfo->szUrl[1] == ':') || hUrlInfo->szUrl[0] == '\\')
- tszUrl.Format(L"file:///%s", hUrlInfo->szUrl.get());
- else {
- int i;
- for (i = 0; iswalpha(hUrlInfo->szUrl[i]); i++);
- if (hUrlInfo->szUrl[i] == ':')
- tszUrl = hUrlInfo->szUrl;
- else if (!wcsnicmp(hUrlInfo->szUrl, L"ftp.", 4))
- tszUrl.Format(L"ftp://%s", hUrlInfo->szUrl.get());
- else
- tszUrl.Format(L"http://%s", hUrlInfo->szUrl.get());
- }
-
- // check user defined browser for opening urls
- ptrW tszBrowser(db_get_wsa(0, "Miranda", "OpenUrlBrowser"));
- if (tszBrowser)
- ShellExecute(nullptr, L"open", tszBrowser, tszUrl, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
- else
- ShellExecute(nullptr, L"open", tszUrl, nullptr, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
-
- delete hUrlInfo;
-}
-
-MIR_CORE_DLL(void) Utils_OpenUrl(const char *pszUrl, bool bOpenInNewWindow)
-{
- if (pszUrl)
- mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_a2u(pszUrl), bOpenInNewWindow));
-}
-
-MIR_CORE_DLL(void) Utils_OpenUrlW(const wchar_t *pszUrl, bool bOpenInNewWindow)
-{
- if (pszUrl)
- mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_wstrdup(pszUrl), bOpenInNewWindow));
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 <ctype.h> + +struct TOpenUrlInfo +{ + TOpenUrlInfo(wchar_t *_url, int _bNew) : + szUrl(_url), + newWindow(_bNew) + {} + + ptrW szUrl; + int newWindow; +}; + +static void __cdecl OpenURLThread(TOpenUrlInfo *hUrlInfo) +{ + // wack a protocol on it + CMStringW tszUrl; + if ((isalpha(hUrlInfo->szUrl[0]) && hUrlInfo->szUrl[1] == ':') || hUrlInfo->szUrl[0] == '\\') + tszUrl.Format(L"file:///%s", hUrlInfo->szUrl.get()); + else { + int i; + for (i = 0; iswalpha(hUrlInfo->szUrl[i]); i++); + if (hUrlInfo->szUrl[i] == ':') + tszUrl = hUrlInfo->szUrl; + else if (!wcsnicmp(hUrlInfo->szUrl, L"ftp.", 4)) + tszUrl.Format(L"ftp://%s", hUrlInfo->szUrl.get()); + else + tszUrl.Format(L"http://%s", hUrlInfo->szUrl.get()); + } + + // check user defined browser for opening urls + ptrW tszBrowser(db_get_wsa(0, "Miranda", "OpenUrlBrowser")); + if (tszBrowser) + ShellExecute(nullptr, L"open", tszBrowser, tszUrl, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT); + else + ShellExecute(nullptr, L"open", tszUrl, nullptr, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT); + + delete hUrlInfo; +} + +MIR_CORE_DLL(void) Utils_OpenUrl(const char *pszUrl, bool bOpenInNewWindow) +{ + if (pszUrl) + mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_a2u(pszUrl), bOpenInNewWindow)); +} + +MIR_CORE_DLL(void) Utils_OpenUrlW(const wchar_t *pszUrl, bool bOpenInNewWindow) +{ + if (pszUrl) + mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_wstrdup(pszUrl), bOpenInNewWindow)); +} diff --git a/src/mir_core/src/path.cpp b/src/mir_core/src/Windows/path.cpp index c26e712d06..a09c44a1cb 100644 --- a/src/mir_core/src/path.cpp +++ b/src/mir_core/src/Windows/path.cpp @@ -1,246 +1,246 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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 char szMirandaPath[MAX_PATH];
-static wchar_t szMirandaPathW[MAX_PATH];
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) PathIsAbsolute(const char *path)
-{
- if (path && strlen(path) > 2)
- if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
- return 1;
- return 0;
-}
-
-MIR_CORE_DLL(int) PathToRelative(const char *pSrc, char *pOut, const char *pBase)
-{
- if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- if (!PathIsAbsolute(pSrc))
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- else {
- if (pBase == nullptr)
- pBase = szMirandaPath;
-
- size_t cbBaseLen = strlen(pBase);
- if (!strnicmp(pSrc, pBase, cbBaseLen))
- strncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
- else
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- }
-
- return (int)strlen(pOut);
-}
-
-MIR_CORE_DLL(int) PathToAbsolute(const char *pSrc, char *pOut, const char *base)
-{
- if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- char buf[MAX_PATH];
- if (pSrc[0] < ' ')
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
-
- if (PathIsAbsolute(pSrc))
- return GetFullPathNameA(pSrc, MAX_PATH, pOut, nullptr);
-
- if (base == nullptr)
- base = szMirandaPath;
-
- if (pSrc[0] == '\\')
- pSrc++;
- mir_snprintf(buf, "%s%s", base, pSrc);
- return GetFullPathNameA(buf, _countof(buf), pOut, nullptr);
-}
-
-MIR_CORE_DLL(int) CreatePathToFile(const char *szFilePath)
-{
- if (szFilePath == nullptr)
- return ERROR_INVALID_PARAMETER;
-
- char *buf = NEWSTR_ALLOCA(szFilePath);
- char *p = strrchr(buf, '\\');
- if (p == nullptr)
- return 0;
-
- *p = '\0';
- return CreateDirectoryTree(buf);
-}
-
-MIR_CORE_DLL(int) CreateDirectoryTree(const char *szDir)
-{
- if (szDir == nullptr)
- return 1;
-
- DWORD dwAttributes = GetFileAttributesA(szDir);
- if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
- return 0;
-
- char szTestDir[MAX_PATH];
- mir_strncpy(szTestDir, szDir, _countof(szTestDir));
- char *pszLastBackslash = strrchr(szTestDir, '\\');
- if (pszLastBackslash == nullptr)
- return 0;
-
- *pszLastBackslash = '\0';
- CreateDirectoryTree(szTestDir);
- *pszLastBackslash = '\\';
- return (CreateDirectoryA(szTestDir, nullptr) == 0) ? GetLastError() : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) PathIsAbsoluteW(const wchar_t *path)
-{
- if (path && wcslen(path) > 2)
- if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
- return 1;
- return 0;
-}
-
-MIR_CORE_DLL(int) PathToRelativeW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *pBase)
-{
- if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH)
- return 0;
-
- if (!PathIsAbsoluteW(pSrc))
- wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- else {
- if (pBase == nullptr)
- pBase = szMirandaPathW;
-
- size_t cbBaseLen = wcslen(pBase);
- if (!wcsnicmp(pSrc, pBase, cbBaseLen))
- wcsncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
- else
- wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- }
- return (int)wcslen(pOut);
-}
-
-MIR_CORE_DLL(int) PathToAbsoluteW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *base)
-{
- if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- wchar_t buf[MAX_PATH];
- if (pSrc[0] < ' ')
- return mir_snwprintf(pOut, MAX_PATH, L"%s", pSrc);
-
- if (PathIsAbsoluteW(pSrc))
- return GetFullPathName(pSrc, MAX_PATH, pOut, nullptr);
-
- if (base == nullptr)
- base = szMirandaPathW;
-
- if (pSrc[0] == '\\')
- pSrc++;
-
- mir_snwprintf(buf, MAX_PATH, L"%s%s", base, pSrc);
- return GetFullPathName(buf, MAX_PATH, pOut, nullptr);
-}
-
-MIR_CORE_DLL(int) CreatePathToFileW(const wchar_t *wszFilePath)
-{
- if (wszFilePath == nullptr)
- return ERROR_INVALID_PARAMETER;
-
- wchar_t *buf = NEWWSTR_ALLOCA(wszFilePath);
- wchar_t *p = wcsrchr(buf, '\\');
- if (p == nullptr)
- return 0;
-
- *p = '\0';
- return CreateDirectoryTreeW(buf);
-}
-
-MIR_CORE_DLL(int) CreateDirectoryTreeW(const wchar_t *szDir)
-{
- if (szDir == nullptr)
- return 1;
-
- DWORD dwAttributes = GetFileAttributesW(szDir);
- if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
- return 0;
-
- wchar_t szTestDir[MAX_PATH];
- mir_wstrncpy(szTestDir, szDir, _countof(szTestDir));
- wchar_t *pszLastBackslash = wcsrchr(szTestDir, '\\');
- if (pszLastBackslash == nullptr)
- return 0;
-
- *pszLastBackslash = '\0';
- CreateDirectoryTreeW(szTestDir);
- *pszLastBackslash = '\\';
- return (CreateDirectoryW(szTestDir, nullptr) == 0) ? GetLastError() : 0;
-}
-
-MIR_CORE_DLL(int) DeleteDirectoryTreeW(const wchar_t *pwszDir, bool bAllowUndo)
-{
- if (pwszDir == nullptr)
- return ERROR_BAD_ARGUMENTS;
-
- CMStringW wszPath(pwszDir);
- wszPath.AppendChar(0);
-
- SHFILEOPSTRUCTW file_op = {
- nullptr,
- FO_DELETE,
- wszPath,
- L"",
- FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION,
- false,
- nullptr,
- L"" };
-
- if (bAllowUndo)
- file_op.fFlags |= FOF_ALLOWUNDO;
-
- return SHFileOperationW(&file_op);
-}
-
-int InitPathUtils(void)
-{
- GetModuleFileNameA(nullptr, szMirandaPath, _countof(szMirandaPath));
- char *p = strrchr(szMirandaPath, '\\');
- if (p)
- p[1] = 0;
-
- GetModuleFileNameW(nullptr, szMirandaPathW, _countof(szMirandaPathW));
- wchar_t *tp = wcsrchr(szMirandaPathW, '\\');
- if (tp)
- tp[1] = 0;
- return 0;
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 char szMirandaPath[MAX_PATH]; +static wchar_t szMirandaPathW[MAX_PATH]; + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) PathIsAbsolute(const char *path) +{ + if (path && strlen(path) > 2) + if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\')) + return 1; + return 0; +} + +MIR_CORE_DLL(int) PathToRelative(const char *pSrc, char *pOut, const char *pBase) +{ + if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) { + *pOut = 0; + return 0; + } + + if (!PathIsAbsolute(pSrc)) + strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE); + else { + if (pBase == nullptr) + pBase = szMirandaPath; + + size_t cbBaseLen = strlen(pBase); + if (!strnicmp(pSrc, pBase, cbBaseLen)) + strncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE); + else + strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE); + } + + return (int)strlen(pOut); +} + +MIR_CORE_DLL(int) PathToAbsolute(const char *pSrc, char *pOut, const char *base) +{ + if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) { + *pOut = 0; + return 0; + } + + char buf[MAX_PATH]; + if (pSrc[0] < ' ') + strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE); + + if (PathIsAbsolute(pSrc)) + return GetFullPathNameA(pSrc, MAX_PATH, pOut, nullptr); + + if (base == nullptr) + base = szMirandaPath; + + if (pSrc[0] == '\\') + pSrc++; + mir_snprintf(buf, "%s%s", base, pSrc); + return GetFullPathNameA(buf, _countof(buf), pOut, nullptr); +} + +MIR_CORE_DLL(int) CreatePathToFile(const char *szFilePath) +{ + if (szFilePath == nullptr) + return ERROR_INVALID_PARAMETER; + + char *buf = NEWSTR_ALLOCA(szFilePath); + char *p = strrchr(buf, '\\'); + if (p == nullptr) + return 0; + + *p = '\0'; + return CreateDirectoryTree(buf); +} + +MIR_CORE_DLL(int) CreateDirectoryTree(const char *szDir) +{ + if (szDir == nullptr) + return 1; + + DWORD dwAttributes = GetFileAttributesA(szDir); + if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) + return 0; + + char szTestDir[MAX_PATH]; + mir_strncpy(szTestDir, szDir, _countof(szTestDir)); + char *pszLastBackslash = strrchr(szTestDir, '\\'); + if (pszLastBackslash == nullptr) + return 0; + + *pszLastBackslash = '\0'; + CreateDirectoryTree(szTestDir); + *pszLastBackslash = '\\'; + return (CreateDirectoryA(szTestDir, nullptr) == 0) ? GetLastError() : 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) PathIsAbsoluteW(const wchar_t *path) +{ + if (path && wcslen(path) > 2) + if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\')) + return 1; + return 0; +} + +MIR_CORE_DLL(int) PathToRelativeW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *pBase) +{ + if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH) + return 0; + + if (!PathIsAbsoluteW(pSrc)) + wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE); + else { + if (pBase == nullptr) + pBase = szMirandaPathW; + + size_t cbBaseLen = wcslen(pBase); + if (!wcsnicmp(pSrc, pBase, cbBaseLen)) + wcsncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE); + else + wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE); + } + return (int)wcslen(pOut); +} + +MIR_CORE_DLL(int) PathToAbsoluteW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *base) +{ + if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH) { + *pOut = 0; + return 0; + } + + wchar_t buf[MAX_PATH]; + if (pSrc[0] < ' ') + return mir_snwprintf(pOut, MAX_PATH, L"%s", pSrc); + + if (PathIsAbsoluteW(pSrc)) + return GetFullPathName(pSrc, MAX_PATH, pOut, nullptr); + + if (base == nullptr) + base = szMirandaPathW; + + if (pSrc[0] == '\\') + pSrc++; + + mir_snwprintf(buf, MAX_PATH, L"%s%s", base, pSrc); + return GetFullPathName(buf, MAX_PATH, pOut, nullptr); +} + +MIR_CORE_DLL(int) CreatePathToFileW(const wchar_t *wszFilePath) +{ + if (wszFilePath == nullptr) + return ERROR_INVALID_PARAMETER; + + wchar_t *buf = NEWWSTR_ALLOCA(wszFilePath); + wchar_t *p = wcsrchr(buf, '\\'); + if (p == nullptr) + return 0; + + *p = '\0'; + return CreateDirectoryTreeW(buf); +} + +MIR_CORE_DLL(int) CreateDirectoryTreeW(const wchar_t *szDir) +{ + if (szDir == nullptr) + return 1; + + DWORD dwAttributes = GetFileAttributesW(szDir); + if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) + return 0; + + wchar_t szTestDir[MAX_PATH]; + mir_wstrncpy(szTestDir, szDir, _countof(szTestDir)); + wchar_t *pszLastBackslash = wcsrchr(szTestDir, '\\'); + if (pszLastBackslash == nullptr) + return 0; + + *pszLastBackslash = '\0'; + CreateDirectoryTreeW(szTestDir); + *pszLastBackslash = '\\'; + return (CreateDirectoryW(szTestDir, nullptr) == 0) ? GetLastError() : 0; +} + +MIR_CORE_DLL(int) DeleteDirectoryTreeW(const wchar_t *pwszDir, bool bAllowUndo) +{ + if (pwszDir == nullptr) + return ERROR_BAD_ARGUMENTS; + + CMStringW wszPath(pwszDir); + wszPath.AppendChar(0); + + SHFILEOPSTRUCTW file_op = { + nullptr, + FO_DELETE, + wszPath, + L"", + FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION, + false, + nullptr, + L"" }; + + if (bAllowUndo) + file_op.fFlags |= FOF_ALLOWUNDO; + + return SHFileOperationW(&file_op); +} + +int InitPathUtils(void) +{ + GetModuleFileNameA(nullptr, szMirandaPath, _countof(szMirandaPath)); + char *p = strrchr(szMirandaPath, '\\'); + if (p) + p[1] = 0; + + GetModuleFileNameW(nullptr, szMirandaPathW, _countof(szMirandaPathW)); + wchar_t *tp = wcsrchr(szMirandaPathW, '\\'); + if (tp) + tp[1] = 0; + return 0; +} diff --git a/src/mir_core/src/resizer.cpp b/src/mir_core/src/Windows/resizer.cpp index 01d65a7916..a8a6be41e4 100644 --- a/src/mir_core/src/resizer.cpp +++ b/src/mir_core/src/Windows/resizer.cpp @@ -1,151 +1,151 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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"
-
-#pragma pack(2)
-
-struct START_OF_DLGITEMTEMPLATEEX
-{
- DWORD helpID;
- DWORD exStyle;
- DWORD style;
- short x, y, cx, cy;
- DWORD id;
-};
-
-struct START_OF_DLGTEMPLATEEX
-{
- WORD dlgVer;
- WORD signature;
- DWORD helpID;
- DWORD exStyle;
- DWORD style;
- WORD cDlgItems;
- short x, y, cx, cy;
-};
-
-MIR_CORE_DLL(int) Utils_ResizeDialog(HWND hwndDlg, HINSTANCE hInstance, LPCSTR lpTemplate, DIALOGRESIZERPROC pfnResizer, LPARAM lParam)
-{
- DLGTEMPLATE *pTemplate = (DLGTEMPLATE*)LockResource(LoadResource(hInstance, FindResourceA(hInstance, lpTemplate, MAKEINTRESOURCEA(5))));
- START_OF_DLGTEMPLATEEX *pTemplateEx = (START_OF_DLGTEMPLATEEX*)pTemplate;
- int extendedDlg = pTemplateEx->signature == 0xFFFF;
- if (extendedDlg && pTemplateEx->dlgVer != 1)
- return 1;
-
- PWORD pWord = (extendedDlg) ? (PWORD)(pTemplateEx + 1) : (PWORD)(pTemplate + 1);
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
- while (*pWord++); // skip title
- if (extendedDlg) {
- if (pTemplateEx->style & DS_SETFONT) {
- pWord += 3; // font size, weight, italic
- while (*pWord++); // font name
- }
- }
- else {
- if (pTemplate->style & DS_SETFONT) {
- pWord++; // font size
- while (*pWord++); // font name
- }
- }
-
- UTILRESIZECONTROL urc;
- urc.cbSize = sizeof(UTILRESIZECONTROL);
-
- RECT rc;
- rc.left = 0; rc.top = 0;
- if (extendedDlg) {
- rc.right = pTemplateEx->cx;
- rc.bottom = pTemplateEx->cy;
- }
- else {
- rc.right = pTemplate->cx;
- rc.bottom = pTemplate->cy;
- }
-
- MapDialogRect(hwndDlg, &rc);
- urc.dlgOriginalSize.cx = rc.right; urc.dlgOriginalSize.cy = rc.bottom;
- GetClientRect(hwndDlg, &rc);
- urc.dlgNewSize.cx = rc.right; urc.dlgNewSize.cy = rc.bottom;
-
- int itemCount = (extendedDlg) ? pTemplateEx->cDlgItems : pTemplate->cdit;
-
- HDWP hDwp = BeginDeferWindowPos(itemCount);
- for (int i = 0; i < itemCount; i++) {
- if ((UINT_PTR)pWord & 2) pWord++; //dword align
-
- if (extendedDlg) {
- START_OF_DLGITEMTEMPLATEEX *pItemEx = (START_OF_DLGITEMTEMPLATEEX*)pWord;
- pWord = (PWORD)(pItemEx + 1);
-
- urc.wId = pItemEx->id;
- urc.rcItem.left = pItemEx->x; urc.rcItem.top = pItemEx->y;
- urc.rcItem.right = urc.rcItem.left + pItemEx->cx; urc.rcItem.bottom = urc.rcItem.top + pItemEx->cy;
- }
- else {
- DLGITEMTEMPLATE *pItem = (DLGITEMTEMPLATE*)pWord;
- pWord = (PWORD)(pItem + 1);
-
- urc.wId = pItem->id;
- urc.rcItem.left = pItem->x; urc.rcItem.top = pItem->y;
- urc.rcItem.right = urc.rcItem.left + pItem->cx; urc.rcItem.bottom = urc.rcItem.top + pItem->cy;
- }
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
- pWord += 1 + (1 + *pWord) / 2; //creation data
-
- if (urc.wId == 65535) // using this breaks the dwp, so just ignore it
- continue;
-
- MapDialogRect(hwndDlg, &urc.rcItem);
- int procResult = (pfnResizer)(hwndDlg, lParam, &urc);
- if (procResult & RD_ANCHORX_RIGHT) {
- urc.rcItem.left += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- }
- else if (procResult & RD_ANCHORX_WIDTH)
- urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- else if (procResult & RD_ANCHORX_CENTRE) {
- urc.rcItem.left += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
- urc.rcItem.right += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
- }
- if (procResult & RD_ANCHORY_BOTTOM) {
- urc.rcItem.top += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- }
- else if (procResult & RD_ANCHORY_HEIGHT)
- urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- else if (procResult & RD_ANCHORY_CENTRE) {
- urc.rcItem.top += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
- urc.rcItem.bottom += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
- }
-
- HWND hCtrl = GetDlgItem(hwndDlg, urc.wId);
- if (hCtrl != nullptr)
- hDwp = DeferWindowPos(hDwp, hCtrl, nullptr, urc.rcItem.left, urc.rcItem.top, urc.rcItem.right - urc.rcItem.left, urc.rcItem.bottom - urc.rcItem.top, SWP_NOZORDER);
- }
- EndDeferWindowPos(hDwp);
- return 0;
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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" + +#pragma pack(2) + +struct START_OF_DLGITEMTEMPLATEEX +{ + DWORD helpID; + DWORD exStyle; + DWORD style; + short x, y, cx, cy; + DWORD id; +}; + +struct START_OF_DLGTEMPLATEEX +{ + WORD dlgVer; + WORD signature; + DWORD helpID; + DWORD exStyle; + DWORD style; + WORD cDlgItems; + short x, y, cx, cy; +}; + +MIR_CORE_DLL(int) Utils_ResizeDialog(HWND hwndDlg, HINSTANCE hInstance, LPCSTR lpTemplate, DIALOGRESIZERPROC pfnResizer, LPARAM lParam) +{ + DLGTEMPLATE *pTemplate = (DLGTEMPLATE*)LockResource(LoadResource(hInstance, FindResourceA(hInstance, lpTemplate, MAKEINTRESOURCEA(5)))); + START_OF_DLGTEMPLATEEX *pTemplateEx = (START_OF_DLGTEMPLATEEX*)pTemplate; + int extendedDlg = pTemplateEx->signature == 0xFFFF; + if (extendedDlg && pTemplateEx->dlgVer != 1) + return 1; + + PWORD pWord = (extendedDlg) ? (PWORD)(pTemplateEx + 1) : (PWORD)(pTemplate + 1); + if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu + if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class + while (*pWord++); // skip title + if (extendedDlg) { + if (pTemplateEx->style & DS_SETFONT) { + pWord += 3; // font size, weight, italic + while (*pWord++); // font name + } + } + else { + if (pTemplate->style & DS_SETFONT) { + pWord++; // font size + while (*pWord++); // font name + } + } + + UTILRESIZECONTROL urc; + urc.cbSize = sizeof(UTILRESIZECONTROL); + + RECT rc; + rc.left = 0; rc.top = 0; + if (extendedDlg) { + rc.right = pTemplateEx->cx; + rc.bottom = pTemplateEx->cy; + } + else { + rc.right = pTemplate->cx; + rc.bottom = pTemplate->cy; + } + + MapDialogRect(hwndDlg, &rc); + urc.dlgOriginalSize.cx = rc.right; urc.dlgOriginalSize.cy = rc.bottom; + GetClientRect(hwndDlg, &rc); + urc.dlgNewSize.cx = rc.right; urc.dlgNewSize.cy = rc.bottom; + + int itemCount = (extendedDlg) ? pTemplateEx->cDlgItems : pTemplate->cdit; + + HDWP hDwp = BeginDeferWindowPos(itemCount); + for (int i = 0; i < itemCount; i++) { + if ((UINT_PTR)pWord & 2) pWord++; //dword align + + if (extendedDlg) { + START_OF_DLGITEMTEMPLATEEX *pItemEx = (START_OF_DLGITEMTEMPLATEEX*)pWord; + pWord = (PWORD)(pItemEx + 1); + + urc.wId = pItemEx->id; + urc.rcItem.left = pItemEx->x; urc.rcItem.top = pItemEx->y; + urc.rcItem.right = urc.rcItem.left + pItemEx->cx; urc.rcItem.bottom = urc.rcItem.top + pItemEx->cy; + } + else { + DLGITEMTEMPLATE *pItem = (DLGITEMTEMPLATE*)pWord; + pWord = (PWORD)(pItem + 1); + + urc.wId = pItem->id; + urc.rcItem.left = pItem->x; urc.rcItem.top = pItem->y; + urc.rcItem.right = urc.rcItem.left + pItem->cx; urc.rcItem.bottom = urc.rcItem.top + pItem->cy; + } + if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu + if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class + pWord += 1 + (1 + *pWord) / 2; //creation data + + if (urc.wId == 65535) // using this breaks the dwp, so just ignore it + continue; + + MapDialogRect(hwndDlg, &urc.rcItem); + int procResult = (pfnResizer)(hwndDlg, lParam, &urc); + if (procResult & RD_ANCHORX_RIGHT) { + urc.rcItem.left += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx; + urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx; + } + else if (procResult & RD_ANCHORX_WIDTH) + urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx; + else if (procResult & RD_ANCHORX_CENTRE) { + urc.rcItem.left += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2; + urc.rcItem.right += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2; + } + if (procResult & RD_ANCHORY_BOTTOM) { + urc.rcItem.top += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy; + urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy; + } + else if (procResult & RD_ANCHORY_HEIGHT) + urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy; + else if (procResult & RD_ANCHORY_CENTRE) { + urc.rcItem.top += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2; + urc.rcItem.bottom += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2; + } + + HWND hCtrl = GetDlgItem(hwndDlg, urc.wId); + if (hCtrl != nullptr) + hDwp = DeferWindowPos(hDwp, hCtrl, nullptr, urc.rcItem.left, urc.rcItem.top, urc.rcItem.right - urc.rcItem.left, urc.rcItem.bottom - urc.rcItem.top, SWP_NOZORDER); + } + EndDeferWindowPos(hDwp); + return 0; +} diff --git a/src/mir_core/src/subclass.cpp b/src/mir_core/src/Windows/subclass.cpp index ecf53b470f..99d5d355b2 100644 --- a/src/mir_core/src/subclass.cpp +++ b/src/mir_core/src/Windows/subclass.cpp @@ -1,201 +1,201 @@ -/*
-Copyright (C) 2012-21 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"
-
-struct MSubclassData
-{
- HWND m_hWnd;
-
- int m_iHooks;
- WNDPROC *m_hooks;
- WNDPROC m_origWndProc;
-
- ~MSubclassData()
- {
- free(m_hooks);
- }
-};
-
-static LIST<MSubclassData> arSubclass(10, HandleKeySortT);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static LRESULT CALLBACK MSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hwnd);
- if (p != nullptr) {
- if (p->m_iHooks)
- return p->m_hooks[p->m_iHooks-1](hwnd, uMsg, wParam, lParam);
-
- return p->m_origWndProc(hwnd, uMsg, wParam, lParam);
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// This is for wine: it return wrong WNDPROC for edit control in some cases.
-#ifdef WIN64
-#define STD_WND_PROC_ADDR_MASK 0x7FFF00000
-#else
-#define STD_WND_PROC_ADDR_MASK 0xFFFF0000
-#endif
-
-MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc)
-{
- if (hWnd == nullptr)
- return;
-
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr) {
- p = new MSubclassData;
- p->m_hWnd = hWnd;
- p->m_origWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
- if (((SIZE_T)p->m_origWndProc & STD_WND_PROC_ADDR_MASK) == STD_WND_PROC_ADDR_MASK) { /* XXX: fix me. Wine fix. */
- p->m_origWndProc = (WNDPROC)GetClassLongPtr(hWnd, GCLP_WNDPROC);
- if (((SIZE_T)p->m_origWndProc & 0x7FFF0000) == 0x7FFF0000) /* Delay crash. */
- p->m_origWndProc = DefWindowProc;
- }
- p->m_iHooks = 0;
- p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
- arSubclass.insert(p);
- }
- else {
- for (int i=0; i < p->m_iHooks; i++)
- if (p->m_hooks[i] == wndProc)
- return;
-
- void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
- if (tmp == nullptr)
- return;
-
- p->m_hooks = (WNDPROC *)tmp;
- }
-
- p->m_hooks[p->m_iHooks++] = wndProc;
-}
-
-MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC oldWndProc)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr) {
- p = new MSubclassData;
- p->m_hWnd = hWnd;
- p->m_origWndProc = oldWndProc;
- p->m_iHooks = 0;
- p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
- arSubclass.insert(p);
-
- SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
- }
- else {
- for (int i=0; i < p->m_iHooks; i++)
- if (p->m_hooks[i] == wndProc)
- return;
-
- void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
- if (tmp == nullptr)
- return;
-
- p->m_hooks = (WNDPROC *)tmp;
- }
-
- p->m_hooks[p->m_iHooks++] = wndProc;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void removeHook(MSubclassData *p, int idx)
-{
- // untie hook from a window to prevent calling mir_callNextSubclass from saveProc
- for (int i = idx + 1; i < p->m_iHooks; i++)
- p->m_hooks[i-1] = p->m_hooks[i];
- p->m_iHooks--;
-}
-
-static WNDPROC finalizeSubclassing(HWND hWnd, MSubclassData *p)
-{
- WNDPROC saveProc = p->m_origWndProc;
- arSubclass.remove(p);
- delete p;
-
- SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)saveProc);
- return saveProc;
-}
-
-MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr)
- return;
-
- for (int i = 0; i < p->m_iHooks; i++) {
- if (p->m_hooks[i] == wndProc) {
- removeHook(p, i);
- i--;
- }
- }
-
- if (p->m_iHooks == 0)
- finalizeSubclassing(hWnd, p);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr)
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
-
- for (int i = p->m_iHooks - 1; i >= 0; i--) {
- if (p->m_hooks[i] != wndProc)
- continue;
-
- // next hook exists, call it
- if (i != 0)
- return p->m_hooks[i-1](hWnd, uMsg, wParam, lParam);
-
- // last hook called, ping the default window procedure
- if (uMsg != WM_NCDESTROY)
- return p->m_origWndProc(hWnd, uMsg, wParam, lParam);
-
- WNDPROC saveProc = finalizeSubclassing(hWnd, p);
- return saveProc(hWnd, uMsg, wParam, lParam);
- }
-
- // invalid / closed hook
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst)
-{
- for (auto &it : arSubclass.rev_iter()) {
- for (int j = 0; j < it->m_iHooks; j++) {
- if (GetInstByAddress(it->m_hooks[j]) == hInst) {
- removeHook(it, j);
- j--;
- }
- }
-
- if (it->m_iHooks == 0)
- finalizeSubclassing(it->m_hWnd, it);
- }
-}
+/* +Copyright (C) 2012-21 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" + +struct MSubclassData +{ + HWND m_hWnd; + + int m_iHooks; + WNDPROC *m_hooks; + WNDPROC m_origWndProc; + + ~MSubclassData() + { + free(m_hooks); + } +}; + +static LIST<MSubclassData> arSubclass(10, HandleKeySortT); + +///////////////////////////////////////////////////////////////////////////////////////// + +static LRESULT CALLBACK MSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MSubclassData *p = arSubclass.find((MSubclassData*)&hwnd); + if (p != nullptr) { + if (p->m_iHooks) + return p->m_hooks[p->m_iHooks-1](hwnd, uMsg, wParam, lParam); + + return p->m_origWndProc(hwnd, uMsg, wParam, lParam); + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// This is for wine: it return wrong WNDPROC for edit control in some cases. +#ifdef WIN64 +#define STD_WND_PROC_ADDR_MASK 0x7FFF00000 +#else +#define STD_WND_PROC_ADDR_MASK 0xFFFF0000 +#endif + +MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc) +{ + if (hWnd == nullptr) + return; + + MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd); + if (p == nullptr) { + p = new MSubclassData; + p->m_hWnd = hWnd; + p->m_origWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc); + if (((SIZE_T)p->m_origWndProc & STD_WND_PROC_ADDR_MASK) == STD_WND_PROC_ADDR_MASK) { /* XXX: fix me. Wine fix. */ + p->m_origWndProc = (WNDPROC)GetClassLongPtr(hWnd, GCLP_WNDPROC); + if (((SIZE_T)p->m_origWndProc & 0x7FFF0000) == 0x7FFF0000) /* Delay crash. */ + p->m_origWndProc = DefWindowProc; + } + p->m_iHooks = 0; + p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC)); + arSubclass.insert(p); + } + else { + for (int i=0; i < p->m_iHooks; i++) + if (p->m_hooks[i] == wndProc) + return; + + void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC)); + if (tmp == nullptr) + return; + + p->m_hooks = (WNDPROC *)tmp; + } + + p->m_hooks[p->m_iHooks++] = wndProc; +} + +MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC oldWndProc) +{ + MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd); + if (p == nullptr) { + p = new MSubclassData; + p->m_hWnd = hWnd; + p->m_origWndProc = oldWndProc; + p->m_iHooks = 0; + p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC)); + arSubclass.insert(p); + + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc); + } + else { + for (int i=0; i < p->m_iHooks; i++) + if (p->m_hooks[i] == wndProc) + return; + + void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC)); + if (tmp == nullptr) + return; + + p->m_hooks = (WNDPROC *)tmp; + } + + p->m_hooks[p->m_iHooks++] = wndProc; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static void removeHook(MSubclassData *p, int idx) +{ + // untie hook from a window to prevent calling mir_callNextSubclass from saveProc + for (int i = idx + 1; i < p->m_iHooks; i++) + p->m_hooks[i-1] = p->m_hooks[i]; + p->m_iHooks--; +} + +static WNDPROC finalizeSubclassing(HWND hWnd, MSubclassData *p) +{ + WNDPROC saveProc = p->m_origWndProc; + arSubclass.remove(p); + delete p; + + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)saveProc); + return saveProc; +} + +MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc) +{ + MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd); + if (p == nullptr) + return; + + for (int i = 0; i < p->m_iHooks; i++) { + if (p->m_hooks[i] == wndProc) { + removeHook(p, i); + i--; + } + } + + if (p->m_iHooks == 0) + finalizeSubclassing(hWnd, p); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd); + if (p == nullptr) + return DefWindowProc(hWnd, uMsg, wParam, lParam); + + for (int i = p->m_iHooks - 1; i >= 0; i--) { + if (p->m_hooks[i] != wndProc) + continue; + + // next hook exists, call it + if (i != 0) + return p->m_hooks[i-1](hWnd, uMsg, wParam, lParam); + + // last hook called, ping the default window procedure + if (uMsg != WM_NCDESTROY) + return p->m_origWndProc(hWnd, uMsg, wParam, lParam); + + WNDPROC saveProc = finalizeSubclassing(hWnd, p); + return saveProc(hWnd, uMsg, wParam, lParam); + } + + // invalid / closed hook + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst) +{ + for (auto &it : arSubclass.rev_iter()) { + for (int j = 0; j < it->m_iHooks; j++) { + if (GetInstByAddress(it->m_hooks[j]) == hInst) { + removeHook(it, j); + j--; + } + } + + if (it->m_iHooks == 0) + finalizeSubclassing(it->m_hWnd, it); + } +} diff --git a/src/mir_core/src/threads.cpp b/src/mir_core/src/Windows/threads.cpp index 917ecc5bb5..fdd9f5e85f 100644 --- a/src/mir_core/src/threads.cpp +++ b/src/mir_core/src/Windows/threads.cpp @@ -1,400 +1,400 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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 <m_netlib.h>
-
-static mir_cs csThreads;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// APC and mutex functions
-
-static void __stdcall DummyAPCFunc(ULONG_PTR)
-{
- /* called in the context of thread that cleared it's APC queue */
- return;
-}
-
-static int MirandaWaitForMutex(HANDLE hEvent)
-{
- // will get WAIT_IO_COMPLETE for QueueUserAPC() which isnt a result
- for (;;) {
- DWORD rc = MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
- if (rc == WAIT_OBJECT_0 + 1) {
- MSG msg;
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
- if (msg.hwnd != nullptr && IsDialogMessage(msg.hwnd, &msg)) /* Wine fix. */
- continue;
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- else if (rc == WAIT_OBJECT_0) { // got object
- return 1;
- }
- else if (rc == WAIT_ABANDONED_0 || rc == WAIT_FAILED)
- return 0;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// exception handling
-
-static DWORD __cdecl sttDefaultFilter(DWORD, EXCEPTION_POINTERS*)
-{
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter;
-
-MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter()
-{
- return pMirandaExceptFilter;
-}
-
-MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter _mirandaExceptFilter)
-{
- pfnExceptionFilter oldOne = pMirandaExceptFilter;
- if (_mirandaExceptFilter != nullptr)
- pMirandaExceptFilter = _mirandaExceptFilter;
- return oldOne;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// thread support functions
-
-struct THREAD_WAIT_ENTRY
-{
- DWORD dwThreadId; // valid if hThread isn't signalled
- HANDLE hThread;
- HINSTANCE hOwner;
- void *pObject, *pEntryPoint;
-};
-
-static LIST<THREAD_WAIT_ENTRY> threads(10, NumericKeySortT);
-
-struct FORK_ARG
-{
- HANDLE hEvent, hThread;
- union
- {
- pThreadFunc threadcode;
- pThreadFuncEx threadcodeex;
- };
- void *arg, *owner;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// forkthread - starts a new thread
-
-DWORD WINAPI forkthread_r(void *arg)
-{
- FORK_ARG *fa = (FORK_ARG*)arg;
- pThreadFunc callercode = fa->threadcode;
- void *cookie = fa->arg;
- HANDLE hThread = fa->hThread;
- Thread_Push((HINSTANCE)callercode);
- SetEvent(fa->hEvent);
-
- callercode(cookie);
-
- CloseHandle(hThread);
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- Thread_Pop();
- return 0;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthread(void(__cdecl *threadcode)(void*), void *arg)
-{
- FORK_ARG fa;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
- fa.threadcode = threadcode;
- fa.arg = arg;
-
- DWORD threadID;
- fa.hThread = CreateThread(nullptr, 0, forkthread_r, &fa, 0, &threadID);
- if (fa.hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- CloseHandle(fa.hEvent);
- return fa.hThread;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// forkthreadex - starts a new thread with the extended info and returns the thread id
-
-DWORD WINAPI forkthreadex_r(void * arg)
-{
- struct FORK_ARG *fa = (struct FORK_ARG *)arg;
- pThreadFuncEx threadcode = fa->threadcodeex;
- pThreadFuncOwner threadcodeex = (pThreadFuncOwner)fa->threadcodeex;
- void *cookie = fa->arg;
- void *owner = fa->owner;
- unsigned long rc = 0;
-
- Thread_Push((HINSTANCE)threadcode, fa->owner);
- SetEvent(fa->hEvent);
- if (owner)
- rc = threadcodeex(owner, cookie);
- else
- rc = threadcode(cookie);
-
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- Thread_Pop();
- return rc;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void* arg, unsigned *pThreadID)
-{
- struct FORK_ARG fa = {};
- fa.threadcodeex = aFunc;
- fa.arg = arg;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
-
- DWORD threadID = 0;
- HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
- if (hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- if (pThreadID != nullptr)
- *pThreadID = threadID;
-
- CloseHandle(fa.hEvent);
- return hThread;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg, unsigned *pThreadID)
-{
- struct FORK_ARG fa = {};
- fa.threadcodeex = (pThreadFuncEx)aFunc;
- fa.arg = arg;
- fa.owner = owner;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
-
- DWORD threadID = 0;
- HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
- if (hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- if (pThreadID != nullptr)
- *pThreadID = threadID;
-
- CloseHandle(fa.hEvent);
- return hThread;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void __cdecl KillObjectThreadsWorker(void* owner)
-{
- HANDLE *threadPool = (HANDLE*)alloca(threads.getCount() * sizeof(HANDLE));
- int threadCount = 0;
- {
- mir_cslock lck(csThreads);
-
- for (auto &it : threads)
- if (it->pObject == owner)
- threadPool[threadCount++] = it->hThread;
- }
-
- // is there anything to kill?
- if (threadCount == 0)
- return;
-
- // wait'em all
- if (WaitForMultipleObjects(threadCount, threadPool, TRUE, 5000) != WAIT_TIMEOUT)
- return;
-
- // forcibly kill all remaining threads after 5 secs
- mir_cslock lck(csThreads);
- auto T = threads.rev_iter();
- for (auto &it : T) {
- if (it->pObject == owner) {
- char szModuleName[MAX_PATH];
- GetModuleFileNameA(it->hOwner, szModuleName, sizeof(szModuleName));
- Netlib_Logf(nullptr, "Killing object thread %s:%08x", szModuleName, it->dwThreadId);
- TerminateThread(it->hThread, 9999);
- CloseHandle(it->hThread);
- mir_free(it);
- threads.removeItem(&it);
- }
- }
-}
-
-MIR_CORE_DLL(void) KillObjectThreads(void* owner)
-{
- if (owner == nullptr)
- return;
-
- DWORD dwTicks = GetTickCount() + 6000;
- HANDLE hThread = mir_forkthread(KillObjectThreadsWorker, owner);
- while (GetTickCount() < dwTicks) {
- int res = MsgWaitForMultipleObjectsEx(1, &hThread, 50, QS_ALLPOSTMESSAGE | QS_ALLINPUT, MWMO_ALERTABLE);
- if (res == WAIT_OBJECT_0 || res == WAIT_FAILED)
- break;
-
- MSG msg;
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void CALLBACK KillAllThreads(HWND, UINT, UINT_PTR, DWORD)
-{
- mir_cslock lck(csThreads);
- for (auto &p : threads) {
- char szModuleName[MAX_PATH];
- GetModuleFileNameA(p->hOwner, szModuleName, sizeof(szModuleName));
- Netlib_Logf(nullptr, "Killing thread %s:%08x (%p)", szModuleName, p->dwThreadId, p->pEntryPoint);
- TerminateThread(p->hThread, 9999);
- CloseHandle(p->hThread);
- mir_free(p);
- }
-
- threads.destroy();
-
- SetEvent(hThreadQueueEmpty);
-}
-
-MIR_CORE_DLL(void) Thread_Wait(void)
-{
- // acquire the list and wake up any alertable threads
- {
- mir_cslock lck(csThreads);
- for (auto &p : threads)
- QueueUserAPC(DummyAPCFunc, p->hThread, 0);
- }
-
- // give all unclosed threads 5 seconds to close
- SetTimer(nullptr, 0, 5000, KillAllThreads);
-
- // wait til the thread list is empty
- MirandaWaitForMutex(hThreadQueueEmpty);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG);
-#define ThreadQuerySetWin32StartAddress 9
-
-static void* GetCurrentThreadEntryPoint()
-{
- pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread");
- if (NtQueryInformationThread == nullptr)
- return nullptr;
-
- HANDLE hDupHandle, hCurrentProcess = GetCurrentProcess();
- if (!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)) {
- SetLastError(ERROR_ACCESS_DENIED);
- return nullptr;
- }
-
- DWORD_PTR dwStartAddress;
- LONG ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), nullptr);
- CloseHandle(hDupHandle);
-
- return (ntStatus != ERROR_SUCCESS) ? nullptr : (void*)dwStartAddress;
-}
-
-MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner)
-{
- ResetEvent(hThreadQueueEmpty); // thread list is not empty
-
- mir_cslock lck(csThreads);
-
- THREAD_WAIT_ENTRY *p = (THREAD_WAIT_ENTRY*)mir_calloc(sizeof(THREAD_WAIT_ENTRY));
- DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
- p->dwThreadId = GetCurrentThreadId();
- p->pObject = pOwner;
- p->pEntryPoint = hInst;
-
- // try to find the precise match
- CMPluginBase &pPlugin = GetPluginByInstance(hInst);
- if (pPlugin.getInst() == hInst)
- p->hOwner = hInst;
- else
- GetInstByAddress((hInst != nullptr) ? (PVOID)hInst : GetCurrentThreadEntryPoint());
-
- threads.insert(p);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(INT_PTR) Thread_Pop()
-{
- DWORD dwThreadId = GetCurrentThreadId();
-
- mir_cslock lck(csThreads);
- THREAD_WAIT_ENTRY *p = threads.find((THREAD_WAIT_ENTRY*)&dwThreadId);
- if (p == nullptr)
- return 1;
-
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- CloseHandle(p->hThread);
- threads.remove(p);
- mir_free(p);
-
- if (!threads.getCount()) {
- threads.destroy();
- SetEvent(hThreadQueueEmpty); // thread list is empty now
- }
-
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-const DWORD MS_VC_EXCEPTION=0x406D1388;
-
-#pragma pack(push,8)
-typedef struct tagTHREADNAME_INFO
-{
- DWORD dwType; // Must be 0x1000.
- LPCSTR szName; // Pointer to name (in user addr space).
- DWORD dwThreadID; // Thread ID (-1=caller thread).
- DWORD dwFlags; // Reserved for future use, must be zero.
-} THREADNAME_INFO;
-#pragma pack(pop)
-
-MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName)
-{
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = szThreadName;
- info.dwThreadID = GetCurrentThreadId();
- info.dwFlags = 0;
-
- __try {
- RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {}
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 <m_netlib.h> + +static mir_cs csThreads; + +///////////////////////////////////////////////////////////////////////////////////////// +// APC and mutex functions + +static void __stdcall DummyAPCFunc(ULONG_PTR) +{ + /* called in the context of thread that cleared it's APC queue */ + return; +} + +static int MirandaWaitForMutex(HANDLE hEvent) +{ + // will get WAIT_IO_COMPLETE for QueueUserAPC() which isnt a result + for (;;) { + DWORD rc = MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); + if (rc == WAIT_OBJECT_0 + 1) { + MSG msg; + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + if (msg.hwnd != nullptr && IsDialogMessage(msg.hwnd, &msg)) /* Wine fix. */ + continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else if (rc == WAIT_OBJECT_0) { // got object + return 1; + } + else if (rc == WAIT_ABANDONED_0 || rc == WAIT_FAILED) + return 0; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// exception handling + +static DWORD __cdecl sttDefaultFilter(DWORD, EXCEPTION_POINTERS*) +{ + return EXCEPTION_EXECUTE_HANDLER; +} + +pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter; + +MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter() +{ + return pMirandaExceptFilter; +} + +MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter _mirandaExceptFilter) +{ + pfnExceptionFilter oldOne = pMirandaExceptFilter; + if (_mirandaExceptFilter != nullptr) + pMirandaExceptFilter = _mirandaExceptFilter; + return oldOne; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// thread support functions + +struct THREAD_WAIT_ENTRY +{ + DWORD dwThreadId; // valid if hThread isn't signalled + HANDLE hThread; + HINSTANCE hOwner; + void *pObject, *pEntryPoint; +}; + +static LIST<THREAD_WAIT_ENTRY> threads(10, NumericKeySortT); + +struct FORK_ARG +{ + HANDLE hEvent, hThread; + union + { + pThreadFunc threadcode; + pThreadFuncEx threadcodeex; + }; + void *arg, *owner; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// forkthread - starts a new thread + +DWORD WINAPI forkthread_r(void *arg) +{ + FORK_ARG *fa = (FORK_ARG*)arg; + pThreadFunc callercode = fa->threadcode; + void *cookie = fa->arg; + HANDLE hThread = fa->hThread; + Thread_Push((HINSTANCE)callercode); + SetEvent(fa->hEvent); + + callercode(cookie); + + CloseHandle(hThread); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + Thread_Pop(); + return 0; +} + +MIR_CORE_DLL(HANDLE) mir_forkthread(void(__cdecl *threadcode)(void*), void *arg) +{ + FORK_ARG fa; + fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + fa.threadcode = threadcode; + fa.arg = arg; + + DWORD threadID; + fa.hThread = CreateThread(nullptr, 0, forkthread_r, &fa, 0, &threadID); + if (fa.hThread != nullptr) + WaitForSingleObject(fa.hEvent, INFINITE); + + CloseHandle(fa.hEvent); + return fa.hThread; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// forkthreadex - starts a new thread with the extended info and returns the thread id + +DWORD WINAPI forkthreadex_r(void * arg) +{ + struct FORK_ARG *fa = (struct FORK_ARG *)arg; + pThreadFuncEx threadcode = fa->threadcodeex; + pThreadFuncOwner threadcodeex = (pThreadFuncOwner)fa->threadcodeex; + void *cookie = fa->arg; + void *owner = fa->owner; + unsigned long rc = 0; + + Thread_Push((HINSTANCE)threadcode, fa->owner); + SetEvent(fa->hEvent); + if (owner) + rc = threadcodeex(owner, cookie); + else + rc = threadcode(cookie); + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + Thread_Pop(); + return rc; +} + +MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void* arg, unsigned *pThreadID) +{ + struct FORK_ARG fa = {}; + fa.threadcodeex = aFunc; + fa.arg = arg; + fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + + DWORD threadID = 0; + HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID); + if (hThread != nullptr) + WaitForSingleObject(fa.hEvent, INFINITE); + + if (pThreadID != nullptr) + *pThreadID = threadID; + + CloseHandle(fa.hEvent); + return hThread; +} + +MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg, unsigned *pThreadID) +{ + struct FORK_ARG fa = {}; + fa.threadcodeex = (pThreadFuncEx)aFunc; + fa.arg = arg; + fa.owner = owner; + fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + + DWORD threadID = 0; + HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID); + if (hThread != nullptr) + WaitForSingleObject(fa.hEvent, INFINITE); + + if (pThreadID != nullptr) + *pThreadID = threadID; + + CloseHandle(fa.hEvent); + return hThread; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static void __cdecl KillObjectThreadsWorker(void* owner) +{ + HANDLE *threadPool = (HANDLE*)alloca(threads.getCount() * sizeof(HANDLE)); + int threadCount = 0; + { + mir_cslock lck(csThreads); + + for (auto &it : threads) + if (it->pObject == owner) + threadPool[threadCount++] = it->hThread; + } + + // is there anything to kill? + if (threadCount == 0) + return; + + // wait'em all + if (WaitForMultipleObjects(threadCount, threadPool, TRUE, 5000) != WAIT_TIMEOUT) + return; + + // forcibly kill all remaining threads after 5 secs + mir_cslock lck(csThreads); + auto T = threads.rev_iter(); + for (auto &it : T) { + if (it->pObject == owner) { + char szModuleName[MAX_PATH]; + GetModuleFileNameA(it->hOwner, szModuleName, sizeof(szModuleName)); + Netlib_Logf(nullptr, "Killing object thread %s:%08x", szModuleName, it->dwThreadId); + TerminateThread(it->hThread, 9999); + CloseHandle(it->hThread); + mir_free(it); + threads.removeItem(&it); + } + } +} + +MIR_CORE_DLL(void) KillObjectThreads(void* owner) +{ + if (owner == nullptr) + return; + + DWORD dwTicks = GetTickCount() + 6000; + HANDLE hThread = mir_forkthread(KillObjectThreadsWorker, owner); + while (GetTickCount() < dwTicks) { + int res = MsgWaitForMultipleObjectsEx(1, &hThread, 50, QS_ALLPOSTMESSAGE | QS_ALLINPUT, MWMO_ALERTABLE); + if (res == WAIT_OBJECT_0 || res == WAIT_FAILED) + break; + + MSG msg; + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static void CALLBACK KillAllThreads(HWND, UINT, UINT_PTR, DWORD) +{ + mir_cslock lck(csThreads); + for (auto &p : threads) { + char szModuleName[MAX_PATH]; + GetModuleFileNameA(p->hOwner, szModuleName, sizeof(szModuleName)); + Netlib_Logf(nullptr, "Killing thread %s:%08x (%p)", szModuleName, p->dwThreadId, p->pEntryPoint); + TerminateThread(p->hThread, 9999); + CloseHandle(p->hThread); + mir_free(p); + } + + threads.destroy(); + + SetEvent(hThreadQueueEmpty); +} + +MIR_CORE_DLL(void) Thread_Wait(void) +{ + // acquire the list and wake up any alertable threads + { + mir_cslock lck(csThreads); + for (auto &p : threads) + QueueUserAPC(DummyAPCFunc, p->hThread, 0); + } + + // give all unclosed threads 5 seconds to close + SetTimer(nullptr, 0, 5000, KillAllThreads); + + // wait til the thread list is empty + MirandaWaitForMutex(hThreadQueueEmpty); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG); +#define ThreadQuerySetWin32StartAddress 9 + +static void* GetCurrentThreadEntryPoint() +{ + pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread"); + if (NtQueryInformationThread == nullptr) + return nullptr; + + HANDLE hDupHandle, hCurrentProcess = GetCurrentProcess(); + if (!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)) { + SetLastError(ERROR_ACCESS_DENIED); + return nullptr; + } + + DWORD_PTR dwStartAddress; + LONG ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), nullptr); + CloseHandle(hDupHandle); + + return (ntStatus != ERROR_SUCCESS) ? nullptr : (void*)dwStartAddress; +} + +MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner) +{ + ResetEvent(hThreadQueueEmpty); // thread list is not empty + + mir_cslock lck(csThreads); + + THREAD_WAIT_ENTRY *p = (THREAD_WAIT_ENTRY*)mir_calloc(sizeof(THREAD_WAIT_ENTRY)); + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); + p->dwThreadId = GetCurrentThreadId(); + p->pObject = pOwner; + p->pEntryPoint = hInst; + + // try to find the precise match + CMPluginBase &pPlugin = GetPluginByInstance(hInst); + if (pPlugin.getInst() == hInst) + p->hOwner = hInst; + else + GetInstByAddress((hInst != nullptr) ? (PVOID)hInst : GetCurrentThreadEntryPoint()); + + threads.insert(p); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(INT_PTR) Thread_Pop() +{ + DWORD dwThreadId = GetCurrentThreadId(); + + mir_cslock lck(csThreads); + THREAD_WAIT_ENTRY *p = threads.find((THREAD_WAIT_ENTRY*)&dwThreadId); + if (p == nullptr) + return 1; + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + CloseHandle(p->hThread); + threads.remove(p); + mir_free(p); + + if (!threads.getCount()) { + threads.destroy(); + SetEvent(hThreadQueueEmpty); // thread list is empty now + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +const DWORD MS_VC_EXCEPTION=0x406D1388; + +#pragma pack(push,8) +typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. +} THREADNAME_INFO; +#pragma pack(pop) + +MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName) +{ + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = szThreadName; + info.dwThreadID = GetCurrentThreadId(); + info.dwFlags = 0; + + __try { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except (EXCEPTION_EXECUTE_HANDLER) + {} +} diff --git a/src/mir_core/src/timezones.cpp b/src/mir_core/src/Windows/timezones.cpp index 10d2ad6225..8de5704d30 100644 --- a/src/mir_core/src/timezones.cpp +++ b/src/mir_core/src/Windows/timezones.cpp @@ -1,592 +1,592 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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.
-
-implements services to handle location - based timezones, instead of
-simple UTC offsets.
-*/
-
-#include "stdafx.h"
-
-typedef DWORD (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi);
-static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation;
-
-struct REG_TZI_FORMAT
-{
- LONG Bias;
- LONG StandardBias;
- LONG DaylightBias;
- SYSTEMTIME StandardDate;
- SYSTEMTIME DaylightDate;
-};
-
-#define MIM_TZ_DISPLAYLEN 128
-
-struct MIM_TIMEZONE
-{
- unsigned hash;
- int offset;
-
- wchar_t tszName[MIM_TZ_NAMELEN]; // windows name for the time zone
- wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs)
- // every hour should be sufficient.
- TIME_ZONE_INFORMATION tzi;
-
- static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2)
- { return p2->tzi.Bias - p1->tzi.Bias;
- }
-};
-
-struct TZ_INT_INFO
-{
- DWORD timestamp; // last time updated
- MIM_TIMEZONE myTZ; // set to my own timezone
-};
-
-static TZ_INT_INFO myInfo;
-
-static OBJLIST<MIM_TIMEZONE> g_timezones(55, NumericKeySortT);
-static LIST<MIM_TIMEZONE> g_timezonesBias(55, MIM_TIMEZONE::compareBias);
-
-// KB167296
-void UnixTimeToFileTime(mir_time ts, LPFILETIME pft)
-{
- unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64;
- pft->dwLowDateTime = (DWORD)ll;
- pft->dwHighDateTime = ll >> 32;
-}
-
-mir_time FileTimeToUnixTime(LPFILETIME pft)
-{
- unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime;
- ll -= 116444736000000000i64;
- return (mir_time)(ll / 10000000);
-}
-
-void FormatTime(const SYSTEMTIME *st, const wchar_t *szFormat, wchar_t *szDest, size_t cbDest)
-{
- if (szDest == nullptr || cbDest == 0) return;
-
- CMStringW tszTemp;
-
- for (const wchar_t* pFormat = szFormat; *pFormat; ++pFormat) {
- DWORD fmt = 0;
- bool date = false, iso = false;
- switch (*pFormat) {
- case 't':
- fmt = TIME_NOSECONDS;
- date = false;
- break;
-
- case 's':
- fmt = 0;
- date = false;
- break;
-
- case 'm':
- fmt = TIME_NOMINUTESORSECONDS;
- date = false;
- break;
-
- case 'd':
- fmt = DATE_SHORTDATE;
- date = true;
- break;
-
- case 'D':
- fmt = DATE_LONGDATE;
- date = true;
- break;
-
- case 'I':
- iso = true;
- break;
-
- default:
- tszTemp.AppendChar(*pFormat);
- continue;
- }
-
- wchar_t dateTimeStr[64];
- if (iso)
- tszTemp.AppendFormat(L"%d-%02d-%02dT%02d:%02d:%02dZ", st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond);
- else if (date) {
- GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
- tszTemp.Append(dateTimeStr);
- }
- else {
- GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
- tszTemp.Append(dateTimeStr);
- }
- }
-
- wcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE);
-}
-
-MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st)
-{
- if (st == nullptr) return 1;
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == UTC_TIME_HANDLE)
- GetSystemTime(st);
- else if (tz && tz != &myInfo.myTZ) {
- SYSTEMTIME sto;
- GetSystemTime(&sto);
- return !SystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st);
- }
- else
- GetLocalTime(st);
-
- return 0;
-}
-
-MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr)
- return myInfo.myTZ.tszName;
- if (tz == UTC_TIME_HANDLE)
- return L"UTC";
-
- return tz->tszName;
-}
-
-MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname)
-{
- for (auto &tz : g_timezonesBias)
- if (!mir_wstrcmp(tz->tszName, TZname))
- return tz->szDisplay;
-
- return L"";
-}
-
-static void CalcTsOffset(MIM_TIMEZONE *tz)
-{
- SYSTEMTIME st, stl;
- GetSystemTime(&st);
-
- FILETIME ft;
- SystemTimeToFileTime(&st, &ft);
- mir_time ts1 = FileTimeToUnixTime(&ft);
-
- if (!SystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl))
- return;
-
- SystemTimeToFileTime(&stl, &ft);
- mir_time ts2 = FileTimeToUnixTime(&ft);
-
- tz->offset = ts2 - ts1;
-}
-
-static bool IsSameTime(MIM_TIMEZONE *tz)
-{
- SYSTEMTIME st, stl;
-
- if (tz == &myInfo.myTZ)
- return true;
-
- TimeZone_GetTimeZoneTime(tz, &stl);
- TimeZone_GetTimeZoneTime(nullptr, &st);
-
- return st.wHour == stl.wHour && st.wMinute == stl.wMinute;
-}
-
-MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, DWORD dwFlags)
-{
- if (tszName == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (mir_wstrcmp(myInfo.myTZ.tszName, tszName) == 0)
- return (dwFlags & TZF_DIFONLY) ? nullptr : &myInfo.myTZ;
-
- MIM_TIMEZONE tzsearch;
- tzsearch.hash = mir_hashstrT(tszName);
-
- MIM_TIMEZONE *tz = g_timezones.find(&tzsearch);
- if (tz == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (dwFlags & TZF_DIFONLY)
- return IsSameTime(tz) ? nullptr : tz;
-
- return tz;
-}
-
-MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags)
-{
- if (hContact == NULL && szModule == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (szModule == nullptr) szModule = "UserInfo";
-
- DBVARIANT dbv;
- if (!db_get_ws(hContact, szModule, "TzName", &dbv)) {
- HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
- db_free(&dbv);
- if (res) return res;
- }
-
- signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1);
- if (timezone == -1) {
- char *szProto = Proto_GetBaseAccountName(hContact);
- if (!db_get_ws(hContact, szProto, "TzName", &dbv)) {
- HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
- db_free(&dbv);
- if (res) return res;
- }
- timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1);
- }
-
- if (timezone != -1) {
- MIM_TIMEZONE tzsearch;
- tzsearch.tzi.Bias = timezone * 30;
- if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) {
- if (dwFlags & TZF_DIFONLY) return nullptr;
- return &myInfo.myTZ;
- }
-
- int i = g_timezonesBias.getIndex(&tzsearch);
- while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i;
-
- int delta = LONG_MAX;
- for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) {
- int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth);
- if (delta1 <= delta) {
- delta = delta1;
- i = j;
- }
- }
-
- if (i >= 0) {
- MIM_TIMEZONE *tz = g_timezonesBias[i];
- return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? nullptr : tz;
- }
- }
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-}
-
-MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ)
-{
- if (szModule == nullptr) szModule = "UserInfo";
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz) {
- db_set_ws(hContact, szModule, "TzName", tz->tszName);
- db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30));
- }
- else {
- db_unset(hContact, szModule, "TzName");
- db_unset(hContact, szModule, "Timezone");
- }
-}
-
-MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)))
- return 1;
-
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- SYSTEMTIME st;
- if (TimeZone_GetTimeZoneTime(tz, &st))
- return 1;
-
- FormatTime(&st, szFormat, szDest, cbDest);
- return 0;
-}
-
-MIR_CORE_DLL(int) TimeZone_GetSystemTime(HANDLE hTZ, mir_time ts, SYSTEMTIME *dest, DWORD dwFlags)
-{
- if (dest == nullptr)
- return 2;
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE *)hTZ;
- if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) {
- memset(dest, 0, sizeof(SYSTEMTIME));
- return 1;
- }
-
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- FILETIME ft;
- if (tz == UTC_TIME_HANDLE)
- UnixTimeToFileTime(ts, &ft);
- else {
- if (tz->offset == INT_MIN)
- CalcTsOffset(tz);
-
- UnixTimeToFileTime(ts + tz->offset, &ft);
- }
-
- FileTimeToSystemTime(&ft, dest);
- return 0;
-}
-
-MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags)
-{
- SYSTEMTIME st;
- if (!TimeZone_GetSystemTime(hTZ, ts, &st, dwFlags))
- FormatTime(&st, szFormat, szDest, cbDest);
- return 0;
-}
-
-MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- return tz ? &tz->tzi : &myInfo.myTZ.tzi;
-}
-
-MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- if (tz == UTC_TIME_HANDLE)
- return ts;
-
- if (tz->offset == INT_MIN)
- CalcTsOffset(tz);
-
- return ts + tz->offset;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-struct ListMessages
-{
- UINT addStr, getSel, setSel, getData, setData;
-};
-
-static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA };
-static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA };
-
-static const ListMessages* GetListMessages(HWND hWnd, DWORD dwFlags)
-{
- if (hWnd == nullptr)
- return nullptr;
-
- if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) {
- wchar_t tszClassName[128];
- GetClassName(hWnd, tszClassName, _countof(tszClassName));
- if (!mir_wstrcmpi(tszClassName, L"COMBOBOX"))
- dwFlags |= TZF_PLF_CB;
- else if (!mir_wstrcmpi(tszClassName, L"LISTBOX"))
- dwFlags |= TZF_PLF_LB;
- }
-
- if (dwFlags & TZF_PLF_CB)
- return &cbMessages;
- if (dwFlags & TZF_PLF_LB)
- return &lbMessages;
- return nullptr;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
-{
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg == nullptr)
- return -1;
-
- if (szModule == nullptr)
- szModule = "UserInfo";
-
- int iSelection = 0;
- ptrW tszName(db_get_wsa(hContact, szModule, "TzName"));
- if (tszName != NULL) {
- unsigned hash = mir_hashstrT(tszName);
- for (auto &it : g_timezonesBias) {
- if (hash == it->hash) {
- iSelection = g_timezonesBias.indexOf(&it) + 1;
- break;
- }
- }
- }
- else {
- signed char cBias = db_get_b(hContact, szModule, "Timezone", -100);
- if (cBias != -100) {
- int iBias = cBias * 30;
- for (auto &it : g_timezonesBias) {
- if (iBias == it->tzi.Bias) {
- iSelection = g_timezonesBias.indexOf(&it) + 1;
- break;
- }
- }
- }
- }
-
- SendMessage(hWnd, lstMsg->setSel, iSelection, 0);
- return iSelection;
-}
-
-MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
-{
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg == nullptr)
- return 0;
-
- SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateW_LP(L"<unspecified>"));
-
- for (auto &it : g_timezonesBias) {
- SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)it->szDisplay);
- SendMessage(hWnd, lstMsg->setData, g_timezonesBias.indexOf(&it) + 1, (LPARAM)it);
- }
-
- return TimeZone_SelectListItem(hContact, szModule, hWnd, dwFlags);
-}
-
-MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
-{
- if (szModule == nullptr) szModule = "UserInfo";
-
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg) {
- LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0);
- if (offset > 0) {
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0);
- if ((INT_PTR)tz != CB_ERR && tz != nullptr)
- TimeZone_StoreByContact(hContact, szModule, tz);
- }
- else TimeZone_StoreByContact(hContact, szModule, nullptr);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(DWORD) TimeZone_ToLocal(DWORD timeVal)
-{
- return TimeZone_UtcToLocal(nullptr, (mir_time)timeVal);
-}
-
-MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest)
-{
- wchar_t *szTemp = (wchar_t*)alloca(cchDest*sizeof(wchar_t));
- TimeZone_PrintTimeStamp(nullptr, timeVal, _A2T(szFormat), szTemp, cchDest, 0);
- WideCharToMultiByte(CP_ACP, 0, szTemp, -1, szDest, (int)cchDest, nullptr, nullptr);
- return szDest;
-}
-
-MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest)
-{
- TimeZone_PrintTimeStamp(nullptr, timeVal, wszFormat, wszDest, cchDest, 0);
- return wszDest;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GetLocalizedString(HKEY hSubKey, const wchar_t *szName, wchar_t *szBuf, DWORD cbLen)
-{
- DWORD dwLength = cbLen * sizeof(wchar_t);
- RegQueryValueEx(hSubKey, szName, nullptr, nullptr, (unsigned char *)szBuf, &dwLength);
- szBuf[min(dwLength / sizeof(wchar_t), cbLen - 1)] = 0;
-}
-
-void RecalculateTime(void)
-{
- GetTimeZoneInformation(&myInfo.myTZ.tzi);
- myInfo.timestamp = time(0);
- myInfo.myTZ.offset = INT_MIN;
-
- bool found = false;
- DYNAMIC_TIME_ZONE_INFORMATION dtzi;
-
- if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) {
- wcsncpy_s(myInfo.myTZ.tszName, dtzi.TimeZoneKeyName, _TRUNCATE);
- found = true;
- }
-
- for (auto &tz : g_timezones) {
- if (tz->offset != INT_MIN)
- tz->offset = INT_MIN;
-
- if (!found) {
- if (!mir_wstrcmp(tz->tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz->tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) {
- wcsncpy_s(myInfo.myTZ.tszName, tz->tszName, _TRUNCATE);
- found = true;
- }
- }
- }
-}
-
-void InitTimeZones(void)
-{
- REG_TZI_FORMAT tzi;
- HKEY hKey;
-
- const wchar_t *tszKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
-
- /*
- * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with
- * the registry key name, so finding our own time zone later will be MUCH easier for
- * localized systems or systems with a MUI pack installed
- */
- if (IsWinVerVistaPlus())
- pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(L"kernel32"), "GetDynamicTimeZoneInformation");
-
- if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) {
- DWORD dwIndex = 0;
- HKEY hSubKey;
- wchar_t tszName[MIM_TZ_NAMELEN];
-
- DWORD dwSize = _countof(tszName);
- while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, nullptr, nullptr, nullptr, nullptr)) {
- if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) {
- dwSize = sizeof(tszName);
-
- DWORD dwLength = sizeof(tzi);
- if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, L"TZI", nullptr, nullptr, (unsigned char *)&tzi, &dwLength))
- continue;
-
- MIM_TIMEZONE *tz = new MIM_TIMEZONE;
-
- tz->tzi.Bias = tzi.Bias;
- tz->tzi.StandardDate = tzi.StandardDate;
- tz->tzi.StandardBias = tzi.StandardBias;
- tz->tzi.DaylightDate = tzi.DaylightDate;
- tz->tzi.DaylightBias = tzi.DaylightBias;
-
- mir_wstrcpy(tz->tszName, tszName);
- tz->hash = mir_hashstrT(tszName);
- tz->offset = INT_MIN;
-
- GetLocalizedString(hSubKey, L"Display", tz->szDisplay, _countof(tz->szDisplay));
- GetLocalizedString(hSubKey, L"Std", tz->tzi.StandardName, _countof(tz->tzi.StandardName));
- GetLocalizedString(hSubKey, L"Dlt", tz->tzi.DaylightName, _countof(tz->tzi.DaylightName));
-
- g_timezones.insert(tz);
- g_timezonesBias.insert(tz);
-
- RegCloseKey(hSubKey);
- }
- dwSize = _countof(tszName);
- }
- RegCloseKey(hKey);
- }
-
- RecalculateTime();
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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. + +implements services to handle location - based timezones, instead of +simple UTC offsets. +*/ + +#include "../stdafx.h" + +typedef DWORD (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi); +static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation; + +struct REG_TZI_FORMAT +{ + LONG Bias; + LONG StandardBias; + LONG DaylightBias; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +}; + +#define MIM_TZ_DISPLAYLEN 128 + +struct MIM_TIMEZONE +{ + unsigned hash; + int offset; + + wchar_t tszName[MIM_TZ_NAMELEN]; // windows name for the time zone + wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs) + // every hour should be sufficient. + TIME_ZONE_INFORMATION tzi; + + static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2) + { return p2->tzi.Bias - p1->tzi.Bias; + } +}; + +struct TZ_INT_INFO +{ + DWORD timestamp; // last time updated + MIM_TIMEZONE myTZ; // set to my own timezone +}; + +static TZ_INT_INFO myInfo; + +static OBJLIST<MIM_TIMEZONE> g_timezones(55, NumericKeySortT); +static LIST<MIM_TIMEZONE> g_timezonesBias(55, MIM_TIMEZONE::compareBias); + +// KB167296 +void UnixTimeToFileTime(mir_time ts, LPFILETIME pft) +{ + unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64; + pft->dwLowDateTime = (DWORD)ll; + pft->dwHighDateTime = ll >> 32; +} + +mir_time FileTimeToUnixTime(LPFILETIME pft) +{ + unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime; + ll -= 116444736000000000i64; + return (mir_time)(ll / 10000000); +} + +void FormatTime(const SYSTEMTIME *st, const wchar_t *szFormat, wchar_t *szDest, size_t cbDest) +{ + if (szDest == nullptr || cbDest == 0) return; + + CMStringW tszTemp; + + for (const wchar_t* pFormat = szFormat; *pFormat; ++pFormat) { + DWORD fmt = 0; + bool date = false, iso = false; + switch (*pFormat) { + case 't': + fmt = TIME_NOSECONDS; + date = false; + break; + + case 's': + fmt = 0; + date = false; + break; + + case 'm': + fmt = TIME_NOMINUTESORSECONDS; + date = false; + break; + + case 'd': + fmt = DATE_SHORTDATE; + date = true; + break; + + case 'D': + fmt = DATE_LONGDATE; + date = true; + break; + + case 'I': + iso = true; + break; + + default: + tszTemp.AppendChar(*pFormat); + continue; + } + + wchar_t dateTimeStr[64]; + if (iso) + tszTemp.AppendFormat(L"%d-%02d-%02dT%02d:%02d:%02dZ", st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond); + else if (date) { + GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr)); + tszTemp.Append(dateTimeStr); + } + else { + GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr)); + tszTemp.Append(dateTimeStr); + } + } + + wcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE); +} + +MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st) +{ + if (st == nullptr) return 1; + + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == UTC_TIME_HANDLE) + GetSystemTime(st); + else if (tz && tz != &myInfo.myTZ) { + SYSTEMTIME sto; + GetSystemTime(&sto); + return !SystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st); + } + else + GetLocalTime(st); + + return 0; +} + +MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == nullptr) + return myInfo.myTZ.tszName; + if (tz == UTC_TIME_HANDLE) + return L"UTC"; + + return tz->tszName; +} + +MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname) +{ + for (auto &tz : g_timezonesBias) + if (!mir_wstrcmp(tz->tszName, TZname)) + return tz->szDisplay; + + return L""; +} + +static void CalcTsOffset(MIM_TIMEZONE *tz) +{ + SYSTEMTIME st, stl; + GetSystemTime(&st); + + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + mir_time ts1 = FileTimeToUnixTime(&ft); + + if (!SystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl)) + return; + + SystemTimeToFileTime(&stl, &ft); + mir_time ts2 = FileTimeToUnixTime(&ft); + + tz->offset = ts2 - ts1; +} + +static bool IsSameTime(MIM_TIMEZONE *tz) +{ + SYSTEMTIME st, stl; + + if (tz == &myInfo.myTZ) + return true; + + TimeZone_GetTimeZoneTime(tz, &stl); + TimeZone_GetTimeZoneTime(nullptr, &st); + + return st.wHour == stl.wHour && st.wMinute == stl.wMinute; +} + +MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, DWORD dwFlags) +{ + if (tszName == nullptr) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ; + + if (mir_wstrcmp(myInfo.myTZ.tszName, tszName) == 0) + return (dwFlags & TZF_DIFONLY) ? nullptr : &myInfo.myTZ; + + MIM_TIMEZONE tzsearch; + tzsearch.hash = mir_hashstrT(tszName); + + MIM_TIMEZONE *tz = g_timezones.find(&tzsearch); + if (tz == nullptr) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ; + + if (dwFlags & TZF_DIFONLY) + return IsSameTime(tz) ? nullptr : tz; + + return tz; +} + +MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags) +{ + if (hContact == NULL && szModule == nullptr) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ; + + if (szModule == nullptr) szModule = "UserInfo"; + + DBVARIANT dbv; + if (!db_get_ws(hContact, szModule, "TzName", &dbv)) { + HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags); + db_free(&dbv); + if (res) return res; + } + + signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1); + if (timezone == -1) { + char *szProto = Proto_GetBaseAccountName(hContact); + if (!db_get_ws(hContact, szProto, "TzName", &dbv)) { + HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags); + db_free(&dbv); + if (res) return res; + } + timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1); + } + + if (timezone != -1) { + MIM_TIMEZONE tzsearch; + tzsearch.tzi.Bias = timezone * 30; + if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) { + if (dwFlags & TZF_DIFONLY) return nullptr; + return &myInfo.myTZ; + } + + int i = g_timezonesBias.getIndex(&tzsearch); + while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i; + + int delta = LONG_MAX; + for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) { + int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth); + if (delta1 <= delta) { + delta = delta1; + i = j; + } + } + + if (i >= 0) { + MIM_TIMEZONE *tz = g_timezonesBias[i]; + return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? nullptr : tz; + } + } + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ; +} + +MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ) +{ + if (szModule == nullptr) szModule = "UserInfo"; + + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz) { + db_set_ws(hContact, szModule, "TzName", tz->tszName); + db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30)); + } + else { + db_unset(hContact, szModule, "TzName"); + db_unset(hContact, szModule, "Timezone"); + } +} + +MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) + return 1; + + if (tz == nullptr) + tz = &myInfo.myTZ; + + SYSTEMTIME st; + if (TimeZone_GetTimeZoneTime(tz, &st)) + return 1; + + FormatTime(&st, szFormat, szDest, cbDest); + return 0; +} + +MIR_CORE_DLL(int) TimeZone_GetSystemTime(HANDLE hTZ, mir_time ts, SYSTEMTIME *dest, DWORD dwFlags) +{ + if (dest == nullptr) + return 2; + + MIM_TIMEZONE *tz = (MIM_TIMEZONE *)hTZ; + if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) { + memset(dest, 0, sizeof(SYSTEMTIME)); + return 1; + } + + if (tz == nullptr) + tz = &myInfo.myTZ; + + FILETIME ft; + if (tz == UTC_TIME_HANDLE) + UnixTimeToFileTime(ts, &ft); + else { + if (tz->offset == INT_MIN) + CalcTsOffset(tz); + + UnixTimeToFileTime(ts + tz->offset, &ft); + } + + FileTimeToSystemTime(&ft, dest); + return 0; +} + +MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags) +{ + SYSTEMTIME st; + if (!TimeZone_GetSystemTime(hTZ, ts, &st, dwFlags)) + FormatTime(&st, szFormat, szDest, cbDest); + return 0; +} + +MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + return tz ? &tz->tzi : &myInfo.myTZ.tzi; +} + +MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == nullptr) + tz = &myInfo.myTZ; + + if (tz == UTC_TIME_HANDLE) + return ts; + + if (tz->offset == INT_MIN) + CalcTsOffset(tz); + + return ts + tz->offset; +} + +/////////////////////////////////////////////////////////////////////////////// + +struct ListMessages +{ + UINT addStr, getSel, setSel, getData, setData; +}; + +static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA }; +static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA }; + +static const ListMessages* GetListMessages(HWND hWnd, DWORD dwFlags) +{ + if (hWnd == nullptr) + return nullptr; + + if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) { + wchar_t tszClassName[128]; + GetClassName(hWnd, tszClassName, _countof(tszClassName)); + if (!mir_wstrcmpi(tszClassName, L"COMBOBOX")) + dwFlags |= TZF_PLF_CB; + else if (!mir_wstrcmpi(tszClassName, L"LISTBOX")) + dwFlags |= TZF_PLF_LB; + } + + if (dwFlags & TZF_PLF_CB) + return &cbMessages; + if (dwFlags & TZF_PLF_LB) + return &lbMessages; + return nullptr; +} + +/////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg == nullptr) + return -1; + + if (szModule == nullptr) + szModule = "UserInfo"; + + int iSelection = 0; + ptrW tszName(db_get_wsa(hContact, szModule, "TzName")); + if (tszName != NULL) { + unsigned hash = mir_hashstrT(tszName); + for (auto &it : g_timezonesBias) { + if (hash == it->hash) { + iSelection = g_timezonesBias.indexOf(&it) + 1; + break; + } + } + } + else { + signed char cBias = db_get_b(hContact, szModule, "Timezone", -100); + if (cBias != -100) { + int iBias = cBias * 30; + for (auto &it : g_timezonesBias) { + if (iBias == it->tzi.Bias) { + iSelection = g_timezonesBias.indexOf(&it) + 1; + break; + } + } + } + } + + SendMessage(hWnd, lstMsg->setSel, iSelection, 0); + return iSelection; +} + +MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg == nullptr) + return 0; + + SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateW_LP(L"<unspecified>")); + + for (auto &it : g_timezonesBias) { + SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)it->szDisplay); + SendMessage(hWnd, lstMsg->setData, g_timezonesBias.indexOf(&it) + 1, (LPARAM)it); + } + + return TimeZone_SelectListItem(hContact, szModule, hWnd, dwFlags); +} + +MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + if (szModule == nullptr) szModule = "UserInfo"; + + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg) { + LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0); + if (offset > 0) { + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0); + if ((INT_PTR)tz != CB_ERR && tz != nullptr) + TimeZone_StoreByContact(hContact, szModule, tz); + } + else TimeZone_StoreByContact(hContact, szModule, nullptr); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(DWORD) TimeZone_ToLocal(DWORD timeVal) +{ + return TimeZone_UtcToLocal(nullptr, (mir_time)timeVal); +} + +MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest) +{ + wchar_t *szTemp = (wchar_t*)alloca(cchDest*sizeof(wchar_t)); + TimeZone_PrintTimeStamp(nullptr, timeVal, _A2T(szFormat), szTemp, cchDest, 0); + WideCharToMultiByte(CP_ACP, 0, szTemp, -1, szDest, (int)cchDest, nullptr, nullptr); + return szDest; +} + +MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest) +{ + TimeZone_PrintTimeStamp(nullptr, timeVal, wszFormat, wszDest, cchDest, 0); + return wszDest; +} + +/////////////////////////////////////////////////////////////////////////////// + +void GetLocalizedString(HKEY hSubKey, const wchar_t *szName, wchar_t *szBuf, DWORD cbLen) +{ + DWORD dwLength = cbLen * sizeof(wchar_t); + RegQueryValueEx(hSubKey, szName, nullptr, nullptr, (unsigned char *)szBuf, &dwLength); + szBuf[min(dwLength / sizeof(wchar_t), cbLen - 1)] = 0; +} + +void RecalculateTime(void) +{ + GetTimeZoneInformation(&myInfo.myTZ.tzi); + myInfo.timestamp = time(0); + myInfo.myTZ.offset = INT_MIN; + + bool found = false; + DYNAMIC_TIME_ZONE_INFORMATION dtzi; + + if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) { + wcsncpy_s(myInfo.myTZ.tszName, dtzi.TimeZoneKeyName, _TRUNCATE); + found = true; + } + + for (auto &tz : g_timezones) { + if (tz->offset != INT_MIN) + tz->offset = INT_MIN; + + if (!found) { + if (!mir_wstrcmp(tz->tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz->tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) { + wcsncpy_s(myInfo.myTZ.tszName, tz->tszName, _TRUNCATE); + found = true; + } + } + } +} + +void InitTimeZones(void) +{ + REG_TZI_FORMAT tzi; + HKEY hKey; + + const wchar_t *tszKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"; + + /* + * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with + * the registry key name, so finding our own time zone later will be MUCH easier for + * localized systems or systems with a MUI pack installed + */ + if (IsWinVerVistaPlus()) + pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(L"kernel32"), "GetDynamicTimeZoneInformation"); + + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) { + DWORD dwIndex = 0; + HKEY hSubKey; + wchar_t tszName[MIM_TZ_NAMELEN]; + + DWORD dwSize = _countof(tszName); + while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, nullptr, nullptr, nullptr, nullptr)) { + if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) { + dwSize = sizeof(tszName); + + DWORD dwLength = sizeof(tzi); + if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, L"TZI", nullptr, nullptr, (unsigned char *)&tzi, &dwLength)) + continue; + + MIM_TIMEZONE *tz = new MIM_TIMEZONE; + + tz->tzi.Bias = tzi.Bias; + tz->tzi.StandardDate = tzi.StandardDate; + tz->tzi.StandardBias = tzi.StandardBias; + tz->tzi.DaylightDate = tzi.DaylightDate; + tz->tzi.DaylightBias = tzi.DaylightBias; + + mir_wstrcpy(tz->tszName, tszName); + tz->hash = mir_hashstrT(tszName); + tz->offset = INT_MIN; + + GetLocalizedString(hSubKey, L"Display", tz->szDisplay, _countof(tz->szDisplay)); + GetLocalizedString(hSubKey, L"Std", tz->tzi.StandardName, _countof(tz->tzi.StandardName)); + GetLocalizedString(hSubKey, L"Dlt", tz->tzi.DaylightName, _countof(tz->tzi.DaylightName)); + + g_timezones.insert(tz); + g_timezonesBias.insert(tz); + + RegCloseKey(hSubKey); + } + dwSize = _countof(tszName); + } + RegCloseKey(hKey); + } + + RecalculateTime(); +} diff --git a/src/mir_core/src/windowlist.cpp b/src/mir_core/src/Windows/windowlist.cpp index 99631cb9a5..6549b28812 100644 --- a/src/mir_core/src/windowlist.cpp +++ b/src/mir_core/src/Windows/windowlist.cpp @@ -1,105 +1,105 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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"
-
-struct TWindowListItem
-{
- TWindowListItem(UINT_PTR _param, HWND _wnd) :
- param(_param),
- hWnd(_wnd)
- {}
-
- UINT_PTR param;
- HWND hWnd;
-};
-
-struct TWindowList : public OBJLIST<TWindowListItem>
-{
- TWindowList() :
- OBJLIST<TWindowListItem>(10, NumericKeySortT)
- {}
-};
-
-MIR_CORE_DLL(MWindowList) WindowList_Create(void)
-{
- return new TWindowList();
-}
-
-MIR_CORE_DLL(void) WindowList_Destroy(MWindowList &hList)
-{
- delete hList;
- hList = nullptr;
-}
-
-MIR_CORE_DLL(int) WindowList_Add(MWindowList hList, HWND hwnd, UINT_PTR param)
-{
- if (hList == nullptr)
- return 1;
-
- hList->insert(new TWindowListItem(param, hwnd));
- return 0;
-}
-
-MIR_CORE_DLL(int) WindowList_Remove(MWindowList hList, HWND hwnd)
-{
- if (hList == nullptr) return 1;
-
- for (auto &it : *hList)
- if (it->hWnd == hwnd) {
- hList->removeItem(&it);
- return 0;
- }
-
- return 1;
-}
-
-MIR_CORE_DLL(HWND) WindowList_Find(MWindowList hList, UINT_PTR param)
-{
- if (hList == nullptr)
- return nullptr;
-
- TWindowListItem *p = hList->find((TWindowListItem*)¶m);
- return (p == nullptr) ? nullptr : p->hWnd;
-}
-
-MIR_CORE_DLL(int) WindowList_Broadcast(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
-{
- if (hList == nullptr)
- return 0;
-
- for (auto &it : hList->rev_iter())
- SendMessage(it->hWnd, message, wParam, lParam);
- return 0;
-}
-
-MIR_CORE_DLL(int) WindowList_BroadcastAsync(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
-{
- if (hList == nullptr)
- return 0;
-
- for (auto &it : hList->rev_iter())
- PostMessage(it->hWnd, message, wParam, lParam);
- return 0;
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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" + +struct TWindowListItem +{ + TWindowListItem(UINT_PTR _param, HWND _wnd) : + param(_param), + hWnd(_wnd) + {} + + UINT_PTR param; + HWND hWnd; +}; + +struct TWindowList : public OBJLIST<TWindowListItem> +{ + TWindowList() : + OBJLIST<TWindowListItem>(10, NumericKeySortT) + {} +}; + +MIR_CORE_DLL(MWindowList) WindowList_Create(void) +{ + return new TWindowList(); +} + +MIR_CORE_DLL(void) WindowList_Destroy(MWindowList &hList) +{ + delete hList; + hList = nullptr; +} + +MIR_CORE_DLL(int) WindowList_Add(MWindowList hList, HWND hwnd, UINT_PTR param) +{ + if (hList == nullptr) + return 1; + + hList->insert(new TWindowListItem(param, hwnd)); + return 0; +} + +MIR_CORE_DLL(int) WindowList_Remove(MWindowList hList, HWND hwnd) +{ + if (hList == nullptr) return 1; + + for (auto &it : *hList) + if (it->hWnd == hwnd) { + hList->removeItem(&it); + return 0; + } + + return 1; +} + +MIR_CORE_DLL(HWND) WindowList_Find(MWindowList hList, UINT_PTR param) +{ + if (hList == nullptr) + return nullptr; + + TWindowListItem *p = hList->find((TWindowListItem*)¶m); + return (p == nullptr) ? nullptr : p->hWnd; +} + +MIR_CORE_DLL(int) WindowList_Broadcast(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (hList == nullptr) + return 0; + + for (auto &it : hList->rev_iter()) + SendMessage(it->hWnd, message, wParam, lParam); + return 0; +} + +MIR_CORE_DLL(int) WindowList_BroadcastAsync(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (hList == nullptr) + return 0; + + for (auto &it : hList->rev_iter()) + PostMessage(it->hWnd, message, wParam, lParam); + return 0; +} diff --git a/src/mir_core/src/winutil.cpp b/src/mir_core/src/Windows/winutil.cpp index a09fa90016..dbd729c896 100644 --- a/src/mir_core/src/winutil.cpp +++ b/src/mir_core/src/Windows/winutil.cpp @@ -1,118 +1,118 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 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"
-
-MIR_CORE_DLL(int) Utils_SaveWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix)
-{
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- GetWindowPlacement(hwnd, &wp);
-
- char szSettingName[64];
- mir_snprintf(szSettingName, "%sx", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.left);
-
- mir_snprintf(szSettingName, "%sy", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.top);
-
- mir_snprintf(szSettingName, "%swidth", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.right-wp.rcNormalPosition.left);
-
- mir_snprintf(szSettingName, "%sheight", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.bottom-wp.rcNormalPosition.top);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-EXTERN_C MIR_CORE_DLL(int) Utils_RestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags)
-{
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- GetWindowPlacement(hwnd, &wp);
-
- char szSettingName[64];
- mir_snprintf(szSettingName, "%sx", szNamePrefix);
- int x = db_get_dw(hContact, szModule, szSettingName, -1);
- if (x == -1)
- return 1;
-
- mir_snprintf(szSettingName, "%sy", szNamePrefix);
- int y = (int)db_get_dw(hContact, szModule, szSettingName, -1);
-
- if (flags & RWPF_NOSIZE)
- OffsetRect(&wp.rcNormalPosition, x-wp.rcNormalPosition.left, y-wp.rcNormalPosition.top);
- else {
- wp.rcNormalPosition.left = x;
- wp.rcNormalPosition.top = y;
-
- mir_snprintf(szSettingName, "%swidth", szNamePrefix);
- wp.rcNormalPosition.right = wp.rcNormalPosition.left+db_get_dw(hContact, szModule, szSettingName, -1);
-
- mir_snprintf(szSettingName, "%sheight", szNamePrefix);
- wp.rcNormalPosition.bottom = wp.rcNormalPosition.top+db_get_dw(hContact, szModule, szSettingName, -1);
- }
- wp.flags = 0;
- if (flags & RWPF_HIDDEN)
- wp.showCmd = SW_HIDE;
- if (flags & RWPF_NOACTIVATE)
- wp.showCmd = SW_SHOWNOACTIVATE;
-
- if (!(flags & RWPF_NOMOVE))
- Utils_AssertInsideScreen(&wp.rcNormalPosition);
-
- SetWindowPlacement(hwnd, &wp);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) Utils_AssertInsideScreen(RECT *rc)
-{
- if (rc == nullptr)
- return -1;
-
- RECT rcScreen;
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, FALSE);
- if (MonitorFromRect(rc, MONITOR_DEFAULTTONULL))
- return 0;
-
- MONITORINFO mi = { 0 };
- HMONITOR hMonitor = MonitorFromRect(rc, MONITOR_DEFAULTTONEAREST);
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMonitor, &mi))
- rcScreen = mi.rcWork;
-
- if (rc->top >= rcScreen.bottom)
- OffsetRect(rc, 0, rcScreen.bottom - rc->bottom);
- else if (rc->bottom <= rcScreen.top)
- OffsetRect(rc, 0, rcScreen.top - rc->top);
- if (rc->left >= rcScreen.right)
- OffsetRect(rc, rcScreen.right - rc->right, 0);
- else if (rc->right <= rcScreen.left)
- OffsetRect(rc, rcScreen.left - rc->left, 0);
-
- return 1;
-}
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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" + +MIR_CORE_DLL(int) Utils_SaveWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix) +{ + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + GetWindowPlacement(hwnd, &wp); + + char szSettingName[64]; + mir_snprintf(szSettingName, "%sx", szNamePrefix); + db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.left); + + mir_snprintf(szSettingName, "%sy", szNamePrefix); + db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.top); + + mir_snprintf(szSettingName, "%swidth", szNamePrefix); + db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.right-wp.rcNormalPosition.left); + + mir_snprintf(szSettingName, "%sheight", szNamePrefix); + db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.bottom-wp.rcNormalPosition.top); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +EXTERN_C MIR_CORE_DLL(int) Utils_RestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags) +{ + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + GetWindowPlacement(hwnd, &wp); + + char szSettingName[64]; + mir_snprintf(szSettingName, "%sx", szNamePrefix); + int x = db_get_dw(hContact, szModule, szSettingName, -1); + if (x == -1) + return 1; + + mir_snprintf(szSettingName, "%sy", szNamePrefix); + int y = (int)db_get_dw(hContact, szModule, szSettingName, -1); + + if (flags & RWPF_NOSIZE) + OffsetRect(&wp.rcNormalPosition, x-wp.rcNormalPosition.left, y-wp.rcNormalPosition.top); + else { + wp.rcNormalPosition.left = x; + wp.rcNormalPosition.top = y; + + mir_snprintf(szSettingName, "%swidth", szNamePrefix); + wp.rcNormalPosition.right = wp.rcNormalPosition.left+db_get_dw(hContact, szModule, szSettingName, -1); + + mir_snprintf(szSettingName, "%sheight", szNamePrefix); + wp.rcNormalPosition.bottom = wp.rcNormalPosition.top+db_get_dw(hContact, szModule, szSettingName, -1); + } + wp.flags = 0; + if (flags & RWPF_HIDDEN) + wp.showCmd = SW_HIDE; + if (flags & RWPF_NOACTIVATE) + wp.showCmd = SW_SHOWNOACTIVATE; + + if (!(flags & RWPF_NOMOVE)) + Utils_AssertInsideScreen(&wp.rcNormalPosition); + + SetWindowPlacement(hwnd, &wp); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) Utils_AssertInsideScreen(RECT *rc) +{ + if (rc == nullptr) + return -1; + + RECT rcScreen; + SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, FALSE); + if (MonitorFromRect(rc, MONITOR_DEFAULTTONULL)) + return 0; + + MONITORINFO mi = { 0 }; + HMONITOR hMonitor = MonitorFromRect(rc, MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hMonitor, &mi)) + rcScreen = mi.rcWork; + + if (rc->top >= rcScreen.bottom) + OffsetRect(rc, 0, rcScreen.bottom - rc->bottom); + else if (rc->bottom <= rcScreen.top) + OffsetRect(rc, 0, rcScreen.top - rc->top); + if (rc->left >= rcScreen.right) + OffsetRect(rc, rcScreen.right - rc->right, 0); + else if (rc->right <= rcScreen.left) + OffsetRect(rc, rcScreen.left - rc->left, 0); + + return 1; +} diff --git a/src/mir_core/src/winver.cpp b/src/mir_core/src/Windows/winver.cpp index 28ced22337..d519d10478 100644 --- a/src/mir_core/src/winver.cpp +++ b/src/mir_core/src/Windows/winver.cpp @@ -1,372 +1,372 @@ -/*
-Copyright (C) 2012-21 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"
-
-#ifndef _WIN32_WINNT_WIN8
-#define _WIN32_WINNT_WIN8 0x0602 // Windows 8
-#endif
-
-#ifndef _WIN32_WINNT_WINBLUE
-#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1
-#endif
-
-#ifndef _WIN32_WINNT_WIN10
-#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10
-#endif
-
-static int dwWinVer;
-
-void InitWinver()
-{
- DWORD dwVer = LOWORD(GetVersion());
- dwWinVer = MAKEWORD(HIBYTE(dwVer), LOBYTE(dwVer));
-}
-
-MIR_CORE_DLL(BOOL) IsWinVerVistaPlus()
-{
- return dwWinVer >= _WIN32_WINNT_VISTA;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer7Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN7;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer8Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN8;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer81Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WINBLUE;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer10Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN10;
-}
-
-MIR_CORE_DLL(BOOL) IsFullScreen()
-{
- RECT rcScreen = { 0 };
-
- rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
- rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
-
- HMONITOR hMon = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONEAREST);
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMon, &mi))
- rcScreen = mi.rcMonitor;
-
- HWND hWndDesktop = GetDesktopWindow();
- HWND hWndShell = GetShellWindow();
-
- // check foregroundwindow
- HWND hWnd = GetForegroundWindow();
- if (hWnd && hWnd != hWndDesktop && hWnd != hWndShell) {
- wchar_t tszClassName[128] = L"";
- GetClassName(hWnd, tszClassName, _countof(tszClassName));
- if (wcscmp(tszClassName, L"WorkerW")) {
- RECT rect, rectw, recti;
- GetWindowRect(hWnd, &rectw);
-
- GetClientRect(hWnd, &rect);
- ClientToScreen(hWnd, (LPPOINT)&rect);
- ClientToScreen(hWnd, (LPPOINT)&rect.right);
-
- if (EqualRect(&rect, &rectw) && IntersectRect(&recti, &rect, &rcScreen) && EqualRect(&recti, &rcScreen))
- return true;
- }
- }
-
- return false;
-}
-
-MIR_CORE_DLL(BOOL) IsWorkstationLocked(void)
-{
- HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
- if (hDesk == nullptr)
- return true;
-
- wchar_t tszName[100];
- DWORD cbName;
- BOOL bLocked = (!GetUserObjectInformation(hDesk, UOI_NAME, tszName, _countof(tszName), &cbName) || mir_wstrcmpi(tszName, L"default") != 0);
- CloseDesktop(hDesk);
- return bLocked;
-}
-
-MIR_CORE_DLL(BOOL) IsTerminalDisconnected(void)
-{
- PVOID pBuffer = nullptr;
- DWORD pBytesReturned = 0;
- BOOL result = FALSE;
-
- if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&pBuffer, &pBytesReturned))
- if (*(PDWORD)pBuffer == WTSDisconnected)
- result = TRUE;
-
- if (pBuffer)
- WTSFreeMemory(pBuffer);
- return result;
-}
-
-MIR_CORE_DLL(BOOL) IsScreenSaverRunning(void)
-{
- BOOL rc = FALSE;
- SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &rc, FALSE);
- return rc != 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(BOOL) OS_GetShortString(char *buf, size_t bufSize)
-{
- if (buf == nullptr || bufSize == 0)
- return false;
-
- mir_snprintf(buf, bufSize, "Windows NT %d.%d", HIBYTE(dwWinVer), LOBYTE(dwWinVer));
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifndef PRODUCT_CORE_N // Win8
-#define PRODUCT_CORE_SINGLELANGUAGE 0x00000064
-#define PRODUCT_PROFESSIONAL_WMC 0x00000067
-#endif
-
-typedef BOOL(WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
-typedef LPCSTR(WINAPI *WGV)(void);
-
-MIR_CORE_DLL(BOOL) OS_GetDisplayString(char *buf, size_t bufSize)
-{
- if (buf == nullptr || bufSize == 0)
- return 0;
-
- buf[0] = 0;
-
- OSVERSIONINFOEX osvi = { 0 };
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
- if (!bOsVersionInfoEx) {
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx((OSVERSIONINFO*)&osvi))
- return false;
- }
-
- if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId || osvi.dwMajorVersion <= 4)
- return false;
-
- SYSTEM_INFO sysInfo = { 0 };
- GetNativeSystemInfo(&sysInfo);
-
- CMStringA ret("Microsoft ");
-
- // Test for the specific product.
- if (osvi.dwMajorVersion >= 6) {
- if (osvi.dwMajorVersion == 10) {
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 10 ");
- else
- ret.Append("Windows Server 10 ");
- }
- else switch (osvi.dwMinorVersion) {
- case 0:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows Vista ");
- else
- ret.Append("Windows Server 2008 ");
- break;
-
- case 1:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 7 ");
- else
- ret.Append("Windows Server 2008 R2 ");
- break;
-
- case 2:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 8 ");
- else
- ret.Append("Windows Server 2012 ");
- break;
-
- case 3:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 8.1 ");
- else
- ret.Append("Windows Server 2012 R2 ");
- break;
- }
-
- DWORD dwType = 0;
- HMODULE hKernel = GetModuleHandle(L"kernel32.dll");
- PGPI pGPI = (PGPI)GetProcAddress(hKernel, "GetProductInfo");
- if (pGPI != nullptr)
- pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
-
- switch (dwType) {
- case PRODUCT_ULTIMATE:
- ret.Append("Ultimate Edition");
- break;
- case PRODUCT_PROFESSIONAL:
- ret.Append("Professional Edition");
- break;
- case PRODUCT_PROFESSIONAL_WMC:
- ret.Append("Professional Edition with Media Center");
- break;
- case PRODUCT_HOME_PREMIUM:
- ret.Append("Home Premium Edition");
- break;
- case PRODUCT_HOME_BASIC:
- ret.Append("Home Basic Edition");
- break;
- case PRODUCT_ENTERPRISE:
- ret.Append("Enterprise Edition");
- break;
- case PRODUCT_BUSINESS:
- ret.Append("Business Edition");
- break;
- case PRODUCT_STARTER:
- ret.Append("Starter Edition");
- break;
- case PRODUCT_CLUSTER_SERVER:
- ret.Append("Cluster Server Edition");
- break;
- case PRODUCT_DATACENTER_SERVER:
- ret.Append("Datacenter Edition");
- break;
- case PRODUCT_DATACENTER_SERVER_CORE:
- ret.Append("Datacenter Edition (core installation)");
- break;
- case PRODUCT_ENTERPRISE_SERVER:
- ret.Append("Enterprise Edition");
- break;
- case PRODUCT_ENTERPRISE_SERVER_CORE:
- ret.Append("Enterprise Edition (core installation)");
- break;
- case PRODUCT_ENTERPRISE_SERVER_IA64:
- ret.Append("Enterprise Edition for Itanium-based Systems");
- break;
- case PRODUCT_SMALLBUSINESS_SERVER:
- ret.Append("Small Business Server");
- break;
- case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
- ret.Append("Small Business Server Premium Edition");
- break;
- case PRODUCT_STANDARD_SERVER:
- ret.Append("Standard Edition");
- break;
- case PRODUCT_STANDARD_SERVER_CORE:
- ret.Append("Standard Edition (core installation)");
- break;
- case PRODUCT_WEB_SERVER:
- ret.Append("Web Server Edition");
- break;
- case PRODUCT_CORE_SINGLELANGUAGE:
- ret.Append("Home Single Language");
- break;
- }
- if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- ret.Append(", 64-bit");
- else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
- ret.Append(", 32-bit");
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
- if (GetSystemMetrics(SM_SERVERR2))
- ret.Append("Windows Server 2003 R2, ");
- else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER)
- ret.Append("Windows Storage Server 2003");
- else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER)
- ret.Append("Windows Home Server");
- else if (osvi.wProductType == VER_NT_WORKSTATION && sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- ret.Append("Windows XP Professional x64 Edition");
- else
- ret.Append("Windows Server 2003, ");
-
- // Test for the server type.
- if (osvi.wProductType != VER_NT_WORKSTATION) {
- if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Edition for Itanium-based Systems");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise Edition for Itanium-based Systems");
- }
- else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter x64 Edition");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise x64 Edition");
- else ret.Append("Standard x64 Edition");
- }
- else {
- if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
- ret.Append("Compute Cluster Edition");
- else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Edition");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise Edition");
- else if (osvi.wSuiteMask & VER_SUITE_BLADE)
- ret.Append("Web Edition");
- else ret.Append("Standard Edition");
- }
- }
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
- ret.Append("Windows XP ");
- if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
- ret.Append("Home Edition");
- else ret.Append("Professional");
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
- ret.Append("Windows 2000 ");
-
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Professional");
- else {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Server");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Advanced Server");
- else ret.Append("Server");
- }
- }
-
- // Include service pack (if any) and build number.
- if (mir_wstrlen(osvi.szCSDVersion) > 0) {
- ret.Append(" ");
- ret.Append(_T2A(osvi.szCSDVersion));
- }
-
- ret.AppendFormat(" (build %d)", osvi.dwBuildNumber);
-
- HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
- if (WGV wine_get_version = (WGV)GetProcAddress(hNtDll, "wine_get_version"))
- {
- ret.AppendFormat(" (Wine %s)", wine_get_version());
- }
-
- mir_strncpy(buf, ret, bufSize);
- return true;
-}
+/* +Copyright (C) 2012-21 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" + +#ifndef _WIN32_WINNT_WIN8 +#define _WIN32_WINNT_WIN8 0x0602 // Windows 8 +#endif + +#ifndef _WIN32_WINNT_WINBLUE +#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1 +#endif + +#ifndef _WIN32_WINNT_WIN10 +#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10 +#endif + +static int dwWinVer; + +void InitWinver() +{ + DWORD dwVer = LOWORD(GetVersion()); + dwWinVer = MAKEWORD(HIBYTE(dwVer), LOBYTE(dwVer)); +} + +MIR_CORE_DLL(BOOL) IsWinVerVistaPlus() +{ + return dwWinVer >= _WIN32_WINNT_VISTA; +} + +MIR_CORE_DLL(BOOL) IsWinVer7Plus() +{ + return dwWinVer >= _WIN32_WINNT_WIN7; +} + +MIR_CORE_DLL(BOOL) IsWinVer8Plus() +{ + return dwWinVer >= _WIN32_WINNT_WIN8; +} + +MIR_CORE_DLL(BOOL) IsWinVer81Plus() +{ + return dwWinVer >= _WIN32_WINNT_WINBLUE; +} + +MIR_CORE_DLL(BOOL) IsWinVer10Plus() +{ + return dwWinVer >= _WIN32_WINNT_WIN10; +} + +MIR_CORE_DLL(BOOL) IsFullScreen() +{ + RECT rcScreen = { 0 }; + + rcScreen.right = GetSystemMetrics(SM_CXSCREEN); + rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN); + + HMONITOR hMon = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONEAREST); + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hMon, &mi)) + rcScreen = mi.rcMonitor; + + HWND hWndDesktop = GetDesktopWindow(); + HWND hWndShell = GetShellWindow(); + + // check foregroundwindow + HWND hWnd = GetForegroundWindow(); + if (hWnd && hWnd != hWndDesktop && hWnd != hWndShell) { + wchar_t tszClassName[128] = L""; + GetClassName(hWnd, tszClassName, _countof(tszClassName)); + if (wcscmp(tszClassName, L"WorkerW")) { + RECT rect, rectw, recti; + GetWindowRect(hWnd, &rectw); + + GetClientRect(hWnd, &rect); + ClientToScreen(hWnd, (LPPOINT)&rect); + ClientToScreen(hWnd, (LPPOINT)&rect.right); + + if (EqualRect(&rect, &rectw) && IntersectRect(&recti, &rect, &rcScreen) && EqualRect(&recti, &rcScreen)) + return true; + } + } + + return false; +} + +MIR_CORE_DLL(BOOL) IsWorkstationLocked(void) +{ + HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP); + if (hDesk == nullptr) + return true; + + wchar_t tszName[100]; + DWORD cbName; + BOOL bLocked = (!GetUserObjectInformation(hDesk, UOI_NAME, tszName, _countof(tszName), &cbName) || mir_wstrcmpi(tszName, L"default") != 0); + CloseDesktop(hDesk); + return bLocked; +} + +MIR_CORE_DLL(BOOL) IsTerminalDisconnected(void) +{ + PVOID pBuffer = nullptr; + DWORD pBytesReturned = 0; + BOOL result = FALSE; + + if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&pBuffer, &pBytesReturned)) + if (*(PDWORD)pBuffer == WTSDisconnected) + result = TRUE; + + if (pBuffer) + WTSFreeMemory(pBuffer); + return result; +} + +MIR_CORE_DLL(BOOL) IsScreenSaverRunning(void) +{ + BOOL rc = FALSE; + SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &rc, FALSE); + return rc != 0; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(BOOL) OS_GetShortString(char *buf, size_t bufSize) +{ + if (buf == nullptr || bufSize == 0) + return false; + + mir_snprintf(buf, bufSize, "Windows NT %d.%d", HIBYTE(dwWinVer), LOBYTE(dwWinVer)); + return true; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef PRODUCT_CORE_N // Win8 +#define PRODUCT_CORE_SINGLELANGUAGE 0x00000064 +#define PRODUCT_PROFESSIONAL_WMC 0x00000067 +#endif + +typedef BOOL(WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); +typedef LPCSTR(WINAPI *WGV)(void); + +MIR_CORE_DLL(BOOL) OS_GetDisplayString(char *buf, size_t bufSize) +{ + if (buf == nullptr || bufSize == 0) + return 0; + + buf[0] = 0; + + OSVERSIONINFOEX osvi = { 0 }; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi); + if (!bOsVersionInfoEx) { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO*)&osvi)) + return false; + } + + if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId || osvi.dwMajorVersion <= 4) + return false; + + SYSTEM_INFO sysInfo = { 0 }; + GetNativeSystemInfo(&sysInfo); + + CMStringA ret("Microsoft "); + + // Test for the specific product. + if (osvi.dwMajorVersion >= 6) { + if (osvi.dwMajorVersion == 10) { + if (osvi.wProductType == VER_NT_WORKSTATION) + ret.Append("Windows 10 "); + else + ret.Append("Windows Server 10 "); + } + else switch (osvi.dwMinorVersion) { + case 0: + if (osvi.wProductType == VER_NT_WORKSTATION) + ret.Append("Windows Vista "); + else + ret.Append("Windows Server 2008 "); + break; + + case 1: + if (osvi.wProductType == VER_NT_WORKSTATION) + ret.Append("Windows 7 "); + else + ret.Append("Windows Server 2008 R2 "); + break; + + case 2: + if (osvi.wProductType == VER_NT_WORKSTATION) + ret.Append("Windows 8 "); + else + ret.Append("Windows Server 2012 "); + break; + + case 3: + if (osvi.wProductType == VER_NT_WORKSTATION) + ret.Append("Windows 8.1 "); + else + ret.Append("Windows Server 2012 R2 "); + break; + } + + DWORD dwType = 0; + HMODULE hKernel = GetModuleHandle(L"kernel32.dll"); + PGPI pGPI = (PGPI)GetProcAddress(hKernel, "GetProductInfo"); + if (pGPI != nullptr) + pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType); + + switch (dwType) { + case PRODUCT_ULTIMATE: + ret.Append("Ultimate Edition"); + break; + case PRODUCT_PROFESSIONAL: + ret.Append("Professional Edition"); + break; + case PRODUCT_PROFESSIONAL_WMC: + ret.Append("Professional Edition with Media Center"); + break; + case PRODUCT_HOME_PREMIUM: + ret.Append("Home Premium Edition"); + break; + case PRODUCT_HOME_BASIC: + ret.Append("Home Basic Edition"); + break; + case PRODUCT_ENTERPRISE: + ret.Append("Enterprise Edition"); + break; + case PRODUCT_BUSINESS: + ret.Append("Business Edition"); + break; + case PRODUCT_STARTER: + ret.Append("Starter Edition"); + break; + case PRODUCT_CLUSTER_SERVER: + ret.Append("Cluster Server Edition"); + break; + case PRODUCT_DATACENTER_SERVER: + ret.Append("Datacenter Edition"); + break; + case PRODUCT_DATACENTER_SERVER_CORE: + ret.Append("Datacenter Edition (core installation)"); + break; + case PRODUCT_ENTERPRISE_SERVER: + ret.Append("Enterprise Edition"); + break; + case PRODUCT_ENTERPRISE_SERVER_CORE: + ret.Append("Enterprise Edition (core installation)"); + break; + case PRODUCT_ENTERPRISE_SERVER_IA64: + ret.Append("Enterprise Edition for Itanium-based Systems"); + break; + case PRODUCT_SMALLBUSINESS_SERVER: + ret.Append("Small Business Server"); + break; + case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: + ret.Append("Small Business Server Premium Edition"); + break; + case PRODUCT_STANDARD_SERVER: + ret.Append("Standard Edition"); + break; + case PRODUCT_STANDARD_SERVER_CORE: + ret.Append("Standard Edition (core installation)"); + break; + case PRODUCT_WEB_SERVER: + ret.Append("Web Server Edition"); + break; + case PRODUCT_CORE_SINGLELANGUAGE: + ret.Append("Home Single Language"); + break; + } + if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + ret.Append(", 64-bit"); + else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) + ret.Append(", 32-bit"); + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) { + if (GetSystemMetrics(SM_SERVERR2)) + ret.Append("Windows Server 2003 R2, "); + else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER) + ret.Append("Windows Storage Server 2003"); + else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER) + ret.Append("Windows Home Server"); + else if (osvi.wProductType == VER_NT_WORKSTATION && sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + ret.Append("Windows XP Professional x64 Edition"); + else + ret.Append("Windows Server 2003, "); + + // Test for the server type. + if (osvi.wProductType != VER_NT_WORKSTATION) { + if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + ret.Append("Datacenter Edition for Itanium-based Systems"); + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + ret.Append("Enterprise Edition for Itanium-based Systems"); + } + else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + ret.Append("Datacenter x64 Edition"); + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + ret.Append("Enterprise x64 Edition"); + else ret.Append("Standard x64 Edition"); + } + else { + if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) + ret.Append("Compute Cluster Edition"); + else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + ret.Append("Datacenter Edition"); + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + ret.Append("Enterprise Edition"); + else if (osvi.wSuiteMask & VER_SUITE_BLADE) + ret.Append("Web Edition"); + else ret.Append("Standard Edition"); + } + } + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { + ret.Append("Windows XP "); + if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + ret.Append("Home Edition"); + else ret.Append("Professional"); + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) { + ret.Append("Windows 2000 "); + + if (osvi.wProductType == VER_NT_WORKSTATION) + ret.Append("Professional"); + else { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + ret.Append("Datacenter Server"); + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + ret.Append("Advanced Server"); + else ret.Append("Server"); + } + } + + // Include service pack (if any) and build number. + if (mir_wstrlen(osvi.szCSDVersion) > 0) { + ret.Append(" "); + ret.Append(_T2A(osvi.szCSDVersion)); + } + + ret.AppendFormat(" (build %d)", osvi.dwBuildNumber); + + HMODULE hNtDll = GetModuleHandleA("ntdll.dll"); + if (WGV wine_get_version = (WGV)GetProcAddress(hNtDll, "wine_get_version")) + { + ret.AppendFormat(" (Wine %s)", wine_get_version()); + } + + mir_strncpy(buf, ret, bufSize); + return true; +} |