2 * @file DiffFileData.cpp
4 * @brief Code for DiffFileData class
6 * @date Created: 2003-08-22
10 #include "DiffFileData.h"
14 #include "FileLocation.h"
17 #include "FileTransform.h"
22 * @brief Simple initialization of DiffFileData
23 * @note Diffcounts are initialized to invalid values, not zeros.
25 DiffFileData::DiffFileData()
26 : m_inf(new file_data[2])
29 for (i = 0; i < 2; ++i)
30 memset(&m_inf[i], 0, sizeof(m_inf[i]));
35 /** @brief deallocate member data */
36 DiffFileData::~DiffFileData()
42 /** @brief Open file descriptors in the inf structure (return false if failure) */
43 bool DiffFileData::OpenFiles(const String& szFilepath1, const String& szFilepath2)
45 m_FileLocation[0].setPath(szFilepath1);
46 m_FileLocation[1].setPath(szFilepath2);
47 bool b = DoOpenFiles();
53 /** @brief stash away true names for display, before opening files */
54 void DiffFileData::SetDisplayFilepaths(const String& szTrueFilepath1, const String& szTrueFilepath2)
56 m_sDisplayFilepath[0] = szTrueFilepath1;
57 m_sDisplayFilepath[1] = szTrueFilepath2;
61 /** @brief Open file descriptors in the inf structure (return false if failure) */
62 bool DiffFileData::DoOpenFiles()
66 for (int i = 0; i < 2; ++i)
68 // Fill in 8-bit versions of names for diffutils (WinMerge doesn't use these)
69 // Actual paths are m_FileLocation[i].filepath
70 // but these are often temporary files
71 // Displayable (original) paths are m_sDisplayFilepath[i]
72 m_inf[i].name = _strdup(ucr::toSystemCP(m_sDisplayFilepath[i]).c_str());
73 if (m_inf[i].name == nullptr)
76 // Open up file descriptors
77 // Always use O_BINARY mode, to avoid terminating file read on ctrl-Z (DOS EOF)
78 // Also, WinMerge-modified diffutils handles all three major eol styles
79 if (m_inf[i].desc == 0)
81 _tsopen_s(&m_inf[i].desc, TFile(m_FileLocation[i].filepath).wpath().c_str(),
82 O_RDONLY | O_BINARY, _SH_DENYWR, _S_IREAD);
84 if (m_inf[i].desc < 0)
87 // Get file stats (diffutils uses these)
88 if (myfstat(m_inf[i].desc, &m_inf[i].stat) != 0)
93 if (strutils::compare_nocase(m_FileLocation[0].filepath,
94 m_FileLocation[1].filepath) == 0)
96 m_inf[1].desc = m_inf[0].desc;
104 /** @brief Clear inf structure to pristine */
105 void DiffFileData::Reset()
107 assert(m_inf != nullptr);
108 // If diffutils put data in, have it cleanup
111 cleanup_file_buffers(m_inf);
114 // clean up any open file handles, and zero stuff out
115 // open file handles might be leftover from a failure in DiffFileData::OpenFiles
116 for (int i = 0; i < 2; ++i)
118 if (m_inf[1].desc == m_inf[0].desc)
122 free((void *)m_inf[i].name);
123 m_inf[i].name = nullptr;
125 if (m_inf[i].desc > 0)
127 _close(m_inf[i].desc);
130 memset(&m_inf[i], 0, sizeof(m_inf[i]));
135 * @brief Invoke appropriate plugins for prediffing
136 * return false if anything fails
137 * caller has to DeleteFile filepathTransformed, if it differs from filepath
139 bool DiffFileData::Filepath_Transform(bool bForceUTF8,
140 const FileTextEncoding & encoding, const String & filepath, String & filepathTransformed,
141 const String& filteredFilenames, PrediffingInfo * infoPrediffer)
143 // third step : prediff (plugins)
144 bool bMayOverwrite = // temp variable set each time it is used
145 (filepathTransformed != filepath); // may overwrite if we've already copied to temp file
147 // FileTransform_Prediffing tries each prediffer for the pointed out filteredFilenames
148 // if a prediffer fails, we consider it is not the good one, that's all
149 // FileTransform_Prediffing returns `false` only if the prediffer works,
150 // but the data can not be saved to disk (no more place ??)
151 if (!FileTransform::Prediffing(infoPrediffer, filepathTransformed, filteredFilenames, bMayOverwrite))
154 if ((encoding.m_unicoding && encoding.m_unicoding != ucr::UTF8) || bForceUTF8)
156 // fourth step : prepare for diffing
157 // may overwrite if we've already copied to temp file
158 bool bMayOverwrite1 = 0 != strutils::compare_nocase(filepathTransformed, filepath);
159 if (!FileTransform::AnyCodepageToUTF8(encoding.m_codepage, filepathTransformed, bMayOverwrite1))