1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/textfile.cpp 
   3 // Purpose:     implementation of wxTextFile class 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 #include  "wx/wxprec.h" 
  22 #if !wxUSE_FILE || !wxUSE_TEXTBUFFER 
  24     #define wxUSE_TEXTFILE 0 
  30     #include "wx/string.h" 
  36 #include "wx/textfile.h" 
  37 #include "wx/filename.h" 
  38 #include "wx/buffer.h" 
  40 // ============================================================================ 
  41 // wxTextFile class implementation 
  42 // ============================================================================ 
  44 wxTextFile::wxTextFile(const wxString
& strFileName
) 
  45           : wxTextBuffer(strFileName
) 
  50 // ---------------------------------------------------------------------------- 
  52 // ---------------------------------------------------------------------------- 
  54 bool wxTextFile::OnExists() const 
  56     return wxFile::Exists(m_strBufferName
); 
  60 bool wxTextFile::OnOpen(const wxString 
&strBufferName
, wxTextBufferOpenMode OpenMode
) 
  62     wxFile::OpenMode FileOpenMode
; 
  67             wxFAIL_MSG( _T("unknown open mode in wxTextFile::Open") ); 
  71             FileOpenMode 
= wxFile::read
; 
  75             FileOpenMode 
= wxFile::write
; 
  79     return m_file
.Open(strBufferName
.c_str(), FileOpenMode
); 
  83 bool wxTextFile::OnClose() 
  85     return m_file
.Close(); 
  89 bool wxTextFile::OnRead(wxMBConv
& conv
) 
  91     // file should be opened and we must be in it's beginning 
  92     wxASSERT( m_file
.IsOpened() && m_file
.Tell() == 0 ); 
  94     // read the entire file in memory: this is not the most efficient thing to 
  95     // do but there is no good way to avoid it in Unicode build because if we 
  96     // read the file block by block we can't convert each block to Unicode 
  97     // separately (the last multibyte char in the block might be only partially 
  98     // read and so the conversion would fail) and, as the file contents is kept 
  99     // in memory by wxTextFile anyhow, it shouldn't be a big problem to read 
 101     const size_t bufSize 
= m_file
.Length() + 4 /* for trailing NULs */; 
 103     wxCharBuffer 
buf(bufSize 
- 1 /* it adds 1 internally */); 
 106     for ( bool eof 
= false; !eof
; ) 
 108         // try to read up to the size of the entire block 
 109         ssize_t nRead 
= m_file
.Read(block
, WXSIZEOF(block
)); 
 111         if ( nRead 
== wxInvalidOffset 
) 
 113             // read error (error message already given in wxFile::Read) 
 120             // append 4 trailing NUL bytes: this is needed to ensure that the 
 121             // string is going to be NUL-terminated, whatever is the encoding 
 122             // used (even UTF-32) 
 130         // this shouldn't happen but don't overwrite the buffer if it does 
 131         wxCHECK_MSG( bufPos 
+ nRead 
<= bufSize
, false, 
 132                      _T("read more than file length?") ); 
 134         // append to the buffer 
 135         memcpy(buf
.data() + bufPos
, block
, nRead
); 
 139     const wxString 
str(buf
, conv
); 
 141     // this doesn't risk to happen in ANSI build 
 143     if ( bufSize 
> 4 && str
.empty() ) 
 145         wxLogError(_("Failed to convert file contents to Unicode.")); 
 148 #endif // wxUSE_UNICODE 
 150     free(buf
.release()); // we don't need this memory any more 
 153     // now break the buffer in lines 
 155     // last processed character, we need to know if it was a CR or not 
 156     wxChar chLast 
= '\0'; 
 158     // the beginning of the current line, changes inside the loop 
 159     wxString::const_iterator lineStart 
= str
.begin(); 
 160     const wxString::const_iterator end 
= str
.end(); 
 161     for ( wxString::const_iterator p 
= lineStart
; p 
!= end
; p
++ ) 
 163         const wxChar ch 
= *p
; 
 167                 // could be a DOS or Unix EOL 
 168                 if ( chLast 
== '\r' ) 
 170                     AddLine(wxString(lineStart
, p 
- 1), wxTextFileType_Dos
); 
 172                 else // bare '\n', Unix style 
 174                     AddLine(wxString(lineStart
, p
), wxTextFileType_Unix
); 
 181                 if ( chLast 
== '\r' ) 
 184                     AddLine(wxEmptyString
, wxTextFileType_Mac
); 
 187                 //else: we don't know what this is yet -- could be a Mac EOL or 
 188                 //      start of DOS EOL so wait for next char 
 192                 if ( chLast 
== '\r' ) 
 194                     // Mac line termination 
 195                     AddLine(wxString(lineStart
, p 
- 1), wxTextFileType_Mac
); 
 203     // anything in the last line? 
 204     if ( lineStart 
!= end 
) 
 206         // add unterminated last line 
 207         AddLine(wxString(lineStart
, end
), wxTextFileType_None
); 
 214 bool wxTextFile::OnWrite(wxTextFileType typeNew
, wxMBConv
& conv
) 
 216     wxFileName fn 
= m_strBufferName
; 
 218     // We do NOT want wxPATH_NORM_CASE here, or the case will not 
 220     if ( !fn
.IsAbsolute() ) 
 221         fn
.Normalize(wxPATH_NORM_ENV_VARS 
| wxPATH_NORM_DOTS 
| wxPATH_NORM_TILDE 
| 
 222                      wxPATH_NORM_ABSOLUTE 
| wxPATH_NORM_LONG
); 
 224     wxTempFile 
fileTmp(fn
.GetFullPath()); 
 226     if ( !fileTmp
.IsOpened() ) { 
 227         wxLogError(_("can't write buffer '%s' to disk."), m_strBufferName
.c_str()); 
 231     size_t nCount 
= GetLineCount(); 
 232     for ( size_t n 
= 0; n 
< nCount
; n
++ ) { 
 233         fileTmp
.Write(GetLine(n
) + 
 234                       GetEOL(typeNew 
== wxTextFileType_None 
? GetLineType(n
) 
 239     // replace the old file with this one 
 240     return fileTmp
.Commit(); 
 243 #endif // wxUSE_TEXTFILE