// ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "util.h" #include #include #include #include #include "localization.h" #include "file_handling.h" #include "string_conv.h" #include #include "system_func.h" #include "check_exist.h" #ifdef FFS_WIN #include //includes "windows.h" #endif wxString ffs3::formatFilesizeToShortString(const wxLongLong& filesize) { return ffs3::formatFilesizeToShortString(filesize.ToDouble()); } wxString ffs3::formatFilesizeToShortString(const wxULongLong& filesize) { return ffs3::formatFilesizeToShortString(filesize.ToDouble()); } wxString ffs3::formatFilesizeToShortString(double filesize) { if (filesize < 0) return _("Error"); wxString output = _("%x Byte"); if (filesize > 999) { filesize /= 1024; output = _("%x kB"); if (filesize > 999) { filesize /= 1024; output = _("%x MB"); if (filesize > 999) { filesize /= 1024; output = _("%x GB"); if (filesize > 999) { filesize /= 1024; output = _("%x TB"); if (filesize > 999) { filesize /= 1024; output = _("%x PB"); } } } } //print just three significant digits: 0,01 | 0,11 | 1,11 | 11,1 | 111 const size_t leadDigitCount = common::getDigitCount(static_cast(filesize)); //number of digits before decimal point if (leadDigitCount == 0 || leadDigitCount > 3) return _("Error"); output.Replace(wxT("%x"), wxString::Format(wxT("%.*f"), static_cast(3 - leadDigitCount), filesize)); } else { output.Replace(wxT("%x"), common::numberToString(static_cast(filesize))); //no decimal places in case of bytes } return output; } wxString ffs3::formatPercentage(const wxLongLong& dividend, const wxLongLong& divisor) { const double ratio = divisor != 0 ? dividend.ToDouble() * 100 / divisor.ToDouble() : 0; wxString output = _("%x%"); output.Replace(wxT("%x"), wxString::Format(wxT("%3.2f"), ratio), false); return output; } wxString ffs_Impl::includeNumberSeparator(const wxString& number) { wxString output(number); for (size_t i = output.size(); i > 3; i -= 3) output.insert(i - 3, ffs3::getThousandsSeparator()); return output; } template void setDirectoryNameImpl(const wxString& dirname, T* txtCtrl, wxDirPickerCtrl* dirPicker) { using namespace ffs3; txtCtrl->SetValue(dirname); const Zstring dirFormatted = ffs3::getFormattedDirectoryName(wxToZ(dirname)); if (util::dirExists(dirFormatted, 200) == util::EXISTING_TRUE) //potentially slow network access: wait 200ms at most dirPicker->SetPath(zToWx(dirFormatted)); } void ffs3::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker) { setDirectoryNameImpl(dirname, txtCtrl, dirPicker); } void ffs3::setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker) { txtCtrl->SetSelection(wxNOT_FOUND); setDirectoryNameImpl(dirname, txtCtrl, dirPicker); } void ffs3::scrollToBottom(wxScrolledWindow* scrWindow) { int height = 0; scrWindow->GetClientSize(NULL, &height); int pixelPerLine = 0; scrWindow->GetScrollPixelsPerUnit(NULL, &pixelPerLine); if (height > 0 && pixelPerLine > 0) { const int scrollLinesTotal = scrWindow->GetScrollLines(wxVERTICAL); const int scrollLinesOnScreen = height / pixelPerLine; const int scrollPosBottom = scrollLinesTotal - scrollLinesOnScreen; if (0 <= scrollPosBottom) scrWindow->Scroll(0, scrollPosBottom); } } namespace { inline void writeTwoDigitNumber(size_t number, wxString& string) { assert (number < 100); string += wxChar('0' + number / 10); string += wxChar('0' + number % 10); } inline void writeFourDigitNumber(size_t number, wxString& string) { assert (number < 10000); string += wxChar('0' + number / 1000); number %= 1000; string += wxChar('0' + number / 100); number %= 100; string += wxChar('0' + number / 10); number %= 10; string += wxChar('0' + number); } } wxString ffs3::utcTimeToLocalString(const wxLongLong& utcTime) { #ifdef FFS_WIN //convert ansi C time to FILETIME wxLongLong fileTimeLong(utcTime); fileTimeLong += wxLongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s fileTimeLong *= 10000000; FILETIME lastWriteTimeUtc; lastWriteTimeUtc.dwLowDateTime = fileTimeLong.GetLo(); //GetLo() returns unsigned lastWriteTimeUtc.dwHighDateTime = unsigned(fileTimeLong.GetHi()); //GetHi() returns signed FILETIME localFileTime; if (::FileTimeToLocalFileTime( //convert to local time &lastWriteTimeUtc, //pointer to UTC file time to convert &localFileTime //pointer to converted file time ) == 0) throw std::runtime_error(std::string((wxString(_("Conversion error:")) + wxT(" FILETIME -> local FILETIME: ") + wxT("(") + wxULongLong(lastWriteTimeUtc.dwHighDateTime, lastWriteTimeUtc.dwLowDateTime).ToString() + wxT(") ") + wxT("\n\n") + getLastErrorFormatted()).ToAscii())); if (localFileTime.dwHighDateTime > 0x7fffffff) return _("Error"); //this actually CAN happen if UTC time is just below this border and ::FileTimeToLocalFileTime() adds 2 hours due to DST or whatever! //Testcase (UTC): dateHigh = 2147483647 (=0x7fffffff) -> year 30000 // dateLow = 4294967295 SYSTEMTIME time; if (::FileTimeToSystemTime( &localFileTime, //pointer to file time to convert &time //pointer to structure to receive system time ) == 0) throw std::runtime_error(std::string((wxString(_("Conversion error:")) + wxT(" local FILETIME -> SYSTEMTIME: ") + wxT("(") + wxULongLong(localFileTime.dwHighDateTime, localFileTime.dwLowDateTime).ToString() + wxT(") ") + wxT("\n\n") + getLastErrorFormatted()).ToAscii())); //assemble time string (performance optimized) -> note: performance argument may not be valid any more wxString formattedTime; formattedTime.reserve(20); writeFourDigitNumber(time.wYear, formattedTime); formattedTime += wxChar('-'); writeTwoDigitNumber(time.wMonth, formattedTime); formattedTime += wxChar('-'); writeTwoDigitNumber(time.wDay, formattedTime); formattedTime += wxChar(' '); formattedTime += wxChar(' '); writeTwoDigitNumber(time.wHour, formattedTime); formattedTime += wxChar(':'); writeTwoDigitNumber(time.wMinute, formattedTime); formattedTime += wxChar(':'); writeTwoDigitNumber(time.wSecond, formattedTime); return formattedTime; #elif defined FFS_LINUX tm* timeinfo; const time_t fileTime = utcTime.ToLong(); timeinfo = localtime(&fileTime); //convert to local time char buffer[50]; strftime(buffer, 50, "%Y-%m-%d %H:%M:%S", timeinfo); return zToWx(buffer); #endif }