#endif
static bool IsTextFileStylePure(const UniMemFile::txtstats & stats);
-static void EscapeControlChars(String &s);
static CRLFSTYLE GetTextFileStyle(const UniMemFile::txtstats & stats);
/**
}
/**
- * @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(String &s)
-{
- // Compute buffer length required for escaping
- size_t n = s.length();
- LPCTSTR q = s.c_str();
- size_t 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.length();
- s.reserve(n + 1);
- s.resize(n + 1);
- LPTSTR p = &s[0];
- // 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'))
- {
- // TODO: speed this up via table lookup
- // Bitwise OR with 0x100 so _itot_s() will output 3 hex digits
- _itot_s(0x100 | c, p + n - 4, 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;
- }
- s.resize(s.length() - 1);
-}
-
-/**
* @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;
}
}
AddUndoRecord(bool bInsert, const CPoint & ptStartPos,
const CPoint & ptEndPos, LPCTSTR pszText, size_t cchText,
int nActionType /*= CE_ACTION_UNKNOWN*/,
- CDWordArray *paSavedRevisionNumbers)
+ CDWordArray *paSavedRevisionNumbers /*= nullptr*/)
{
CGhostTextBuffer::AddUndoRecord(bInsert, ptStartPos, ptEndPos, pszText,
cchText, nActionType, paSavedRevisionNumbers);
}
/**
- * @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
ASSERT(m_aLines.size() == 0);
// Unpacking the file here, save the result in a temporary file
- String sFileName(pszFileNameInit);
- if (!FileTransform::Unpacking(infoUnpacker, sFileName, sToFindUnpacker))
+ m_strTempFileName = pszFileNameInit;
+ if (!FileTransform::Unpacking(infoUnpacker, &m_unpackerSubcode, m_strTempFileName, sToFindUnpacker))
{
InitNew(); // leave crystal editor in valid, empty state
return FileLoadResult::FRESULT_ERROR_UNPACK;
}
- m_unpackerSubcode = infoUnpacker->subcode;
// 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
- paths::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
}
else
{
- if (infoUnpacker->pluginName.length() > 0)
+ if (infoUnpacker->m_PluginName.length() > 0)
{
// re-detect codepage
int iGuessEncodingType = GetOptionsMgr()->GetInt(OPT_CP_DETECT);
- FileTextEncoding encoding2 = GuessCodepageEncoding(pszFileName, iGuessEncodingType);
+ FileTextEncoding encoding2 = codepage_detect::Guess(pszFileName, iGuessEncodingType);
pufile->SetUnicoding(encoding2.m_unicoding);
pufile->SetCodepage(encoding2.m_codepage);
pufile->SetBom(encoding2.m_bom);
//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
* @return SAVE_DONE or an error code (list in MergeDoc.h)
*/
int CDiffTextBuffer::SaveToFile (const String& pszFileName,
- bool bTempFile, String & sError, PackingInfo * infoUnpacker /*= NULL*/,
- CRLFSTYLE nCrlfStyle /*= CRLF_STYLE_AUTOMATIC*/,
+ 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 (nLines == -1)
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;
UniStdioFile file;
- file.SetUnicoding(m_encoding.m_unicoding);
- file.SetBom(m_encoding.m_bom);
- file.SetCodepage(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
{
+ 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_"), NULL);
+ _T("MRG_"), nullptr);
if (sIntermediateFilename.empty())
return SAVE_FAILED; //Nothing to do if even tempfile name fails
bOpenSuccess = !!file.OpenCreate(sIntermediateFilename);
sError = uniErr.GetError();
if (bTempFile)
LogErrorString(strutils::format(_T("Opening file %s failed: %s"),
- pszFileName.c_str(), sError.c_str()));
+ pszFileName, sError));
else
LogErrorString(strutils::format(_T("Opening file %s failed: %s"),
- sIntermediateFilename.c_str(), sError.c_str()));
+ sIntermediateFilename, sError));
}
return SAVE_FAILED;
}
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 ?
if (line == lastRealLine || lastRealLine == -1 )
}
// normal line : append an EOL
- if (nCrlfStyle == CRLF_STYLE_AUTOMATIC || nCrlfStyle == CRLF_STYLE_MIXED)
+ if (nCrlfStyle == CRLFSTYLE::AUTOMATIC || nCrlfStyle == CRLFSTYLE::MIXED)
{
// either the EOL of the line (when preserve original EOL chars is on)
sLine += GetLineEol(line);
{
// 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
{
- try
- {
- TFile(sIntermediateFilename).remove();
- }
- catch (Exception& e)
- {
- LogErrorStringUTF8(e.displayText());
- }
- // 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)
{
- try
- {
- TFile(sIntermediateFilename).remove();
- }
- catch (Exception& e)
- {
- LogErrorStringUTF8(e.displayText());
- }
- sIntermediateFilename = csTempFileName;
+ LogErrorStringUTF8(e.displayText());
}
-
- // Write tempfile over original file
- try
+ if (!bSaveSuccess)
{
- TFile file1(sIntermediateFilename);
- file1.copyTo(pszFileName);
- file1.remove();
- 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;
}
- catch (Exception& e)
+
+ if (bClearModifiedFlag)
{
- LogErrorStringUTF8(e.displayText());
+ 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
{