1 // PercentPrinter.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../Common/IntToString.h"
6 
7 #include "PercentPrinter.h"
8 
9 static const unsigned kPercentsSize = 4;
10 
~CPercentPrinter()11 CPercentPrinter::~CPercentPrinter()
12 {
13   ClosePrint(false);
14 }
15 
ClearCurState()16 void CPercentPrinterState::ClearCurState()
17 {
18   Completed = 0;
19   Total = ((UInt64)(Int64)-1);
20   Files = 0;
21   Command.Empty();
22   FileName.Empty();
23 }
24 
ClosePrint(bool needFlush)25 void 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 
GetPercents()59 void 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     {
68       val = Completed >> 20;
69       c = 'M';
70     }
71     else if (Total != 0)
72       val = Completed * 100 / Total;
73     ConvertUInt64ToString(val, s);
74     size = (unsigned)strlen(s);
75     s[size++] = c;
76     s[size] = 0;
77   }
78 
79   while (size < kPercentsSize)
80   {
81     _s += ' ';
82     size++;
83   }
84 
85   _s += s;
86 }
87 
Print()88 void CPercentPrinter::Print()
89 {
90   DWORD tick = 0;
91   if (_tickStep != 0)
92     tick = GetTickCount();
93 
94   bool onlyPercentsChanged = false;
95 
96   if (!_printedString.IsEmpty())
97   {
98     if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep)
99       return;
100 
101     CPercentPrinterState &st = *this;
102     if (_printedState.Command == st.Command
103         && _printedState.FileName == st.FileName
104         && _printedState.Files == st.Files)
105     {
106       if (_printedState.Total == st.Total
107           && _printedState.Completed == st.Completed)
108         return;
109       onlyPercentsChanged = true;
110     }
111   }
112 
113   _s.Empty();
114 
115   GetPercents();
116 
117   if (onlyPercentsChanged && _s == _printedPercents)
118     return;
119 
120   _printedPercents = _s;
121 
122   if (Files != 0)
123   {
124     char s[32];
125     ConvertUInt64ToString(Files, s);
126     // unsigned size = (unsigned)strlen(s);
127     // for (; size < 3; size++) _s += ' ';
128     _s += ' ';
129     _s += s;
130     // _s += "f";
131   }
132 
133 
134   if (!Command.IsEmpty())
135   {
136     _s += ' ';
137     _s += Command;
138   }
139 
140   if (!FileName.IsEmpty() && _s.Len() < MaxLen)
141   {
142     _s += ' ';
143 
144     _tempU = FileName;
145     _so->Normalize_UString(_tempU);
146     _so->Convert_UString_to_AString(_tempU, _temp);
147     if (_s.Len() + _temp.Len() > MaxLen)
148     {
149       unsigned len = FileName.Len();
150       for (; len != 0;)
151       {
152         unsigned delta = len / 8;
153         if (delta == 0)
154           delta = 1;
155         len -= delta;
156         _tempU = FileName;
157         _tempU.Delete(len / 2, _tempU.Len() - len);
158         _tempU.Insert(len / 2, L" . ");
159         _so->Normalize_UString(_tempU);
160         _so->Convert_UString_to_AString(_tempU, _temp);
161         if (_s.Len() + _temp.Len() <= MaxLen)
162           break;
163       }
164       if (len == 0)
165         _temp.Empty();
166     }
167     _s += _temp;
168   }
169 
170   if (_printedString != _s)
171   {
172     ClosePrint(false);
173     *_so << _s;
174     if (NeedFlush)
175       _so->Flush();
176     _printedString = _s;
177   }
178 
179   _printedState = *this;
180 
181   if (_tickStep != 0)
182     _prevTick = tick;
183 }
184