View Issue Details

IDProjectCategoryView StatusLast Update
0001536Double CommanderGraphical user interfacepublic2021-09-05 15:10
Reportercordylus Assigned ToAlexx2000  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
ProjectionnoneETAnone 
Product Version0.7.5 
Target Version0.9.0Fixed in Version0.9.0 
Summary0001536: Добавить "Сравнить" в диалог "Заменить ... файлом ...?"
DescriptionДиалог, который открывается при попытке скопировать или переместить файл, когда в месте назначения уже есть файл с таким именем.
TagsNo tags attached.
Attached Files
bug1536-preview1.patch (50,831 bytes)   
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -677,13 +683,20 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +731,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +846,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -163,6 +166,23 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+  TargetFile := TFile.Create('');
+  TargetFile.FullPath := TargetFilePath;
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
 begin
   // Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -75,7 +73,13 @@
 procedure TfrmMsg.ButtonClick(Sender: TObject);
 begin
   iSelected:= (Sender as TComponent).Tag;
-  Close;
+  if (iSelected < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(iSelected);
+  end
+  else
+    Close;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +88,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -94,7 +94,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -669,6 +669,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview1.patch (50,831 bytes)   
bug1536-preview2.patch (51,687 bytes)   
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +111,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +731,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +846,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -163,6 +166,23 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+  TargetFile := TFile.Create('');
+  TargetFile.FullPath := TargetFilePath;
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
 begin
   // Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -75,7 +73,13 @@
 procedure TfrmMsg.ButtonClick(Sender: TObject);
 begin
   iSelected:= (Sender as TComponent).Tag;
-  Close;
+  if (iSelected < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(iSelected);
+  end
+  else
+    Close;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +88,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -94,7 +94,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -669,6 +669,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview2.patch (51,687 bytes)   
bug1536-preview3.patch (52,019 bytes)   
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +111,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +731,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +846,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -163,6 +166,23 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+  TargetFile := TFile.Create('');
+  TargetFile.FullPath := TargetFilePath;
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
 begin
   // Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,12 +17,11 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
+    procedure HandleAction(aTag: PtrInt);
     procedure ButtonClick(Sender:TObject);
     procedure ButtonOtherClick(Sender:TObject);
     procedure MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -44,7 +43,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -72,10 +71,23 @@
   end;
 end;
 
+procedure TfrmMsg.HandleAction(aTag: PtrInt);
+begin
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
+end;
+
 procedure TfrmMsg.ButtonClick(Sender: TObject);
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  HandleAction((Sender as TComponent).Tag);
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +96,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    HandleAction((Sender as TButton).Tag);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -94,7 +94,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -669,6 +669,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview3.patch (52,019 bytes)   
bug1536-preview4.patch (52,018 bytes)   
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +111,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +731,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +846,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -163,6 +166,23 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+  TargetFile := TFile.Create('');
+  TargetFile.FullPath := TargetFilePath;
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
 begin
   // Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -94,7 +94,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -669,6 +669,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +683,7 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    OperationsManager.AddOperationModal(Operation);
 
     Exit(pdrInCallback);
   end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview4.patch (52,018 bytes)   
bug1536-preview5.patch (52,919 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -269,7 +269,7 @@
     FWaitData := WaitData;
     edtFileNameLeft.Text:= FileNameLeft;
     edtFileNameRight.Text:= FileNameRight;
-    FShowIdentical:= actAutoCompare.Checked;
+    FShowIdentical:= False;//actAutoCompare.Checked;
     actBinaryCompare.Checked:= not (FileIsText(FileNameLeft) and FileIsText(FileNameRight));
     if actBinaryCompare.Checked then
       actBinaryCompareExecute(actBinaryCompare)
@@ -278,7 +278,8 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    //if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    ShowModal;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +111,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +731,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +846,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -163,6 +166,23 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+  TargetFile := TFile.Create('');
+  TargetFile.FullPath := TargetFilePath;
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
 begin
   // Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -94,7 +94,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -669,6 +669,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +683,7 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    OperationsManager.AddOperationModal(Operation);
 
     Exit(pdrInCallback);
   end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview5.patch (52,919 bytes)   
bug1536-preview6.patch (56,556 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -269,7 +269,7 @@
     FWaitData := WaitData;
     edtFileNameLeft.Text:= FileNameLeft;
     edtFileNameRight.Text:= FileNameRight;
-    FShowIdentical:= actAutoCompare.Checked;
+    FShowIdentical:= False;//actAutoCompare.Checked;
     actBinaryCompare.Checked:= not (FileIsText(FileNameLeft) and FileIsText(FileNameRight));
     if actBinaryCompare.Checked then
       actBinaryCompareExecute(actBinaryCompare)
@@ -278,7 +278,8 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    //if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    ShowModal;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesource.pas	(working copy)
@@ -39,7 +39,7 @@
       function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
 
       class function CreateFile(const APath: String): TFile; override;
-      class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+      class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 
       procedure Reload(const PathsToReload: TPathsArray); override;
       function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
   end;
 end;
 
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
-  AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+  AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 var
   AFile: PGFile;
   ATarget: Pgchar;
   AFileType: TGFileType;
   ASymlinkInfo: PGFileInfo;
+  OwnFolder: Boolean = False;
 begin
   Result:= CreateFile(APath);
   Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
     end
   else if AFileType =  G_FILE_TYPE_SYMBOLIC_LINK then
     begin
+      if not Assigned(AFolder) then
+      begin
+        AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+        OwnFolder:= True;
+      end;
+
       ATarget:= g_file_info_get_symlink_target(AFileInfo);
       AFile:= g_file_get_child(AFolder, ATarget);
 
@@ -143,6 +150,8 @@
         g_object_unref(ASymlinkInfo);
       end;
       g_object_unref(PGObject(AFile));
+      if OwnFolder then
+        g_object_unref(PGObject(AFolder));
     end
   else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
   begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetInfo: PGFileInfo;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +112,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
 
           if (aFileName <> '.') and (aFileName <> '..') then
           begin
-            aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+            aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
             NewFiles.Add(aFile);
 
             if aFile.IsLink then
@@ -270,7 +277,7 @@
       while Assigned(AInfo) do
       begin
         CheckOperationState;
-        AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+        AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
         g_object_unref(AInfo);
         AddItem(aFile, CurrentNode);
         AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,29 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  TargetFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo);
+    try
+      ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+    finally
+      TargetFile.Free;
+    end;
+  end;
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +741,12 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetInfo := aTargetInfo;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +857,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +867,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas	(working copy)
@@ -72,7 +72,7 @@
           while Assigned(AInfo) do
           begin
             CheckOperationState;
-            AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+            AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
             g_object_unref(AInfo);
             FFiles.Add(AFile);
             AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -163,6 +166,23 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+  TargetFile := TFile.Create('');
+  TargetFile.FullPath := TargetFilePath;
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
 begin
   // Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -94,7 +94,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -669,6 +669,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +683,7 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    OperationsManager.AddOperationModal(Operation);
 
     Exit(pdrInCallback);
   end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview6.patch (56,556 bytes)   
bug1536-preview7.patch (58,133 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -269,7 +269,7 @@
     FWaitData := WaitData;
     edtFileNameLeft.Text:= FileNameLeft;
     edtFileNameRight.Text:= FileNameRight;
-    FShowIdentical:= actAutoCompare.Checked;
+    FShowIdentical:= False;//actAutoCompare.Checked;
     actBinaryCompare.Checked:= not (FileIsText(FileNameLeft) and FileIsText(FileNameRight));
     if actBinaryCompare.Checked then
       actBinaryCompareExecute(actBinaryCompare)
@@ -278,7 +278,8 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    //if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    ShowModal;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesource.pas	(working copy)
@@ -39,7 +39,7 @@
       function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
 
       class function CreateFile(const APath: String): TFile; override;
-      class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+      class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 
       procedure Reload(const PathsToReload: TPathsArray); override;
       function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
   end;
 end;
 
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
-  AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+  AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 var
   AFile: PGFile;
   ATarget: Pgchar;
   AFileType: TGFileType;
   ASymlinkInfo: PGFileInfo;
+  OwnFolder: Boolean = False;
 begin
   Result:= CreateFile(APath);
   Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
     end
   else if AFileType =  G_FILE_TYPE_SYMBOLIC_LINK then
     begin
+      if not Assigned(AFolder) then
+      begin
+        AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+        OwnFolder:= True;
+      end;
+
       ATarget:= g_file_info_get_symlink_target(AFileInfo);
       AFile:= g_file_get_child(AFolder, ATarget);
 
@@ -143,6 +150,8 @@
         g_object_unref(ASymlinkInfo);
       end;
       g_object_unref(PGObject(AFile));
+      if OwnFolder then
+        g_object_unref(PGObject(AFolder));
     end
   else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
   begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetInfo: PGFileInfo;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +112,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
 
           if (aFileName <> '.') and (aFileName <> '..') then
           begin
-            aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+            aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
             NewFiles.Add(aFile);
 
             if aFile.IsLink then
@@ -270,7 +277,7 @@
       while Assigned(AInfo) do
       begin
         CheckOperationState;
-        AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+        AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
         g_object_unref(AInfo);
         AddItem(aFile, CurrentNode);
         AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,42 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  TargetFileSource: IFileSource;
+  TargetFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    if FOperation is TFileSourceCopyOperation then
+      TargetFileSource := TFileSourceCopyOperation(FOperation).TargetFileSource
+    else
+      TargetFileSource := (FOperation as TFileSourceMoveOperation).TargetFileSource;
+
+    if TargetFileSource is TGioFileSource then
+      TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo)
+    else
+    begin
+      TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(FCurrentTargetFilePath));
+      TargetFile.Name := ExtractFileName(FCurrentTargetFilePath);
+    end;
+
+    try
+      ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+    finally
+      TargetFile.Free;
+    end;
+  end;
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +754,12 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetInfo := aTargetInfo;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +870,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +880,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas	(working copy)
@@ -72,7 +72,7 @@
           while Assigned(AInfo) do
           begin
             CheckOperationState;
-            AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+            AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
             g_object_unref(AInfo);
             FFiles.Add(AFile);
             AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -163,6 +166,23 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+  TargetFile := TFile.Create('');
+  TargetFile.FullPath := TargetFilePath;
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
 begin
   // Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -94,7 +94,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -267,6 +267,10 @@
 
 procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
 begin
+  writeln('--------------- differ: --------------------');
+  writeln(CompareList[0]);
+  writeln(CompareList[1]);
+  writeln('--------------- /differ --------------------');
   if gExternalTools[etDiffer].Enabled then
   begin
     if Assigned(WaitData) then
@@ -669,6 +673,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +687,7 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    OperationsManager.AddOperationModal(Operation);
 
     Exit(pdrInCallback);
   end;
@@ -792,6 +798,19 @@
 var
   I: Integer;
 begin
+  writeln('----------- prepare files: ----------------');
+  writeln('--------------- file 1 --------------------');
+  writeln(FileSource1.ClassName);
+  writeln(SelectedFiles1[0].FullPath);
+  writeln(SelectedFiles1[0].Path);
+  writeln(SelectedFiles1[0].Name);
+  writeln('--------------- file 2 --------------------');
+  writeln(FileSource2.ClassName);
+  writeln(SelectedFiles2[0].FullPath);
+  writeln(SelectedFiles2[0].Path);
+  writeln(SelectedFiles2[0].Name);
+  writeln('--------------- /files --------------------');
+
   case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
   pdrSynchronous:
     begin
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview7.patch (58,133 bytes)   
bug1536-preview8.patch (58,159 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -269,7 +269,7 @@
     FWaitData := WaitData;
     edtFileNameLeft.Text:= FileNameLeft;
     edtFileNameRight.Text:= FileNameRight;
-    FShowIdentical:= actAutoCompare.Checked;
+    FShowIdentical:= False;//actAutoCompare.Checked;
     actBinaryCompare.Checked:= not (FileIsText(FileNameLeft) and FileIsText(FileNameRight));
     if actBinaryCompare.Checked then
       actBinaryCompareExecute(actBinaryCompare)
@@ -278,7 +278,8 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    //if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    ShowModal;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesource.pas	(working copy)
@@ -39,7 +39,7 @@
       function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
 
       class function CreateFile(const APath: String): TFile; override;
-      class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+      class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 
       procedure Reload(const PathsToReload: TPathsArray); override;
       function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
   end;
 end;
 
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
-  AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+  AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 var
   AFile: PGFile;
   ATarget: Pgchar;
   AFileType: TGFileType;
   ASymlinkInfo: PGFileInfo;
+  OwnFolder: Boolean = False;
 begin
   Result:= CreateFile(APath);
   Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
     end
   else if AFileType =  G_FILE_TYPE_SYMBOLIC_LINK then
     begin
+      if not Assigned(AFolder) then
+      begin
+        AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+        OwnFolder:= True;
+      end;
+
       ATarget:= g_file_info_get_symlink_target(AFileInfo);
       AFile:= g_file_get_child(AFolder, ATarget);
 
@@ -143,6 +150,8 @@
         g_object_unref(ASymlinkInfo);
       end;
       g_object_unref(PGObject(AFile));
+      if OwnFolder then
+        g_object_unref(PGObject(AFolder));
     end
   else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
   begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetInfo: PGFileInfo;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +112,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceMoveOperation,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
 
           if (aFileName <> '.') and (aFileName <> '..') then
           begin
-            aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+            aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
             NewFiles.Add(aFile);
 
             if aFile.IsLink then
@@ -270,7 +277,7 @@
       while Assigned(AInfo) do
       begin
         CheckOperationState;
-        AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+        AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
         g_object_unref(AInfo);
         AddItem(aFile, CurrentNode);
         AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,42 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  TargetFileSource: IFileSource;
+  TargetFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    if FOperation is TFileSourceCopyOperation then
+      TargetFileSource := TFileSourceCopyOperation(FOperation).TargetFileSource
+    else
+      TargetFileSource := (FOperation as TFileSourceMoveOperation).TargetFileSource;
+
+    if TargetFileSource is TGioFileSource then
+      TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo)
+    else
+    begin
+      TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(FCurrentTargetFilePath));
+      TargetFile.Name := ExtractFileName(FCurrentTargetFilePath);
+    end;
+
+    try
+      ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+    finally
+      TargetFile.Free;
+    end;
+  end;
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +754,12 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetInfo := aTargetInfo;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +870,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +880,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas	(working copy)
@@ -72,7 +72,7 @@
           while Assigned(AInfo) do
           begin
             CheckOperationState;
-            AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+            AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
             g_object_unref(AInfo);
             FFiles.Add(AFile);
             AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -163,6 +166,23 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+  TargetFile := TFile.Create('');
+  TargetFile.FullPath := TargetFilePath;
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
 begin
   // Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -94,7 +94,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -267,6 +267,10 @@
 
 procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
 begin
+  writeln('--------------- differ: --------------------');
+  writeln(CompareList[0]);
+  writeln(CompareList[1]);
+  writeln('--------------- /differ --------------------');
   if gExternalTools[etDiffer].Enabled then
   begin
     if Assigned(WaitData) then
@@ -669,6 +673,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +687,7 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    OperationsManager.AddOperationModal(Operation);
 
     Exit(pdrInCallback);
   end;
@@ -792,6 +798,19 @@
 var
   I: Integer;
 begin
+  writeln('----------- prepare files: ----------------');
+  writeln('--------------- file 1 --------------------');
+  writeln(FileSource1.ClassName);
+  writeln(SelectedFiles1[0].FullPath);
+  writeln(SelectedFiles1[0].Path);
+  writeln(SelectedFiles1[0].Name);
+  writeln('--------------- file 2 --------------------');
+  writeln(FileSource2.ClassName);
+  writeln(SelectedFiles2[0].FullPath);
+  writeln(SelectedFiles2[0].Path);
+  writeln(SelectedFiles2[0].Name);
+  writeln('--------------- /files --------------------');
+
   case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
   pdrSynchronous:
     begin
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview8.patch (58,159 bytes)   
bug1536-preview9.patch (64,161 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -249,7 +249,7 @@
     procedure cm_SaveRight(const Params: array of string);
   end; 
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 
 implementation
 
@@ -262,7 +262,7 @@
 const
   HotkeysCategory = 'Differ';
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 begin
   with TfrmDiffer.Create(Application) do
   begin
@@ -278,7 +278,13 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    if actBinaryCompare.Checked or (FShowIdentical = False) then
+    begin
+      if Modal then
+        ShowModal
+      else
+        ShowOnTop;
+    end;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesource.pas	(working copy)
@@ -39,7 +39,7 @@
       function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
 
       class function CreateFile(const APath: String): TFile; override;
-      class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+      class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 
       procedure Reload(const PathsToReload: TPathsArray); override;
       function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
   end;
 end;
 
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
-  AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+  AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 var
   AFile: PGFile;
   ATarget: Pgchar;
   AFileType: TGFileType;
   ASymlinkInfo: PGFileInfo;
+  OwnFolder: Boolean = False;
 begin
   Result:= CreateFile(APath);
   Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
     end
   else if AFileType =  G_FILE_TYPE_SYMBOLIC_LINK then
     begin
+      if not Assigned(AFolder) then
+      begin
+        AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+        OwnFolder:= True;
+      end;
+
       ATarget:= g_file_info_get_symlink_target(AFileInfo);
       AFile:= g_file_get_child(AFolder, ATarget);
 
@@ -143,6 +150,8 @@
         g_object_unref(ASymlinkInfo);
       end;
       g_object_unref(PGObject(AFile));
+      if OwnFolder then
+        g_object_unref(PGObject(AFolder));
     end
   else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
   begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetInfo: PGFileInfo;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +112,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceMoveOperation,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
 
           if (aFileName <> '.') and (aFileName <> '..') then
           begin
-            aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+            aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
             NewFiles.Add(aFile);
 
             if aFile.IsLink then
@@ -270,7 +277,7 @@
       while Assigned(AInfo) do
       begin
         CheckOperationState;
-        AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+        AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
         g_object_unref(AInfo);
         AddItem(aFile, CurrentNode);
         AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,42 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  TargetFileSource: IFileSource;
+  TargetFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    if FOperation is TFileSourceCopyOperation then
+      TargetFileSource := TFileSourceCopyOperation(FOperation).TargetFileSource
+    else
+      TargetFileSource := (FOperation as TFileSourceMoveOperation).TargetFileSource;
+
+    if TargetFileSource is TGioFileSource then
+      TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo)
+    else
+    begin
+      TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(FCurrentTargetFilePath));
+      TargetFile.Name := ExtractFileName(FCurrentTargetFilePath);
+    end;
+
+    try
+      ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+    finally
+      TargetFile.Free;
+    end;
+  end;
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +754,12 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetInfo := aTargetInfo;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +870,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +880,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas	(working copy)
@@ -72,7 +72,7 @@
           while Assigned(AInfo) do
           begin
             CheckOperationState;
-            AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+            AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
             g_object_unref(AInfo);
             FFiles.Add(AFile);
             AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -175,6 +178,24 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
 begin
   Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +606,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -56,7 +56,7 @@
                                    State: TFileSourceOperationState);
   end;
 
-  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
   // Callback may be called either asynchoronously or synchronously (for modal operations)
   // pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
   TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 
 procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
                           FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc); overload;
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False); overload;
 
 procedure RunExtDiffer(CompareList: TStringList);
 
@@ -82,7 +84,7 @@
 procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
 
 procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
 procedure ShowViewerByGlob(const sFileName: String);
 procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +96,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -265,8 +267,12 @@
     ShowDiffer(LeftName, RightName);
 end;
 
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 begin
+  writeln('--------------- differ: --------------------');
+  writeln(CompareList[0]);
+  writeln(CompareList[1]);
+  writeln('--------------- /differ --------------------');
   if gExternalTools[etDiffer].Enabled then
   begin
     if Assigned(WaitData) then
@@ -275,7 +281,7 @@
       RunExtDiffer(CompareList);
   end
   else
-    ShowDiffer(CompareList[0], CompareList[1], WaitData);
+    ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
 end;
 
 procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -635,7 +641,8 @@
 { PrepareData }
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 var
   aFile: TFile;
   I: Integer;
@@ -669,6 +676,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +690,10 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    if Modal then
+      OperationsManager.AddOperationModal(Operation)
+    else
+      OperationsManager.AddOperation(Operation);
 
     Exit(pdrInCallback);
   end;
@@ -762,6 +774,7 @@
   protected
     FFunc: TToolDataPreparedProc;
     FCallOnFail: Boolean;
+    FModal: Boolean;
     FFailed: Boolean;
     FFileList1: TStringList;
     FFileList2: TStringList;
@@ -777,7 +790,8 @@
   public
     constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
     procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                      FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                      FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                      Modal: Boolean = False);
     destructor Destroy; override;
   end;
 
@@ -788,11 +802,27 @@
 end;
 
 procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                                       FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                                       FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                                       Modal: Boolean = False);
 var
   I: Integer;
 begin
-  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+  writeln('----------- prepare files: ----------------');
+  writeln('--------------- file 1 --------------------');
+  writeln(FileSource1.ClassName);
+  writeln(SelectedFiles1[0].FullPath);
+  writeln(SelectedFiles1[0].Path);
+  writeln(SelectedFiles1[0].Name);
+  writeln('--------------- file 2 --------------------');
+  writeln(FileSource2.ClassName);
+  writeln(SelectedFiles2[0].FullPath);
+  writeln(SelectedFiles2[0].Path);
+  writeln(SelectedFiles2[0].Name);
+  writeln('--------------- /files --------------------');
+
+  FModal := Modal;
+
+  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
   pdrSynchronous:
     begin
       FFileList1 := TStringList.Create;
@@ -804,7 +834,7 @@
     begin
       try
         if FCallOnFail then
-          FFunc(nil, nil);
+          FFunc(nil, nil, FModal);
       finally
         Free;
       end;
@@ -812,7 +842,7 @@
     end;
   end;
 
-  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
   pdrSynchronous:
     begin
       FFileList2 := TStringList.Create;
@@ -886,7 +916,7 @@
     if FFailed then
     begin
       if FCallOnFail then
-        FFunc(nil, nil);
+        FFunc(nil, nil, FModal);
       Exit;
     end;
     if Assigned(FFileList2) then
@@ -897,10 +927,10 @@
       WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
       FWaitData1 := nil;
       FWaitData2 := nil;
-      FFunc(FFileList1, WaitData);
+      FFunc(FFileList1, WaitData, FModal);
     end
     else
-      FFunc(FFileList1, nil);
+      FFunc(FFileList1, nil, FModal);
   finally
     Free;
   end;
@@ -936,7 +966,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc);
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False);
 var Files1, Files2: TFiles;
 begin
   Files1 := TFiles.Create(File1.Path);
@@ -946,7 +977,7 @@
     try
       Files2.Add(File2.Clone);
       with TToolDataPreparator2.Create(FunctionToCall) do
-        Prepare(FileSource1, Files1, FileSource2, Files2);
+        Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
     finally
       Files2.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview9.patch (64,161 bytes)   
bug1536-preview10.patch (64,027 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -249,7 +249,7 @@
     procedure cm_SaveRight(const Params: array of string);
   end; 
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 
 implementation
 
@@ -262,7 +262,7 @@
 const
   HotkeysCategory = 'Differ';
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 begin
   with TfrmDiffer.Create(Application) do
   begin
@@ -278,7 +278,13 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    if actBinaryCompare.Checked or (FShowIdentical = False) then
+    begin
+      if Modal then
+        ShowModal
+      else
+        ShowOnTop;
+    end;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesource.pas	(working copy)
@@ -39,7 +39,7 @@
       function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
 
       class function CreateFile(const APath: String): TFile; override;
-      class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+      class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 
       procedure Reload(const PathsToReload: TPathsArray); override;
       function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
   end;
 end;
 
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
-  AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+  AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
 var
   AFile: PGFile;
   ATarget: Pgchar;
   AFileType: TGFileType;
   ASymlinkInfo: PGFileInfo;
+  OwnFolder: Boolean = False;
 begin
   Result:= CreateFile(APath);
   Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
     end
   else if AFileType =  G_FILE_TYPE_SYMBOLIC_LINK then
     begin
+      if not Assigned(AFolder) then
+      begin
+        AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+        OwnFolder:= True;
+      end;
+
       ATarget:= g_file_info_get_symlink_target(AFileInfo);
       AFile:= g_file_get_child(AFolder, ATarget);
 
@@ -143,6 +150,8 @@
         g_object_unref(ASymlinkInfo);
       end;
       g_object_unref(PGObject(AFile));
+      if OwnFolder then
+        g_object_unref(PGObject(AFolder));
     end
   else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
   begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetInfo: PGFileInfo;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +112,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
 
           if (aFileName <> '.') and (aFileName <> '..') then
           begin
-            aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+            aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
             NewFiles.Add(aFile);
 
             if aFile.IsLink then
@@ -270,7 +277,7 @@
       while Assigned(AInfo) do
       begin
         CheckOperationState;
-        AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+        AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
         g_object_unref(AInfo);
         AddItem(aFile, CurrentNode);
         AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,37 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  TargetFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    if (FOperation is TFileSourceCopyOperation) and
+       not (TFileSourceCopyOperation(FOperation).TargetFileSource is TGioFileSource) then // CopyOut detection
+    begin
+      TargetFile := TFileSourceCopyOperation(FOperation).TargetFileSource.CreateFileObject(ExtractFilePath(FCurrentTargetFilePath));
+      TargetFile.Name := ExtractFileName(FCurrentTargetFilePath);
+    end
+    else
+      TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo);
+
+    try
+      ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+    finally
+      TargetFile.Free;
+    end;
+  end;
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +749,12 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetInfo := aTargetInfo;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +865,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +875,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas	(working copy)
@@ -72,7 +72,7 @@
           while Assigned(AInfo) do
           begin
             CheckOperationState;
-            AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+            AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
             g_object_unref(AInfo);
             FFiles.Add(AFile);
             AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUIByFileObject,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -175,6 +178,24 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
 begin
   Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +607,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -56,7 +56,7 @@
                                    State: TFileSourceOperationState);
   end;
 
-  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
   // Callback may be called either asynchoronously or synchronously (for modal operations)
   // pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
   TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 
 procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
                           FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc); overload;
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False); overload;
 
 procedure RunExtDiffer(CompareList: TStringList);
 
@@ -82,7 +84,7 @@
 procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
 
 procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
 procedure ShowViewerByGlob(const sFileName: String);
 procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +96,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -265,8 +267,12 @@
     ShowDiffer(LeftName, RightName);
 end;
 
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 begin
+  writeln('--------------- differ: --------------------');
+  writeln(CompareList[0]);
+  writeln(CompareList[1]);
+  writeln('--------------- /differ --------------------');
   if gExternalTools[etDiffer].Enabled then
   begin
     if Assigned(WaitData) then
@@ -275,7 +281,7 @@
       RunExtDiffer(CompareList);
   end
   else
-    ShowDiffer(CompareList[0], CompareList[1], WaitData);
+    ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
 end;
 
 procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -635,7 +641,8 @@
 { PrepareData }
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 var
   aFile: TFile;
   I: Integer;
@@ -669,6 +676,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +690,10 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    if Modal then
+      OperationsManager.AddOperationModal(Operation)
+    else
+      OperationsManager.AddOperation(Operation);
 
     Exit(pdrInCallback);
   end;
@@ -762,6 +774,7 @@
   protected
     FFunc: TToolDataPreparedProc;
     FCallOnFail: Boolean;
+    FModal: Boolean;
     FFailed: Boolean;
     FFileList1: TStringList;
     FFileList2: TStringList;
@@ -777,7 +790,8 @@
   public
     constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
     procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                      FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                      FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                      Modal: Boolean = False);
     destructor Destroy; override;
   end;
 
@@ -788,11 +802,27 @@
 end;
 
 procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                                       FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                                       FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                                       Modal: Boolean = False);
 var
   I: Integer;
 begin
-  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+  writeln('----------- prepare files: ----------------');
+  writeln('--------------- file 1 --------------------');
+  writeln(FileSource1.ClassName);
+  writeln(SelectedFiles1[0].FullPath);
+  writeln(SelectedFiles1[0].Path);
+  writeln(SelectedFiles1[0].Name);
+  writeln('--------------- file 2 --------------------');
+  writeln(FileSource2.ClassName);
+  writeln(SelectedFiles2[0].FullPath);
+  writeln(SelectedFiles2[0].Path);
+  writeln(SelectedFiles2[0].Name);
+  writeln('--------------- /files --------------------');
+
+  FModal := Modal;
+
+  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
   pdrSynchronous:
     begin
       FFileList1 := TStringList.Create;
@@ -804,7 +834,7 @@
     begin
       try
         if FCallOnFail then
-          FFunc(nil, nil);
+          FFunc(nil, nil, FModal);
       finally
         Free;
       end;
@@ -812,7 +842,7 @@
     end;
   end;
 
-  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
   pdrSynchronous:
     begin
       FFileList2 := TStringList.Create;
@@ -886,7 +916,7 @@
     if FFailed then
     begin
       if FCallOnFail then
-        FFunc(nil, nil);
+        FFunc(nil, nil, FModal);
       Exit;
     end;
     if Assigned(FFileList2) then
@@ -897,10 +927,10 @@
       WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
       FWaitData1 := nil;
       FWaitData2 := nil;
-      FFunc(FFileList1, WaitData);
+      FFunc(FFileList1, WaitData, FModal);
     end
     else
-      FFunc(FFileList1, nil);
+      FFunc(FFileList1, nil, FModal);
   finally
     Free;
   end;
@@ -936,7 +966,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc);
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False);
 var Files1, Files2: TFiles;
 begin
   Files1 := TFiles.Create(File1.Path);
@@ -946,7 +977,7 @@
     try
       Files2.Add(File2.Clone);
       with TToolDataPreparator2.Create(FunctionToCall) do
-        Prepare(FileSource1, Files1, FileSource2, Files2);
+        Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
     finally
       Files2.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview10.patch (64,027 bytes)   
bug1536-preview11.patch (59,375 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -249,7 +249,7 @@
     procedure cm_SaveRight(const Params: array of string);
   end; 
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 
 implementation
 
@@ -262,7 +262,7 @@
 const
   HotkeysCategory = 'Differ';
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 begin
   with TfrmDiffer.Create(Application) do
   begin
@@ -278,7 +278,13 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    if actBinaryCompare.Checked or (FShowIdentical = False) then
+    begin
+      if Modal then
+        ShowModal
+      else
+        ShowOnTop;
+    end;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +111,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +731,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +846,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -175,6 +178,24 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
 begin
   Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +607,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -56,7 +56,7 @@
                                    State: TFileSourceOperationState);
   end;
 
-  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
   // Callback may be called either asynchoronously or synchronously (for modal operations)
   // pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
   TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 
 procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
                           FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc); overload;
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False); overload;
 
 procedure RunExtDiffer(CompareList: TStringList);
 
@@ -82,7 +84,7 @@
 procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
 
 procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
 procedure ShowViewerByGlob(const sFileName: String);
 procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +96,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -265,7 +267,7 @@
     ShowDiffer(LeftName, RightName);
 end;
 
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 begin
   if gExternalTools[etDiffer].Enabled then
   begin
@@ -275,7 +277,7 @@
       RunExtDiffer(CompareList);
   end
   else
-    ShowDiffer(CompareList[0], CompareList[1], WaitData);
+    ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
 end;
 
 procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -635,7 +637,8 @@
 { PrepareData }
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 var
   aFile: TFile;
   I: Integer;
@@ -669,6 +672,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +686,10 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    if Modal then
+      OperationsManager.AddOperationModal(Operation)
+    else
+      OperationsManager.AddOperation(Operation);
 
     Exit(pdrInCallback);
   end;
@@ -762,6 +770,7 @@
   protected
     FFunc: TToolDataPreparedProc;
     FCallOnFail: Boolean;
+    FModal: Boolean;
     FFailed: Boolean;
     FFileList1: TStringList;
     FFileList2: TStringList;
@@ -777,7 +786,8 @@
   public
     constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
     procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                      FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                      FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                      Modal: Boolean = False);
     destructor Destroy; override;
   end;
 
@@ -788,11 +798,14 @@
 end;
 
 procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                                       FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                                       FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                                       Modal: Boolean = False);
 var
   I: Integer;
 begin
-  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+  FModal := Modal;
+
+  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
   pdrSynchronous:
     begin
       FFileList1 := TStringList.Create;
@@ -804,7 +817,7 @@
     begin
       try
         if FCallOnFail then
-          FFunc(nil, nil);
+          FFunc(nil, nil, FModal);
       finally
         Free;
       end;
@@ -812,7 +825,7 @@
     end;
   end;
 
-  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
   pdrSynchronous:
     begin
       FFileList2 := TStringList.Create;
@@ -886,7 +899,7 @@
     if FFailed then
     begin
       if FCallOnFail then
-        FFunc(nil, nil);
+        FFunc(nil, nil, FModal);
       Exit;
     end;
     if Assigned(FFileList2) then
@@ -897,10 +910,10 @@
       WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
       FWaitData1 := nil;
       FWaitData2 := nil;
-      FFunc(FFileList1, WaitData);
+      FFunc(FFileList1, WaitData, FModal);
     end
     else
-      FFunc(FFileList1, nil);
+      FFunc(FFileList1, nil, FModal);
   finally
     Free;
   end;
@@ -936,17 +949,20 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc);
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False);
 var Files1, Files2: TFiles;
 begin
   Files1 := TFiles.Create(File1.Path);
   try
     Files1.Add(File1.Clone);
+    Files1.Path := File1.Path;
     Files2 := TFiles.Create(File2.Path);
     try
       Files2.Add(File2.Clone);
+      Files2.Path := File2.Path;
       with TToolDataPreparator2.Create(FunctionToCall) do
-        Prepare(FileSource1, Files1, FileSource2, Files2);
+        Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
     finally
       Files2.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview11.patch (59,375 bytes)   
bug1536-preview12.patch (59,859 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -249,7 +249,7 @@
     procedure cm_SaveRight(const Params: array of string);
   end; 
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 
 implementation
 
@@ -262,7 +262,7 @@
 const
   HotkeysCategory = 'Differ';
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 begin
   with TfrmDiffer.Create(Application) do
   begin
@@ -278,7 +278,13 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    if actBinaryCompare.Checked or (FShowIdentical = False) then
+    begin
+      if Modal then
+        ShowModal
+      else
+        ShowOnTop;
+    end;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesource.pas	(working copy)
@@ -427,7 +427,7 @@
   SourceFileSource: IFileSource;
 begin
   SourceFileSource := Self;
-  SourceFiles.Path:= FCurrentAddress + SourceFiles.Path;
+  if not StrBegins(SourceFiles.Path, FCurrentAddress) then SourceFiles.Path:= FCurrentAddress + SourceFiles.Path;
   Result := TGioCopyOutOperation.Create(SourceFileSource, TargetFileSource, SourceFiles, TargetPath);
 end;
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +111,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +731,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +846,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -175,6 +178,24 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
 begin
   Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +607,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -56,7 +56,7 @@
                                    State: TFileSourceOperationState);
   end;
 
-  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
   // Callback may be called either asynchoronously or synchronously (for modal operations)
   // pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
   TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 
 procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
                           FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc); overload;
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False); overload;
 
 procedure RunExtDiffer(CompareList: TStringList);
 
@@ -82,7 +84,7 @@
 procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
 
 procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
 procedure ShowViewerByGlob(const sFileName: String);
 procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +96,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -265,7 +267,7 @@
     ShowDiffer(LeftName, RightName);
 end;
 
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 begin
   if gExternalTools[etDiffer].Enabled then
   begin
@@ -275,7 +277,7 @@
       RunExtDiffer(CompareList);
   end
   else
-    ShowDiffer(CompareList[0], CompareList[1], WaitData);
+    ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
 end;
 
 procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -635,7 +637,8 @@
 { PrepareData }
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 var
   aFile: TFile;
   I: Integer;
@@ -669,6 +672,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +686,10 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    if Modal then
+      OperationsManager.AddOperationModal(Operation)
+    else
+      OperationsManager.AddOperation(Operation);
 
     Exit(pdrInCallback);
   end;
@@ -762,6 +770,7 @@
   protected
     FFunc: TToolDataPreparedProc;
     FCallOnFail: Boolean;
+    FModal: Boolean;
     FFailed: Boolean;
     FFileList1: TStringList;
     FFileList2: TStringList;
@@ -777,7 +786,8 @@
   public
     constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
     procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                      FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                      FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                      Modal: Boolean = False);
     destructor Destroy; override;
   end;
 
@@ -788,11 +798,14 @@
 end;
 
 procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                                       FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                                       FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                                       Modal: Boolean = False);
 var
   I: Integer;
 begin
-  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+  FModal := Modal;
+
+  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
   pdrSynchronous:
     begin
       FFileList1 := TStringList.Create;
@@ -804,7 +817,7 @@
     begin
       try
         if FCallOnFail then
-          FFunc(nil, nil);
+          FFunc(nil, nil, FModal);
       finally
         Free;
       end;
@@ -812,7 +825,7 @@
     end;
   end;
 
-  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
   pdrSynchronous:
     begin
       FFileList2 := TStringList.Create;
@@ -886,7 +899,7 @@
     if FFailed then
     begin
       if FCallOnFail then
-        FFunc(nil, nil);
+        FFunc(nil, nil, FModal);
       Exit;
     end;
     if Assigned(FFileList2) then
@@ -897,10 +910,10 @@
       WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
       FWaitData1 := nil;
       FWaitData2 := nil;
-      FFunc(FFileList1, WaitData);
+      FFunc(FFileList1, WaitData, FModal);
     end
     else
-      FFunc(FFileList1, nil);
+      FFunc(FFileList1, nil, FModal);
   finally
     Free;
   end;
@@ -936,7 +949,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc);
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False);
 var Files1, Files2: TFiles;
 begin
   Files1 := TFiles.Create(File1.Path);
@@ -946,7 +960,7 @@
     try
       Files2.Add(File2.Clone);
       with TToolDataPreparator2.Create(FunctionToCall) do
-        Prepare(FileSource1, Files1, FileSource2, Files2);
+        Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
     finally
       Files2.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview12.patch (59,859 bytes)   
bug1536-preview13.patch (61,266 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -249,7 +249,7 @@
     procedure cm_SaveRight(const Params: array of string);
   end; 
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 
 implementation
 
@@ -262,7 +262,7 @@
 const
   HotkeysCategory = 'Differ';
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 begin
   with TfrmDiffer.Create(Application) do
   begin
@@ -278,7 +278,13 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    if actBinaryCompare.Checked or (FShowIdentical = False) then
+    begin
+      if Modal then
+        ShowModal
+      else
+        ShowOnTop;
+    end;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +111,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationTypes,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -677,13 +683,29 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  SourceFilesPath: String = '';
+  TargetFilesPath: String = '';
+begin
+  if Action = fsouaCompare then
+  begin
+    if FOperation.ID <> fsoCopyIn then
+      SourceFilesPath := Copy(ExtractFilePath(FCurrentFile.FullPath), Length(FGioFileSource.CurrentAddress)+1, MaxInt);
+    if FOperation.ID <> fsoCopyOut then
+      TargetFilesPath := Copy(ExtractFilePath(FCurrentTargetFilePath), Length(FGioFileSource.CurrentAddress)+1, MaxInt);
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath, SourceFilesPath, TargetFilesPath);
+  end;
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +740,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +855,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +865,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,10 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String;
+                                 SourceFilesPath: String = ''; TargetFilesPath: String = '');
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +139,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +276,26 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, '', '', True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String;
+                                                      SourceFilesPath: String = ''; TargetFilesPath: String = '');
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList,
+                    SourceFilesPath, TargetFilesPath, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,10 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String;
+                                 SourceFilesPath: String = ''; TargetFilesPath: String = '');
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +82,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -175,6 +179,26 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, '', '', True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String;
+                                                      SourceFilesPath: String = ''; TargetFilesPath: String = '');
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList,
+                    SourceFilesPath, TargetFilesPath, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
 begin
   Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,15 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String;
+                                          SourceFilesPath: String = ''; TargetFilesPath: String = '') of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +176,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +323,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1180,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1212,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1290,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +607,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -56,7 +56,7 @@
                                    State: TFileSourceOperationState);
   end;
 
-  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
   // Callback may be called either asynchoronously or synchronously (for modal operations)
   // pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
   TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 
 procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
                           FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,10 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc); overload;
+                          FunctionToCall: TToolDataPreparedProc;
+                          Files1Path: String = '';
+                          Files2Path: String = '';
+                          Modal: Boolean = False); overload;
 
 procedure RunExtDiffer(CompareList: TStringList);
 
@@ -82,7 +86,7 @@
 procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
 
 procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
 procedure ShowViewerByGlob(const sFileName: String);
 procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +98,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -265,7 +269,7 @@
     ShowDiffer(LeftName, RightName);
 end;
 
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 begin
   if gExternalTools[etDiffer].Enabled then
   begin
@@ -275,7 +279,7 @@
       RunExtDiffer(CompareList);
   end
   else
-    ShowDiffer(CompareList[0], CompareList[1], WaitData);
+    ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
 end;
 
 procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -389,7 +393,10 @@
 
 function TEditorWaitData.GetFromPath: string;
 begin
-  Result := TargetFileSource.CurrentAddress + TargetPath;
+  if StrBegins(TargetPath, TargetFileSource.CurrentAddress) then
+    Result := TargetPath // Workaround for TGioFileSource
+  else
+    Result := TargetFileSource.CurrentAddress + TargetPath;
 end;
 
 procedure TEditorWaitData.ShowWaitForm;
@@ -635,7 +642,8 @@
 { PrepareData }
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 var
   aFile: TFile;
   I: Integer;
@@ -669,6 +677,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +691,10 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    if Modal then
+      OperationsManager.AddOperationModal(Operation)
+    else
+      OperationsManager.AddOperation(Operation);
 
     Exit(pdrInCallback);
   end;
@@ -762,6 +775,7 @@
   protected
     FFunc: TToolDataPreparedProc;
     FCallOnFail: Boolean;
+    FModal: Boolean;
     FFailed: Boolean;
     FFileList1: TStringList;
     FFileList2: TStringList;
@@ -777,7 +791,8 @@
   public
     constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
     procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                      FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                      FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                      Modal: Boolean = False);
     destructor Destroy; override;
   end;
 
@@ -788,11 +803,14 @@
 end;
 
 procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                                       FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                                       FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                                       Modal: Boolean = False);
 var
   I: Integer;
 begin
-  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+  FModal := Modal;
+
+  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
   pdrSynchronous:
     begin
       FFileList1 := TStringList.Create;
@@ -804,7 +822,7 @@
     begin
       try
         if FCallOnFail then
-          FFunc(nil, nil);
+          FFunc(nil, nil, FModal);
       finally
         Free;
       end;
@@ -812,7 +830,7 @@
     end;
   end;
 
-  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
   pdrSynchronous:
     begin
       FFileList2 := TStringList.Create;
@@ -886,7 +904,7 @@
     if FFailed then
     begin
       if FCallOnFail then
-        FFunc(nil, nil);
+        FFunc(nil, nil, FModal);
       Exit;
     end;
     if Assigned(FFileList2) then
@@ -897,10 +915,10 @@
       WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
       FWaitData1 := nil;
       FWaitData2 := nil;
-      FFunc(FFileList1, WaitData);
+      FFunc(FFileList1, WaitData, FModal);
     end
     else
-      FFunc(FFileList1, nil);
+      FFunc(FFileList1, nil, FModal);
   finally
     Free;
   end;
@@ -936,17 +954,26 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc);
+                          FunctionToCall: TToolDataPreparedProc;
+                          Files1Path: String = '';
+                          Files2Path: String = '';
+                          Modal: Boolean = False);
 var Files1, Files2: TFiles;
 begin
-  Files1 := TFiles.Create(File1.Path);
+  if Files1Path <> '' then
+    Files1 := TFiles.Create(Files1Path)
+  else
+    Files1 := TFiles.Create(File1.Path);
   try
     Files1.Add(File1.Clone);
-    Files2 := TFiles.Create(File2.Path);
+    if Files2Path <> '' then
+      Files2 := TFiles.Create(Files2Path)
+    else
+      Files2 := TFiles.Create(File2.Path);
     try
       Files2.Add(File2.Clone);
       with TToolDataPreparator2.Create(FunctionToCall) do
-        Prepare(FileSource1, Files1, FileSource2, Files2);
+        Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
     finally
       Files2.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview13.patch (61,266 bytes)   
bug1536-preview14.patch (63,902 bytes)   
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas	(revision 7965)
+++ src/fdiffer.pas	(working copy)
@@ -249,7 +249,7 @@
     procedure cm_SaveRight(const Params: array of string);
   end; 
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 
 implementation
 
@@ -262,7 +262,7 @@
 const
   HotkeysCategory = 'Differ';
 
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
 begin
   with TfrmDiffer.Create(Application) do
   begin
@@ -278,7 +278,13 @@
       OpenFileRight(FileNameRight);
       if actAutoCompare.Checked then actStartCompare.Execute;
     end;
-    if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+    if actBinaryCompare.Checked or (FShowIdentical = False) then
+    begin
+      if Modal then
+        ShowModal
+      else
+        ShowOnTop;
+    end;
   end;
 end;
 
Index: src/ffileexecuteyourself.pas
===================================================================
--- src/ffileexecuteyourself.pas	(revision 7965)
+++ src/ffileexecuteyourself.pas	(working copy)
@@ -52,7 +52,7 @@
     destructor Destroy; override;
   end; 
 
-  procedure ShowFileEditExternal(const FileName, FromPath: string; aWaitData: TWaitData);
+  procedure ShowFileEditExternal(const FileName, FromPath: string; aWaitData: TWaitData; Modal: Boolean = False);
   function ShowFileExecuteYourSelf(aFileView: TFileView; aFile: TFile; bWithAll: Boolean): Boolean;
 
 implementation
@@ -62,7 +62,7 @@
 uses
   DCOSUtils, DCStrUtils, uTempFileSystemFileSource, uFileSourceOperation, uShellExecute;
 
-procedure ShowFileEditExternal(const FileName, FromPath: string; aWaitData: TWaitData);
+procedure ShowFileEditExternal(const FileName, FromPath: string; aWaitData: TWaitData; Modal: Boolean = False);
 begin
   // Create wait window
   with TfrmFileExecuteYourSelf.Create(Application, nil, FileName, FromPath) do
@@ -69,7 +69,10 @@
   begin
     FWaitData:= aWaitData;
     // Show wait window
-    Visible := True;
+    if Modal then
+      ShowModal
+    else
+      Visible := True;
   end;
 end;
 
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas	(working copy)
@@ -172,6 +172,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmCopy,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas	(working copy)
@@ -137,6 +137,7 @@
                         @AppProcessMessages,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         Thread,
                         fsohmMove,
                         TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas	(revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas	(working copy)
@@ -83,11 +83,15 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
     AppProcessMessages: TAppProcessMessagesFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
     MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
 
     procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean;
                        AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         var AbsoluteTargetFileName: String;
                         AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
                        AppProcessMessagesFunction: TAppProcessMessagesFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
                        OperationThread: TThread;
                        Mode: TFileSystemOperationHelperMode;
                        TargetPath: String;
@@ -315,6 +322,7 @@
   AppProcessMessagesFunction: TAppProcessMessagesFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
   TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
 begin
@@ -323,6 +331,7 @@
   AppProcessMessages := AppProcessMessagesFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
 
   FOperationThread := OperationThread;
   FMode := Mode;
@@ -1355,18 +1364,26 @@
       Result := FDirExistsOption;
 end;
 
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TFileSystemOperationHelper.FileExists(aFile: TFile;
   var AbsoluteTargetFileName: String; AllowAppend: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..11] of TFileSourceOperationUIResponse
+  Responses: array[0..12] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
-       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
-       fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
-  ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+       fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+       fsourAutoRenameSource);
+  ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource,  fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
-       fsourOverwriteLarger, fsourAutoRenameSource);
+       fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
 var
   Answer: Boolean;
   Message: String;
@@ -1407,8 +1424,11 @@
         end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas	(working copy)
@@ -116,6 +116,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_copy,
                         TargetPath);
 
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesource.pas	(working copy)
@@ -427,7 +427,7 @@
   SourceFileSource: IFileSource;
 begin
   SourceFileSource := Self;
-  SourceFiles.Path:= FCurrentAddress + SourceFiles.Path;
+  if not StrBegins(SourceFiles.Path, FCurrentAddress) then SourceFiles.Path:= FCurrentAddress + SourceFiles.Path;
   Result := TGioCopyOutOperation.Create(SourceFileSource, TargetFileSource, SourceFiles, TargetPath);
 end;
 
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas	(revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas	(working copy)
@@ -7,9 +7,9 @@
 uses
   Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
   uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
-  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+  uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+  uFileSourceOperationUI;
 
-
 const
   CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
                                         FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
     FFileExistsOption: TFileSourceOperationOptionFileExists;
     FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
 
     procedure ShowError(const Message: String; AError: PGError);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
     function DirExists(aFile: TFile;
                        AbsoluteTargetFileName: String;
                        AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         aTargetInfo: PGFileInfo;
                         var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
                        CopyMoveFileFunction: TCopyMoveFileFunction;
                        TargetPath: String
                        );
@@ -105,7 +111,7 @@
 implementation
 
 uses
-  Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+  Forms, StrUtils, DCDateTimeUtils, uFileProperty,
   uShowMsg, uLng, uGObject2, DCFileAttributes;
 
 procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
   end;
 end;
 
+procedure TGioOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
 function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..8] of TFileSourceOperationUIResponse
+  Responses: array[0..9] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
-       fsourOverwriteLarger, fsourCancel);
+       fsourCancel, fsouaCompare, fsourOverwriteLarger);
 var
   Answer: Boolean;
   Message: String;
@@ -718,8 +731,11 @@
       repeat
         Answer := True;
         Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         Responses, fsourOverwrite, fsourSkip) of
+                         Responses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -830,6 +846,7 @@
   AbortOperationFunction: TAbortOperationFunction;
   CheckOperationStateFunction: TCheckOperationStateFunction;
   UpdateStatisticsFunction: TUpdateStatisticsFunction;
+  ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
   CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
 begin
   FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
   FCopyMoveFile := CopyMoveFileFunction;
 
   FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas	(revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas	(working copy)
@@ -80,6 +80,7 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
                         g_file_move,
                         TargetPath);
 
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas	(working copy)
@@ -8,6 +8,7 @@
   LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
   uFileSourceOperation,
   uFileSourceCopyOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFileSource,
@@ -60,6 +61,11 @@
     procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
 
   protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+  protected
     FExProcess: TExProcess;
     FTempFile: String;
     FFileMask: String;
@@ -91,7 +97,7 @@
 implementation
 
 uses
-  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+  LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
   fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
   DCBasicTypes, uShowMsg, uFileSystemUtil;
 
@@ -445,12 +451,29 @@
   end;
 end;
 
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := FCurrentFile.Clone;
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
   const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
-       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+       fsourCancel);
 var
   Message: String;
 
@@ -486,8 +509,11 @@
       begin
         Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
                                     aFile.Size, aFile.ModificationTime);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas	(working copy)
@@ -58,6 +58,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property TargetPath: String read FTargetPath;
 
   public
@@ -135,7 +138,7 @@
 implementation
 
 uses
-  uDCUtils, uLng, uGlobs;
+  uDCUtils, uLng, uGlobs, uShowForm;
 
 // -- TFileSourceCopyOperation ------------------------------------------------
 
@@ -272,6 +275,24 @@
   end;
 end;
 
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 // -- TFileSourceCopyInOperation ----------------------------------------------
 
 function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas	(revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas	(working copy)
@@ -46,6 +46,9 @@
     procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
     procedure UpdateStatisticsAtStartTime; override;
 
+    procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+    procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
     property FileSource: IFileSource read FFileSource;
     property SourceFiles: TFiles read FSourceFiles;
     property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
 implementation
 
 uses
-  uDCUtils, uLng;
+  uDCUtils, uLng, uShowForm;
 
 // -- TFileSourceMoveOperation ------------------------------------------------
 
@@ -175,6 +178,24 @@
   end;
 end;
 
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+  PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+  TargetFile: TFile = nil;
+begin
+  TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+  TargetFile.Name := ExtractFileName(TargetFilePath);
+  try
+    PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+  finally
+    TargetFile.Free;
+  end;
+end;
+
 function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
 begin
   Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas	(revision 7965)
+++ src/filesources/ufilesourceoperation.pas	(working copy)
@@ -25,7 +25,8 @@
   Classes, SysUtils, syncobjs, uLng,
   uFileSourceOperationOptionsUI,
   uFileSourceOperationTypes,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uFile;
 
 type
 
@@ -75,11 +76,14 @@
       function(Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse of object;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer of object;
   TAbortOperationFunction = procedure of object;
   TCheckOperationStateFunction = procedure of object;
   TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+  TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+  TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
 
   TFileSourceOperationClass = class of TFileSourceOperation;
   {en
@@ -171,8 +175,9 @@
     FUIQuestion: String;
     FUIPossibleResponses: array of TFileSourceOperationUIResponse;
     FUIDefaultOKResponse: TFileSourceOperationUIResponse;
-    FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
-    FUIResponse: TFileSourceOperationUIResponse;
+    FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+    FUIResponse: TFileSourceOperationUIAnswer;
     FTryAskQuestionResult: Boolean;
 
     {en
@@ -317,8 +322,9 @@
                Msg: String; Question: String;
                PossibleResponses: array of TFileSourceOperationUIResponse;
                DefaultOKResponse: TFileSourceOperationUIResponse;
-               DefaultCancelResponse: TFileSourceOperationUIResponse
-             ) : TFileSourceOperationUIResponse;
+               DefaultCancelResponse: TFileSourceOperationUIAnswer;
+               ActionHandler: TFileSourceOperationUIActionHandler = nil
+             ) : TFileSourceOperationUIAnswer;
 
     {en
        Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+           ) : TFileSourceOperationUIAnswer;
 var
   i: Integer;
   bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
     FUIPossibleResponses[i] := PossibleResponses[i];
   FUIDefaultOKResponse := DefaultOKResponse;
   FUIDefaultCancelResponse := DefaultCancelResponse;
+  FUIActionHandler := ActionHandler;
 
   if GetCurrentThreadID <> MainThreadID then
   begin
@@ -1280,7 +1289,8 @@
                       FUIQuestion,
                       FUIPossibleResponses,
                       FUIDefaultOKResponse,
-                      FUIDefaultCancelResponse);
+                      FUIDefaultCancelResponse,
+                      FUIActionHandler);
 
     FTryAskQuestionResult := True;  // We do have an answer now.
   end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas	(working copy)
@@ -6,7 +6,8 @@
 
 uses
   Classes, SysUtils,
-  uFileSourceOperationUI;
+  uFileSourceOperationUI,
+  uShowMsg;
 
 type
 
@@ -13,7 +14,14 @@
   {en
      We assume here the UI is used only from the GUI thread.
   }
+
+  { TFileSourceOperationMessageBoxesUI }
+
   TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+  private
+    FUIActionHandler: TFileSourceOperationUIActionHandler;
+  protected
+    procedure QuestionActionHandler(Button: TMyMsgActionButton);
   public
     constructor Create; override;
     destructor Destroy; override;
@@ -21,21 +29,21 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; override;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; override;
   end;
 
 implementation
 
-uses
-  uShowMsg;
-
 const
   ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
     (msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
      msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
      msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+     msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+     // Actions:
+     msmbCompare);
 
   ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
     (fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
      fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
      fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
 
+  ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+    (fsouaCompare);
+
 constructor TFileSourceOperationMessageBoxesUI.Create;
 begin
   inherited;
@@ -57,8 +68,9 @@
              Msg: String; Question: String;
              PossibleResponses: array of TFileSourceOperationUIResponse;
              DefaultOKResponse: TFileSourceOperationUIResponse;
-             DefaultCancelResponse: TFileSourceOperationUIResponse
-         ) : TFileSourceOperationUIResponse;
+             DefaultCancelResponse: TFileSourceOperationUIAnswer;
+             ActionHandler: TFileSourceOperationUIActionHandler = nil
+         ) : TFileSourceOperationUIAnswer;
 var
   Buttons: array of TMyMsgButton;
   i: Integer;
@@ -65,6 +77,8 @@
   MsgResult: TMyMsgResult;
   TextMessage: String;
 begin
+  FUIActionHandler := ActionHandler;
+
   SetLength(Buttons, Length(PossibleResponses));
   for i := 0 to Length(PossibleResponses) - 1 do
     Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
   MsgResult := MsgBox(TextMessage,
                       Buttons,
                       ResponseToButton[DefaultOKResponse],
-                      ResponseToButton[DefaultCancelResponse]);
+                      ResponseToButton[DefaultCancelResponse],
+                      @QuestionActionHandler);
 
   Result := ResultToResponse[MsgResult];
 end;
 
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+  Button: TMyMsgActionButton);
+begin
+  if Assigned(FUIActionHandler) then
+    FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
 end.
 
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas	(working copy)
@@ -69,7 +69,8 @@
 
 procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
 begin
-  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+//  with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+  with TfrmFileOp.Create(OpManItem.Handle) do
   try
     ShowModal;
   finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas	(revision 7965)
+++ src/filesources/ufilesourceoperationui.pas	(working copy)
@@ -34,8 +34,16 @@
      fsourAll,
      fsourRetry,
      fsourAbort,
-     fsourRetryAdmin);
+     fsourRetryAdmin,
+     // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+     fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
 
+  TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+  TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+  TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
   {en
      General interface for communication: operation <-> user.
   }
@@ -47,8 +55,9 @@
     function AskQuestion(Msg: String; Question: String;
                          PossibleResponses: array of TFileSourceOperationUIResponse;
                          DefaultOKResponse: TFileSourceOperationUIResponse;
-                         DefaultCancelResponse: TFileSourceOperationUIResponse
-                        ) : TFileSourceOperationUIResponse; virtual abstract;
+                         DefaultCancelResponse: TFileSourceOperationUIAnswer;
+                         ActionHandler: TFileSourceOperationUIActionHandler = nil
+                        ) : TFileSourceOperationUIAnswer; virtual abstract;
     // Add possibility to display files properties (for example: to compare older - newer)
     // Add general option "remember this choice for all files of this type" (checkbox)
   end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas	(working copy)
@@ -13,6 +13,7 @@
   uFile,
   uWcxModule,
   uWcxArchiveFileSource,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI;
 
@@ -44,6 +45,10 @@
     function Tar: Boolean;
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
+  protected
+    FCurrentFile: TFile;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
     function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 
@@ -71,7 +76,7 @@
 
 uses
   LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
-  uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+  uFileSystemFileSource, DCOSUtils, uTarWriter,
   DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
 
 // ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
   end;
 end;
 
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+    ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
 function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
 function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
   aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+  PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
        fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
-       fsourOverwriteOlder, fsourCancel);
+       fsourOverwriteOlder, fsouaCompare, fsourCancel);
 
   function OverwriteOlder: TFileSourceOperationOptionFileExists;
   begin
@@ -456,8 +468,11 @@
   case FFileExistsOption of
     fsoofeNone:
       begin
+        FCurrentFile := aSourceFile;
+        FCurrentTargetFilePath := aTargetHeader.FileName;
         case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas	(working copy)
@@ -10,6 +10,7 @@
   uFileSourceCopyOperation,
   uFileSource,
   uFileSourceOperation,
+  uFileSourceOperationUI,
   uFileSourceOperationOptions,
   uFileSourceOperationOptionsUI,
   uFile,
@@ -65,6 +66,10 @@
     procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
 
   protected
+    FCurrentFilePath: String;
+    FCurrentTargetFilePath: String;
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
     procedure SetProcessDataProc(hArcData: TArcHandle);
 
   public
@@ -91,7 +96,7 @@
 
 uses
   Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
-  uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+  fWcxArchiveCopyOperationOptions, uFileSystemUtil,
   uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
 
 // ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
   end;
 end;
 
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+var
+  aFile: TFile;
+begin
+  if Action = fsouaCompare then
+  begin
+    aFile := TFile.Create('');
+    try
+      aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+      ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+    finally
+      aFile.Free;
+    end;
+  end;
+end;
+
 function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
   var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
 const
-  PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+  Responses: array[0..10] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
        fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+       fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+  ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+       fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
        fsourRenameSource, fsourAutoRenameSource);
 var
+  PossibleResponses: array of TFileSourceOperationUIResponse;
   Answer: Boolean;
   Message: String;
 
@@ -580,10 +607,19 @@
     fsoofeNone:
       repeat
         Answer := True;
+        // Can't asynchoronously extract file for comparison when multiple operations are not supported
+        // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+        case FNeedsConnection of
+          True :  PossibleResponses := ResponsesNoCompare;
+          False:  PossibleResponses := Responses;
+        end;
         Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
                                     Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+        FCurrentFilePath := Header.FileName;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyIn,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas	(working copy)
@@ -130,6 +130,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopy,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas	(working copy)
@@ -142,6 +142,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmCopyOut,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas	(working copy)
@@ -128,6 +128,8 @@
                         @RaiseAbortOperation,
                         @CheckOperationState,
                         @UpdateStatistics,
+                        @ShowCompareFilesUI,
+                        @ShowCompareFilesUIByFileObject,
                         Thread,
                         wpohmMove,
                         TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas	(revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas	(working copy)
@@ -39,10 +39,16 @@
     FCopyAttributesOptions: TCopyAttributesOptions;
     FFileExistsOption: TFileSourceOperationOptionFileExists;
 
+    FCurrentFile: TFile;
+    FCurrentTargetFile: TFile;
+    FCurrentTargetFilePath: String;
+
     AskQuestion: TAskQuestionFunction;
     AbortOperation: TAbortOperationFunction;
     CheckOperationState: TCheckOperationStateFunction;
     UpdateStatistics: TUpdateStatisticsFunction;
+    ShowCompareFilesUI: TShowCompareFilesUIFunction;
+    ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
 
     procedure ShowError(sMessage: String);
     procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
     function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
     function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
 
+    procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
     function FileExists(aFile: TFile;
                         AbsoluteTargetFileName: String;
                         AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
                        AbortOperationFunction: TAbortOperationFunction;
                        CheckOperationStateFunction: TCheckOperationStateFunction;
                        UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                       ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                       ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                        OperationThread: TThread;
                        Mode: TWfxPluginOperationHelperMode;
                        TargetPath: String
@@ -233,6 +242,18 @@
   end;
 end;
 
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+  Action: TFileSourceOperationUIAction);
+begin
+  if Action = fsouaCompare then
+  begin
+    if Assigned(FCurrentTargetFile) then
+      ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+    else
+      ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+  end;
+end;
+
 function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
 begin
   Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
   AbsoluteTargetFileName: String; AllowResume: Boolean
   ): TFileSourceOperationOptionFileExists;
 const
-  Responses: array[0..5] of TFileSourceOperationUIResponse
+  Responses: array[0..6] of TFileSourceOperationUIResponse
     = (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+       fsouaCompare, fsourCancel);
+  ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
        fsourCancel);
-  ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
-    = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
 var
   Message: String;
   PossibleResponses: array of TFileSourceOperationUIResponse;
-  TargetFile: TFile;
 begin
   case FFileExistsOption of
     fsoofeNone:
-      begin
+      try
+        FCurrentTargetFile := nil;
         case AllowResume of
           True :  PossibleResponses := Responses;
           False:  PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
         end;
         if FMode = wpohmCopyOut then
           Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
-        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
-        begin
-          Message := FileExistsMessage(TargetFile, aFile);
-          TargetFile.Free;
-        end
+        else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+          Message := FileExistsMessage(FCurrentTargetFile, aFile)
         else
           Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+        FCurrentFile := aFile;
+        FCurrentTargetFilePath := AbsoluteTargetFileName;
         case AskQuestion(Message, '',
-                         PossibleResponses, fsourOverwrite, fsourSkip) of
+                         PossibleResponses, fsourOverwrite, fsourSkip,
+                         @QuestionActionHandler) of
           fsourOverwrite:
             Result := fsoofeOverwrite;
           fsourSkip:
@@ -296,6 +318,8 @@
           fsourCancel:
             AbortOperation;
         end;
+      finally
+        FreeAndNil(FCurrentTargetFile);
       end;
 
     else
@@ -324,6 +348,8 @@
                                              AbortOperationFunction: TAbortOperationFunction;
                                              CheckOperationStateFunction: TCheckOperationStateFunction;
                                              UpdateStatisticsFunction: TUpdateStatisticsFunction;
+                                             ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+                                             ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
                                              OperationThread: TThread;
                                              Mode: TWfxPluginOperationHelperMode;
                                              TargetPath: String
@@ -334,6 +360,8 @@
   AbortOperation := AbortOperationFunction;
   CheckOperationState := CheckOperationStateFunction;
   UpdateStatistics := UpdateStatisticsFunction;
+  ShowCompareFilesUI := ShowCompareFilesUIFunction;
+  ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
   FOperationThread:= OperationThread;
   FMode := Mode;
   FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas	(revision 7965)
+++ src/fMsg.pas	(working copy)
@@ -17,10 +17,8 @@
     procedure FormCreate(Sender: TObject);
     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure FormKeyPress(Sender: TObject; var Key: Char);
-  private
-    { Private declarations }
   public
-    { Public declarations }
+    ActionHandler: procedure(Tag: PtrInt) of object;
     Escape: Integer;
     iSelected: Integer;
     procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
 
 procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
-  if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+  if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
 end;
 
 procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
 end;
 
 procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+  aTag: PtrInt;
 begin
-  iSelected:= (Sender as TComponent).Tag;
-  Close;
+  aTag:= (Sender as TComponent).Tag;
+  if (aTag < -1) then
+  begin
+    if Assigned(ActionHandler) then
+      ActionHandler(aTag);
+  end
+  else
+  begin
+    iSelected:= aTag;
+    Close;
+  end;
 end;
 
 procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
 {$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
   if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
   begin
-    iSelected:= (Sender as TButton).Tag;
-    Close;
+    ButtonClick(Sender);
   end;
 {$ENDIF}
 end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas	(revision 7965)
+++ src/platform/uosforms.pas	(working copy)
@@ -319,9 +319,9 @@
   end;
 
   // If parent window is normal window then call inherited method
-  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
-    Result:= inherited ShowModal
-  else
+//  if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+//    Result:= inherited ShowModal
+//  else
     begin
       Include(FFormState, fsModal);
       FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas	(revision 7965)
+++ src/ulng.pas	(working copy)
@@ -329,6 +329,7 @@
   rsDlgButtonAbort = 'Ab&ort';
   rsDlgButtonOther = 'Ot&her';
   rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+  rsDlgButtonCompare = 'Compare &by content';
 
   rsDlgButtonContinue = '&Continue';
   rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas	(revision 7966)
+++ src/ushowform.pas	(working copy)
@@ -43,11 +43,12 @@
     TargetPath: String;
     SourceFileSource: IFileSource;
     TargetFileSource: IFileSource;
+    FModal: Boolean;
     function GetRelativeFileName(const FullPath: string): string;
     function GetRelativeFileNames: string;
     function GetFromPath: string;
   public
-    constructor Create(aCopyOutOperation: TFileSourceCopyOperation);
+    constructor Create(aCopyOutOperation: TFileSourceCopyOperation; Modal: Boolean = False);
     destructor Destroy; override;
     procedure ShowWaitForm; override;
     procedure Done; override;
@@ -56,7 +57,7 @@
                                    State: TFileSourceOperationState);
   end;
 
-  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+  TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
   // Callback may be called either asynchoronously or synchronously (for modal operations)
   // pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +64,8 @@
   TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 
 procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
                           FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +76,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc); overload;
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False); overload;
 
 procedure RunExtDiffer(CompareList: TStringList);
 
@@ -82,7 +85,7 @@
 procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
 
 procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 
 procedure ShowViewerByGlob(const sFileName: String);
 procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +97,7 @@
   SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
   uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
   uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
-  DCStrUtils, uFileSourceProperty,
+  DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
   uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
   uMultiArchiveFileSource, fFileExecuteYourSelf;
 
@@ -265,7 +268,7 @@
     ShowDiffer(LeftName, RightName);
 end;
 
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
 begin
   if gExternalTools[etDiffer].Enabled then
   begin
@@ -275,7 +278,7 @@
       RunExtDiffer(CompareList);
   end
   else
-    ShowDiffer(CompareList[0], CompareList[1], WaitData);
+    ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
 end;
 
 procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -349,7 +352,7 @@
 
 { TEditorWaitData }
 
-constructor TEditorWaitData.Create(aCopyOutOperation: TFileSourceCopyOperation);
+constructor TEditorWaitData.Create(aCopyOutOperation: TFileSourceCopyOperation; Modal: Boolean = False);
 var
   I: Integer;
   aFileSource: ITempFileSystemFileSource;
@@ -363,6 +366,7 @@
     FileTimes[I] := mbFileAge(Files[I].FullPath);
   SourceFileSource := aFileSource;
   TargetFileSource := aCopyOutOperation.FileSource as IFileSource;
+  FModal := Modal;
 end;
 
 destructor TEditorWaitData.Destroy;
@@ -389,12 +393,15 @@
 
 function TEditorWaitData.GetFromPath: string;
 begin
-  Result := TargetFileSource.CurrentAddress + TargetPath;
+  if StrBegins(TargetPath, TargetFileSource.CurrentAddress) then
+    Result := TargetPath // Workaround for TGioFileSource
+  else
+    Result := TargetFileSource.CurrentAddress + TargetPath;
 end;
 
 procedure TEditorWaitData.ShowWaitForm;
 begin
-  ShowFileEditExternal(GetRelativeFileNames, GetFromPath, Self);
+  ShowFileEditExternal(GetRelativeFileNames, GetFromPath, Self, FModal);
 end;
 
 procedure TEditorWaitData.Done;
@@ -422,7 +429,10 @@
         begin
           Operation.AddStateChangedListener([fsosStopped], @OnCopyInStateChanged);
           Operation.FileExistsOption:= fsoofeOverwrite;
-          OperationsManager.AddOperation(Operation);
+          if FModal then
+            OperationsManager.AddOperationModal(Operation)
+          else
+            OperationsManager.AddOperation(Operation);
           DoNotFreeYet:= True; // Will be free in operation
         end;
       end
@@ -635,7 +645,8 @@
 { PrepareData }
 
 function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
-                     FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+                     FunctionToCall: TFileSourceOperationStateChangedNotify;
+                     Modal: Boolean = False): TPrepareDataResult;
 var
   aFile: TFile;
   I: Integer;
@@ -669,6 +680,8 @@
                        TempFileSource,
                        TempFiles,
                        TempFileSource.FileSystemRoot);
+      if Operation is TWfxPluginCopyOutOperation then
+        (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
     finally
       TempFiles.Free;
     end;
@@ -681,7 +694,10 @@
 
     Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
 
-    OperationsManager.AddOperation(Operation);
+    if Modal then
+      OperationsManager.AddOperationModal(Operation)
+    else
+      OperationsManager.AddOperation(Operation);
 
     Exit(pdrInCallback);
   end;
@@ -762,6 +778,7 @@
   protected
     FFunc: TToolDataPreparedProc;
     FCallOnFail: Boolean;
+    FModal: Boolean;
     FFailed: Boolean;
     FFileList1: TStringList;
     FFileList2: TStringList;
@@ -777,7 +794,8 @@
   public
     constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
     procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                      FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                      FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                      Modal: Boolean = False);
     destructor Destroy; override;
   end;
 
@@ -788,11 +806,14 @@
 end;
 
 procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
-                                       FileSource2: IFileSource; var SelectedFiles2: TFiles);
+                                       FileSource2: IFileSource; var SelectedFiles2: TFiles;
+                                       Modal: Boolean = False);
 var
   I: Integer;
 begin
-  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+  FModal := Modal;
+
+  case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
   pdrSynchronous:
     begin
       FFileList1 := TStringList.Create;
@@ -804,7 +825,7 @@
     begin
       try
         if FCallOnFail then
-          FFunc(nil, nil);
+          FFunc(nil, nil, FModal);
       finally
         Free;
       end;
@@ -812,7 +833,7 @@
     end;
   end;
 
-  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+  case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
   pdrSynchronous:
     begin
       FFileList2 := TStringList.Create;
@@ -840,7 +861,7 @@
   begin
     if Operation.Result = fsorFinished then
     begin
-      FWaitData1 := TEditorWaitData.Create(Operation as TFileSourceCopyOperation);
+      FWaitData1 := TEditorWaitData.Create(Operation as TFileSourceCopyOperation, FModal);
       FFileList1 := FWaitData1.GetFileList;
     end
     else
@@ -863,7 +884,7 @@
   begin
     if Operation.Result = fsorFinished then
     begin
-      FWaitData2 := TEditorWaitData.Create(Operation as TFileSourceCopyOperation);
+      FWaitData2 := TEditorWaitData.Create(Operation as TFileSourceCopyOperation, FModal);
       FFileList2 := FWaitData2.GetFileList;
     end
     else
@@ -886,7 +907,7 @@
     if FFailed then
     begin
       if FCallOnFail then
-        FFunc(nil, nil);
+        FFunc(nil, nil, FModal);
       Exit;
     end;
     if Assigned(FFileList2) then
@@ -897,10 +918,10 @@
       WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
       FWaitData1 := nil;
       FWaitData2 := nil;
-      FFunc(FFileList1, WaitData);
+      FFunc(FFileList1, WaitData, FModal);
     end
     else
-      FFunc(FFileList1, nil);
+      FFunc(FFileList1, nil, FModal);
   finally
     Free;
   end;
@@ -936,7 +957,8 @@
 
 procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
                           FileSource2: IFileSource; File2: TFile;
-                          FunctionToCall: TToolDataPreparedProc);
+                          FunctionToCall: TToolDataPreparedProc;
+                          Modal: Boolean = False);
 var Files1, Files2: TFiles;
 begin
   Files1 := TFiles.Create(File1.Path);
@@ -946,7 +968,7 @@
     try
       Files2.Add(File2.Clone);
       with TToolDataPreparator2.Create(FunctionToCall) do
-        Prepare(FileSource1, Files1, FileSource2, Files2);
+        Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
     finally
       Files2.Free;
     end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas	(revision 7965)
+++ src/uShowMsg.pas	(working copy)
@@ -54,9 +54,14 @@
                 msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
                 msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
                 msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
-                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+                msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+                // Actions, they do not close the form and therefore have no corresponding result value:
+                msmbCompare);
 
+  TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
 
+  TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
   { TDialogMainThread }
 
   TDialogMainThread = class
@@ -103,7 +108,7 @@
 procedure msgError(const sMsg: String); overload;
 procedure msgError(Thread: TThread; const sMsg: String); overload;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
 function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
 
 function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
       Caption:= cLngButton[Buttons[iIndex]];
       Parent:= frmMsg.pnlButtons;
       Constraints.MinWidth:= MinButtonWidth;
-      Tag:= iIndex;
+      if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+        Tag:= -2-iIndex
+      else
+        Tag:= iIndex;
       OnClick:= frmMsg.ButtonClick;
       OnMouseUp:= frmMsg.MouseUpEvent;
       if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
     for iIndex:= 0 to pred(frmMsg.ComponentCount) do
     begin
       if frmMsg.Components[iIndex] is TButton then
-      begin
-        with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
-      end;
+        with frmMsg.Components[iIndex] as TButton do
+        begin
+          if Tag >= 0 then
+            TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+          else
+            TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+        end;
     end;
   end;
 
@@ -332,7 +344,10 @@
       MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
       with MenuItem do
       begin
-        Tag:= iIndex;
+        if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+          Tag:= -2-iIndex
+        else
+          Tag:= iIndex;
         Caption:= cLngButton[Buttons[iIndex]];
         OnClick:= frmMsg.ButtonClick;
         frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
   end;
 end;
 
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+  Buttons: array of TMyMsgButton;
+  ActionHandler: TMyMsgActionHandler;
+  procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+  ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
 var
   frmMsg:TfrmMsg;
+  MsgBoxHelper: TMsgBoxHelper = nil;
+  I: Integer;
 begin
   frmMsg:=TfrmMsg.Create(Application);
   try
+    MsgBoxHelper := TMsgBoxHelper.Create();
+    SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+    for I := Low(Buttons) to High(Buttons) do
+      MsgBoxHelper.Buttons[I] := Buttons[I];
+    MsgBoxHelper.ActionHandler := ActionHandler;
+    frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
   
-   SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+    SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
   
     frmMsg.ShowModal;
     if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
       Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
   finally
     frmMsg.Free;
+    MsgBoxHelper.Free;
   end;
 end;
 
@@ -769,6 +804,7 @@
   cLngButton[msmbRetry]            := rsDlgButtonRetry;
   cLngButton[msmbAbort]            := rsDlgButtonAbort;
   cLngButton[msmbRetryAdmin]       := rsDlgButtonRetryAdmin;
+  cLngButton[msmbCompare]          := rsDlgButtonCompare;
 
   for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
   begin
bug1536-preview14.patch (63,902 bytes)   
Fixed in Revision8197
Operating system
Widgetset
Architecture

Activities

cordylus

2018-01-08 08:21

developer   ~0002497

Last edited: 2018-01-08 17:03

Загрузил предварительный патч.

Для всех операций, кроме CopyOut из WCX, когда плагин не поддерживает фоновые операции. GIO не тестировалось.

Изменения в следующих файлах под вопросом, они потребовались для запуска модальной операции в процессе другой модальной операций (WFX FTP):
src/filesources/ufilesourceoperationmisc.pas
src/platform/uosforms.pas

cordylus

2018-01-08 18:28

developer   ~0002501

Last edited: 2018-01-09 03:06

Новые версии патчей в соответствии с обсуждением здесь: https://doublecmd.sourceforge.io/forum/viewtopic.php?p=22589#p22589

2 - фикс сборки под линукс
3 - фикс закрытия по крестику после нажатия кнопки "сравнить"
4 - модальная операция распаковки
5 - модальный диффер
6 - фикс для gio

Alexx2000

2018-01-09 08:11

administrator   ~0002502

Изменения "src/filesources/ufilesourceoperationmisc.pas" теоретически не должны иметь негативных последствий.

Изменения "src/platform/uosforms.pas" - время покажет.

>>>5 - модальный диффер

Полагаю это временный вариант? Все таки модальным диффер должен быть только в этом конкретном случае.

cordylus

2018-01-10 01:34

developer   ~0002503

Да, модальность в таком виде только для проверки добавлена. Надеялся, что обойдется вообще без нее - под win почему-то и без нее работает. В конечной версии сделаю только для вызовов из этого окна.

А в перспективе есть идея само окно подтверждения file exists сделать немодальным, что скажете? Открыть его немодально и заблокировать поток операции на mutex, который освободить при закрытии окна. По идее, так для самого потока AskQuestion останется "модальным", но всё остальное приложение блокироваться не будет.

cordylus

2018-01-10 05:55

developer   ~0002504

Last edited: 2018-01-10 23:04

7 - добавлен отладочный вывод
8 - фикс сборки под линукс
9 - модальные операции и диффер только из окна операции
10 - фикс сборки под линукс

cordylus

2018-01-10 23:11

developer   ~0002505

Можно как-то сделать опциональную поддержку GIO под Windows, как с SVG сделали? У GIMP в папке libgio dll тоже есть. file:// в таком случае я же смогу открывать?

Alexx2000

2018-01-14 00:57

administrator   ~0002507

На постоянно его включать мне кажется излишним. А вот чисто для теста можно включить, надо лишь поправить имена библиотек, и добавить регистрацию GioFileSource. Полагаю file:// будет работать.

Хотя как по мне проще поставить Линукс в VirtualBox и тестировать в реальном окружении. У меня к примеру десяток виртуальных машин для этого.

cordylus

2018-01-19 10:30

developer   ~0002508

Last edited: 2018-01-20 01:00

11 - откачены изменения в gio до начальной версии, попытка исправить в другом файле
12 - наконец, рабочий фикс gio, причина оказалась в том, что File.FullPath содержит протокол (CurrentAddress), а от Files.Path при копировании ожидалось, что не будет его содержать
13 - альтернативный фикс, отрезание CurrentAddress вместо дополнительной проверки в CopyOut. Плюс workaround для отображения правильного пути обратного копирования.
14 - модальное окно ожидания внешнего редактора и операция обратного копирования (при запуске из окна замены). Основан на версии 12 + фикс пути из версии 13.

Alexx2000

2018-07-08 14:35

administrator   ~0002671

Применил последнюю версию патча.

Issue History

Date Modified Username Field Change
2016-09-19 02:22 cordylus New Issue
2018-01-08 08:21 cordylus File Added: bug1536-preview1.patch
2018-01-08 08:21 cordylus Note Added: 0002497
2018-01-08 16:51 cordylus File Added: bug1536-preview2.patch
2018-01-08 17:03 cordylus Note Edited: 0002497
2018-01-08 18:22 cordylus File Added: bug1536-preview3.patch
2018-01-08 18:28 cordylus Note Added: 0002501
2018-01-08 22:56 cordylus File Added: bug1536-preview4.patch
2018-01-09 01:10 cordylus File Added: bug1536-preview5.patch
2018-01-09 02:58 cordylus File Added: bug1536-preview6.patch
2018-01-09 03:06 cordylus Note Edited: 0002501
2018-01-09 08:11 Alexx2000 Note Added: 0002502
2018-01-10 01:09 cordylus File Added: bug1536-preview7.patch
2018-01-10 01:34 cordylus Note Added: 0002503
2018-01-10 01:39 cordylus File Added: bug1536-preview8.patch
2018-01-10 05:53 cordylus File Added: bug1536-preview9.patch
2018-01-10 05:55 cordylus Note Added: 0002504
2018-01-10 19:18 cordylus File Added: bug1536-preview10.patch
2018-01-10 23:04 cordylus Note Edited: 0002504
2018-01-10 23:11 cordylus Note Added: 0002505
2018-01-13 21:47 cordylus File Added: bug1536-preview11.patch
2018-01-14 00:57 Alexx2000 Note Added: 0002507
2018-01-17 09:44 cordylus File Added: bug1536-preview12.patch
2018-01-19 10:12 cordylus File Added: bug1536-preview13.patch
2018-01-19 10:30 cordylus Note Added: 0002508
2018-01-19 10:34 cordylus Note Edited: 0002508
2018-01-20 00:58 cordylus File Added: bug1536-preview14.patch
2018-01-20 01:00 cordylus Note Edited: 0002508
2018-07-08 14:35 Alexx2000 Note Added: 0002671
2018-07-08 14:35 Alexx2000 Status new => feedback
2018-07-08 14:36 Alexx2000 Fixed in Revision => 8197
2018-07-08 14:36 Alexx2000 Target Version => 0.9.0
2018-12-10 09:00 Alexx2000 Status feedback => resolved
2018-12-10 09:00 Alexx2000 Fixed in Version => 0.9.0
2018-12-10 09:00 Alexx2000 Resolution open => fixed
2018-12-10 09:00 Alexx2000 Assigned To => Alexx2000
2021-09-05 15:10 Alexx2000 Status resolved => closed