mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 13:14:59 -06:00
306 lines
6.3 KiB
C++
Executable File
306 lines
6.3 KiB
C++
Executable File
// ProgressBox.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "../../../Common/IntToString.h"
|
|
#include "../../../Common/StringConvert.h"
|
|
|
|
#include "FarUtils.h"
|
|
#include "ProgressBox.h"
|
|
|
|
void CPercentPrinterState::ClearCurState()
|
|
{
|
|
Completed = 0;
|
|
Total = ((UInt64)(Int64)-1);
|
|
Files = 0;
|
|
FilesTotal = 0;
|
|
Command.Empty();
|
|
FileName.Empty();
|
|
}
|
|
|
|
void CProgressBox::Init(const char *title)
|
|
{
|
|
_title = title;
|
|
_wasPrinted = false;
|
|
StartTick = GetTickCount();
|
|
_prevTick = StartTick;
|
|
_prevElapsedSec = 0;
|
|
}
|
|
|
|
static unsigned GetPower32(UInt32 val)
|
|
{
|
|
const unsigned kStart = 32;
|
|
UInt32 mask = ((UInt32)1 << (kStart - 1));
|
|
for (unsigned i = kStart;; i--)
|
|
{
|
|
if (i == 0 || (val & mask) != 0)
|
|
return i;
|
|
mask >>= 1;
|
|
}
|
|
}
|
|
|
|
static unsigned GetPower64(UInt64 val)
|
|
{
|
|
UInt32 high = (UInt32)(val >> 32);
|
|
if (high == 0)
|
|
return GetPower32((UInt32)val);
|
|
return GetPower32(high) + 32;
|
|
}
|
|
|
|
static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider)
|
|
{
|
|
unsigned pow1 = GetPower64(mult1);
|
|
unsigned pow2 = GetPower64(mult2);
|
|
while (pow1 + pow2 > 64)
|
|
{
|
|
if (pow1 > pow2) { pow1--; mult1 >>= 1; }
|
|
else { pow2--; mult2 >>= 1; }
|
|
divider >>= 1;
|
|
}
|
|
UInt64 res = mult1 * mult2;
|
|
if (divider != 0)
|
|
res /= divider;
|
|
return res;
|
|
}
|
|
|
|
#define UINT_TO_STR_2(val) { s[0] = (char)('0' + (val) / 10); s[1] = (char)('0' + (val) % 10); s += 2; }
|
|
|
|
static void GetTimeString(UInt64 timeValue, char *s)
|
|
{
|
|
const UInt64 hours = timeValue / 3600;
|
|
UInt32 seconds = (UInt32)(timeValue - hours * 3600);
|
|
const UInt32 minutes = seconds / 60;
|
|
seconds %= 60;
|
|
if (hours > 99)
|
|
{
|
|
ConvertUInt64ToString(hours, s);
|
|
for (; *s != 0; s++);
|
|
}
|
|
else
|
|
{
|
|
const UInt32 hours32 = (UInt32)hours;
|
|
UINT_TO_STR_2(hours32)
|
|
}
|
|
*s++ = ':'; UINT_TO_STR_2(minutes)
|
|
*s++ = ':'; UINT_TO_STR_2(seconds)
|
|
*s = 0;
|
|
}
|
|
|
|
void CProgressBox::ReduceString(const UString &src, AString &dest)
|
|
{
|
|
UnicodeStringToMultiByte2(dest, src, CP_OEMCP);
|
|
|
|
if (dest.Len() <= MaxLen)
|
|
return;
|
|
unsigned len = FileName.Len();
|
|
for (; len != 0;)
|
|
{
|
|
unsigned delta = len / 8;
|
|
if (delta == 0)
|
|
delta = 1;
|
|
len -= delta;
|
|
_tempU = FileName;
|
|
_tempU.Delete(len / 2, FileName.Len() - len);
|
|
_tempU.Insert(len / 2, L" . ");
|
|
UnicodeStringToMultiByte2(dest, _tempU, CP_OEMCP);
|
|
if (dest.Len() <= MaxLen)
|
|
return;
|
|
}
|
|
dest.Empty();
|
|
}
|
|
|
|
static void Print_UInt64_and_String(AString &s, UInt64 val, const char *name)
|
|
{
|
|
char temp[32];
|
|
ConvertUInt64ToString(val, temp);
|
|
s += temp;
|
|
s.Add_Space();
|
|
s += name;
|
|
}
|
|
|
|
|
|
static void PrintSize_bytes_Smart(AString &s, UInt64 val)
|
|
{
|
|
// Print_UInt64_and_String(s, val, "bytes");
|
|
{
|
|
char temp[32];
|
|
ConvertUInt64ToString(val, temp);
|
|
s += temp;
|
|
}
|
|
|
|
if (val == 0)
|
|
return;
|
|
|
|
unsigned numBits = 10;
|
|
char c = 'K';
|
|
char temp[4] = { 'K', 'i', 'B', 0 };
|
|
if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; }
|
|
else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; }
|
|
temp[0] = c;
|
|
s += " (";
|
|
Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);
|
|
s += ')';
|
|
}
|
|
|
|
|
|
static const unsigned kPercentsSize = 4;
|
|
|
|
void CProgressBox::Print()
|
|
{
|
|
DWORD tick = GetTickCount();
|
|
DWORD elapsedTicks = tick - StartTick;
|
|
DWORD elapsedSec = elapsedTicks / 1000;
|
|
|
|
if (_wasPrinted)
|
|
{
|
|
if (elapsedSec == _prevElapsedSec)
|
|
{
|
|
if ((UInt32)(tick - _prevTick) < _tickStep)
|
|
return;
|
|
if (_printedState.IsEqualTo((const CPercentPrinterState &)*this))
|
|
return;
|
|
}
|
|
}
|
|
|
|
UInt64 cur = Completed;
|
|
UInt64 total = Total;
|
|
|
|
if (!UseBytesForPercents)
|
|
{
|
|
cur = Files;
|
|
total = FilesTotal;
|
|
}
|
|
|
|
{
|
|
_timeStr.Empty();
|
|
_timeStr = "Elapsed time: ";
|
|
char s[40];
|
|
GetTimeString(elapsedSec, s);
|
|
_timeStr += s;
|
|
|
|
if (cur != 0)
|
|
{
|
|
UInt64 remainingTime = 0;
|
|
if (cur < total)
|
|
remainingTime = MyMultAndDiv(elapsedTicks, total - cur, cur);
|
|
UInt64 remainingSec = remainingTime / 1000;
|
|
_timeStr += " Remaining time: ";
|
|
|
|
GetTimeString(remainingSec, s);
|
|
_timeStr += s;
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
_perc.Empty();
|
|
char s[32];
|
|
unsigned size;
|
|
{
|
|
UInt64 val = 0;
|
|
if (total != (UInt64)(Int64)-1 && total != 0)
|
|
val = cur * 100 / Total;
|
|
|
|
ConvertUInt64ToString(val, s);
|
|
size = (unsigned)strlen(s);
|
|
s[size++] = '%';
|
|
s[size] = 0;
|
|
}
|
|
|
|
unsigned len = size;
|
|
while (len < kPercentsSize)
|
|
len = kPercentsSize;
|
|
len++;
|
|
|
|
if (len < MaxLen)
|
|
{
|
|
unsigned numChars = MaxLen - len;
|
|
unsigned filled = 0;
|
|
if (total != (UInt64)(Int64)-1 && total != 0)
|
|
filled = (unsigned)(cur * numChars / total);
|
|
if (filled > numChars)
|
|
filled = numChars;
|
|
unsigned i = 0;
|
|
for (i = 0; i < filled; i++)
|
|
_perc += (char)(Byte)0xDB; // '=';
|
|
for (; i < numChars; i++)
|
|
_perc += (char)(Byte)0xB0; // '.';
|
|
}
|
|
|
|
_perc.Add_Space();
|
|
while (size < kPercentsSize)
|
|
{
|
|
_perc.Add_Space();
|
|
size++;
|
|
}
|
|
_perc += s;
|
|
}
|
|
|
|
_files.Empty();
|
|
if (Files != 0 || FilesTotal != 0)
|
|
{
|
|
_files += "Files: ";
|
|
char s[32];
|
|
// if (Files != 0)
|
|
{
|
|
ConvertUInt64ToString(Files, s);
|
|
_files += s;
|
|
}
|
|
if (FilesTotal != 0)
|
|
{
|
|
_files += " / ";
|
|
ConvertUInt64ToString(FilesTotal, s);
|
|
_files += s;
|
|
}
|
|
}
|
|
|
|
_sizesStr.Empty();
|
|
if (Total != 0)
|
|
{
|
|
_sizesStr += "Size: ";
|
|
PrintSize_bytes_Smart(_sizesStr, Completed);
|
|
if (Total != 0 && Total != (UInt64)(Int64)-1)
|
|
{
|
|
_sizesStr += " / ";
|
|
PrintSize_bytes_Smart(_sizesStr, Total);
|
|
}
|
|
}
|
|
|
|
_name1.Empty();
|
|
_name2.Empty();
|
|
|
|
if (!FileName.IsEmpty())
|
|
{
|
|
_name1U.Empty();
|
|
_name2U.Empty();
|
|
|
|
/*
|
|
if (_isDir)
|
|
s1 = _filePath;
|
|
else
|
|
*/
|
|
{
|
|
const int slashPos = FileName.ReverseFind_PathSepar();
|
|
if (slashPos >= 0)
|
|
{
|
|
_name1U.SetFrom(FileName, (unsigned)(slashPos + 1));
|
|
_name2U = FileName.Ptr(slashPos + 1);
|
|
}
|
|
else
|
|
_name2U = FileName;
|
|
}
|
|
ReduceString(_name1U, _name1);
|
|
ReduceString(_name2U, _name2);
|
|
}
|
|
|
|
{
|
|
const char *strings[] = { _title, _timeStr, _files, _sizesStr, Command, _name1, _name2, _perc };
|
|
NFar::g_StartupInfo.ShowMessage(FMSG_LEFTALIGN, NULL, strings, Z7_ARRAY_SIZE(strings), 0);
|
|
}
|
|
|
|
_wasPrinted = true;
|
|
_printedState = *this;
|
|
_prevTick = tick;
|
|
_prevElapsedSec = elapsedSec;
|
|
}
|