hook the docview-specific customization of event handling logic at TryValidator(...
[wxWidgets.git] / src / common / ffile.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: ffile.cpp
3 // Purpose: wxFFile encapsulates "FILE *" IO stream
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 14.07.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_FFILE
28
29 #ifndef WX_PRECOMP
30 #include "wx/intl.h"
31 #include "wx/log.h"
32 #include "wx/crt.h"
33 #endif
34
35 #ifdef __WINDOWS__
36 #include "wx/msw/mslu.h"
37 #endif
38
39 #include "wx/ffile.h"
40
41 // ============================================================================
42 // implementation
43 // ============================================================================
44
45 // ----------------------------------------------------------------------------
46 // seek and tell with large file support if available
47 // ----------------------------------------------------------------------------
48
49 #ifdef HAVE_FSEEKO
50 # define wxFseek fseeko
51 # define wxFtell ftello
52 #else
53 # define wxFseek fseek
54 # define wxFtell ftell
55 #endif
56
57 // ----------------------------------------------------------------------------
58 // opening the file
59 // ----------------------------------------------------------------------------
60
61 wxFFile::wxFFile(const wxString& filename, const wxString& mode)
62 {
63 Detach();
64
65 (void)Open(filename, mode);
66 }
67
68 bool wxFFile::Open(const wxString& filename, const wxString& mode)
69 {
70 wxASSERT_MSG( !m_fp, wxT("should close or detach the old file first") );
71
72 m_fp = wxFopen(filename, mode);
73
74 if ( !m_fp )
75 {
76 wxLogSysError(_("can't open file '%s'"), filename);
77
78 return false;
79 }
80
81 m_name = filename;
82
83 return true;
84 }
85
86 bool wxFFile::Close()
87 {
88 if ( IsOpened() )
89 {
90 if ( fclose(m_fp) != 0 )
91 {
92 wxLogSysError(_("can't close file '%s'"), m_name.c_str());
93
94 return false;
95 }
96
97 Detach();
98 }
99
100 return true;
101 }
102
103 // ----------------------------------------------------------------------------
104 // read/write
105 // ----------------------------------------------------------------------------
106
107 bool wxFFile::ReadAll(wxString *str, const wxMBConv& conv)
108 {
109 wxCHECK_MSG( str, false, wxT("invalid parameter") );
110 wxCHECK_MSG( IsOpened(), false, wxT("can't read from closed file") );
111 wxCHECK_MSG( Length() >= 0, false, wxT("invalid length") );
112 size_t length = wx_truncate_cast(size_t, Length());
113 wxCHECK_MSG( (wxFileOffset)length == Length(), false, wxT("huge file not supported") );
114
115 clearerr(m_fp);
116
117 wxCharBuffer buf(length + 1);
118
119 // note that real length may be less than file length for text files with DOS EOLs
120 // ('\r's get dropped by CRT when reading which means that we have
121 // realLen = fileLen - numOfLinesInTheFile)
122 length = fread(buf.data(), sizeof(char), length, m_fp);
123
124 if ( Error() )
125 {
126 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
127
128 return false;
129 }
130
131 buf.data()[length] = 0;
132 *str = wxString(buf, conv);
133
134 return true;
135 }
136
137 size_t wxFFile::Read(void *pBuf, size_t nCount)
138 {
139 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
140 wxCHECK_MSG( IsOpened(), 0, wxT("can't read from closed file") );
141
142 size_t nRead = fread(pBuf, 1, nCount, m_fp);
143 if ( (nRead < nCount) && Error() )
144 {
145 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
146 }
147
148 return nRead;
149 }
150
151 size_t wxFFile::Write(const void *pBuf, size_t nCount)
152 {
153 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
154 wxCHECK_MSG( IsOpened(), 0, wxT("can't write to closed file") );
155
156 size_t nWritten = fwrite(pBuf, 1, nCount, m_fp);
157 if ( nWritten < nCount )
158 {
159 wxLogSysError(_("Write error on file '%s'"), m_name.c_str());
160 }
161
162 return nWritten;
163 }
164
165 bool wxFFile::Write(const wxString& s, const wxMBConv& conv)
166 {
167 const wxWX2MBbuf buf = s.mb_str(conv);
168 if ( !buf )
169 return false;
170
171 const size_t size = strlen(buf); // FIXME: use buf.length() when available
172 return Write(buf, size) == size;
173 }
174
175 bool wxFFile::Flush()
176 {
177 if ( IsOpened() )
178 {
179 if ( fflush(m_fp) != 0 )
180 {
181 wxLogSysError(_("failed to flush the file '%s'"), m_name.c_str());
182
183 return false;
184 }
185 }
186
187 return true;
188 }
189
190 // ----------------------------------------------------------------------------
191 // seeking
192 // ----------------------------------------------------------------------------
193
194 bool wxFFile::Seek(wxFileOffset ofs, wxSeekMode mode)
195 {
196 wxCHECK_MSG( IsOpened(), false, wxT("can't seek on closed file") );
197
198 int origin;
199 switch ( mode )
200 {
201 default:
202 wxFAIL_MSG(wxT("unknown seek mode"));
203 // still fall through
204
205 case wxFromStart:
206 origin = SEEK_SET;
207 break;
208
209 case wxFromCurrent:
210 origin = SEEK_CUR;
211 break;
212
213 case wxFromEnd:
214 origin = SEEK_END;
215 break;
216 }
217
218 #ifndef HAVE_FSEEKO
219 if ((long)ofs != ofs)
220 {
221 wxLogError(_("Seek error on file '%s' (large files not supported by stdio)"), m_name.c_str());
222
223 return false;
224 }
225
226 if ( wxFseek(m_fp, (long)ofs, origin) != 0 )
227 #else
228 if ( wxFseek(m_fp, ofs, origin) != 0 )
229 #endif
230 {
231 wxLogSysError(_("Seek error on file '%s'"), m_name.c_str());
232
233 return false;
234 }
235
236 return true;
237 }
238
239 wxFileOffset wxFFile::Tell() const
240 {
241 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
242 _T("wxFFile::Tell(): file is closed!") );
243
244 wxFileOffset rc = wxFtell(m_fp);
245 if ( rc == wxInvalidOffset )
246 {
247 wxLogSysError(_("Can't find current position in file '%s'"),
248 m_name.c_str());
249 }
250
251 return rc;
252 }
253
254 wxFileOffset wxFFile::Length() const
255 {
256 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
257 _T("wxFFile::Length(): file is closed!") );
258
259 wxFFile& self = *(wxFFile *)this; // const_cast
260
261 wxFileOffset posOld = Tell();
262 if ( posOld != wxInvalidOffset )
263 {
264 if ( self.SeekEnd() )
265 {
266 wxFileOffset len = Tell();
267
268 (void)self.Seek(posOld);
269
270 return len;
271 }
272 }
273
274 return wxInvalidOffset;
275 }
276
277 #endif // wxUSE_FFILE