]> git.saurik.com Git - wxWidgets.git/blame - src/common/txtstrm.cpp
Fix for #15520: wxRichTextCtrl: Drawing the selection doesn't respect its container...
[wxWidgets.git] / src / common / txtstrm.cpp
CommitLineData
5a96d2f4 1///////////////////////////////////////////////////////////////////////////////
40ff126a 2// Name: src/common/txtstrm.cpp
fae05df5
GL
3// Purpose: Text stream classes
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 28/06/98
717b9bf2 7// Copyright: (c) Guilhem Lavaux
65571936 8// Licence: wxWindows licence
fae05df5
GL
9/////////////////////////////////////////////////////////////////////////////
10
fae05df5
GL
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18#if wxUSE_STREAMS
19
c22eea9c
PC
20#include "wx/txtstrm.h"
21
0bf751e7
VS
22#ifndef WX_PRECOMP
23 #include "wx/crt.h"
24#endif
25
c980c992 26#include <ctype.h>
fae05df5 27
cd25b18c
RR
28// ----------------------------------------------------------------------------
29// wxTextInputStream
30// ----------------------------------------------------------------------------
31
2b5f62a0 32#if wxUSE_UNICODE
830f8f11
VZ
33wxTextInputStream::wxTextInputStream(wxInputStream &s,
34 const wxString &sep,
35 const wxMBConv& conv)
d36c9347 36 : m_input(s), m_separators(sep), m_conv(conv.Clone())
2b5f62a0 37{
2348a842 38 memset((void*)m_lastBytes, 0, 10);
2b5f62a0
VZ
39}
40#else
191549ed
SB
41wxTextInputStream::wxTextInputStream(wxInputStream &s, const wxString &sep)
42 : m_input(s), m_separators(sep)
fae05df5 43{
2348a842 44 memset((void*)m_lastBytes, 0, 10);
fae05df5 45}
2b5f62a0 46#endif
fae05df5
GL
47
48wxTextInputStream::~wxTextInputStream()
49{
d36c9347
VZ
50#if wxUSE_UNICODE
51 delete m_conv;
52#endif // wxUSE_UNICODE
fae05df5
GL
53}
54
2348a842
VZ
55void wxTextInputStream::UngetLast()
56{
57 size_t byteCount = 0;
58 while(m_lastBytes[byteCount]) // pseudo ANSI strlen (even for Unicode!)
59 byteCount++;
60 m_input.Ungetch(m_lastBytes, byteCount);
61 memset((void*)m_lastBytes, 0, 10);
62}
63
64wxChar wxTextInputStream::NextChar()
65{
66#if wxUSE_UNICODE
67 wxChar wbuf[2];
68 memset((void*)m_lastBytes, 0, 10);
cb719f2e 69 for(size_t inlen = 0; inlen < 9; inlen++)
2348a842
VZ
70 {
71 // actually read the next character
72 m_lastBytes[inlen] = m_input.GetC();
73
cb719f2e 74 if(m_input.LastRead() <= 0)
2348a842 75 return wxEOT;
cb719f2e 76
32dd8aa2
VZ
77 switch ( m_conv->ToWChar(wbuf, WXSIZEOF(wbuf), m_lastBytes, inlen + 1) )
78 {
79 case 0:
80 // this is a bug in converter object as it should either fail
81 // or decode non-empty string to something non-empty
82 wxFAIL_MSG("ToWChar() can't return 0 for non-empty input");
83 break;
84
85 case wxCONV_FAILED:
86 // the buffer probably doesn't contain enough bytes to decode
87 // as a complete character, try with more bytes
88 break;
89
90 default:
91 // if we couldn't decode a single character during the last
92 // loop iteration we shouldn't be able to decode 2 or more of
93 // them with an extra single byte, something fishy is going on
94 wxFAIL_MSG("unexpected decoding result");
95 // fall through nevertheless and return at least something
96
97 case 1:
98 // we finally decoded a character
99 return wbuf[0];
100 }
2348a842 101 }
32dd8aa2
VZ
102
103 // there should be no encoding which requires more than nine bytes for one
104 // character so something must be wrong with our conversion but we have no
105 // way to signal it from here
2348a842
VZ
106 return wxEOT;
107#else
108 m_lastBytes[0] = m_input.GetC();
cb719f2e
WS
109
110 if(m_input.LastRead() <= 0)
2348a842 111 return wxEOT;
cb719f2e 112
2348a842
VZ
113 return m_lastBytes[0];
114#endif
cb719f2e 115
2348a842
VZ
116}
117
191549ed 118wxChar wxTextInputStream::NextNonSeparators()
fae05df5 119{
cd25b18c
RR
120 for (;;)
121 {
999836aa 122 wxChar c = NextChar();
2348a842 123 if (c == wxEOT) return (wxChar) 0;
cd6ce4a9
VZ
124
125 if (c != wxT('\n') &&
126 c != wxT('\r') &&
c22eea9c 127 m_separators.Find(c) < 0)
cd6ce4a9 128 return c;
cd25b18c 129 }
717b9bf2 130
cd25b18c 131}
fae05df5 132
f6bcfd97 133bool wxTextInputStream::EatEOL(const wxChar &c)
cd25b18c 134{
cb719f2e 135 if (c == wxT('\n')) return true; // eat on UNIX
cd6ce4a9 136
f6bcfd97 137 if (c == wxT('\r')) // eat on both Mac and DOS
717b9bf2 138 {
2348a842 139 wxChar c2 = NextChar();
cb719f2e 140 if(c2 == wxEOT) return true; // end of stream reached, had enough :-)
cd6ce4a9 141
2348a842 142 if (c2 != wxT('\n')) UngetLast(); // Don't eat on Mac
cb719f2e 143 return true;
cd25b18c 144 }
717b9bf2 145
cb719f2e 146 return false;
191549ed
SB
147}
148
2348a842 149wxUint32 wxTextInputStream::Read32(int base)
191549ed 150{
9a83f860 151 wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );
2348a842
VZ
152 if(!m_input) return 0;
153
154 wxString word = ReadWord();
7448de8d 155 if(word.empty())
2348a842
VZ
156 return 0;
157 return wxStrtoul(word.c_str(), 0, base);
cd25b18c 158}
fae05df5 159
2348a842 160wxUint16 wxTextInputStream::Read16(int base)
cd25b18c 161{
2348a842
VZ
162 return (wxUint16)Read32(base);
163}
cd6ce4a9 164
2348a842
VZ
165wxUint8 wxTextInputStream::Read8(int base)
166{
167 return (wxUint8)Read32(base);
168}
717b9bf2 169
2348a842
VZ
170wxInt32 wxTextInputStream::Read32S(int base)
171{
9a83f860 172 wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );
2348a842 173 if(!m_input) return 0;
cd25b18c 174
2348a842 175 wxString word = ReadWord();
7448de8d 176 if(word.empty())
cd25b18c 177 return 0;
2348a842 178 return wxStrtol(word.c_str(), 0, base);
fae05df5
GL
179}
180
2348a842 181wxInt16 wxTextInputStream::Read16S(int base)
fae05df5 182{
2348a842 183 return (wxInt16)Read32S(base);
fae05df5
GL
184}
185
2348a842 186wxInt8 wxTextInputStream::Read8S(int base)
fae05df5 187{
2348a842 188 return (wxInt8)Read32S(base);
fae05df5
GL
189}
190
191double wxTextInputStream::ReadDouble()
192{
2348a842
VZ
193 if(!m_input) return 0;
194 wxString word = ReadWord();
7448de8d 195 if(word.empty())
f6bcfd97 196 return 0;
2348a842 197 return wxStrtod(word.c_str(), 0);
fae05df5
GL
198}
199
40ff126a
WS
200#if WXWIN_COMPATIBILITY_2_6
201
fae05df5 202wxString wxTextInputStream::ReadString()
9853d977 203{
cd6ce4a9 204 return ReadLine();
9853d977
SB
205}
206
40ff126a
WS
207#endif // WXWIN_COMPATIBILITY_2_6
208
9853d977 209wxString wxTextInputStream::ReadLine()
fae05df5 210{
cd25b18c
RR
211 wxString line;
212
cd6ce4a9 213 while ( !m_input.Eof() )
cd25b18c 214 {
2348a842
VZ
215 wxChar c = NextChar();
216 if(c == wxEOT)
217 break;
cb719f2e 218
cd6ce4a9
VZ
219 if (EatEOL(c))
220 break;
221
cd25b18c
RR
222 line += c;
223 }
717b9bf2 224
cd25b18c 225 return line;
fae05df5 226}
717b9bf2 227
9853d977
SB
228wxString wxTextInputStream::ReadWord()
229{
9853d977 230 wxString word;
9853d977 231
cd6ce4a9
VZ
232 if ( !m_input )
233 return word;
234
235 wxChar c = NextNonSeparators();
236 if ( !c )
237 return word;
238
f6bcfd97 239 word += c;
cb719f2e 240
cd6ce4a9 241 while ( !m_input.Eof() )
9853d977 242 {
2348a842
VZ
243 c = NextChar();
244 if(c == wxEOT)
f6bcfd97 245 break;
cb719f2e 246
c22eea9c 247 if (m_separators.Find(c) >= 0)
cd6ce4a9
VZ
248 break;
249
250 if (EatEOL(c))
251 break;
252
9853d977 253 word += c;
9853d977
SB
254 }
255
256 return word;
257}
258
259wxTextInputStream& wxTextInputStream::operator>>(wxString& word)
fae05df5 260{
cd6ce4a9
VZ
261 word = ReadWord();
262 return *this;
fae05df5
GL
263}
264
f6bcfd97 265wxTextInputStream& wxTextInputStream::operator>>(char& c)
fae05df5 266{
191549ed 267 c = m_input.GetC();
2348a842 268 if(m_input.LastRead() <= 0) c = 0;
717b9bf2 269
f6bcfd97
BP
270 if (EatEOL(c))
271 c = '\n';
272
cd25b18c 273 return *this;
fae05df5
GL
274}
275
fcbe123e
VZ
276#if wxUSE_UNICODE && wxWCHAR_T_IS_REAL_TYPE
277
278wxTextInputStream& wxTextInputStream::operator>>(wchar_t& wc)
279{
280 wc = GetChar();
281
282 return *this;
283}
284
285#endif // wxUSE_UNICODE
286
fae05df5
GL
287wxTextInputStream& wxTextInputStream::operator>>(wxInt16& i)
288{
cd25b18c
RR
289 i = (wxInt16)Read16();
290 return *this;
fae05df5
GL
291}
292
293wxTextInputStream& wxTextInputStream::operator>>(wxInt32& i)
294{
cd25b18c
RR
295 i = (wxInt32)Read32();
296 return *this;
fae05df5
GL
297}
298
fae05df5
GL
299wxTextInputStream& wxTextInputStream::operator>>(wxUint16& i)
300{
cd25b18c
RR
301 i = Read16();
302 return *this;
fae05df5
GL
303}
304
305wxTextInputStream& wxTextInputStream::operator>>(wxUint32& i)
306{
cd25b18c
RR
307 i = Read32();
308 return *this;
fae05df5
GL
309}
310
311wxTextInputStream& wxTextInputStream::operator>>(double& i)
312{
cd25b18c
RR
313 i = ReadDouble();
314 return *this;
fae05df5
GL
315}
316
317wxTextInputStream& wxTextInputStream::operator>>(float& f)
318{
cd25b18c
RR
319 f = (float)ReadDouble();
320 return *this;
fae05df5
GL
321}
322
2b5f62a0
VZ
323
324
325#if wxUSE_UNICODE
830f8f11
VZ
326wxTextOutputStream::wxTextOutputStream(wxOutputStream& s,
327 wxEOL mode,
328 const wxMBConv& conv)
d36c9347 329 : m_output(s), m_conv(conv.Clone())
2b5f62a0 330#else
c7a9fa36 331wxTextOutputStream::wxTextOutputStream(wxOutputStream& s, wxEOL mode)
191549ed 332 : m_output(s)
2b5f62a0 333#endif
fae05df5 334{
c7a9fa36
RR
335 m_mode = mode;
336 if (m_mode == wxEOL_NATIVE)
337 {
d98a58c5 338#if defined(__WINDOWS__) || defined(__WXPM__)
c7a9fa36 339 m_mode = wxEOL_DOS;
c7a9fa36
RR
340#else
341 m_mode = wxEOL_UNIX;
342#endif
343 }
fae05df5
GL
344}
345
346wxTextOutputStream::~wxTextOutputStream()
347{
d36c9347
VZ
348#if wxUSE_UNICODE
349 delete m_conv;
350#endif // wxUSE_UNICODE
fae05df5
GL
351}
352
cd0b1709 353void wxTextOutputStream::SetMode(wxEOL mode)
c7a9fa36
RR
354{
355 m_mode = mode;
356 if (m_mode == wxEOL_NATIVE)
357 {
d98a58c5 358#if defined(__WINDOWS__) || defined(__WXPM__)
c7a9fa36 359 m_mode = wxEOL_DOS;
c7a9fa36
RR
360#else
361 m_mode = wxEOL_UNIX;
362#endif
363 }
364}
365
fae05df5
GL
366void wxTextOutputStream::Write32(wxUint32 i)
367{
cd25b18c 368 wxString str;
223d09f6 369 str.Printf(wxT("%u"), i);
717b9bf2 370
cd25b18c 371 WriteString(str);
fae05df5
GL
372}
373
374void wxTextOutputStream::Write16(wxUint16 i)
375{
cd25b18c 376 wxString str;
17a1ebd1 377 str.Printf(wxT("%u"), (unsigned)i);
717b9bf2 378
cd25b18c 379 WriteString(str);
fae05df5
GL
380}
381
382void wxTextOutputStream::Write8(wxUint8 i)
383{
cd25b18c 384 wxString str;
17a1ebd1 385 str.Printf(wxT("%u"), (unsigned)i);
717b9bf2 386
cd25b18c 387 WriteString(str);
fae05df5
GL
388}
389
390void wxTextOutputStream::WriteDouble(double d)
391{
cd25b18c 392 wxString str;
fae05df5 393
223d09f6 394 str.Printf(wxT("%f"), d);
cd25b18c 395 WriteString(str);
fae05df5
GL
396}
397
398void wxTextOutputStream::WriteString(const wxString& string)
399{
20ea6894
VZ
400 size_t len = string.length();
401
402 wxString out;
403 out.reserve(len);
404
405 for ( size_t i = 0; i < len; i++ )
cd25b18c 406 {
20ea6894
VZ
407 const wxChar c = string[i];
408 if ( c == wxT('\n') )
cd25b18c 409 {
20ea6894 410 switch ( m_mode )
cd6ce4a9 411 {
20ea6894 412 case wxEOL_DOS:
9a83f860 413 out << wxT("\r\n");
20ea6894
VZ
414 continue;
415
416 case wxEOL_MAC:
9a83f860 417 out << wxT('\r');
20ea6894
VZ
418 continue;
419
420 default:
9a83f860 421 wxFAIL_MSG( wxT("unknown EOL mode in wxTextOutputStream") );
20ea6894
VZ
422 // fall through
423
424 case wxEOL_UNIX:
425 // don't treat '\n' specially
426 ;
c7a9fa36 427 }
cd25b18c 428 }
20ea6894
VZ
429
430 out << c;
7448de8d 431 }
20ea6894 432
2b5f62a0 433#if wxUSE_UNICODE
86501081
VS
434 // FIXME-UTF8: use wxCharBufferWithLength if/when we have it
435 wxCharBuffer buffer = m_conv->cWC2MB(out.wc_str(), out.length(), &len);
bfaee57e 436 m_output.Write(buffer, len);
2b5f62a0
VZ
437#else
438 m_output.Write(out.c_str(), out.length() );
439#endif
fae05df5
GL
440}
441
ba854691
RN
442wxTextOutputStream& wxTextOutputStream::PutChar(wxChar c)
443{
444#if wxUSE_UNICODE
d36c9347 445 WriteString( wxString(&c, *m_conv, 1) );
ba854691
RN
446#else
447 WriteString( wxString(&c, wxConvLocal, 1) );
448#endif
449 return *this;
450}
451
ca8cf4ff
VZ
452void wxTextOutputStream::Flush()
453{
454#if wxUSE_UNICODE
455 const size_t len = m_conv->FromWChar(NULL, 0, L"", 1);
456 if ( len > m_conv->GetMBNulLen() )
457 {
458 wxCharBuffer buf(len);
459 m_conv->FromWChar(buf.data(), len, L"", 1);
460 m_output.Write(buf, len - m_conv->GetMBNulLen());
461 }
462#endif // wxUSE_UNICODE
463}
464
fae05df5
GL
465wxTextOutputStream& wxTextOutputStream::operator<<(const wxString& string)
466{
cd25b18c
RR
467 WriteString( string );
468 return *this;
fae05df5
GL
469}
470
f6bcfd97 471wxTextOutputStream& wxTextOutputStream::operator<<(char c)
fae05df5 472{
2b5f62a0 473 WriteString( wxString::FromAscii(c) );
cb719f2e 474
cd25b18c 475 return *this;
fae05df5
GL
476}
477
e4940feb 478#if wxUSE_UNICODE && wxWCHAR_T_IS_REAL_TYPE
3ca1bf5a
VZ
479
480wxTextOutputStream& wxTextOutputStream::operator<<(wchar_t wc)
481{
d36c9347 482 WriteString( wxString(&wc, *m_conv, 1) );
65a1bb98
VZ
483
484 return *this;
3ca1bf5a
VZ
485}
486
e4940feb 487#endif // wxUSE_UNICODE
3ca1bf5a 488
fae05df5
GL
489wxTextOutputStream& wxTextOutputStream::operator<<(wxInt16 c)
490{
78e848ca
RR
491 wxString str;
492 str.Printf(wxT("%d"), (signed int)c);
493 WriteString(str);
cd6ce4a9 494
cd25b18c 495 return *this;
fae05df5
GL
496}
497
498wxTextOutputStream& wxTextOutputStream::operator<<(wxInt32 c)
499{
78e848ca
RR
500 wxString str;
501 str.Printf(wxT("%ld"), (signed long)c);
502 WriteString(str);
cd6ce4a9 503
cd25b18c 504 return *this;
fae05df5
GL
505}
506
fae05df5
GL
507wxTextOutputStream& wxTextOutputStream::operator<<(wxUint16 c)
508{
78e848ca
RR
509 wxString str;
510 str.Printf(wxT("%u"), (unsigned int)c);
511 WriteString(str);
cd6ce4a9 512
cd25b18c 513 return *this;
fae05df5
GL
514}
515
516wxTextOutputStream& wxTextOutputStream::operator<<(wxUint32 c)
517{
78e848ca
RR
518 wxString str;
519 str.Printf(wxT("%lu"), (unsigned long)c);
520 WriteString(str);
521
cd25b18c 522 return *this;
fae05df5
GL
523}
524
525wxTextOutputStream &wxTextOutputStream::operator<<(double f)
526{
cd25b18c
RR
527 WriteDouble(f);
528 return *this;
fae05df5
GL
529}
530
531wxTextOutputStream& wxTextOutputStream::operator<<(float f)
532{
cd25b18c
RR
533 WriteDouble((double)f);
534 return *this;
fae05df5
GL
535}
536
ed58dbea
RR
537wxTextOutputStream &endl( wxTextOutputStream &stream )
538{
ba854691 539 return stream.PutChar(wxT('\n'));
ed58dbea
RR
540}
541
fae05df5
GL
542#endif
543 // wxUSE_STREAMS