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         (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 
Print()89 void 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