1 /////////////////////////////////////////////////////////////////////////////
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or (at
6 // your option) any later version.
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 /////////////////////////////////////////////////////////////////////////////
20 * @brief Code file routines
22 // ID line follows -- this is updated by SVN
23 // $Id: PatchTool.cpp 6858 2009-06-25 07:48:26Z kimmov $
26 #include "UnicodeString.h"
27 #include "DiffWrapper.h"
28 #include "PathContext.h"
29 #include "PatchTool.h"
36 static char THIS_FILE[] = __FILE__;
40 * @brief Default constructor.
42 CPatchTool::CPatchTool() : m_bOpenToEditor(false)
47 * @brief Default destructor.
49 CPatchTool::~CPatchTool()
54 * @brief Adds files to list for patching.
55 * @param [in] file1 First file to add.
56 * @param [in] file2 Second file to add.
58 void CPatchTool::AddFiles(const String &file1, const String &file2)
64 // TODO: Read and add file's timestamps
65 m_fileList.push_back(files);
69 * @brief Add files with alternative paths.
70 * This function adds files with alternative paths. Alternative path is the
71 * one that is added to the patch file. So while @p file1 and @p file2 are
72 * paths in disk (can be temp file names), @p altPath1 and @p altPath2 are
73 * "visible " paths printed to the patch file.
74 * @param [in] file1 First path in disk.
75 * @param [in] altPath1 First path as printed to the patch file.
76 * @param [in] file2 Second path in disk.
77 * @param [in] altPath2 Second path as printed to the patch file.
79 void CPatchTool::AddFiles(const String &file1, const String &altPath1,
80 const String &file2, const String &altPath2)
85 files.pathLeft = altPath1;
86 files.pathRight = altPath2;
88 // TODO: Read and add file's timestamps
89 m_fileList.push_back(files);
93 * @brief Create a patch from files given.
94 * @note Files can be given using AddFiles() or selecting using
97 int CPatchTool::CreatePatch()
106 // If files already inserted, add them to dialog
107 for(std::vector<PATCHFILES>::iterator iter = m_fileList.begin(); iter != m_fileList.end(); ++iter)
109 dlgPatch.AddItem(*iter);
112 if (ShowDialog(&dlgPatch))
114 if (!paths_CreateIfNeeded(paths_GetPathOnly(dlgPatch.m_fileResult)))
116 LangMessageBox(IDS_FOLDER_NOTEXIST, MB_OK | MB_ICONSTOP);
120 // Select patch create -mode
121 m_diffWrapper.SetCreatePatchFile(dlgPatch.m_fileResult);
122 m_diffWrapper.SetAppendFiles(dlgPatch.m_appendFile);
123 m_diffWrapper.SetPrediffer(NULL);
125 size_t fileCount = dlgPatch.GetItemCount();
127 m_diffWrapper.WritePatchFileHeader(dlgPatch.m_outputStyle, dlgPatch.m_appendFile);
128 m_diffWrapper.SetAppendFiles(true);
130 for (int index = 0; index < fileCount; index++)
132 const PATCHFILES& files = dlgPatch.GetItemAt(index);
133 String filename1 = files.lfile.length() == 0 ? _T("NUL") : files.lfile;
134 String filename2 = files.rfile.length() == 0 ? _T("NUL") : files.rfile;
136 // Set up DiffWrapper
137 m_diffWrapper.SetPaths(PathContext(filename1, filename2), false);
138 m_diffWrapper.SetAlternativePaths(PathContext(files.pathLeft, files.pathRight));
139 m_diffWrapper.SetCompareFiles(PathContext(files.lfile, files.rfile));
140 bDiffSuccess = m_diffWrapper.RunFileDiff();
141 m_diffWrapper.GetDiffStatus(&status);
145 LangMessageBox(IDS_FILEERROR, MB_ICONSTOP);
149 else if (status.bBinaries)
151 LangMessageBox(IDS_CANNOT_CREATE_BINARYPATCH, MB_ICONSTOP);
155 else if (status.bPatchFileFailed)
157 String errMsg = string_format_string1(_("Could not write to file %1."), dlgPatch.m_fileResult);
158 AfxMessageBox(errMsg.c_str(), MB_ICONSTOP);
164 m_diffWrapper.WritePatchFileTerminator(dlgPatch.m_outputStyle);
166 if (bResult && fileCount > 0)
168 LangMessageBox(IDS_DIFF_SUCCEEDED, MB_ICONINFORMATION|MB_DONT_DISPLAY_AGAIN,
171 m_sPatchFile = dlgPatch.m_fileResult;
172 m_bOpenToEditor = dlgPatch.m_openToEditor;
176 dlgPatch.ClearItems();
181 * @brief Show patch options dialog and check options selected.
182 * @return TRUE if user wants to create a patch (didn't cancel dialog).
184 bool CPatchTool::ShowDialog(CPatchDlg *pDlgPatch)
186 DIFFOPTIONS diffOptions = {0};
187 PATCHOPTIONS patchOptions;
190 if (pDlgPatch->DoModal() == IDOK)
192 // There must be one filepair
193 if (pDlgPatch->GetItemCount() < 1)
196 // These two are from dropdown list - can't be wrong
197 patchOptions.outputStyle = pDlgPatch->m_outputStyle;
198 patchOptions.nContext = pDlgPatch->m_contextLines;
200 // Checkbox - can't be wrong
201 patchOptions.bAddCommandline = !!pDlgPatch->m_includeCmdLine;
202 m_diffWrapper.SetPatchOptions(&patchOptions);
204 // These are from checkboxes and radiobuttons - can't be wrong
205 diffOptions.nIgnoreWhitespace = pDlgPatch->m_whitespaceCompare;
206 diffOptions.bIgnoreBlankLines = pDlgPatch->m_ignoreBlanks;
207 m_diffWrapper.SetAppendFiles(pDlgPatch->m_appendFile);
209 // Use this because non-sensitive setting can't write
210 // patch file EOLs correctly
211 diffOptions.bIgnoreEol = pDlgPatch->m_ignoreEOLDifference;
213 diffOptions.bIgnoreCase = pDlgPatch->m_caseSensitive == false;
214 m_diffWrapper.SetOptions(&diffOptions);
223 * @brief Returns filename and path for patch-file
225 String CPatchTool::GetPatchFile() const
231 * @brief Returns TRUE if user wants to open patch file
232 * to external editor (specified in WinMerge options).
234 bool CPatchTool::GetOpenToEditor() const
236 return m_bOpenToEditor;