From 6128789b97f3cba634ea2d26146d1a83e53b99cd Mon Sep 17 00:00:00 2001 From: softworkz Date: Fri, 17 Apr 2026 07:26:21 +0200 Subject: [PATCH] Use Chained Extraction in Explorer context menu actions This commit unconditionally enables chained extraction for explorer integration (context menus). It's still possible to choose "Open" instead and extract the tar only. --- CPP/7zip/UI/Explorer/ContextMenu.cpp | 64 ++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 0630d78..25f384d 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -444,6 +444,56 @@ static bool IsItArcExt(const UString &ext) return false; } +static bool IsTarCompoundExtension(const UString &ext) +{ + return ext.IsEqualTo_Ascii_NoCase("gz") + || ext.IsEqualTo_Ascii_NoCase("gzip") + || ext.IsEqualTo_Ascii_NoCase("bz2") + || ext.IsEqualTo_Ascii_NoCase("bzip2") + || ext.IsEqualTo_Ascii_NoCase("xz") + || ext.IsEqualTo_Ascii_NoCase("zst") + || ext.IsEqualTo_Ascii_NoCase("zstd") + || ext.IsEqualTo_Ascii_NoCase("z"); +} + +static bool GetChainedExtractFolderName(const UString &arcName, UString &folderName) +{ + int dotPos = arcName.ReverseFind_Dot(); + if (dotPos < 0) + return false; + + const UString ext = arcName.Ptr(dotPos + 1); + UString base = arcName.Left(dotPos); + + if (ext.IsEqualTo_Ascii_NoCase("tgz") + || ext.IsEqualTo_Ascii_NoCase("tpz") + || ext.IsEqualTo_Ascii_NoCase("tbz") + || ext.IsEqualTo_Ascii_NoCase("tbz2") + || ext.IsEqualTo_Ascii_NoCase("txz") + || ext.IsEqualTo_Ascii_NoCase("tzst") + || ext.IsEqualTo_Ascii_NoCase("taz")) + { + base.TrimRight(); + folderName = Get_Correct_FsFile_Name(base); + return true; + } + + if (!IsTarCompoundExtension(ext)) + return false; + + dotPos = base.ReverseFind_Dot(); + if (dotPos < 0) + return false; + + if (!StringsAreEqualNoCase_Ascii(base.Ptr((unsigned)(dotPos + 1)), "tar")) + return false; + + base.DeleteFrom((unsigned)dotPos); + base.TrimRight(); + folderName = Get_Correct_FsFile_Name(base); + return true; +} + UString GetSubFolderNameForExtract(const UString &arcName); UString GetSubFolderNameForExtract(const UString &arcName) { @@ -831,9 +881,14 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) baseFolder = _dropPath; - UString specFolder ('*'); + UString specFolderName ('*'); if (_fileNames.Size() == 1) - specFolder = GetSubFolderNameForExtract(fs2us(fi0.Name)); + { + const UString arcName = fs2us(fi0.Name); + if (!GetChainedExtractFolderName(arcName, specFolderName)) + specFolderName = GetSubFolderNameForExtract(arcName); + } + UString specFolder = specFolderName; specFolder.Add_PathSepar(); if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) @@ -861,7 +916,7 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UString s; cmi.Folder = baseFolder + specFolder; AddCommand(kExtractTo, s, cmi); - MyFormatNew_ReducedName(s, specFolder); + MyFormatNew_ReducedName(s, specFolderName); Set_UserString_in_LastCommand(s); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); } @@ -1285,7 +1340,8 @@ HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi) ExtractArchives(_fileNames, cmi.Folder, (cmdID == kExtract), // showDialog (cmdID == kExtractTo) && _elimDup.Val, // elimDup - _writeZone + _writeZone, + true ); break; }