misc/libphysfs/lzma/CPP/7zip/UI/Console/List.cpp
branchui-scaling
changeset 15283 c4fd2813b127
parent 13390 0135e64c6c66
parent 15279 7ab5cf405686
child 15663 d92eeb468dad
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
     1 // List.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 
       
     5 #include "List.h"
       
     6 #include "ConsoleClose.h"
       
     7 
       
     8 #include "Common/StringConvert.h"
       
     9 #include "Common/StdOutStream.h"
       
    10 #include "Common/IntToString.h"
       
    11 #include "Common/MyCom.h"
       
    12 
       
    13 #include "Windows/PropVariant.h"
       
    14 #include "Windows/Defs.h"
       
    15 #include "Windows/PropVariantConversions.h"
       
    16 #include "Windows/FileDir.h"
       
    17 
       
    18 #include "../../Archive/IArchive.h"
       
    19 
       
    20 #include "../Common/PropIDUtils.h"
       
    21 #include "../Common/OpenArchive.h"
       
    22 
       
    23 #include "OpenCallbackConsole.h"
       
    24 
       
    25 using namespace NWindows;
       
    26 
       
    27 struct CPropIdToName
       
    28 {
       
    29   PROPID PropID;
       
    30   const wchar_t *Name;
       
    31 };
       
    32 
       
    33 static CPropIdToName kPropIdToName[] =  
       
    34 {
       
    35   { kpidPath, L"Path" },
       
    36   { kpidName, L"Name" },
       
    37   { kpidIsFolder, L"Folder" }, 
       
    38   { kpidSize, L"Size" },
       
    39   { kpidPackedSize, L"Packed Size" },
       
    40   { kpidAttributes, L"Attributes" },
       
    41   { kpidCreationTime, L"Created" },
       
    42   { kpidLastAccessTime, L"Accessed" },
       
    43   { kpidLastWriteTime, L"Modified" },
       
    44   { kpidSolid, L"Solid" },
       
    45   { kpidCommented, L"Commented" },
       
    46   { kpidEncrypted, L"Encrypted" },
       
    47   { kpidSplitBefore, L"Split Before" },
       
    48   { kpidSplitAfter, L"Split After" },
       
    49   { kpidDictionarySize, L"Dictionary Size" },
       
    50   { kpidCRC, L"CRC" },
       
    51   { kpidType, L"Type" },
       
    52   { kpidIsAnti, L"Anti" },
       
    53   { kpidMethod, L"Method" },
       
    54   { kpidHostOS, L"Host OS" },
       
    55   { kpidFileSystem, L"File System" },
       
    56   { kpidUser, L"User" },
       
    57   { kpidGroup, L"Group" },
       
    58   { kpidBlock, L"Block" },
       
    59   { kpidComment, L"Comment" },
       
    60   { kpidPosition, L"Position" },
       
    61   { kpidPrefix, L"Prefix" },
       
    62   { kpidNumSubFolders, L"Folders" },
       
    63   { kpidNumSubFiles, L"Files" },
       
    64   { kpidUnpackVer, L"Version" },
       
    65   { kpidVolume, L"Volume" },
       
    66   { kpidIsVolume, L"Multivolume" },
       
    67   { kpidOffset, L"Offset" },
       
    68   { kpidLinks, L"Links" },
       
    69   { kpidNumBlocks, L"Blocks" },
       
    70   { kpidNumVolumes, L"Volumes" }
       
    71 };
       
    72 
       
    73 static const char kEmptyAttributeChar = '.';
       
    74 static const char kDirectoryAttributeChar = 'D';
       
    75 static const char kReadonlyAttributeChar  = 'R';
       
    76 static const char kHiddenAttributeChar    = 'H';
       
    77 static const char kSystemAttributeChar    = 'S';
       
    78 static const char kArchiveAttributeChar   = 'A';
       
    79 
       
    80 static const char *kListing = "Listing archive: ";
       
    81 static const wchar_t *kFilesMessage = L"files";
       
    82 static const wchar_t *kDirsMessage = L"folders";
       
    83 
       
    84 static void GetAttributesString(DWORD wa, bool directory, char *s)
       
    85 {
       
    86   s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ? 
       
    87       kDirectoryAttributeChar: kEmptyAttributeChar;
       
    88   s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0)? 
       
    89       kReadonlyAttributeChar: kEmptyAttributeChar;
       
    90   s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 
       
    91       kHiddenAttributeChar: kEmptyAttributeChar;
       
    92   s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 
       
    93       kSystemAttributeChar: kEmptyAttributeChar;
       
    94   s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 
       
    95       kArchiveAttributeChar: kEmptyAttributeChar;
       
    96   s[5] = '\0';
       
    97 }
       
    98 
       
    99 enum EAdjustment
       
   100 {
       
   101   kLeft,
       
   102   kCenter,
       
   103   kRight
       
   104 };
       
   105 
       
   106 struct CFieldInfo
       
   107 {
       
   108   PROPID PropID;
       
   109   UString Name;
       
   110   EAdjustment TitleAdjustment;
       
   111   EAdjustment TextAdjustment;
       
   112   int PrefixSpacesWidth;
       
   113   int Width;
       
   114 };
       
   115 
       
   116 struct CFieldInfoInit
       
   117 {
       
   118   PROPID PropID;
       
   119   const wchar_t *Name;
       
   120   EAdjustment TitleAdjustment;
       
   121   EAdjustment TextAdjustment;
       
   122   int PrefixSpacesWidth;
       
   123   int Width;
       
   124 };
       
   125 
       
   126 CFieldInfoInit kStandardFieldTable[] = 
       
   127 {
       
   128   { kpidLastWriteTime, L"   Date      Time", kLeft, kLeft, 0, 19 },
       
   129   { kpidAttributes, L"Attr", kRight, kCenter, 1, 5 },
       
   130   { kpidSize, L"Size", kRight, kRight, 1, 12 },
       
   131   { kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 },
       
   132   { kpidPath, L"Name", kLeft, kLeft, 2, 24 }
       
   133 };
       
   134 
       
   135 void PrintSpaces(int numSpaces)
       
   136 {
       
   137   for (int i = 0; i < numSpaces; i++)
       
   138     g_StdOut << ' ';
       
   139 }
       
   140 
       
   141 void PrintString(EAdjustment adjustment, int width, const UString &textString)
       
   142 {
       
   143   const int numSpaces = width - textString.Length();
       
   144   int numLeftSpaces = 0;
       
   145   switch (adjustment)
       
   146   {
       
   147     case kLeft:
       
   148       numLeftSpaces = 0;
       
   149       break;
       
   150     case kCenter:
       
   151       numLeftSpaces = numSpaces / 2;
       
   152       break;
       
   153     case kRight:
       
   154       numLeftSpaces = numSpaces;
       
   155       break;
       
   156   }
       
   157   PrintSpaces(numLeftSpaces);
       
   158   g_StdOut << textString;
       
   159   PrintSpaces(numSpaces - numLeftSpaces);
       
   160 }
       
   161 
       
   162 class CFieldPrinter
       
   163 {
       
   164   CObjectVector<CFieldInfo> _fields;
       
   165 public:
       
   166   void Clear() { _fields.Clear(); }
       
   167   void Init(const CFieldInfoInit *standardFieldTable, int numItems);
       
   168   HRESULT Init(IInArchive *archive);
       
   169   void PrintTitle();
       
   170   void PrintTitleLines();
       
   171   HRESULT PrintItemInfo(IInArchive *archive, 
       
   172       const UString &defaultItemName,
       
   173       const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
       
   174       UInt32 index,
       
   175       bool techMode);
       
   176   HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, 
       
   177       const UInt64 *size, const UInt64 *compressedSize);
       
   178 };
       
   179 
       
   180 void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
       
   181 {
       
   182   Clear();
       
   183   for (int i = 0; i < numItems; i++)
       
   184   {
       
   185     CFieldInfo fieldInfo;
       
   186     const CFieldInfoInit &fieldInfoInit = standardFieldTable[i];
       
   187     fieldInfo.PropID = fieldInfoInit.PropID;
       
   188     fieldInfo.Name = fieldInfoInit.Name;
       
   189     fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment;
       
   190     fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment;
       
   191     fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth;
       
   192     fieldInfo.Width = fieldInfoInit.Width;
       
   193     _fields.Add(fieldInfo);
       
   194   }
       
   195 }
       
   196 
       
   197 static UString GetPropName(PROPID propID, BSTR name)
       
   198 {
       
   199   for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++)
       
   200   {
       
   201     const CPropIdToName &propIdToName = kPropIdToName[i];
       
   202     if (propIdToName.PropID == propID)
       
   203       return propIdToName.Name;
       
   204   }
       
   205   if (name)
       
   206     return name;
       
   207   return L"?";
       
   208 }
       
   209 
       
   210 HRESULT CFieldPrinter::Init(IInArchive *archive)
       
   211 {
       
   212   Clear();
       
   213   UInt32 numProps;
       
   214   RINOK(archive->GetNumberOfProperties(&numProps));
       
   215   for (UInt32 i = 0; i < numProps; i++)
       
   216   {
       
   217     CMyComBSTR name;
       
   218     PROPID propID;
       
   219     VARTYPE vt;
       
   220     RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));
       
   221     CFieldInfo fieldInfo;
       
   222     fieldInfo.PropID = propID;
       
   223     fieldInfo.Name = GetPropName(propID, name);
       
   224     _fields.Add(fieldInfo);
       
   225   }
       
   226   return S_OK;
       
   227 }
       
   228 
       
   229 void CFieldPrinter::PrintTitle()
       
   230 {
       
   231   for (int i = 0; i < _fields.Size(); i++)
       
   232   {
       
   233     const CFieldInfo &fieldInfo = _fields[i];
       
   234     PrintSpaces(fieldInfo.PrefixSpacesWidth);
       
   235     PrintString(fieldInfo.TitleAdjustment, 
       
   236       ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);
       
   237   }
       
   238 }
       
   239 
       
   240 void CFieldPrinter::PrintTitleLines()
       
   241 {
       
   242   for (int i = 0; i < _fields.Size(); i++)
       
   243   {
       
   244     const CFieldInfo &fieldInfo = _fields[i];
       
   245     PrintSpaces(fieldInfo.PrefixSpacesWidth);
       
   246     for (int i = 0; i < fieldInfo.Width; i++)
       
   247       g_StdOut << '-';
       
   248   }
       
   249 }
       
   250 
       
   251 
       
   252 BOOL IsFileTimeZero(CONST FILETIME *lpFileTime)
       
   253 {
       
   254   return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);
       
   255 }
       
   256 
       
   257 static const char *kEmptyTimeString = "                   ";
       
   258 void PrintTime(const NCOM::CPropVariant &propVariant)
       
   259 {
       
   260   if (propVariant.vt != VT_FILETIME)
       
   261     throw "incorrect item";
       
   262   if (IsFileTimeZero(&propVariant.filetime))
       
   263     g_StdOut << kEmptyTimeString;
       
   264   else
       
   265   {
       
   266     FILETIME localFileTime;
       
   267     if (!FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime))
       
   268       throw "FileTimeToLocalFileTime error";
       
   269     char s[32];
       
   270     if (ConvertFileTimeToString(localFileTime, s, true, true))
       
   271       g_StdOut << s;
       
   272     else
       
   273       g_StdOut << kEmptyTimeString;
       
   274   }
       
   275 }
       
   276 
       
   277 HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, 
       
   278     const UString &defaultItemName, 
       
   279     const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
       
   280     UInt32 index,
       
   281     bool techMode)
       
   282 {
       
   283   /*
       
   284   if (techMode)
       
   285   {
       
   286     g_StdOut << "Index = ";
       
   287     g_StdOut << (UInt64)index;
       
   288     g_StdOut << endl;
       
   289   }
       
   290   */
       
   291   for (int i = 0; i < _fields.Size(); i++)
       
   292   {
       
   293     const CFieldInfo &fieldInfo = _fields[i];
       
   294     if (!techMode)
       
   295       PrintSpaces(fieldInfo.PrefixSpacesWidth);
       
   296 
       
   297     NCOM::CPropVariant propVariant;
       
   298     RINOK(archive->GetProperty(index, fieldInfo.PropID, &propVariant));
       
   299     if (techMode)
       
   300     {
       
   301       g_StdOut << fieldInfo.Name << " = ";
       
   302     }
       
   303     int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;
       
   304     if (propVariant.vt == VT_EMPTY)
       
   305     {
       
   306       switch(fieldInfo.PropID)
       
   307       {
       
   308         case kpidPath:
       
   309           propVariant = defaultItemName;
       
   310           break;
       
   311         case kpidLastWriteTime:
       
   312           propVariant = archiveFileInfo.LastWriteTime;
       
   313           break;
       
   314         default:
       
   315           if (techMode)
       
   316             g_StdOut << endl;
       
   317           else
       
   318             PrintSpaces(width);
       
   319           continue;
       
   320       }
       
   321     }
       
   322     if (fieldInfo.PropID == kpidLastWriteTime)
       
   323     {
       
   324       PrintTime(propVariant);
       
   325     }
       
   326     else if (fieldInfo.PropID == kpidAttributes)
       
   327     {
       
   328       if (propVariant.vt != VT_UI4)
       
   329         throw "incorrect item";
       
   330       UInt32 attributes = propVariant.ulVal;
       
   331       bool isFolder;
       
   332       RINOK(IsArchiveItemFolder(archive, index, isFolder));
       
   333       char s[8];
       
   334       GetAttributesString(attributes, isFolder, s);
       
   335       g_StdOut << s;
       
   336     }
       
   337     else if (propVariant.vt == VT_BSTR)
       
   338     {
       
   339       if (techMode)
       
   340         g_StdOut << propVariant.bstrVal;
       
   341       else
       
   342         PrintString(fieldInfo.TextAdjustment, width, propVariant.bstrVal);
       
   343     }
       
   344     else
       
   345     {
       
   346       UString s = ConvertPropertyToString(propVariant, fieldInfo.PropID);
       
   347       s.Replace(wchar_t(0xA), L' '); 
       
   348       s.Replace(wchar_t(0xD), L' '); 
       
   349 
       
   350       if (techMode)
       
   351         g_StdOut << s;
       
   352       else
       
   353         PrintString(fieldInfo.TextAdjustment, width, s);
       
   354     }
       
   355     if (techMode)
       
   356       g_StdOut << endl;
       
   357   }
       
   358   return S_OK;
       
   359 }
       
   360 
       
   361 void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)
       
   362 {
       
   363   wchar_t textString[32] = { 0 };
       
   364   if (value != NULL)
       
   365     ConvertUInt64ToString(*value, textString);
       
   366   PrintString(adjustment, width, textString);
       
   367 }
       
   368 
       
   369 
       
   370 HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, 
       
   371     const UInt64 *size, const UInt64 *compressedSize)
       
   372 {
       
   373   for (int i = 0; i < _fields.Size(); i++)
       
   374   {
       
   375     const CFieldInfo &fieldInfo = _fields[i];
       
   376     PrintSpaces(fieldInfo.PrefixSpacesWidth);
       
   377     NCOM::CPropVariant propVariant;
       
   378     if (fieldInfo.PropID == kpidSize)
       
   379       PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size);
       
   380     else if (fieldInfo.PropID == kpidPackedSize)
       
   381       PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize);
       
   382     else if (fieldInfo.PropID == kpidPath)
       
   383     {
       
   384       wchar_t textString[32];
       
   385       ConvertUInt64ToString(numFiles, textString);
       
   386       UString temp = textString;
       
   387       temp += L" ";
       
   388       temp += kFilesMessage;
       
   389       temp += L", ";
       
   390       ConvertUInt64ToString(numDirs, textString);
       
   391       temp += textString;
       
   392       temp += L" ";
       
   393       temp += kDirsMessage;
       
   394       PrintString(fieldInfo.TextAdjustment, 0, temp);
       
   395     }
       
   396     else 
       
   397       PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");
       
   398   }
       
   399   return S_OK;
       
   400 }
       
   401 
       
   402 bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value)
       
   403 {
       
   404   NCOM::CPropVariant propVariant;
       
   405   if (archive->GetProperty(index, propID, &propVariant) != S_OK)
       
   406     throw "GetPropertyValue error";
       
   407   if (propVariant.vt == VT_EMPTY)
       
   408     return false;
       
   409   value = ConvertPropVariantToUInt64(propVariant);
       
   410   return true;
       
   411 }
       
   412 
       
   413 HRESULT ListArchives(
       
   414     CCodecs *codecs,
       
   415     UStringVector &archivePaths, UStringVector &archivePathsFull,
       
   416     const NWildcard::CCensorNode &wildcardCensor,
       
   417     bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &numErrors)
       
   418 {
       
   419   numErrors = 0;
       
   420   CFieldPrinter fieldPrinter;
       
   421   if (!techMode)
       
   422     fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));
       
   423 
       
   424   UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
       
   425   UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
       
   426   for (int i = 0; i < archivePaths.Size(); i++)
       
   427   {
       
   428     const UString &archiveName = archivePaths[i];
       
   429     NFile::NFind::CFileInfoW archiveFileInfo;
       
   430     if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory())
       
   431     {
       
   432       g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl;
       
   433       numErrors++;
       
   434       continue;
       
   435     }
       
   436     if (archiveFileInfo.IsDirectory())
       
   437     {
       
   438       g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;
       
   439       numErrors++;
       
   440       continue;
       
   441     }
       
   442 
       
   443     CArchiveLink archiveLink;
       
   444 
       
   445     COpenCallbackConsole openCallback;
       
   446     openCallback.OutStream = &g_StdOut;
       
   447     openCallback.PasswordIsDefined = passwordEnabled;
       
   448     openCallback.Password = password;
       
   449 
       
   450     HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, &openCallback);
       
   451     if (result != S_OK)
       
   452     {
       
   453       g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl;
       
   454       numErrors++;
       
   455       continue;
       
   456     }
       
   457 
       
   458     for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
       
   459     {
       
   460       int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
       
   461       if (index >= 0 && index > i)
       
   462       {
       
   463         archivePaths.Delete(index);
       
   464         archivePathsFull.Delete(index);
       
   465       }
       
   466     }
       
   467 
       
   468     IInArchive *archive = archiveLink.GetArchive();
       
   469     const UString defaultItemName = archiveLink.GetDefaultItemName();
       
   470 
       
   471     if (enableHeaders)
       
   472     {
       
   473       g_StdOut << endl << kListing << archiveName << endl << endl;
       
   474 
       
   475       UInt32 numProps;
       
   476       if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK)
       
   477       {
       
   478         for (UInt32 i = 0; i < numProps; i++)
       
   479         {
       
   480           CMyComBSTR name;
       
   481           PROPID propID;
       
   482           VARTYPE vt;
       
   483           if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK)
       
   484             continue;
       
   485           NCOM::CPropVariant prop;
       
   486           if (archive->GetArchiveProperty(propID, &prop) != S_OK)
       
   487             continue;
       
   488           UString s = ConvertPropertyToString(prop, propID);
       
   489           if (!s.IsEmpty())
       
   490             g_StdOut << GetPropName(propID, name) << " = " << s << endl;
       
   491         }
       
   492       }
       
   493       if (techMode)
       
   494         g_StdOut << "----------\n";
       
   495       if (numProps > 0)
       
   496         g_StdOut << endl;
       
   497     }
       
   498 
       
   499     if (enableHeaders && !techMode)
       
   500     {
       
   501       fieldPrinter.PrintTitle();
       
   502       g_StdOut << endl;
       
   503       fieldPrinter.PrintTitleLines();
       
   504       g_StdOut << endl;
       
   505     }
       
   506 
       
   507     if (techMode)
       
   508     {
       
   509       RINOK(fieldPrinter.Init(archive));
       
   510     }
       
   511     UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;
       
   512     UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
       
   513     UInt32 numItems;
       
   514     RINOK(archive->GetNumberOfItems(&numItems));
       
   515     for(UInt32 i = 0; i < numItems; i++)
       
   516     {
       
   517       if (NConsoleClose::TestBreakSignal())
       
   518         return E_ABORT;
       
   519 
       
   520       UString filePath;
       
   521       RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath));
       
   522 
       
   523       bool isFolder;
       
   524       RINOK(IsArchiveItemFolder(archive, i, isFolder));
       
   525       if (!wildcardCensor.CheckPath(filePath, !isFolder))
       
   526         continue;
       
   527       
       
   528       fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i, techMode);
       
   529       
       
   530       UInt64 packSize, unpackSize;
       
   531       if (!GetUInt64Value(archive, i, kpidSize, unpackSize))
       
   532         unpackSize = 0;
       
   533       else
       
   534         totalUnPackSizePointer = &totalUnPackSize;
       
   535       if (!GetUInt64Value(archive, i, kpidPackedSize, packSize))
       
   536         packSize = 0;
       
   537       else
       
   538         totalPackSizePointer = &totalPackSize;
       
   539       
       
   540       g_StdOut << endl;
       
   541 
       
   542       if (isFolder)
       
   543         numDirs++;
       
   544       else
       
   545         numFiles++;
       
   546       totalPackSize += packSize;
       
   547       totalUnPackSize += unpackSize;
       
   548     }
       
   549     if (enableHeaders && !techMode)
       
   550     {
       
   551       fieldPrinter.PrintTitleLines();
       
   552       g_StdOut << endl;
       
   553       fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);
       
   554       g_StdOut << endl;
       
   555     }
       
   556     if (totalPackSizePointer != 0)
       
   557     {
       
   558       totalPackSizePointer2 = &totalPackSize2;
       
   559       totalPackSize2 += totalPackSize;
       
   560     }
       
   561     if (totalUnPackSizePointer != 0)
       
   562     {
       
   563       totalUnPackSizePointer2 = &totalUnPackSize2;
       
   564       totalUnPackSize2 += totalUnPackSize;
       
   565     }
       
   566     numFiles2 += numFiles;
       
   567     numDirs2 += numDirs;
       
   568   }
       
   569   if (enableHeaders && !techMode && archivePaths.Size() > 1)
       
   570   {
       
   571     g_StdOut << endl;
       
   572     fieldPrinter.PrintTitleLines();
       
   573     g_StdOut << endl;
       
   574     fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);
       
   575     g_StdOut << endl;
       
   576     g_StdOut << "Archives: " << archivePaths.Size() << endl;
       
   577   }
       
   578   return S_OK;
       
   579 }