192 lines
5.2 KiB
C++
192 lines
5.2 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/textfile.cpp
|
|
// Purpose: implementation of wxTextFile class
|
|
// Author: Vadim Zeitlin
|
|
// Modified by:
|
|
// Created: 03.04.98
|
|
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// headers
|
|
// ============================================================================
|
|
|
|
#include "wx/wxprec.h"
|
|
|
|
|
|
#if !wxUSE_FILE || !wxUSE_TEXTBUFFER
|
|
#undef wxUSE_TEXTFILE
|
|
#define wxUSE_TEXTFILE 0
|
|
#endif // wxUSE_FILE
|
|
|
|
#if wxUSE_TEXTFILE
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/string.h"
|
|
#include "wx/intl.h"
|
|
#include "wx/file.h"
|
|
#include "wx/log.h"
|
|
#endif
|
|
|
|
#include "wx/textfile.h"
|
|
#include "wx/filename.h"
|
|
#include "wx/buffer.h"
|
|
|
|
// ============================================================================
|
|
// wxTextFile class implementation
|
|
// ============================================================================
|
|
|
|
wxTextFile::wxTextFile(const wxString& strFileName)
|
|
: wxTextBuffer(strFileName)
|
|
{
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// file operations
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool wxTextFile::OnExists() const
|
|
{
|
|
return wxFile::Exists(m_strBufferName);
|
|
}
|
|
|
|
|
|
bool wxTextFile::OnOpen(const wxString &strBufferName, wxTextBufferOpenMode openMode)
|
|
{
|
|
wxFile::OpenMode fileOpenMode = wxFile::read_write;
|
|
|
|
switch ( openMode )
|
|
{
|
|
case ReadAccess:
|
|
fileOpenMode = wxFile::read;
|
|
break;
|
|
|
|
case WriteAccess:
|
|
fileOpenMode = wxFile::write;
|
|
break;
|
|
}
|
|
|
|
if ( fileOpenMode == wxFile::read_write )
|
|
{
|
|
// This must mean it hasn't been initialized in the switch above.
|
|
wxFAIL_MSG( wxT("unknown open mode in wxTextFile::Open") );
|
|
return false;
|
|
}
|
|
|
|
return m_file.Open(strBufferName, fileOpenMode);
|
|
}
|
|
|
|
|
|
bool wxTextFile::OnClose()
|
|
{
|
|
return m_file.Close();
|
|
}
|
|
|
|
|
|
bool wxTextFile::OnRead(const wxMBConv& conv)
|
|
{
|
|
// file should be opened
|
|
wxASSERT_MSG( m_file.IsOpened(), wxT("can't read closed file") );
|
|
|
|
wxString str;
|
|
if ( !m_file.ReadAll(&str, conv) )
|
|
{
|
|
wxLogError(_("Failed to read text file \"%s\"."), GetName());
|
|
return false;
|
|
}
|
|
|
|
// now break the buffer in lines
|
|
|
|
// the beginning of the current line, changes inside the loop
|
|
wxString::const_iterator lineStart = str.begin();
|
|
const wxString::const_iterator end = str.end();
|
|
for ( wxString::const_iterator p = lineStart; p != end; ++p )
|
|
{
|
|
const wxChar ch = *p;
|
|
if ( ch == '\r' || ch == '\n' )
|
|
{
|
|
// Determine the kind of line ending this is.
|
|
wxTextFileType lineType = wxTextFileType_None;
|
|
if ( ch == '\r' )
|
|
{
|
|
wxString::const_iterator next = p + 1;
|
|
if ( next != end && *next == '\n' )
|
|
lineType = wxTextFileType_Dos;
|
|
else
|
|
lineType = wxTextFileType_Mac;
|
|
}
|
|
else // ch == '\n'
|
|
{
|
|
lineType = wxTextFileType_Unix;
|
|
}
|
|
|
|
AddLine(wxString(lineStart, p), lineType);
|
|
|
|
// DOS EOL is the only one consisting of two chars, not one.
|
|
if ( lineType == wxTextFileType_Dos )
|
|
++p;
|
|
|
|
lineStart = p + 1;
|
|
}
|
|
}
|
|
|
|
// anything in the last line?
|
|
if ( lineStart != end )
|
|
{
|
|
// Add the last line; notice that it is certainly not terminated with a
|
|
// newline, otherwise it would be handled above.
|
|
wxString lastLine(lineStart, end);
|
|
AddLine(lastLine, wxTextFileType_None);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool wxTextFile::OnWrite(wxTextFileType typeNew, const wxMBConv& conv)
|
|
{
|
|
wxFileName fn = m_strBufferName;
|
|
|
|
// We do NOT want wxPATH_NORM_CASE here, or the case will not
|
|
// be preserved.
|
|
if ( !fn.IsAbsolute() )
|
|
fn.Normalize(wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE |
|
|
wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG);
|
|
|
|
wxTempFile fileTmp(fn.GetFullPath());
|
|
|
|
if ( !fileTmp.IsOpened() ) {
|
|
wxLogError(_("can't write buffer '%s' to disk."), m_strBufferName);
|
|
return false;
|
|
}
|
|
|
|
// Writing to wxTempFile in reasonably-sized chunks is much faster than
|
|
// doing it line by line.
|
|
const size_t chunk_size = 16384;
|
|
wxString chunk;
|
|
chunk.reserve(chunk_size);
|
|
|
|
size_t nCount = GetLineCount();
|
|
for ( size_t n = 0; n < nCount; n++ )
|
|
{
|
|
chunk += GetLine(n) +
|
|
GetEOL(typeNew == wxTextFileType_None ? GetLineType(n)
|
|
: typeNew);
|
|
if ( chunk.size() >= chunk_size )
|
|
{
|
|
fileTmp.Write(chunk, conv);
|
|
chunk.clear();
|
|
}
|
|
}
|
|
|
|
if ( !chunk.empty() )
|
|
fileTmp.Write(chunk, conv);
|
|
|
|
// replace the old file with this one
|
|
return fileTmp.Commit();
|
|
}
|
|
|
|
#endif // wxUSE_TEXTFILE
|