// headers
// ============================================================================
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
- #pragma implementation "textfile.h"
-#endif
-
#include "wx/wxprec.h"
#ifdef __BORLANDC__
bool wxTextFile::OnRead(wxMBConv& conv)
{
// file should be opened and we must be in it's beginning
- wxASSERT( m_file.IsOpened() && m_file.Tell() == 0 );
-
- char *strBuf, *strPtr, *strEnd;
- char ch, chLast = '\0';
- char buf[1024];
- int n, nRead;
+ wxASSERT( m_file.IsOpened() &&
+ (m_file.GetKind() != wxFILE_KIND_DISK || m_file.Tell() == 0) );
+
+ static const size_t BUF_SIZE = 1024;
+#if wxUSE_UNICODE
+ static const size_t NUL_SIZE = 4;
+#else
+ static const size_t NUL_SIZE = 1;
+#endif
- strPtr = strBuf = new char[1024];
- strEnd = strBuf + 1024;
+ char buf[BUF_SIZE + NUL_SIZE];
+ wxChar chLast = '\0';
+ wxString str;
- do
+ for ( ;; )
{
- nRead = m_file.Read(buf, WXSIZEOF(buf));
- if ( nRead == wxInvalidOffset )
+ // leave space for trailing NUL
+ ssize_t nRead = m_file.Read(buf, BUF_SIZE);
+
+ if ( nRead == wxInvalidOffset )
{
// read error (error message already given in wxFile::Read)
- delete[] strBuf;
- return FALSE;
+ return false;
+ }
+
+ if ( nRead == 0 )
+ break;
+
+ // save the number characters which we already processed during the
+ // last loop iteration
+ const size_t lenOld = str.length();
+
+#if wxUSE_UNICODE
+ // we have to properly NUL-terminate the string for any encoding it may
+ // use -- 4 NULs should be enough for everyone (this is why we add 4
+ // extra bytes to the buffer)
+ buf[nRead] =
+ buf[nRead + 1] =
+ buf[nRead + 2] =
+ buf[nRead + 3] = '\0';
+
+ // append to the remains of the last block, don't overwrite
+ wxString strbuf(buf, conv);
+ if ( strbuf.empty() )
+ {
+ // conversion failed
+ return false;
}
- for (n = 0; n < nRead; n++)
+ str += strbuf;
+#else // ANSI
+ wxUnusedVar(conv);
+ buf[nRead] = '\0';
+ str += buf;
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+
+
+ // 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 + lenOld; p != end; p++ )
{
- ch = buf[n];
- switch ( ch )
+ const wxChar ch = *p;
+ switch ( ch )
{
case '\n':
- // Dos/Unix line termination
- *strPtr = '\0';
- AddLine(wxString(strBuf, conv),
- chLast == '\r' ? wxTextFileType_Dos
- : wxTextFileType_Unix);
- strPtr = strBuf;
- chLast = '\n';
+ // could be a DOS or Unix EOL
+ if ( chLast == '\r' )
+ {
+ AddLine(wxString(lineStart, p - 1), wxTextFileType_Dos);
+ }
+ else // bare '\n', Unix style
+ {
+ AddLine(wxString(lineStart, p), wxTextFileType_Unix);
+ }
+
+ lineStart = p + 1;
break;
case '\r':
- if ( chLast == '\r' )
+ if ( chLast == '\r' )
{
// Mac empty line
AddLine(wxEmptyString, wxTextFileType_Mac);
+ lineStart = p + 1;
}
- else
- chLast = '\r';
+ //else: we don't what this is yet -- could be a Mac EOL or
+ // start of DOS EOL so wait for next char
break;
default:
if ( chLast == '\r' )
{
// Mac line termination
- *strPtr = '\0';
- AddLine(wxString(strBuf, conv), wxTextFileType_Mac);
- chLast = ch;
- strPtr = strBuf;
- *(strPtr++) = ch;
- }
- else
- {
- // add to the current line
- *(strPtr++) = ch;
- if ( strPtr == strEnd )
- {
- // we must allocate more memory
- size_t size = strEnd - strBuf;
- char *newBuf = new char[size + 1024];
- memcpy(newBuf, strBuf, size);
- delete[] strBuf;
- strBuf = newBuf;
- strEnd = strBuf + size + 1024;
- strPtr = strBuf + size;
- }
+ AddLine(wxString(lineStart, p - 1), wxTextFileType_Mac);
+ lineStart = p;
}
}
+
+ chLast = ch;
}
- } while ( nRead == WXSIZEOF(buf) );
+
+ // remove the part we already processed
+ str.erase(0, lineStart - str.begin());
+ }
// anything in the last line?
- if ( strPtr != strBuf )
+ if ( !str.empty() )
{
- *strPtr = '\0';
- AddLine(wxString(strBuf, conv),
- wxTextFileType_None); // no line terminator
+ AddLine(str, wxTextFileType_None); // no line terminator
}
- delete[] strBuf;
- return TRUE;
+ return true;
}
if ( !fileTmp.IsOpened() ) {
wxLogError(_("can't write buffer '%s' to disk."), m_strBufferName.c_str());
- return FALSE;
+ return false;
}
size_t nCount = GetLineCount();