1// PercentPrinter.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6
7#include "PercentPrinter.h"
8
9static const unsigned kPercentsSize = 4;
10
11CPercentPrinter::~CPercentPrinter()
12{
13  ClosePrint(false);
14}
15
16void CPercentPrinterState::ClearCurState()
17{
18  Completed = 0;
19  Total = ((UInt64)(Int64)-1);
20  Files = 0;
21  Command.Empty();
22  FileName.Empty();
23}
24
25void CPercentPrinter::ClosePrint(bool needFlush)
26{
27  unsigned num = _printedString.Len();
28  if (num != 0)
29  {
30
31  unsigned i;
32
33  /* '\r' in old MAC OS means "new line".
34     So we can't use '\r' in some systems */
35
36  #ifdef _WIN32
37    char *start = _temp.GetBuf(num  + 2);
38    char *p = start;
39    *p++ = '\r';
40    for (i = 0; i < num; i++) *p++ = ' ';
41    *p++ = '\r';
42  #else
43    char *start = _temp.GetBuf(num * 3);
44    char *p = start;
45    for (i = 0; i < num; i++) *p++ = '\b';
46    for (i = 0; i < num; i++) *p++ = ' ';
47    for (i = 0; i < num; i++) *p++ = '\b';
48  #endif
49
50  *p = 0;
51  _temp.ReleaseBuf_SetLen((unsigned)(p - start));
52  *_so << _temp;
53  }
54  if (needFlush)
55    _so->Flush();
56  _printedString.Empty();
57}
58
59void CPercentPrinter::GetPercents()
60{
61  char s[32];
62  unsigned size;
63  {
64    char c = '%';
65    UInt64 val = 0;
66    if (Total == (UInt64)(Int64)-1 ||
67        (Total == 0 && Completed != 0))
68    {
69      val = Completed >> 20;
70      c = 'M';
71    }
72    else if (Total != 0)
73      val = Completed * 100 / Total;
74    ConvertUInt64ToString(val, s);
75    size = (unsigned)strlen(s);
76    s[size++] = c;
77    s[size] = 0;
78  }
79
80  while (size < kPercentsSize)
81  {
82    _s.Add_Space();
83    size++;
84  }
85
86  _s += s;
87}
88
89void CPercentPrinter::Print()
90{
91  DWORD tick = 0;
92  if (_tickStep != 0)
93    tick = GetTickCount();
94
95  bool onlyPercentsChanged = false;
96
97  if (!_printedString.IsEmpty())
98  {
99    if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep)
100      return;
101
102    CPercentPrinterState &st = *this;
103    if (_printedState.Command == st.Command
104        && _printedState.FileName == st.FileName
105        && _printedState.Files == st.Files)
106    {
107      if (_printedState.Total == st.Total
108          && _printedState.Completed == st.Completed)
109        return;
110      onlyPercentsChanged = true;
111    }
112  }
113
114  _s.Empty();
115
116  GetPercents();
117
118  if (onlyPercentsChanged && _s == _printedPercents)
119    return;
120
121  _printedPercents = _s;
122
123  if (Files != 0)
124  {
125    char s[32];
126    ConvertUInt64ToString(Files, s);
127    // unsigned size = (unsigned)strlen(s);
128    // for (; size < 3; size++) _s.Add_Space();
129    _s.Add_Space();
130    _s += s;
131    // _s += "f";
132  }
133
134
135  if (!Command.IsEmpty())
136  {
137    _s.Add_Space();
138    _s += Command;
139  }
140
141  if (!FileName.IsEmpty() && _s.Len() < MaxLen)
142  {
143    _s.Add_Space();
144
145    _tempU = FileName;
146    _so->Normalize_UString(_tempU);
147    _so->Convert_UString_to_AString(_tempU, _temp);
148    if (_s.Len() + _temp.Len() > MaxLen)
149    {
150      unsigned len = FileName.Len();
151      for (; len != 0;)
152      {
153        unsigned delta = len / 8;
154        if (delta == 0)
155          delta = 1;
156        len -= delta;
157        _tempU = FileName;
158        _tempU.Delete(len / 2, _tempU.Len() - len);
159        _tempU.Insert(len / 2, L" . ");
160        _so->Normalize_UString(_tempU);
161        _so->Convert_UString_to_AString(_tempU, _temp);
162        if (_s.Len() + _temp.Len() <= MaxLen)
163          break;
164      }
165      if (len == 0)
166        _temp.Empty();
167    }
168    _s += _temp;
169  }
170
171  if (_printedString != _s)
172  {
173    ClosePrint(false);
174    *_so << _s;
175    if (NeedFlush)
176      _so->Flush();
177    _printedString = _s;
178  }
179
180  _printedState = *this;
181
182  if (_tickStep != 0)
183    _prevTick = tick;
184}
185