* @brief Implementation file for CDiffTextBuffer
*
*/
-// ID line follows -- this is updated by SVN
-// $Id: DiffTextBuffer.cpp 7082 2010-01-03 22:15:50Z sdottaka $
#include "StdAfx.h"
+#include "DiffTextBuffer.h"
+#include <Poco/Exception.h>
#include "UniFile.h"
#include "files.h"
-#include "cs2cs.h"
#include "locality.h"
-#include "coretools.h"
-#include "Merge.h"
+#include "paths.h"
#include "OptionsDef.h"
+#include "OptionsMgr.h"
#include "Environment.h"
#include "MergeLineFlags.h"
#include "MergeDoc.h"
#include "FileTransform.h"
#include "FileTextEncoding.h"
-#include "DiffTextBuffer.h"
#include "codepage_detect.h"
+#include "TFile.h"
+
+using Poco::Exception;
#ifdef _DEBUG
#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
#endif
static bool IsTextFileStylePure(const UniMemFile::txtstats & stats);
-static CString GetLineByteTimeReport(UINT lines, __int64 bytes,
- const COleDateTime & start);
-static void EscapeControlChars(CString &s);
-static LPCTSTR GetEol(const CString &str);
static CRLFSTYLE GetTextFileStyle(const UniMemFile::txtstats & stats);
/**
}
/**
- * @brief Return a string giving #lines and #bytes and how much time elapsed.
- * @param [in] lines Count of lines.
- * @param [in] bytes Count of bytes.
- * @param [in] start Time used.
- * @return Formatted string.
- */
-static CString GetLineByteTimeReport(UINT lines, __int64 bytes,
- const COleDateTime & start)
-{
- String sLines = locality::NumToLocaleStr((int)lines);
- String sBytes = locality::NumToLocaleStr(bytes);
- COleDateTimeSpan duration = COleDateTime::GetCurrentTime() - start;
- String sMinutes = locality::NumToLocaleStr((int)duration.GetTotalMinutes());
- CString str;
- str.Format(_T("%s lines (%s byte) saved in %sm%02ds")
- , sLines.c_str(), sBytes.c_str(), sMinutes.c_str()
- , duration.GetSeconds()
- );
- return str;
-}
-
-/**
- * @brief Escape control characters.
- * @param [in,out] s Line of text excluding eol chars.
- *
- * @note Escape sequences follow the pattern
- * (leadin character, high nibble, low nibble, leadout character).
- * The leadin character is '\x0F'. The leadout character is a backslash.
- */
-static void EscapeControlChars(CString &s)
-{
- // Compute buffer length required for escaping
- int n = s.GetLength();
- LPCTSTR q = s;
- int i = n;
- while (i)
- {
- TCHAR c = q[--i];
- // Is it a control character in the range 0..31 except TAB?
- if (!(c & ~_T('\x1F')) && c != _T('\t'))
- {
- n += 3; // Need 3 extra characters to escape
- }
- }
- // Reallocate accordingly
- i = s.GetLength();
- LPTSTR p = s.GetBufferSetLength(n);
- // Copy/translate characters starting at end of string
- while (i)
- {
- TCHAR c = p[--i];
- // Is it a control character in the range 0..31 except TAB?
- if (!(c & ~_T('\x1F')) && c != _T('\t'))
- {
- // Bitwise OR with 0x100 so _itot() will output 3 hex digits
- _itot(0x100 | c, p + n - 4, 16);
- // Replace terminating zero with leadout character
- p[n - 1] = _T('\\');
- // Prepare to replace 1st hex digit with leadin character
- c = _T('\x0F');
- n -= 3;
- }
- p[--n] = c;
- }
-}
-
-/**
* @brief Get file's EOL type.
* @param [in] stats File's text stats.
* @return EOL type.
{
// Check if file has more than one EOL type.
if (!IsTextFileStylePure(stats))
- return CRLF_STYLE_MIXED;
+ return CRLFSTYLE::MIXED;
else if (stats.ncrlfs >= stats.nlfs)
{
if (stats.ncrlfs >= stats.ncrs)
- return CRLF_STYLE_DOS;
+ return CRLFSTYLE::DOS;
else
- return CRLF_STYLE_MAC;
+ return CRLFSTYLE::MAC;
}
else
{
if (stats.nlfs >= stats.ncrs)
- return CRLF_STYLE_UNIX;
+ return CRLFSTYLE::UNIX;
else
- return CRLF_STYLE_MAC;
+ return CRLFSTYLE::MAC;
}
}
* @param [in] nLineIndex Index of the line to get.
* @param [out] strLine Returns line text in the index.
*/
-BOOL CDiffTextBuffer::GetLine(int nLineIndex, CString &strLine) const
+bool CDiffTextBuffer::GetLine(int nLineIndex, CString &strLine) const
{
int nLineLength = CCrystalTextBuffer::GetLineLength(nLineIndex);
if (nLineLength < 0)
- return FALSE;
+ return false;
else if (nLineLength == 0)
strLine.Empty();
else
{
- _tcsncpy(strLine.GetBuffer(nLineLength + 1),
+ _tcsncpy_s(strLine.GetBuffer(nLineLength + 1), nLineLength + 1,
CCrystalTextBuffer::GetLineChars(nLineIndex), nLineLength);
strLine.ReleaseBuffer(nLineLength);
}
- return TRUE;
+ return true;
}
/**
* @brief Set the buffer modified status.
- * @param [in] bModified New modified status, TRUE if buffer has been
+ * @param [in] bModified New modified status, true if buffer has been
* modified since last saving.
*/
-void CDiffTextBuffer::SetModified(BOOL bModified /*= TRUE*/)
+void CDiffTextBuffer:: /* virtual override */
+SetModified(bool bModified /*= true*/)
{
CCrystalTextBuffer::SetModified (bModified);
m_pOwnerDoc->SetModifiedFlag (bModified);
* @param [out] strLine Returns line text in the index. Existing content
* of this string is overwritten.
*/
-BOOL CDiffTextBuffer::GetFullLine(int nLineIndex, CString &strLine) const
+bool CDiffTextBuffer::GetFullLine(int nLineIndex, CString &strLine) const
{
int cchText = GetFullLineLength(nLineIndex);
if (cchText == 0)
{
strLine.Empty();
- return FALSE;
+ return false;
}
LPTSTR pchText = strLine.GetBufferSetLength(cchText);
memcpy(pchText, GetLineChars(nLineIndex), cchText * sizeof(TCHAR));
- return TRUE;
+ return true;
}
-void CDiffTextBuffer::AddUndoRecord(BOOL bInsert, const CPoint & ptStartPos,
- const CPoint & ptEndPos, LPCTSTR pszText, int cchText,
- int nLinesToValidate, int nActionType /*= CE_ACTION_UNKNOWN*/,
- CDWordArray *paSavedRevisonNumbers)
+void CDiffTextBuffer:: /* virtual override */
+AddUndoRecord(bool bInsert, const CPoint & ptStartPos,
+ const CPoint & ptEndPos, LPCTSTR pszText, size_t cchText,
+ int nActionType /*= CE_ACTION_UNKNOWN*/,
+ CDWordArray *paSavedRevisionNumbers /*= nullptr*/)
{
CGhostTextBuffer::AddUndoRecord(bInsert, ptStartPos, ptEndPos, pszText,
- cchText, nLinesToValidate, nActionType, paSavedRevisonNumbers);
+ cchText, nActionType, paSavedRevisionNumbers);
if (m_aUndoBuf[m_nUndoPosition - 1].m_dwFlags & UNDO_BEGINGROUP)
{
m_pOwnerDoc->undoTgt.erase(m_pOwnerDoc->curUndo, m_pOwnerDoc->undoTgt.end());
- m_pOwnerDoc->undoTgt.push_back(m_pOwnerDoc->GetView(m_nThisPane));
+ m_pOwnerDoc->undoTgt.push_back(m_nThisPane);
m_pOwnerDoc->curUndo = m_pOwnerDoc->undoTgt.end();
}
}
+
/**
* @brief Checks if a flag is set for line.
* @param [in] line Index (0-based) for line.
* @param [in] flag Flag to check.
- * @return TRUE if flag is set, FALSE otherwise.
+ * @return true if flag is set, false otherwise.
*/
-BOOL CDiffTextBuffer::FlagIsSet(UINT line, DWORD flag) const
+bool CDiffTextBuffer::FlagIsSet(UINT line, DWORD flag) const
{
return ((m_aLines[line].m_dwFlags & flag) == flag);
}
{
SetLineFlag(ct,
LF_INVISIBLE | LF_DIFF | LF_TRIVIAL | LF_MOVED | LF_SNP,
- FALSE, FALSE, FALSE);
+ false, false, false);
}
}
/**
* @brief Called when line has been edited.
* After editing a line, we don't know if there is a diff or not.
- * So we clear the LF_DIFF flag (and it is more easy to read during edition).
+ * So we clear the LF_DIFF flag (and it is more easy to read during editing).
* Rescan will set the proper color.
* @param [in] nLine Line that has been edited.
*/
-void CDiffTextBuffer::OnNotifyLineHasBeenEdited(int nLine)
+void CDiffTextBuffer:: /* virtual override */
+OnNotifyLineHasBeenEdited(int nLine)
{
- SetLineFlag(nLine, LF_DIFF, FALSE, FALSE, FALSE);
- SetLineFlag(nLine, LF_TRIVIAL, FALSE, FALSE, FALSE);
- SetLineFlag(nLine, LF_MOVED, FALSE, FALSE, FALSE);
- SetLineFlag(nLine, LF_SNP, FALSE, FALSE, FALSE);
+ SetLineFlag(nLine, LF_DIFF, false, false, false);
+ SetLineFlag(nLine, LF_TRIVIAL, false, false, false);
+ SetLineFlag(nLine, LF_MOVED, false, false, false);
+ SetLineFlag(nLine, LF_SNP, false, false, false);
CGhostTextBuffer::OnNotifyLineHasBeenEdited(nLine);
}
/**
- * @brief Set the folder for temp files.
- * @param [in] path Temp files folder.
- */
-void CDiffTextBuffer::SetTempPath(const String &path)
-{
- m_strTempPath = path;
-}
-
-/**
- * @brief Is the buffer initialized?
- * @return TRUE if the buffer is initialized, FALSE otherwise.
- */
-bool CDiffTextBuffer::IsInitialized() const
-{
- return !!m_bInit;
-}
-
-/**
* @brief Load file from disk into buffer
*
* @param [in] pszFileNameInit File to load
* @note If this method fails, it calls InitNew so the CDiffTextBuffer is in a valid state
*/
int CDiffTextBuffer::LoadFromFile(LPCTSTR pszFileNameInit,
- PackingInfo * infoUnpacker, LPCTSTR sToFindUnpacker, BOOL & readOnly,
+ PackingInfo * infoUnpacker, LPCTSTR sToFindUnpacker, bool & readOnly,
CRLFSTYLE nCrlfStyle, const FileTextEncoding & encoding, CString &sError)
{
ASSERT(!m_bInit);
ASSERT(m_aLines.size() == 0);
// Unpacking the file here, save the result in a temporary file
- String sFileName(pszFileNameInit);
- if (infoUnpacker->bToBeScanned)
- {
- if (!FileTransform_Unpacking(sFileName, sToFindUnpacker, infoUnpacker,
- &m_unpackerSubcode))
- {
- InitNew(); // leave crystal editor in valid, empty state
- return FileLoadResult::FRESULT_ERROR_UNPACK;
- }
- }
- else
+ m_strTempFileName = pszFileNameInit;
+ if (!FileTransform::Unpacking(infoUnpacker, &m_unpackerSubcode, m_strTempFileName, sToFindUnpacker))
{
- if (!FileTransform_Unpacking(sFileName, infoUnpacker, &m_unpackerSubcode))
- {
- InitNew(); // leave crystal editor in valid, empty state
- return FileLoadResult::FRESULT_ERROR_UNPACK;
- }
+ InitNew(); // leave crystal editor in valid, empty state
+ return FileLoadResult::FRESULT_ERROR_UNPACK;
}
+
// we use the same unpacker for both files, so it must be defined after first file
- ASSERT(infoUnpacker->bToBeScanned != PLUGIN_AUTO);
+ ASSERT(infoUnpacker->m_PluginOrPredifferMode != PLUGIN_MODE::PLUGIN_AUTO);
// we will load the transformed file
- LPCTSTR pszFileName = sFileName.c_str();
+ LPCTSTR pszFileName = m_strTempFileName.c_str();
String sExt;
DWORD nRetVal = FileLoadResult::FRESULT_OK;
// Set encoding based on extension, if we know one
- SplitFilename(pszFileName, NULL, NULL, &sExt);
- CCrystalTextView::TextDefinition *def =
- CCrystalTextView::GetTextType(sExt.c_str());
+ paths::SplitFilename(pszFileName, nullptr, nullptr, &sExt);
+ CrystalLineParser::TextDefinition *def =
+ CrystalLineParser::GetTextType(sExt.c_str());
if (def && def->encoding != -1)
m_nSourceEncoding = def->encoding;
- UniFile *pufile = infoUnpacker->pufile;
- if (pufile == 0)
+ UniFile *pufile = infoUnpacker->m_pufile;
+ if (pufile == nullptr)
pufile = new UniMemFile;
// Now we only use the UniFile interface
sError = uniErr.GetError().c_str();
}
InitNew(); // leave crystal editor in valid, empty state
- goto LoadFromFileExit;
}
else
{
- if (infoUnpacker->pluginName.length() > 0)
+ if (infoUnpacker->m_PluginName.length() > 0)
{
// re-detect codepage
- FileTextEncoding encoding2;
int iGuessEncodingType = GetOptionsMgr()->GetInt(OPT_CP_DETECT);
- GuessCodepageEncoding(pszFileName, &encoding2,
- iGuessEncodingType);
+ FileTextEncoding encoding2 = codepage_detect::Guess(pszFileName, iGuessEncodingType);
pufile->SetUnicoding(encoding2.m_unicoding);
pufile->SetCodepage(encoding2.m_codepage);
pufile->SetBom(encoding2.m_bom);
String eol, preveol;
String sline;
bool done = false;
- UINT next_line_report = 100; // for trace messages
- UINT next_line_multiple = 5; // for trace messages
COleDateTime start = COleDateTime::GetCurrentTime(); // for trace messages
// Manually grow line array exponentially
{
// TODO: Should record lossy status of line
}
- AppendLine(lineno, sline.c_str(), sline.length());
+ AppendLine(lineno, sline.c_str(), static_cast<int>(sline.length()));
++lineno;
preveol = eol;
-#ifdef _DEBUG
- // send occasional line counts to trace
- // (at 100, 500, 1000, 5000, etc)
- if (lineno == next_line_report)
- {
- __int64 dwBytesRead = pufile->GetPosition();
- COleDateTimeSpan duration = COleDateTime::GetCurrentTime() - start;
- if (duration.GetTotalMinutes() > 0)
- {
- CString strace = GetLineByteTimeReport(lineno, dwBytesRead, start);
- TRACE(_T("%s\n"), (LPCTSTR)strace);
- }
- next_line_report = next_line_multiple * next_line_report;
- next_line_multiple = (next_line_multiple == 5) ? 2 : 5;
- }
-#endif // _DEBUG
} while (!done);
-#ifdef _DEBUG
- // Send report of duration to trace (if it took a while)
- COleDateTime end = COleDateTime::GetCurrentTime();
- COleDateTimeSpan duration = end - start;
- if (duration.GetTotalMinutes() > 0)
- {
- __int64 dwBytesRead = pufile->GetPosition();
- CString strace = GetLineByteTimeReport(lineno, dwBytesRead, start);
- TRACE(_T("%s\n"), (LPCTSTR)strace);
- }
-#endif // _DEBUG
-
// fix array size (due to our manual exponential growth
m_aLines.resize(lineno);
//Try to determine current CRLF mode (most frequent)
- if (nCrlfStyle == CRLF_STYLE_AUTOMATIC)
+ if (nCrlfStyle == CRLFSTYLE::AUTOMATIC)
{
nCrlfStyle = GetTextFileStyle(pufile->GetTxtStats());
}
- ASSERT(nCrlfStyle >= 0 && nCrlfStyle <= 3);
+ ASSERT (nCrlfStyle != CRLFSTYLE::AUTOMATIC);
SetCRLFMode(nCrlfStyle);
// At least one empty line must present
// (view does not work for empty buffers)
ASSERT(m_aLines.size() > 0);
- m_bInit = TRUE;
- m_bModified = FALSE;
- m_bUndoGroup = m_bUndoBeginGroup = FALSE;
+ m_bInit = true;
+ m_bModified = false;
+ m_bUndoGroup = m_bUndoBeginGroup = false;
m_nSyncPosition = m_nUndoPosition = 0;
ASSERT(m_aUndoBuf.size() == 0);
m_ptLastChange.x = m_ptLastChange.y = -1;
if (pufile->GetTxtStats().nlosses)
{
FileLoadResult::AddModifier(nRetVal, FileLoadResult::FRESULT_LOSSY);
- readOnly = TRUE;
+ readOnly = true;
}
}
-LoadFromFileExit:
// close the file now to free the handle
pufile->Close();
delete pufile;
// delete the file that unpacking may have created
if (_tcscmp(pszFileNameInit, pszFileName) != 0)
- if (!::DeleteFile(pszFileName))
+ {
+ try
{
- LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
- pszFileName, GetSysError(GetLastError()).c_str()));
+ TFile(pszFileName).remove();
}
-
+ catch (Exception& e)
+ {
+ LogErrorStringUTF8(e.displayText());
+ }
+ }
return nRetVal;
}
/**
* @brief Saves file from buffer to disk
*
- * @param bTempFile : FALSE if we are saving user files and
- * TRUE if we are saving workin-temp-files for diff-engine
+ * @param bTempFile : false if we are saving user files and
+ * true if we are saving working-temp-files for diff-engine
*
* @return SAVE_DONE or an error code (list in MergeDoc.h)
*/
-int CDiffTextBuffer::SaveToFile (LPCTSTR pszFileName,
- BOOL bTempFile, String & sError, PackingInfo * infoUnpacker /*= NULL*/,
- CRLFSTYLE nCrlfStyle /*= CRLF_STYLE_AUTOMATIC*/,
- BOOL bClearModifiedFlag /*= TRUE*/,
- BOOL bForceUTF8 /*= FALSE*/)
+int CDiffTextBuffer::SaveToFile (const String& pszFileName,
+ bool bTempFile, String & sError, PackingInfo * infoUnpacker /*= nullptr*/,
+ CRLFSTYLE nCrlfStyle /*= CRLFSTYLE::AUTOMATIC*/,
+ bool bClearModifiedFlag /*= true*/,
+ int nStartLine /*= 0*/, int nLines /*= -1*/)
{
- ASSERT (nCrlfStyle == CRLF_STYLE_AUTOMATIC || nCrlfStyle == CRLF_STYLE_DOS ||
- nCrlfStyle == CRLF_STYLE_UNIX || nCrlfStyle == CRLF_STYLE_MAC);
+ ASSERT (nCrlfStyle == CRLFSTYLE::AUTOMATIC || nCrlfStyle == CRLFSTYLE::DOS ||
+ nCrlfStyle == CRLFSTYLE::UNIX || nCrlfStyle == CRLFSTYLE::MAC);
ASSERT (m_bInit);
- if (!pszFileName || _tcslen(pszFileName) == 0)
+ if (nLines == -1)
+ nLines = static_cast<int>(m_aLines.size() - nStartLine);
+
+ if (pszFileName.empty())
return SAVE_FAILED; // No filename, cannot save...
- if (nCrlfStyle == CRLF_STYLE_AUTOMATIC &&
+ if (nCrlfStyle == CRLFSTYLE::AUTOMATIC &&
!GetOptionsMgr()->GetBool(OPT_ALLOW_MIXED_EOL) ||
- infoUnpacker && infoUnpacker->disallowMixedEOL)
+ infoUnpacker!=nullptr && infoUnpacker->m_bDisallowMixedEOL)
{
// get the default nCrlfStyle of the CDiffTextBuffer
nCrlfStyle = GetCRLFMode();
- ASSERT(nCrlfStyle >= 0 && nCrlfStyle <= 3);
+ ASSERT(nCrlfStyle != CRLFSTYLE::AUTOMATIC);
}
- BOOL bOpenSuccess = TRUE;
- BOOL bSaveSuccess = FALSE;
+ bool bOpenSuccess = true;
+ bool bSaveSuccess = false;
UniStdioFile file;
- file.SetUnicoding(bForceUTF8 ? ucr::UTF8 : m_encoding.m_unicoding);
- file.SetBom(bForceUTF8 ? true : m_encoding.m_bom);
- file.SetCodepage(bForceUTF8 ? CP_UTF8 : m_encoding.m_codepage);
String sIntermediateFilename; // used when !bTempFile
if (bTempFile)
{
+ file.SetUnicoding(ucr::UTF8);
+ file.SetBom(GetOptionsMgr()->GetInt(OPT_CMP_DIFF_ALGORITHM) == 0);
bOpenSuccess = !!file.OpenCreate(pszFileName);
}
else
{
- sIntermediateFilename = env_GetTempFileName(m_strTempPath.c_str(),
- _T("MRG_"), NULL);
+ file.SetUnicoding(m_encoding.m_unicoding);
+ file.SetBom(m_encoding.m_bom);
+ file.SetCodepage(m_encoding.m_codepage);
+ sIntermediateFilename = env::GetTemporaryFileName(m_strTempPath,
+ _T("MRG_"), nullptr);
if (sIntermediateFilename.empty())
return SAVE_FAILED; //Nothing to do if even tempfile name fails
- bOpenSuccess = !!file.OpenCreate(sIntermediateFilename.c_str());
+ bOpenSuccess = !!file.OpenCreate(sIntermediateFilename);
}
if (!bOpenSuccess)
UniFile::UniError uniErr = file.GetLastUniError();
if (uniErr.HasError())
{
- sError = uniErr.GetError().c_str();
+ sError = uniErr.GetError();
if (bTempFile)
- LogErrorString(Fmt(_T("Opening file %s failed: %s"),
- pszFileName, sError.c_str()));
+ LogErrorString(strutils::format(_T("Opening file %s failed: %s"),
+ pszFileName, sError));
else
- LogErrorString(Fmt(_T("Opening file %s failed: %s"),
- sIntermediateFilename.c_str(), sError.c_str()));
+ LogErrorString(strutils::format(_T("Opening file %s failed: %s"),
+ sIntermediateFilename, sError));
}
return SAVE_FAILED;
}
file.WriteBom();
// line loop : get each real line and write it in the file
- CString sLine;
- CString sEol = GetStringEol(nCrlfStyle);
- const size_t nLineCount = m_aLines.size();
- for (int line = 0; line < nLineCount; ++line)
+ String sLine;
+ String sEol = GetStringEol(nCrlfStyle);
+ int lastRealLine = ApparentLastRealLine();
+ for (int line = nStartLine; line < nStartLine + nLines; ++line)
{
if (GetLineFlags(line) & LF_GHOST)
continue;
if (GetLineLength(line) > 0)
{
int nLineLength = GetLineLength(line);
- void *pszBuf = sLine.GetBuffer(nLineLength);
- memcpy(pszBuf, GetLineChars(line), nLineLength * sizeof(TCHAR));
- sLine.ReleaseBuffer(nLineLength);
+ sLine.resize(0);
+ sLine.reserve(nLineLength + 4);
+ sLine.append(GetLineChars(line), nLineLength);
}
else
sLine = _T("");
- if (bTempFile)
- EscapeControlChars(sLine);
+ if (bTempFile && m_bTableEditing && m_bAllowNewlinesInQuotes)
+ {
+ strutils::replace(sLine, _T("\x1b"), _T("\x1b\x1b"));
+ strutils::replace(sLine, _T("\r"), _T("\x1br"));
+ strutils::replace(sLine, _T("\n"), _T("\x1bn"));
+ }
+
// last real line ?
- int lastRealLine = ApparentLastRealLine();
if (line == lastRealLine || lastRealLine == -1 )
{
- // last real line is never EOL terminated
- ASSERT (_tcslen(GetLineEol(line)) == 0);
- // write the line and exit loop
- String tmpLine(sLine);
- file.WriteString(tmpLine);
- break;
+ // If original last line had no EOL, then we are done
+ if( !m_aLines[line].HasEol() )
+ {
+ file.WriteString(sLine);
+ break;
+ }
+ // Otherwise, add the appropriate EOL to the last line ...
}
- // normal real line : append an EOL
- if (nCrlfStyle == CRLF_STYLE_AUTOMATIC || nCrlfStyle == CRLF_STYLE_MIXED)
+ // normal line : append an EOL
+ if (nCrlfStyle == CRLFSTYLE::AUTOMATIC || nCrlfStyle == CRLFSTYLE::MIXED)
{
// either the EOL of the line (when preserve original EOL chars is on)
sLine += GetLineEol(line);
sLine += sEol;
}
- // write this line to the file (codeset or unicode conversions are done there)
- String tmpLine(sLine);
- file.WriteString(tmpLine);
+ // write this line to the file (codeset or unicode conversions are done there
+ file.WriteString(sLine);
+
+ if (line == lastRealLine || lastRealLine == -1)
+ {
+ // Last line, so now done
+ break;
+ }
}
file.Close();
{
// If we are saving user files
// we need an unpacker/packer, at least a "do nothing" one
- ASSERT(infoUnpacker != NULL);
+ ASSERT(infoUnpacker != nullptr);
// repack the file here, overwrite the temporary file we did save in
- String csTempFileName = sIntermediateFilename;
- infoUnpacker->subcode = m_unpackerSubcode;
- if (!FileTransform_Packing(csTempFileName, *infoUnpacker))
+ bSaveSuccess = FileTransform::Packing(sIntermediateFilename, pszFileName, *infoUnpacker, m_unpackerSubcode);
+ try
{
- if (!::DeleteFile(sIntermediateFilename.c_str()))
- {
- LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
- sIntermediateFilename.c_str(), GetSysError(GetLastError()).c_str()));
- }
- // returns now, don't overwrite the original file
- return SAVE_PACK_FAILED;
+ TFile(sIntermediateFilename).remove();
}
- // the temp filename may have changed during packing
- if (csTempFileName != sIntermediateFilename)
+ catch (Exception& e)
{
- if (!::DeleteFile(sIntermediateFilename.c_str()))
- {
- LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
- sIntermediateFilename.c_str(), GetSysError(GetLastError()).c_str()));
- }
- sIntermediateFilename = csTempFileName;
+ LogErrorStringUTF8(e.displayText());
}
-
- // Write tempfile over original file
- if (::CopyFile(sIntermediateFilename.c_str(), pszFileName, FALSE))
+ if (!bSaveSuccess)
{
- if (!::DeleteFile(sIntermediateFilename.c_str()))
- {
- LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
- sIntermediateFilename.c_str(), GetSysError(GetLastError()).c_str()));
- }
- if (bClearModifiedFlag)
- {
- SetModified(FALSE);
- m_nSyncPosition = m_nUndoPosition;
- }
- bSaveSuccess = TRUE;
-
- // remember revision number on save
- m_dwRevisionNumberOnSave = m_dwCurrentRevisionNumber;
-
- // redraw line revision marks
- UpdateViews (NULL, NULL, UPDATE_FLAGSONLY);
+ // returns now, don't overwrite the original file
+ return SAVE_PACK_FAILED;
}
- else
+
+ if (bClearModifiedFlag)
{
- sError = GetSysError(GetLastError());
- LogErrorString(Fmt(_T("CopyFile(%s, %s) failed: %s"),
- sIntermediateFilename.c_str(), pszFileName, sError.c_str()));
+ SetModified(false);
+ m_nSyncPosition = m_nUndoPosition;
}
+
+ // remember revision number on save
+ m_dwRevisionNumberOnSave = m_dwCurrentRevisionNumber;
+
+ // redraw line revision marks
+ UpdateViews (nullptr, nullptr, UPDATE_FLAGSONLY);
}
else
{
if (bClearModifiedFlag)
{
- SetModified(FALSE);
+ SetModified(false);
m_nSyncPosition = m_nUndoPosition;
}
- bSaveSuccess = TRUE;
+ bSaveSuccess = true;
}
if (bSaveSuccess)
/// Replace line (removing any eol, and only including one if in strText)
void CDiffTextBuffer::ReplaceFullLines(CDiffTextBuffer& dbuf, CDiffTextBuffer& sbuf, CCrystalTextView * pSource, int nLineBegin, int nLineEnd, int nAction /*=CE_ACTION_UNKNOWN*/)
{
- int endl,endc;
CString strText;
if (nLineBegin != nLineEnd || sbuf.GetLineLength(nLineEnd) > 0)
sbuf.GetTextWithoutEmptys(nLineBegin, 0, nLineEnd, sbuf.GetLineLength(nLineEnd), strText);
}
if (int cchText = strText.GetLength())
+ {
+ int endl,endc;
dbuf.InsertText(pSource, nLineBegin, 0, strText, cchText, endl,endc, nAction);
-
+ }
}
bool CDiffTextBuffer::curUndoGroup()
{
return (m_aUndoBuf.size() != 0 && m_aUndoBuf[0].m_dwFlags&UNDO_BEGINGROUP);
}
+
+bool CDiffTextBuffer:: /* virtual override */
+DeleteText2(CCrystalTextView * pSource, int nStartLine, int nStartChar,
+ int nEndLine, int nEndChar, int nAction /*= CE_ACTION_UNKNOWN*/, bool bHistory /*= true*/)
+{
+ for (auto syncpnt : m_pOwnerDoc->GetSyncPointList())
+ {
+ const int nLineSyncPoint = syncpnt[m_nThisPane];
+ if (((nStartChar == 0 && nStartLine == nLineSyncPoint) || nStartLine < nLineSyncPoint) &&
+ nLineSyncPoint < nEndLine)
+ m_pOwnerDoc->DeleteSyncPoint(m_nThisPane, nLineSyncPoint, false);
+ }
+ return CGhostTextBuffer::DeleteText2(pSource, nStartLine, nStartChar, nEndLine, nEndChar, nAction, bHistory);
+}