Fix processing of events for MRU entries #10 and more in docview.
[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 // opening the file
47 // ----------------------------------------------------------------------------
48
49 wxFFile::wxFFile(const wxString& filename, const wxString& mode)
50 {
51 Detach();
52
53 (void)Open(filename, mode);
54 }
55
56 bool wxFFile::Open(const wxString& filename, const wxString& mode)
57 {
58 wxASSERT_MSG( !m_fp, wxT("should close or detach the old file first") );
59
60 m_fp = wxFopen(filename, mode);
61
62 if ( !m_fp )
63 {
64 wxLogSysError(_("can't open file '%s'"), filename);
65
66 return false;
67 }
68
69 m_name = filename;
70
71 return true;
72 }
73
74 bool wxFFile::Close()
75 {
76 if ( IsOpened() )
77 {
78 if ( fclose(m_fp) != 0 )
79 {
80 wxLogSysError(_("can't close file '%s'"), m_name.c_str());
81
82 return false;
83 }
84
85 Detach();
86 }
87
88 return true;
89 }
90
91 // ----------------------------------------------------------------------------
92 // read/write
93 // ----------------------------------------------------------------------------
94
95 bool wxFFile::ReadAll(wxString *str, const wxMBConv& conv)
96 {
97 wxCHECK_MSG( str, false, wxT("invalid parameter") );
98 wxCHECK_MSG( IsOpened(), false, wxT("can't read from closed file") );
99 wxCHECK_MSG( Length() >= 0, false, wxT("invalid length") );
100 size_t length = wx_truncate_cast(size_t, Length());
101 wxCHECK_MSG( (wxFileOffset)length == Length(), false, wxT("huge file not supported") );
102
103 clearerr(m_fp);
104
105 wxCharBuffer buf(length + 1);
106
107 // note that real length may be less than file length for text files with DOS EOLs
108 // ('\r's get dropped by CRT when reading which means that we have
109 // realLen = fileLen - numOfLinesInTheFile)
110 length = fread(buf.data(), sizeof(char), length, m_fp);
111
112 if ( Error() )
113 {
114 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
115
116 return false;
117 }
118
119 buf.data()[length] = 0;
120 *str = wxString(buf, conv);
121
122 return true;
123 }
124
125 size_t wxFFile::Read(void *pBuf, size_t nCount)
126 {
127 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
128 wxCHECK_MSG( IsOpened(), 0, wxT("can't read from closed file") );
129
130 size_t nRead = fread(pBuf, 1, nCount, m_fp);
131 if ( (nRead < nCount) && Error() )
132 {
133 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
134 }
135
136 return nRead;
137 }
138
139 size_t wxFFile::Write(const void *pBuf, size_t nCount)
140 {
141 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
142 wxCHECK_MSG( IsOpened(), 0, wxT("can't write to closed file") );
143
144 size_t nWritten = fwrite(pBuf, 1, nCount, m_fp);
145 if ( nWritten < nCount )
146 {
147 wxLogSysError(_("Write error on file '%s'"), m_name.c_str());
148 }
149
150 return nWritten;
151 }
152
153 bool wxFFile::Write(const wxString& s, const wxMBConv& conv)
154 {
155 const wxWX2MBbuf buf = s.mb_str(conv);
156 if ( !buf )
157 return false;
158
159 const size_t size = strlen(buf); // FIXME: use buf.length() when available
160 return Write(buf, size) == size;
161 }
162
163 bool wxFFile::Flush()
164 {
165 if ( IsOpened() )
166 {
167 if ( fflush(m_fp) != 0 )
168 {
169 wxLogSysError(_("failed to flush the file '%s'"), m_name.c_str());
170
171 return false;
172 }
173 }
174
175 return true;
176 }
177
178 // ----------------------------------------------------------------------------
179 // seeking
180 // ----------------------------------------------------------------------------
181
182 bool wxFFile::Seek(wxFileOffset ofs, wxSeekMode mode)
183 {
184 wxCHECK_MSG( IsOpened(), false, wxT("can't seek on closed file") );
185
186 int origin;
187 switch ( mode )
188 {
189 default:
190 wxFAIL_MSG(wxT("unknown seek mode"));
191 // still fall through
192
193 case wxFromStart:
194 origin = SEEK_SET;
195 break;
196
197 case wxFromCurrent:
198 origin = SEEK_CUR;
199 break;
200
201 case wxFromEnd:
202 origin = SEEK_END;
203 break;
204 }
205
206 #ifndef wxHAS_LARGE_FFILES
207 if ((long)ofs != ofs)
208 {
209 wxLogError(_("Seek error on file '%s' (large files not supported by stdio)"), m_name.c_str());
210
211 return false;
212 }
213
214 if ( wxFseek(m_fp, (long)ofs, origin) != 0 )
215 #else
216 if ( wxFseek(m_fp, ofs, origin) != 0 )
217 #endif
218 {
219 wxLogSysError(_("Seek error on file '%s'"), m_name.c_str());
220
221 return false;
222 }
223
224 return true;
225 }
226
227 wxFileOffset wxFFile::Tell() const
228 {
229 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
230 wxT("wxFFile::Tell(): file is closed!") );
231
232 wxFileOffset rc = wxFtell(m_fp);
233 if ( rc == wxInvalidOffset )
234 {
235 wxLogSysError(_("Can't find current position in file '%s'"),
236 m_name.c_str());
237 }
238
239 return rc;
240 }
241
242 wxFileOffset wxFFile::Length() const
243 {
244 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
245 wxT("wxFFile::Length(): file is closed!") );
246
247 wxFFile& self = *(wxFFile *)this; // const_cast
248
249 wxFileOffset posOld = Tell();
250 if ( posOld != wxInvalidOffset )
251 {
252 if ( self.SeekEnd() )
253 {
254 wxFileOffset len = Tell();
255
256 (void)self.Seek(posOld);
257
258 return len;
259 }
260 }
261
262 return wxInvalidOffset;
263 }
264
265 #endif // wxUSE_FFILE