OSDN Git Service

FileTransform: Remove m_subcode from PackingInfo class
[winmerge-jp/winmerge-jp.git] / Src / DiffTextBuffer.cpp
index 78911d3..019b950 100644 (file)
@@ -29,7 +29,6 @@ using Poco::Exception;
 #endif
 
 static bool IsTextFileStylePure(const UniMemFile::txtstats & stats);
-static void EscapeControlChars(String &s);
 static CRLFSTYLE GetTextFileStyle(const UniMemFile::txtstats & stats);
 
 /**
@@ -50,54 +49,6 @@ static bool IsTextFileStylePure(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'))
-               {
-                       p[n - 4 + 1] = _T("0123456789ABCDEF")[(c >> 4) & 0xf];
-                       p[n - 4 + 2] = _T("0123456789ABCDEF")[c & 0xf];
-                       // 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.
@@ -106,20 +57,20 @@ static CRLFSTYLE GetTextFileStyle(const UniMemFile::txtstats & stats)
 {
        // 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;
        }
 }
 
@@ -194,7 +145,7 @@ 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)
+               CDWordArray *paSavedRevisionNumbers /*= nullptr*/)
 {
        CGhostTextBuffer::AddUndoRecord(bInsert, ptStartPos, ptEndPos, pszText,
                cchText, nActionType, paSavedRevisionNumbers);
@@ -254,24 +205,6 @@ OnNotifyLineHasBeenEdited(int 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
@@ -296,31 +229,30 @@ int CDiffTextBuffer::LoadFromFile(LPCTSTR pszFileNameInit,
        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
@@ -338,11 +270,11 @@ int CDiffTextBuffer::LoadFromFile(LPCTSTR pszFileNameInit,
        }
        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);
@@ -408,11 +340,11 @@ int CDiffTextBuffer::LoadFromFile(LPCTSTR pszFileNameInit,
        
                
                //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
@@ -480,12 +412,12 @@ int CDiffTextBuffer::LoadFromFile(LPCTSTR pszFileNameInit,
  */
 int CDiffTextBuffer::SaveToFile (const String& pszFileName,
                bool bTempFile, String & sError, PackingInfo * infoUnpacker /*= nullptr*/,
-               CRLFSTYLE nCrlfStyle /*= CRLF_STYLE_AUTOMATIC*/,
+               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)
@@ -494,33 +426,35 @@ int CDiffTextBuffer::SaveToFile (const String& pszFileName,
        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);
@@ -534,10 +468,10 @@ int CDiffTextBuffer::SaveToFile (const String& pszFileName,
                        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;
        }
@@ -564,8 +498,12 @@ int CDiffTextBuffer::SaveToFile (const String& pszFileName,
                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 )
@@ -580,7 +518,7 @@ int CDiffTextBuffer::SaveToFile (const String& pszFileName,
                }
 
                // 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);
@@ -608,58 +546,32 @@ int CDiffTextBuffer::SaveToFile (const String& pszFileName,
                // we need an unpacker/packer, at least a "do nothing" one
                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
        {