Jelajahi Sumber

Bug 251: Allow skipping file actually being transferred

https://winscp.net/tracker/251

Source commit: cf5b8c875424209cfb210fc3845c609047c7ae76
Martin Prikryl 9 tahun lalu
induk
melakukan
74e8caab39

+ 1 - 1
source/core/FileOperationProgress.h

@@ -12,7 +12,7 @@ enum TFileOperation { foNone, foCopy, foMove, foDelete, foSetProperties,
   foRename, foCustomCommand, foCalculateSize, foRemoteMove, foRemoteCopy,
   foGetProperties, foCalculateChecksum, foLock, foUnlock };
 // csCancelTransfer and csRemoteAbort are used with SCP only
-enum TCancelStatus { csContinue = 0, csCancel, csCancelTransfer, csRemoteAbort };
+enum TCancelStatus { csContinue = 0, csCancelFile, csCancel, csCancelTransfer, csRemoteAbort };
 enum TBatchOverwrite { boNo, boAll, boNone, boOlder, boAlternateResume, boAppend, boResume };
 typedef void __fastcall (__closure *TFileOperationProgressEvent)
   (TFileOperationProgressType & ProgressData);

+ 11 - 2
source/core/FtpFileSystem.cpp

@@ -1452,10 +1452,18 @@ void __fastcall TFTPFileSystem::DoFileTransferProgress(__int64 TransferSize,
     OperationProgress->AddTransfered(Diff);
   }
 
-  if (OperationProgress->Cancel == csCancel)
+  if (OperationProgress->Cancel != csContinue)
   {
+    if (OperationProgress->Cancel == csCancelFile)
+    {
+      OperationProgress->Cancel = csContinue;
+      FFileTransferAbort = ftaSkip;
+    }
+    else
+    {
+      FFileTransferAbort = ftaCancel;
+    }
     FFileTransferCancelled = true;
-    FFileTransferAbort = ftaCancel;
     FFileZillaIntf->Cancel();
   }
 
@@ -2318,6 +2326,7 @@ bool __fastcall TFTPFileSystem::IsCapable(int Capability) const
     case fcRemoteMove:
     case fcRemoveBOMUpload:
     case fcMoveToQueue:
+    case fsSkipTransfer:
       return true;
 
     case fcPreservingTimestampUpload:

+ 1 - 0
source/core/ScpFileSystem.cpp

@@ -462,6 +462,7 @@ bool __fastcall TSCPFileSystem::IsCapable(int Capability) const
     case fcLocking:
     case fcPreservingTimestampDirs:
     case fcResumeSupport:
+    case fsSkipTransfer:
       return false;
 
     case fcChangePassword:

+ 1 - 1
source/core/SessionInfo.h

@@ -42,7 +42,7 @@ enum TFSCapability { fcUserGroupListing, fcModeChanging, fcGroupChanging,
   fcModeChangingUpload, fcPreservingTimestampUpload, fcShellAnyCommand,
   fcSecondaryShell, fcRemoveCtrlZUpload, fcRemoveBOMUpload, fcMoveToQueue,
   fcLocking, fcPreservingTimestampDirs, fcResumeSupport,
-  fcChangePassword,
+  fcChangePassword, fsSkipTransfer,
   fcCount };
 //---------------------------------------------------------------------------
 struct TFileSystemInfo

+ 20 - 3
source/core/SftpFileSystem.cpp

@@ -2075,6 +2075,7 @@ bool __fastcall TSFTPFileSystem::IsCapable(int Capability) const
     case fcMoveToQueue:
     case fcPreservingTimestampDirs:
     case fcResumeSupport:
+    case fsSkipTransfer:
       return true;
 
     case fcRename:
@@ -4846,7 +4847,15 @@ void __fastcall TSFTPFileSystem::SFTPSource(const UnicodeString FileName,
           {
             if (OperationProgress->Cancel)
             {
-              Abort();
+              if (OperationProgress->Cancel == csCancelFile)
+              {
+                OperationProgress->Cancel = csContinue;
+                THROW_SKIP_FILE_NULL;
+              }
+              else
+              {
+                Abort();
+              }
             }
           }
 
@@ -5998,9 +6007,17 @@ void __fastcall TSFTPFileSystem::SFTPSink(const UnicodeString FileName,
               OperationProgress->AddLocallyUsed(BlockBuf.Size);
             }
 
-            if (OperationProgress->Cancel == csCancel)
+            if (OperationProgress->Cancel != csContinue)
             {
-              Abort();
+              if (OperationProgress->Cancel == csCancelFile)
+              {
+                OperationProgress->Cancel = csContinue;
+                THROW_SKIP_FILE_NULL;
+              }
+              else
+              {
+                Abort();
+              }
             }
           };
 

+ 24 - 4
source/core/WebDAVFileSystem.cpp

@@ -677,6 +677,7 @@ bool __fastcall TWebDAVFileSystem::IsCapable(int Capability) const
     // Only to make double-click on file edit/open the file,
     // instead of trying to open it as directory
     case fcResolveSymlink:
+    case fsSkipTransfer:
       return true;
 
     case fcUserGroupListing:
@@ -730,6 +731,7 @@ void __fastcall TWebDAVFileSystem::DoStartup()
 void __fastcall TWebDAVFileSystem::ClearNeonError()
 {
   FCancelled = false;
+  FSkipped = false;
   FAuthenticationRequested = false;
   ne_set_error(FNeonSession, "");
 }
@@ -741,10 +743,20 @@ UnicodeString __fastcall TWebDAVFileSystem::GetNeonError()
 //---------------------------------------------------------------------------
 void __fastcall TWebDAVFileSystem::CheckStatus(int NeonStatus)
 {
-  if ((NeonStatus == NE_ERROR) && FCancelled)
+  if ((NeonStatus == NE_ERROR) && (FCancelled || FSkipped))
   {
-    FCancelled = false;
-    Abort();
+    if (FCancelled)
+    {
+      FCancelled = false;
+      FSkipped = false; // just in case
+      Abort();
+    }
+    else
+    {
+      DebugAssert(FSkipped);
+      FSkipped = false;
+      THROW_SKIP_FILE_NULL;
+    }
   }
   else
   {
@@ -2003,7 +2015,15 @@ bool __fastcall TWebDAVFileSystem::CancelTransfer()
       (FTerminal->OperationProgress != NULL) &&
       (FTerminal->OperationProgress->Cancel != csContinue))
   {
-    FCancelled = true;
+    if (FTerminal->OperationProgress->Cancel == csCancelFile)
+    {
+      FTerminal->OperationProgress->Cancel = csContinue;
+      FSkipped = true;
+    }
+    else
+    {
+      FCancelled = true;
+    }
     Result = true;
   }
   return Result;

+ 1 - 0
source/core/WebDAVFileSystem.h

@@ -158,6 +158,7 @@ private:
   UnicodeString FUserName;
   bool FActive;
   bool FHasTrailingSlash;
+  bool FSkipped;
   bool FCancelled;
   bool FStoredPasswordTried;
   bool FUploading;

+ 8 - 1
source/forms/CustomScpExplorer.cpp

@@ -1283,7 +1283,10 @@ void __fastcall TCustomScpExplorerForm::FileOperationProgress(
   // operation is being executed and we still didn't show up progress form
   if (ProgressData.InProgress && !FProgressForm)
   {
-    FProgressForm = new TProgressForm(Application, (FTransferResumeList != NULL));
+    bool AllowSkip =
+      ((ProgressData.Operation == foCopy) || (ProgressData.Operation == foMove)) &&
+      Terminal->IsCapable[fsSkipTransfer];
+    FProgressForm = new TProgressForm(Application, (FTransferResumeList != NULL), AllowSkip);
     // As progress window has delayed show now, we need to lock ourselves,
     // (at least) until then
     LockWindow();
@@ -1353,6 +1356,10 @@ void __fastcall TCustomScpExplorerForm::FileOperationProgress(
       {
         ProgressData.Cancel = FProgressForm->Cancel;
       }
+      if (FProgressForm->Cancel == csCancelFile)
+      {
+        FProgressForm->Cancel = csContinue;
+      }
       // cancel cancels even the move
       FMoveToQueue = false;
     }

+ 42 - 12
source/forms/Progress.cpp

@@ -59,7 +59,7 @@ UnicodeString __fastcall TProgressForm::ProgressStr(TFileOperationProgressType *
   return Result;
 }
 //---------------------------------------------------------------------
-__fastcall TProgressForm::TProgressForm(TComponent * AOwner, bool AllowMoveToQueue)
+__fastcall TProgressForm::TProgressForm(TComponent * AOwner, bool AllowMoveToQueue, bool AllowSkip)
     : FData(), TForm(AOwner)
 {
   FLastOperation = foNone;
@@ -76,6 +76,7 @@ __fastcall TProgressForm::TProgressForm(TComponent * AOwner, bool AllowMoveToQue
   FStarted = Now();
   FModalBeginHooked = false;
   FModalLevel = -1;
+  FPendingSkip = false;
   UseSystemSettings(this);
 
   if (CustomWinConfiguration->OperationProgressOnTop)
@@ -99,6 +100,7 @@ __fastcall TProgressForm::TProgressForm(TComponent * AOwner, bool AllowMoveToQue
 
   SetGlobalMinimizeHandler(this, GlobalMinimize);
   MoveToQueueItem->Visible = AllowMoveToQueue;
+  SkipItem->Visible = AllowSkip;
 }
 //---------------------------------------------------------------------------
 __fastcall TProgressForm::~TProgressForm()
@@ -126,8 +128,9 @@ void __fastcall TProgressForm::UpdateControls()
   bool TransferOperation =
     ((FData.Operation == foCopy) || (FData.Operation == foMove));
 
-  CancelItem->Enabled = !FReadOnly && (FCancel == csContinue);
-  MoveToQueueItem->Enabled = !FMoveToQueue && (FCancel == csContinue);
+  CancelItem->Enabled = !FReadOnly && (FCancel < csCancel);
+  SkipItem->Enabled = !FReadOnly && (FCancel < csCancelFile) && !FPendingSkip;
+  MoveToQueueItem->Enabled = !FMoveToQueue && (FCancel == csContinue) && !FPendingSkip;
   CycleOnceDoneItem->Visible =
     !FReadOnly &&
     (FData.Operation != foCalculateSize) &&
@@ -141,6 +144,7 @@ void __fastcall TProgressForm::UpdateControls()
     UnicodeString Animation;
     UnicodeString CancelCaption = Vcl_Consts_SMsgDlgCancel;
     int MoveToQueueImageIndex = -1;
+    FPendingSkip = false; // just in case
 
     int MoveTransferToQueueImageIndex;
     if (FData.Side == osRemote)
@@ -242,24 +246,30 @@ void __fastcall TProgressForm::UpdateControls()
     FLastTotalSizeSet = FData.TotalSizeSet;
   }
 
+  UnicodeString FileCaption;
   if ((FData.Operation == foCalculateSize) && DebugAlwaysTrue(!FData.Temp))
   {
     if (FData.Side == osRemote)
     {
-      FileLabel->Caption = UnixExtractFileDir(FData.FullFileName);
+      FileCaption = UnixExtractFileDir(FData.FullFileName);
     }
     else
     {
-      FileLabel->Caption = ExtractFileDir(FData.FullFileName);
+      FileCaption = ExtractFileDir(FData.FullFileName);
     }
   }
   else if ((FData.Side == osRemote) || !FData.Temp)
   {
-    FileLabel->Caption = FData.FileName;
+    FileCaption = FData.FileName;
   }
   else
   {
-    FileLabel->Caption = ExtractFileName(FData.FileName);
+    FileCaption = ExtractFileName(FData.FileName);
+  }
+  if (FileLabel->Caption != FileCaption)
+  {
+    FileLabel->Caption = FileCaption;
+    FPendingSkip = false;
   }
   int OverallProgress = FData.OverallProgress();
   FOperationProgress->Position = OverallProgress;
@@ -483,11 +493,7 @@ void __fastcall TProgressForm::CancelOperation()
         ACancel = csCancel;
       }
 
-      if (FCancel < ACancel)
-      {
-        FCancel = ACancel;
-        UpdateControls();
-      }
+      SetCancelLower(ACancel);
     }
     __finally
     {
@@ -668,3 +674,27 @@ void __fastcall TProgressForm::SpeedComboBoxItemClick(TObject * Sender)
   ClickToolbarItem(DebugNotNull(dynamic_cast<TTBCustomItem *>(Sender)), false);
 }
 //---------------------------------------------------------------------------
+void __fastcall TProgressForm::SetCancel(TCancelStatus value)
+{
+  if (DebugAlwaysTrue(FCancel == csCancelFile) &&
+      DebugAlwaysTrue(value == csContinue))
+  {
+    FPendingSkip = true;
+  }
+  FCancel = value;
+}
+//---------------------------------------------------------------------------
+void __fastcall TProgressForm::SetCancelLower(TCancelStatus ACancel)
+{
+  if (FCancel < ACancel)
+  {
+    FCancel = ACancel;
+    UpdateControls();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TProgressForm::SkipItemClick(TObject * /*Sender*/)
+{
+  SetCancelLower(csCancelFile);
+}
+//---------------------------------------------------------------------------

+ 153 - 0
source/forms/Progress.dfm

@@ -224,6 +224,11 @@ object ProgressForm: TProgressForm
           ShortCut = 27
           OnClick = CancelItemClick
         end
+        object SkipItem: TTBXItem
+          Caption = '&Skip this file'
+          ImageIndex = 9
+          OnClick = SkipItemClick
+        end
         object MinimizeItem: TTBXItem
           Caption = '&Minimize'
           ImageIndex = 1
@@ -1276,6 +1281,34 @@ object ProgressForm: TProgressForm
           4CA770F023E247E9935CF8559360FD11C4C2F146AF2960E46BEBEB979FA48944
           94E49BAC294FF977C448081E850D01C9B8C95B1EA8FFB7FE0BBE1B23158EBA00
           EF0000000049454E44AE426082}
+      end
+      item
+        Background = clWindow
+        Name = 'Skip'
+        PngImage.Data = {
+          89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF
+          61000000097048597300000EC300000EC301C76FA864000002914944415478DA
+          75D34B4C13511406E07F6CA46204527CA0883C943410D044A20B45716182B232
+          461EF2900635EACA68448152DAA246346A5CA889D0828A12252582ECD4104104
+          36206A78B868B03C52194A99B6D3A1653AEDB590588243CFEADE7B6EBE9CDC73
+          2E75E9613B41D0A07AADACEB98419BEB0C7AE3E2FD36F2ACF4047861A5B3B8EB
+          FE6182E1F3CF5E86E38322D4857BEF48ED8D9370797CA2A4C3E9C2B0C982E64F
+          DFFBE17265D5690B6645C0F99A16A22B3F856B759D2B12D58AC3D82095806638
+          0CF991B71F0686F515D9A922E0DC1D03D1556483757945150C1A69F48D4C2DAD
+          8D6313A857E65022E0ECED66A253E6E2BAAE13C122634F2CDA3BFAD1A0CA1303
+          2537DF109DEA346C9C103854188E234E9688ABE95AC84237C1C50B503F6DC373
+          75FE12105723EBA6401D22205F29457513D1ABF251A6EF0A00ADF66C448487C3
+          E958408AB408B525B750F6A8052F35854B407C4D2459171102B79D0755AC794D
+          F45505B03A972B48D76FC33EF97ECC0B1CC6A6C710BD360161E62CB46A2A0340
+          58D47AB0F43CA833558D44A72E82B261B982F7CE1C24CB93102291C2477C98E5
+          2CA0FF58E0E1F85AF0A41CD2354C647C38E64C0E5085AA1744AF2EC60CEB0900
+          471B631027DF0E0925099C798917369B0D8C99657C02914525CB408F32A00A94
+          0D44A75160C6B10C6436C5624B924CD40D37CBC33EC9B2C2822F2C266D33A6BE
+          5940E597D78BFEC240B4123B766F0DEC05DE0BEBB80DAC957BE55EF094864A43
+          E8C403B130F64D40D4D7C5487E1C4DE4693B4108C1AC99C1F4383D22F0C2E589
+          4A7BC7BF47DC7B2415835D43AB03294F62C8AEA404187FFD76CF3BB86A13CF3C
+          801681362D021999E9F8F2B1677520FEEEC651FF908C78045C31ABE626FFCFFB
+          07A9C73F4807FD777AFF023A452DD65EA00DDF0000000049454E44AE426082}
       end>
     Left = 40
     Top = 240
@@ -2317,6 +2350,38 @@ object ProgressForm: TProgressForm
           8E6CA8DFF31C74CAF97076F5865AF50B138A513D4C2E35746A8FB032E1020533
           50EC5F6CB1C11ACBE5A4C4CD866BFD8AED14BDAA596D9011B6B4741DFB0F6993
           87E8E4125E890000000049454E44AE426082}
+      end
+      item
+        Background = clWindow
+        Name = 'Skip'
+        PngImage.Data = {
+          89504E470D0A1A0A0000000D49484452000000140000001408060000008D891D
+          0D000000097048597300000EC300000EC301C76FA864000003034944415478DA
+          8DD36B4853611807F0FFB1518262384550D4940C0DB3A2820A34D4483332220C
+          03112F681A5AA2A6585EC812F621F2924E538C2E1F02A320122F0856A0A68248
+          60699A695E9A3AB7E96E7AB67379DB0CA5B91DD7FBE5709EF3F0E37FDEF779A9
+          BCC68F047617F5996649747D5684CE6EA7197C743D1C44803597DFF64E60606C
+          E1BFD02D90E184837EF9B98499252DFAC764C33A90E8A68C08852098DBD04D2A
+          33234133BC20B86E306252B68A5F4B1AF48FCE7FABCA3C7B4810BC55D745AAB3
+          CE21AFA1DB6643456A84299D1A7DA3BF6130B2F831B78CC7D9519420985DD341
+          6A6E9E878EE676DC6CDEB4C94ACD3AAA5FF7A12E274618BC51D94A6A732E22B7
+          BE0BF656794A248A9B3AD190172B0C663C7C476A732F61758DB5FA78BB3D096B
+          8C1E856724F0733DB0512B6D6C4763C1650BD04F22EE373D4E11905E2A4DF286
+          480BAE20AFAEC30A6C5B4F84C87117788303024571789A5E89B2FA5634DF89DB
+          0E124797DDA0354650A9152D445A78154A3D6305863EF1849FAF2F0CAC11F265
+          3982C447E12C8B454B498E15E8E4EE08BD8206955CFE8A488BE2915FDB660576
+          32C9D81FE00F2F276F2869A5696CA640AB59703C9B3F635455E31EF84D70AF97
+          13D4323DA8C4B297A4FE6E0296B5D609239BBDE017E80BB73DEE1BEF2C61B1A4
+          5D8062510596E6068C2C932C2BD58E9B41B1BF0B54D31A5009C5CF88B4381185
+          B5EFADC02E3E0DBEC19E7012395BD4698E8642A18456AE37802345A01CAA3C02
+          5D211F5F0175ADA899484B9320D758278C79EE0DEFC31E1039886CCEA55EA787
+          724AB371E13D43DCB030A204155FD844EA4A536CFEF28517DEF039EE6173DEF4
+          2A1A2BB31A8EE7F8720A0EF77D4E78606E48FE17141AD241D722049CF6B1A871
+          0C07F9D40A74AAB5AF262C65AE443D64DE4373DF64FF1C04277EF3F442C282B6
+          DED50A0DE6271739CEC84B4CA7FCC074CAC67FFB467ABEDB074F461E03CBB098
+          1E9F8552BEB295CA56DFE08761FB60F09183181F9BE0180367916A7B5F785418
+          3E75F5EC0CEE9388BB298A8839964FDF9ECAB2CFB58702156ABECB7F00A76B93
+          004DC89DE00000000049454E44AE426082}
       end>
     Left = 128
     Top = 240
@@ -3408,6 +3473,46 @@ object ProgressForm: TProgressForm
           10F832FF1D267FF45333307D66103EB6D45B9857F438B873F9FC9FEC5C813145
           E7991FC431EFED584F70BBE0176C843AEF991070580000000049454E44AE4260
           82}
+      end
+      item
+        Background = clWindow
+        Name = 'Skip'
+        PngImage.Data = {
+          89504E470D0A1A0A0000000D4948445200000018000000180806000000E0773D
+          F8000000097048597300000EC300000EC301C76FA864000003F34944415478DA
+          8D957B5015551CC7BF6B06DC5198404AF4324031E8845856E4184E51D6C454E3
+          A8F9024588CC5E3235310408172E5813D338092310726FF8EE41189593D3F007
+          90A9A80D3A56231924DC7BE325DCD7DEBDCFBDBB7B5A96C109EF6B7FFF9CEF9E
+          DFF7FC3EE79CDD3D872A3CF43381CC108DBDC4CC647D5EBDCD2E770CB5B7FE2C
+          697CFF6539C5D1D6D38FF37FE87A6175C88650EF1EFC89347DF00A888C755CB8
+          318271931DE7AEDDEAE504B24153BCDE1812F0F667674873D17A88034202F4B7
+          698C8980711383EEABB7FE1427B52E14847AEBC00FE470F106B01C41D3F77D01
+          8D7B37A54310788C8A00096264D07575E086A678635A50C09B9F769096924D70
+          7985902BF8CB6042CF7503387EC63BA41B81A6F4552A28E08DDAD34453B6190E
+          0F8FA6EFAE847E11623C999600A7DB8B1FBBAFE18B7D5B8203767FD24EB4655B
+          C0B87959C5678371B150B79C456BF9D6E080D73F6E23DAF26DA05D1C1ADB2FCA
+          2A5EB875ADD416D775E0886A7B7040C1FEAF89B6221B5627E7D730E598804004
+          2C5EB8D427F761DD691CADCA090EC8AFF95204E4C022021ABF39E76368B7EC01
+          4B9C7844B119698A8DA0300F85D99952AEA4AE1DC7D53BE700926A632E89CD9A
+          694D407AA93CF529A255ED80D9E17F054F35C721222A0CACD38B94E834543C57
+          8F94452BA45C69DDB73851937B378084478649DAC3B0A076559E209AAA5C98EC
+          5E347CD5E50368B3E52239291911F315189A1C849BF122EFF1F750F044112AEB
+          3B70F2A33C1FC0824511927698DCA076AA8E114DE52E18EDFE5790A959828792
+          93A05C180F9667A1B7E9609A32215E9182C8D12C9CD9AFF601442D592069DBB8
+          03D48EF223A4A52A1F4671660DA73A7D001DEE02242D4B40AC22F64E9F8DB561
+          C23C0EC6E882C0710729D65AA1AB867B16109D1829F92C7A06544E592B39ACCE
+          C79408F0172FB42A9190BA1491F746CDE9E7090FDA6D8579C20A37CD0E8BA7E5
+          6E7D85B5671A109B729FE4310E5A4165976A4973554140C08B4795885FF900C2
+          E685FBCD738483CDCA801EB513C27219B867FEA5B8D4182937D16F06B5BD4443
+          9A82005E3A160FE563F723500882201677C061748F783D646D5838A557AE9AF1
+          8F5E9F9A0120485C892E43E2EA38BF3917ED81699806E7115A19D65C64AE866D
+          7A8B12562F96F286DF6E23E85F38FBD296673C3877FFC5D37472C8047A921926
+          44D863A8A0BBFEEF5F969124E9815E9D3CC0AACC15779E69A30D86C131C2B37C
+          03EB31EF1BAB86F36EFFA3CFA44AFAF75FFBE501D63C9F0EAF97C3F04D3DCC93
+          96BFC173AFE954B6CB01FDEBD2257DB9BB4F1EE0E195CB3170F31F9E67B90360
+          2D35B3DF7C20FFB3594F4BFA97CEF3B2009DE2DD1B235E97EFFCABA2FB42F913
+          6BA32F52A032A6B578D85DF80F3183F7BE81CC2F4D0000000049454E44AE4260
+          82}
       end>
     Left = 208
     Top = 240
@@ -4599,6 +4704,54 @@ object ProgressForm: TProgressForm
           50AB886476204B3CF50899B41FF73B6E992D6E1859D477234BCDF88F89D9115A
           C6F1B6E6543A38B904D8DA39E2EFAEDB7314373E818500E81196A5D43A7E6AA5
           2A804E711DE03FC39723EE05E751780000000049454E44AE426082}
+      end
+      item
+        Background = clWindow
+        Name = 'Skip'
+        PngImage.Data = {
+          89504E470D0A1A0A0000000D4948445200000020000000200806000000737A7A
+          F4000000097048597300000EC300000EC301C76FA864000005024944415478DA
+          C5967B704C571CC7BF4BDA151A926852D9289161A4A3CA4C4DCD08518F694AAB
+          4F453CABAA14F52A91C722541B7D68454462D38452A34A5A0CD3315488C73093
+          3F8266AC5162B3F290DDECEBEEEEDD7BEFDE7B7AB2DB5CCF64F76EFEF0DBD97B
+          E677CFEF3BE773BEE7CCB94785A71CAA96C78AA2D344B192E022279953772C9E
+          E2EC30C0F2C253E4A785E3148C0D1C38A3C7257DDD4541B27408C207B0ACE024
+          D9BA68BC22E1DF55B5B0321E9CBF66BC282074081FC0D2FC13246FC91B10A5E0
+          57A2DA6086C9CEC2E26071EEAAA192E3F809BA5593CC21012CD9F617C9FFE24D
+          0862F000CD76379AE8BF15A2E24ACD359EF78E550AE10358BCF538D9BE6C2238
+          2F4146F1E980A2CDF3C722AC1381C9C6CA102D40155535D505CB27BEAC1860D1
+          8FC748C18AB7C00A52F00ED059EB6B9B71ABC1469DF3EBAEFF5B871D2BDF5629
+          0658B8E528295C39092E4E82B6B45C89DE17196923C1B01CB6EC3F8BA22FDF51
+          0EB0E0FBC3A468D5BB603CA2E2C11F8CD5DB8F61E7EAF794037CF6ED1F6467FA
+          FBB0B32272769F513C70CEC7AFFBDAF4FCA3D0ADF94039C0A7B987882EE343D8
+          DCDE0E3990BEED087ECE9CAC1C60DE370729C064585D5E6CDA7B56F1C0DA59A3
+          7DED9AFCC328C9FA4839C0279B0E105DD614589C42871CC8D8F6274AB5539503
+          CCDDB89FE8B2A7A199026CDE57D1AEE006570681B891A49E8C3055B87FE01929
+          BE3633AF0CBBD6A5B509D03737EA9C0AAA91AD390139EF2B9EB3611F29CE4E83
+          390807928B345085A9D0F3D958AC4AD98C5109A9725F66DE21FCB27E469B0009
+          B9D1441DF18C9C738CE07760F6FA5F894E3B1D66FAE287DFCEB50B70D83E0511
+          D1DDC00B02789780B8CEAFA1787A297A74894656DE41ECD930B35D80F028B59C
+          B356CE0F306BED1EA25B3B134D4C600746EBE2A0898F43BFC8FEB869D1C36AB3
+          422D76C5B2E4AF51715CC4DEAF66B70BF05C4CB89C3B4DAC1F608676370598E5
+          03C8FBFD7C4007347D7B6140541208A1DF03F73D186D06B86D1CBA7BFAE31EF4
+          090D5AFAA20D80EE9A6E72EEA877F901A66795929DEBE6A0C911D88171251A68
+          125F409F8804F91D2FF26870D7C16AB181B5F32C254B3770D61DC881F4284054
+          9F0839B7D6327E80B48C1252D402401D2828BB10D081F801B188ED1AF7589F53
+          60E846368131B9E165C54BF47E31DF986DFDE741809E893DE4FAE6DB763FC0B4
+          35C5A470DDDCA0F640EAAE7868926211A98E7A62BF4424308203768B032E13FD
+          BE8AD246036FFB8EBAC1B700C40C8C946B4D376C7E80A9E93A5240014C41004C
+          D8DD1BF18362101ED6B5DD3A2FF1C2ED71C3DEE004E7E4AB5C1EEBA86EEA68A6
+          D7A068B9A6B1DA721F20E0C8FFC7E5A80CC40F8D4127FA7B3054AA87373FF1B9
+          21C2656161333282E8E1123AABBBD469863C2FD7D45F3143D1B1D9BA8EBD5F8D
+          0D58E7E545580D0C3C76BE522464DEDD6CEBD516ED8BC3EE6B8D954DA101240C
+          8F6BB39F1EAF601ADDB01A194E1289D6C05BB6D2F5F7B66AFB0DD7C8B53597EB
+          43031838A2DF13FB38378FC65B66B00E4F39BD62CF33ACB5D73CAA4D4A4E9473
+          FD85DBA1010C1E95F4F0ACE981D4544BAFE9772D0C9DF50A4396A5A42DED2B29
+          2FC9F9D58AEBA1010C1B3344CE9D0E170CFABB605DEC1170FCC23B39AEC6F6B5
+          43E5BCB2BC2A348011E387439224186ED6A2DED8D84CF7FB0243A6BD2C186D32
+          D5B6C6855397430318326C306E54DF04CBB27B551C597A27C7660B563B263545
+          CECB4F542807E89B1B5D49173D9210E9F3DA6CFB4965DAC72F24FF01A3F292B3
+          91577DFB0000000049454E44AE426082}
       end>
     Left = 288
     Top = 240

+ 7 - 2
source/forms/Progress.h

@@ -66,6 +66,7 @@ __published:
   TPngImageList *ImageList144;
   TPngImageList *ImageList192;
   TApplicationEvents *ApplicationEvents;
+  TTBXItem *SkipItem;
   void __fastcall UpdateTimerTimer(TObject *Sender);
   void __fastcall FormShow(TObject *Sender);
   void __fastcall FormHide(TObject *Sender);
@@ -81,9 +82,11 @@ __published:
           int AIndex, int &ImageIndex);
   void __fastcall ApplicationModalBegin(TObject * Sender);
   void __fastcall SpeedComboBoxItemClick(TObject *Sender);
+  void __fastcall SkipItemClick(TObject *Sender);
 
 private:
   TCancelStatus FCancel;
+  bool FPendingSkip;
   bool FMoveToQueue;
   TFileOperationProgressType FData;
   bool FDataGot;
@@ -126,16 +129,18 @@ protected:
   bool __fastcall ReceiveData(bool Force, int ModalLevelOffset);
   void __fastcall Minimize(TObject * Sender);
   virtual void __fastcall Dispatch(void * Message);
+  void __fastcall SetCancelLower(TCancelStatus ACancel);
+  void __fastcall SetCancel(TCancelStatus value);
 
   static bool __fastcall IsIndeterminateOperation(TFileOperation Operation);
 
 public:
   static UnicodeString __fastcall ProgressStr(TFileOperationProgressType * ProgressData);
 
-  virtual __fastcall TProgressForm(TComponent * AOwner, bool AllowMoveToQueue);
+  virtual __fastcall TProgressForm(TComponent * AOwner, bool AllowMoveToQueue, bool AllowSkip);
   virtual __fastcall ~TProgressForm();
   void __fastcall SetProgressData(TFileOperationProgressType & AData);
-  __property TCancelStatus Cancel = { read = FCancel };
+  __property TCancelStatus Cancel = { read = FCancel, write = SetCancel };
   __property bool MoveToQueue = { read = FMoveToQueue };
   __property TOnceDoneOperation OnceDoneOperation = { read=GetOnceDoneOperation, write=SetOnceDoneOperation };
   __property bool AllowMinimize = { read=GetAllowMinimize, write=SetAllowMinimize };