From 7cf6c6c247008e21550ebbb64af7bbf1168882e3 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Sun, 6 Apr 2003 15:05:11 +0000 Subject: [PATCH] PATCH: [ 715457 ] LoadFromFile() rewrote --- Src/MergeDoc.cpp | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ Src/MergeDoc.h | 5 ++ Src/readme.txt | 4 ++ 3 files changed, 209 insertions(+) diff --git a/Src/MergeDoc.cpp b/Src/MergeDoc.cpp index 9471b0133..8a98e5816 100644 --- a/Src/MergeDoc.cpp +++ b/Src/MergeDoc.cpp @@ -1083,6 +1083,206 @@ UINT CMergeDoc::CDiffTextBuffer::GetTextWithoutEmptys(int nStartLine, int nStart return nBufSize; } +BOOL CMergeDoc::CDiffTextBuffer::SafeReadFile(HANDLE hFile, LPVOID lpBuf, DWORD dwLength) +{ + DWORD dwReadBytes = 0; + if (::ReadFile(hFile, lpBuf, dwLength, &dwReadBytes, NULL)) + { + if (dwLength == dwReadBytes) + return TRUE; + } + return FALSE; +} + +// Try to determine current CRLF mode based on first line +int CMergeDoc::CDiffTextBuffer::DetermineCRLFStyle(LPVOID lpBuf, DWORD dwLength) +{ + WORD wLoopSize = 0xffff; + int nCrlfStyle = CRLF_STYLE_DOS; // Default + TCHAR * lpBuffer = (TCHAR *)lpBuf; + + if (dwLength < 0xffff) + wLoopSize = dwLength; + + // Find first linebreak + for (DWORD i = 0; i < wLoopSize; i++, lpBuffer++) + { + if ((*lpBuffer == _T('\r')) || (*lpBuffer == _T('\n'))) + break; + } + + // By default (or in the case of empty file) use DOS style + if (i < wLoopSize) + { + // Otherwise, analyse the first occurance of line-feed character + if (*lpBuffer == _T('\n')) + nCrlfStyle = CRLF_STYLE_UNIX; + else + { + // Found '\r', CRLF is DOS ('\r\n') or MAC ('\r') + if (i < wLoopSize - 1 && *(lpBuffer+1) == _T('\n')) + nCrlfStyle = CRLF_STYLE_DOS; + else + nCrlfStyle = CRLF_STYLE_MAC; + } + } + return nCrlfStyle; +} + +// Reads one line from filebuffer and inserts to textbuffer +void CMergeDoc::CDiffTextBuffer::ReadLineFromBuffer(TCHAR *lpLineBegin, DWORD dwLineLen /* =0 */) +{ + if (m_nSourceEncoding >= 0) + iconvert (lpLineBegin, m_nSourceEncoding, 1, m_nSourceEncoding == 15); + InsertLine(lpLineBegin, dwLineLen); +} + +// Reads different EOL formats and returns length of EOL +// This function is safe: it first checks that there are unread bytes, +// so that we do not read past EOF +int CMergeDoc::CDiffTextBuffer::ReadEOL(TCHAR *lpLineEnd, DWORD bytesLeft, int nCrlfStyle) +{ + int eolBytes = 0; + + // EOL sensitive - ignore '\r' if '\r\n' + if (mf->m_bEolSensitive) + { + // If >1 bytes left, there can be '\n' too + if (*lpLineEnd == '\r' && bytesLeft > 1) + { + if (*(lpLineEnd+1) == '\n') + { + // '\r\n' + *(lpLineEnd+1) = '\0'; + eolBytes = 2; + } + else + { + *(lpLineEnd) = '\0'; + eolBytes = 1; + } + } + else + { + *(lpLineEnd) = '\0'; + eolBytes = 1; + } + } + else + { + if (bytesLeft > 1) + { + if ( (*lpLineEnd == '\r') && *(lpLineEnd+1) == '\n') + eolBytes = 2; + else + eolBytes = 1; + } + else + eolBytes = 1; + + *(lpLineEnd) = '\0'; + } + return eolBytes; +} + +BOOL CMergeDoc::CDiffTextBuffer::LoadFromFile(LPCTSTR pszFileName, + int nCrlfStyle /*= CRLF_STYLE_AUTOMATIC*/) +{ + ASSERT(!m_bInit); + ASSERT(m_aLines.GetSize() == 0); + HANDLE hFile = NULL; + BOOL bSuccess = TRUE; + LPTSTR pcBuf = NULL; + DWORD dwFileSize = 0; + CString sExt; + + SplitFilename(pszFileName, NULL, NULL, &sExt); + CCrystalTextView::TextDefinition *def = + CCrystalTextView::GetTextType((LPCTSTR)sExt); + if (def && def->encoding != -1) + m_nSourceEncoding = def->encoding; + + hFile =::CreateFile(pszFileName, GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + + if (hFile != INVALID_HANDLE_VALUE) + { + dwFileSize = GetFileSize(hFile, NULL); + if ( dwFileSize != INVALID_FILE_SIZE ) + pcBuf = new TCHAR[dwFileSize + 1]; + } + + // pcBuf is != NULL only if file was opened, size read and + // buffer allocated succesfully + if (pcBuf) + { + ZeroMemory( pcBuf, sizeof(TCHAR) * (dwFileSize + 1)); + if (SafeReadFile(hFile, pcBuf, dwFileSize)) + { + //Try to determine current CRLF mode based on first line + if (nCrlfStyle == CRLF_STYLE_AUTOMATIC) + nCrlfStyle = DetermineCRLFStyle(pcBuf, dwFileSize); + } + else + bSuccess = FALSE; + } + + if (bSuccess) + { + ASSERT(nCrlfStyle >= 0 && nCrlfStyle <= 2); + SetCRLFMode(nCrlfStyle); + + m_aLines.SetSize(0, 4096); + + DWORD dwBytesRead = 0; + TCHAR *lpChar = (TCHAR *) pcBuf; + TCHAR *lpLineBegin = lpChar; + int eolChars = 0; + while (dwBytesRead < dwFileSize) + { + TCHAR c = *lpChar; + + // EOL found + if (c == '\n' || c == '\r') + { + eolChars = ReadEOL(lpChar, dwFileSize - dwBytesRead, + nCrlfStyle); + ReadLineFromBuffer(lpLineBegin, lpChar - lpLineBegin); + + lpChar += eolChars; + dwBytesRead += eolChars; // Skip EOL chars + lpLineBegin = lpChar; + } + else + { + lpChar++; + dwBytesRead++; + } + } + ReadLineFromBuffer(lpLineBegin, lpChar - lpLineBegin); + ASSERT(m_aLines.GetSize() > 0); // At least one empty line must present + + m_bInit = TRUE; + m_bModified = FALSE; + m_bUndoGroup = m_bUndoBeginGroup = FALSE; + m_nUndoBufSize = 1024; // crystaltextbuffer.cpp - UNDO_BUF_SIZE; + m_nSyncPosition = m_nUndoPosition = 0; + ASSERT(m_aUndoBuf.GetSize() == 0); + bSuccess = TRUE; + + UpdateViews(NULL, NULL, UPDATE_RESET); + m_ptLastChange.x = m_ptLastChange.y = -1; + } + + if (pcBuf != NULL) + delete[] pcBuf; + + if (hFile != NULL && hFile != INVALID_HANDLE_VALUE) + ::CloseHandle(hFile); + return bSuccess; +} + BOOL CMergeDoc::CDiffTextBuffer::SafeWriteFile(HANDLE hFile, LPVOID lpBuf, DWORD dwLength) { DWORD dwWrittenBytes = 0; diff --git a/Src/MergeDoc.h b/Src/MergeDoc.h index 067ae925a..4066d13ae 100644 --- a/Src/MergeDoc.h +++ b/Src/MergeDoc.h @@ -72,6 +72,10 @@ private : BOOL m_bIsLeft; BOOL FlagIsSet(UINT line, DWORD flag); + BOOL SafeReadFile(HANDLE hFile, LPVOID lpBuf, DWORD dwLength); + int DetermineCRLFStyle(LPVOID lpBuf, DWORD dwLength); + void ReadLineFromBuffer(TCHAR *lpLineBegin, DWORD dwLineLen = 0); + int ReadEOL(TCHAR *lpLineEnd, DWORD bytesLeft, int nCrlfStyle); BOOL SafeWriteFile(HANDLE hFile, LPVOID lpBuf, DWORD dwLength); BOOL SafeReplaceFile(LPCTSTR pszReplaced, LPCTSTR pszReplacement); public : @@ -79,6 +83,7 @@ public : void ReplaceLine(int nLine, const CString& strText); UINT GetTextWithoutEmptys(int nStartLine, int nStartChar, int nEndLine, int nEndChar, CString &text, BOOL bLeft, int nCrlfStyle = CRLF_STYLE_AUTOMATIC); + BOOL LoadFromFile(LPCTSTR pszFileName, int nCrlfStyle = CRLF_STYLE_AUTOMATIC); BOOL SaveToFile (LPCTSTR pszFileName, int nCrlfStyle = CRLF_STYLE_AUTOMATIC , BOOL bClearModifiedFlag = TRUE ); diff --git a/Src/readme.txt b/Src/readme.txt index be49c4358..1a570d255 100644 --- a/Src/readme.txt +++ b/Src/readme.txt @@ -1,3 +1,7 @@ +2003-04-06 Kimmo + PATCH: [ 715457 ] LoadFromFile() rewrote + WinMerge: MergeDoc.h MergeDoc.cpp + 2003-04-06 Perry PATCH: [ 716088 ] Fix bin same/diff bug in Diff.cpp & analyze.c WinMerge: analyze.c Diff.cpp -- 2.11.0