Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update platform info #1183

Merged
merged 2 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/DensifyPointCloud/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(DensifyPointCloud)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/InterfaceCOLMAP/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(InterfaceCOLMAP)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/InterfaceMVSNet/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(InterfaceMVSNet)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/InterfaceMetashape/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(InterfaceMetashape)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/InterfacePolycam/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(InterfacePolycam)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/ReconstructMesh/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(ReconstructMesh)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/RefineMesh/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(RefineMesh)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/Tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(Tests)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/TextureMesh/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(TextureMesh)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/TransformScene/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(TransformScene)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
3 changes: 2 additions & 1 deletion apps/Viewer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ endif()

# List sources files
if(MSVC)
FILE(GLOB LIBRARY_FILES_C "*.cpp" "*.rc")
create_rc_files(${VIEWER_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/Viewer.ico")
FILE(GLOB LIBRARY_FILES_C "*.cpp" "${CMAKE_CURRENT_BINARY_DIR}/*.rc")
else()
FILE(GLOB LIBRARY_FILES_C "*.cpp")
endif()
Expand Down
Binary file added apps/Viewer/Viewer.ico
Binary file not shown.
14 changes: 14 additions & 0 deletions apps/Viewer/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
#include "Common.h"
#include "Window.h"

#ifdef _MSC_VER
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h>
#endif

using namespace VIEWER;


Expand Down Expand Up @@ -99,6 +104,15 @@ bool Window::Init(const cv::Size& _size, LPCTSTR name)
glfwSetDropCallback(window, Window::Drop);
g_mapWindows[window] = this;

#ifdef _MSC_VER
// set application icon from resources
const HICON hIcon = ::LoadIcon(::GetModuleHandle(NULL), MAKEINTRESOURCE(101));
const HWND hwnd = glfwGetWin32Window(window);
::SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
::SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
::DestroyIcon(hIcon);
#endif

Reset();
return true;
}
Expand Down
53 changes: 53 additions & 0 deletions build/Utils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,50 @@ macro(ConfigLibrary)
endforeach()
endmacro()

function(create_rc_files name)
# Create the manifest file
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/app.manifest"
"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly manifestVersion='1.0' xmlns='urn:schemas-microsoft-com:asm.v1'>
<assemblyIdentity type='win32' name='${name}' version='1.0.0.0'/>
<trustInfo xmlns='urn:schemas-microsoft-com:asm.v2'>
<security>
<requestedPrivileges xmlns='urn:schemas-microsoft-com:asm.v3'>
<requestedExecutionLevel level='asInvoker' uiAccess='false'/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns='urn:schemas-microsoft-com:compatibility.v1'>
<application>
<!-- Windows Vista -->
<supportedOS Id='{e2011457-1546-43c5-a5fe-008deee3d3f0}'/>
<!-- Windows 7 -->
<supportedOS Id='{35138b9a-5d96-4fbd-8e2d-a2440225f93a}'/>
<!-- Windows 8 -->
<supportedOS Id='{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}'/>
<!-- Windows 8.1 -->
<supportedOS Id='{1f676c76-80e1-4239-95bb-83d0f6d0da78}'/>
<!-- Windows 10 and Windows 11 -->
<supportedOS Id='{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}'/>
</application>
</compatibility>
</assembly>
")

# Create an RC file that includes the manifest
if(NOT "${ARGN}" STREQUAL "")
set(RC_ICO "
#define IDI_ICON_APP 101
IDI_ICON_APP ICON DISCARDABLE \"${ARGN}\"
")
endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/app.rc"
"#include <windows.h>
1 RT_MANIFEST \"app.manifest\"
${RC_ICO}
")
endfunction()

# Defines the main libraries. User tests should link
# with one of them.
function(cxx_library_with_type name folder type cxx_flags)
Expand Down Expand Up @@ -870,4 +914,13 @@ function(cxx_executable_with_flags name folder cxx_flags libs)
endforeach()
# Set project folder
set_target_properties("${name}" PROPERTIES FOLDER "${folder}")
if (MSVC)
# Check if any of the files listed in ARGN has the extension .rc
foreach (file ${ARGN})
if (file MATCHES "\\.rc$")
set_target_properties("${name}" PROPERTIES LINK_FLAGS "/MANIFEST:NO")
break()
endif()
endforeach()
endif()
endfunction()
161 changes: 29 additions & 132 deletions libs/Common/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,115 +61,6 @@ bool OSSupportsAVX();

const Flags Util::ms_CPUFNC(InitCPU());

/**
* Lookup table (precomputed CRC64 values for each 8 bit string) computation
* takes into account the fact that the reverse polynom has zeros in lower 8 bits:
*
* @code
* for (i = 0; i < 256; i++)
* {
* shiftRegister = i;
* for (j = 0; j < 8; j++)
* {
* if (shiftRegister & 1)
* shiftRegister = (shiftRegister >> 1) ^ Reverse_polynom;
* else
* shiftRegister >>= 1;
* }
* CRCTable[i] = shiftRegister;
* }
* @endcode
*
* Generic code would look as follows:
*
* @code
* for (i = 0; i < 256; i++)
* {
* shiftRegister = 0;
* bitString = i;
* for (j = 0; j < 8; j++)
* {
* if ((shiftRegister ^ (bitString >> j)) & 1)
* shiftRegister = (shiftRegister >> 1) ^ Reverse_polynom;
* else
* shiftRegister >>= 1;
* }
* CRCTable[i] = shiftRegister;
* }
* @endcode
*
* @remark Since the lookup table elements have 0 in the lower 32 bit word,
* the 32 bit assembler implementation of CRC64Process can be optimized,
* avoiding at least one 'xor' operation.
*/
static const uint64_t gs_au64CRC64[256] =
{
0x0000000000000000ULL, 0x01B0000000000000ULL, 0x0360000000000000ULL, 0x02D0000000000000ULL,
0x06C0000000000000ULL, 0x0770000000000000ULL, 0x05A0000000000000ULL, 0x0410000000000000ULL,
0x0D80000000000000ULL, 0x0C30000000000000ULL, 0x0EE0000000000000ULL, 0x0F50000000000000ULL,
0x0B40000000000000ULL, 0x0AF0000000000000ULL, 0x0820000000000000ULL, 0x0990000000000000ULL,
0x1B00000000000000ULL, 0x1AB0000000000000ULL, 0x1860000000000000ULL, 0x19D0000000000000ULL,
0x1DC0000000000000ULL, 0x1C70000000000000ULL, 0x1EA0000000000000ULL, 0x1F10000000000000ULL,
0x1680000000000000ULL, 0x1730000000000000ULL, 0x15E0000000000000ULL, 0x1450000000000000ULL,
0x1040000000000000ULL, 0x11F0000000000000ULL, 0x1320000000000000ULL, 0x1290000000000000ULL,
0x3600000000000000ULL, 0x37B0000000000000ULL, 0x3560000000000000ULL, 0x34D0000000000000ULL,
0x30C0000000000000ULL, 0x3170000000000000ULL, 0x33A0000000000000ULL, 0x3210000000000000ULL,
0x3B80000000000000ULL, 0x3A30000000000000ULL, 0x38E0000000000000ULL, 0x3950000000000000ULL,
0x3D40000000000000ULL, 0x3CF0000000000000ULL, 0x3E20000000000000ULL, 0x3F90000000000000ULL,
0x2D00000000000000ULL, 0x2CB0000000000000ULL, 0x2E60000000000000ULL, 0x2FD0000000000000ULL,
0x2BC0000000000000ULL, 0x2A70000000000000ULL, 0x28A0000000000000ULL, 0x2910000000000000ULL,
0x2080000000000000ULL, 0x2130000000000000ULL, 0x23E0000000000000ULL, 0x2250000000000000ULL,
0x2640000000000000ULL, 0x27F0000000000000ULL, 0x2520000000000000ULL, 0x2490000000000000ULL,
0x6C00000000000000ULL, 0x6DB0000000000000ULL, 0x6F60000000000000ULL, 0x6ED0000000000000ULL,
0x6AC0000000000000ULL, 0x6B70000000000000ULL, 0x69A0000000000000ULL, 0x6810000000000000ULL,
0x6180000000000000ULL, 0x6030000000000000ULL, 0x62E0000000000000ULL, 0x6350000000000000ULL,
0x6740000000000000ULL, 0x66F0000000000000ULL, 0x6420000000000000ULL, 0x6590000000000000ULL,
0x7700000000000000ULL, 0x76B0000000000000ULL, 0x7460000000000000ULL, 0x75D0000000000000ULL,
0x71C0000000000000ULL, 0x7070000000000000ULL, 0x72A0000000000000ULL, 0x7310000000000000ULL,
0x7A80000000000000ULL, 0x7B30000000000000ULL, 0x79E0000000000000ULL, 0x7850000000000000ULL,
0x7C40000000000000ULL, 0x7DF0000000000000ULL, 0x7F20000000000000ULL, 0x7E90000000000000ULL,
0x5A00000000000000ULL, 0x5BB0000000000000ULL, 0x5960000000000000ULL, 0x58D0000000000000ULL,
0x5CC0000000000000ULL, 0x5D70000000000000ULL, 0x5FA0000000000000ULL, 0x5E10000000000000ULL,
0x5780000000000000ULL, 0x5630000000000000ULL, 0x54E0000000000000ULL, 0x5550000000000000ULL,
0x5140000000000000ULL, 0x50F0000000000000ULL, 0x5220000000000000ULL, 0x5390000000000000ULL,
0x4100000000000000ULL, 0x40B0000000000000ULL, 0x4260000000000000ULL, 0x43D0000000000000ULL,
0x47C0000000000000ULL, 0x4670000000000000ULL, 0x44A0000000000000ULL, 0x4510000000000000ULL,
0x4C80000000000000ULL, 0x4D30000000000000ULL, 0x4FE0000000000000ULL, 0x4E50000000000000ULL,
0x4A40000000000000ULL, 0x4BF0000000000000ULL, 0x4920000000000000ULL, 0x4890000000000000ULL,
0xD800000000000000ULL, 0xD9B0000000000000ULL, 0xDB60000000000000ULL, 0xDAD0000000000000ULL,
0xDEC0000000000000ULL, 0xDF70000000000000ULL, 0xDDA0000000000000ULL, 0xDC10000000000000ULL,
0xD580000000000000ULL, 0xD430000000000000ULL, 0xD6E0000000000000ULL, 0xD750000000000000ULL,
0xD340000000000000ULL, 0xD2F0000000000000ULL, 0xD020000000000000ULL, 0xD190000000000000ULL,
0xC300000000000000ULL, 0xC2B0000000000000ULL, 0xC060000000000000ULL, 0xC1D0000000000000ULL,
0xC5C0000000000000ULL, 0xC470000000000000ULL, 0xC6A0000000000000ULL, 0xC710000000000000ULL,
0xCE80000000000000ULL, 0xCF30000000000000ULL, 0xCDE0000000000000ULL, 0xCC50000000000000ULL,
0xC840000000000000ULL, 0xC9F0000000000000ULL, 0xCB20000000000000ULL, 0xCA90000000000000ULL,
0xEE00000000000000ULL, 0xEFB0000000000000ULL, 0xED60000000000000ULL, 0xECD0000000000000ULL,
0xE8C0000000000000ULL, 0xE970000000000000ULL, 0xEBA0000000000000ULL, 0xEA10000000000000ULL,
0xE380000000000000ULL, 0xE230000000000000ULL, 0xE0E0000000000000ULL, 0xE150000000000000ULL,
0xE540000000000000ULL, 0xE4F0000000000000ULL, 0xE620000000000000ULL, 0xE790000000000000ULL,
0xF500000000000000ULL, 0xF4B0000000000000ULL, 0xF660000000000000ULL, 0xF7D0000000000000ULL,
0xF3C0000000000000ULL, 0xF270000000000000ULL, 0xF0A0000000000000ULL, 0xF110000000000000ULL,
0xF880000000000000ULL, 0xF930000000000000ULL, 0xFBE0000000000000ULL, 0xFA50000000000000ULL,
0xFE40000000000000ULL, 0xFFF0000000000000ULL, 0xFD20000000000000ULL, 0xFC90000000000000ULL,
0xB400000000000000ULL, 0xB5B0000000000000ULL, 0xB760000000000000ULL, 0xB6D0000000000000ULL,
0xB2C0000000000000ULL, 0xB370000000000000ULL, 0xB1A0000000000000ULL, 0xB010000000000000ULL,
0xB980000000000000ULL, 0xB830000000000000ULL, 0xBAE0000000000000ULL, 0xBB50000000000000ULL,
0xBF40000000000000ULL, 0xBEF0000000000000ULL, 0xBC20000000000000ULL, 0xBD90000000000000ULL,
0xAF00000000000000ULL, 0xAEB0000000000000ULL, 0xAC60000000000000ULL, 0xADD0000000000000ULL,
0xA9C0000000000000ULL, 0xA870000000000000ULL, 0xAAA0000000000000ULL, 0xAB10000000000000ULL,
0xA280000000000000ULL, 0xA330000000000000ULL, 0xA1E0000000000000ULL, 0xA050000000000000ULL,
0xA440000000000000ULL, 0xA5F0000000000000ULL, 0xA720000000000000ULL, 0xA690000000000000ULL,
0x8200000000000000ULL, 0x83B0000000000000ULL, 0x8160000000000000ULL, 0x80D0000000000000ULL,
0x84C0000000000000ULL, 0x8570000000000000ULL, 0x87A0000000000000ULL, 0x8610000000000000ULL,
0x8F80000000000000ULL, 0x8E30000000000000ULL, 0x8CE0000000000000ULL, 0x8D50000000000000ULL,
0x8940000000000000ULL, 0x88F0000000000000ULL, 0x8A20000000000000ULL, 0x8B90000000000000ULL,
0x9900000000000000ULL, 0x98B0000000000000ULL, 0x9A60000000000000ULL, 0x9BD0000000000000ULL,
0x9FC0000000000000ULL, 0x9E70000000000000ULL, 0x9CA0000000000000ULL, 0x9D10000000000000ULL,
0x9480000000000000ULL, 0x9530000000000000ULL, 0x97E0000000000000ULL, 0x9650000000000000ULL,
0x9240000000000000ULL, 0x93F0000000000000ULL, 0x9120000000000000ULL, 0x9090000000000000ULL
};


// F U N C T I O N S ///////////////////////////////////////////////

Expand Down Expand Up @@ -219,25 +110,6 @@ String Util::getCurrentFolder()
/*----------------------------------------------------------------*/


uint64_t Util::CRC64(const void *pv, size_t cb)
{
const uint8_t* pu8 = (const uint8_t *)pv;
uint64_t uCRC64 = 0ULL;
while (cb--)
uCRC64 = gs_au64CRC64[(uCRC64 ^ *pu8++) & 0xff] ^ (uCRC64 >> 8);
return uCRC64;
}

uint64_t Util::CRC64Process(uint64_t uCRC64, const void *pv, size_t cb)
{
const uint8_t *pu8 = (const uint8_t *)pv;
while (cb--)
uCRC64 = gs_au64CRC64[(uCRC64 ^ *pu8++) & 0xff] ^ (uCRC64 >> 8);
return uCRC64;
}
/*----------------------------------------------------------------*/


String Util::GetCPUInfo()
{
const CPUINFO info(::GetCPUInfo());
Expand Down Expand Up @@ -280,10 +152,28 @@ String Util::GetOSInfo()
#ifndef _WIN32_WINNT_WIN10
#define _WIN32_WINNT_WIN10 0x0A00
if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0))
os = _T("Windows 10+");
#else
if (IsWindows10OrGreater())
// helper function to check for Windows 11+
const auto IsWindows11OrGreater = []() -> bool {
OSVERSIONINFOEXW osvi { sizeof(OSVERSIONINFOEXW) };
DWORDLONG dwlConditionMask = 0;
// Windows 11 starts at build 22000
osvi.dwMajorVersion = 10;
osvi.dwMinorVersion = 0;
osvi.dwBuildNumber = 22000;
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
return VerifyVersionInfoW(&osvi,
VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER,
dwlConditionMask) != FALSE;
};
if (IsWindows11OrGreater())
os = _T("Windows 11+");
else if (IsWindows10OrGreater())
os = _T("Windows 10");
#endif
os = _T("Windows 10+");
else if (IsWindows8Point1OrGreater())
os = _T("Windows 8.1");
else if (IsWindows8OrGreater())
Expand Down Expand Up @@ -397,7 +287,7 @@ String Util::GetOSInfo()

String Util::GetDiskInfo(const String& path)
{
#if defined(_SUPPORT_CPP17) && (!defined(__GNUC__) || (__GNUC__ > 7))
#if defined(_SUPPORT_CPP17) && (defined(__APPLE__) || !defined(__GNUC__) || (__GNUC__ > 7))

const std::filesystem::space_info si = std::filesystem::space(path.c_str());
return String::FormatString("%s (%s) space", formatBytes(si.available).c_str(), formatBytes(si.capacity).c_str());
Expand Down Expand Up @@ -476,10 +366,10 @@ inline void CPUID(int CPUInfo[4], int level) {
CPUINFO GetCPUInfo()
{
CPUINFO info;

// set all values to 0 (false)
memset(&info, 0, sizeof(CPUINFO));

#ifndef __APPLE__
int CPUInfo[4];

// CPUID with an InfoType argument of 0 returns the number of
Expand Down Expand Up @@ -531,6 +421,13 @@ CPUINFO GetCPUInfo()
info.bMMXEX = (CPUInfo[3] & 0x400000) != 0; // indicates AMD extended MMX
}

#else

size_t size = sizeof(info.name);
sysctlbyname("machdep.cpu.brand_string", &info.name, &size, nullptr, 0);

#endif // __APPLE__

return info;
}
/*----------------------------------------------------------------*/
Expand Down
Loading
Loading