]> git.saurik.com Git - wxWidgets.git/blame - src/common/txtstrm.cpp
fix Alt-letter navigation with spin controls (bug 672974)
[wxWidgets.git] / src / common / txtstrm.cpp
CommitLineData
5a96d2f4 1///////////////////////////////////////////////////////////////////////////////
fae05df5
GL
2// Name: txtstrm.cpp
3// Purpose: Text stream classes
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 28/06/98
7// RCS-ID: $Id$
717b9bf2 8// Copyright: (c) Guilhem Lavaux
55d99c7a 9// Licence: wxWindows licence
fae05df5
GL
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "txtstrm.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
23#if wxUSE_STREAMS
24
25#include "wx/txtstrm.h"
c980c992 26#include <ctype.h>
fae05df5 27
cd25b18c
RR
28
29// ----------------------------------------------------------------------------
30// constants
31// ----------------------------------------------------------------------------
32
33// Unix: "\n"
34// Dos: "\r\n"
35// Mac: "\r"
36
37// ----------------------------------------------------------------------------
38// wxTextInputStream
39// ----------------------------------------------------------------------------
40
2b5f62a0
VZ
41#if wxUSE_UNICODE
42wxTextInputStream::wxTextInputStream(wxInputStream &s, const wxString &sep, wxMBConv& conv)
43 : m_input(s), m_separators(sep), m_conv(conv)
44{
45}
46#else
191549ed
SB
47wxTextInputStream::wxTextInputStream(wxInputStream &s, const wxString &sep)
48 : m_input(s), m_separators(sep)
fae05df5
GL
49{
50}
2b5f62a0 51#endif
fae05df5
GL
52
53wxTextInputStream::~wxTextInputStream()
54{
55}
56
191549ed 57wxChar wxTextInputStream::NextNonSeparators()
fae05df5 58{
cd25b18c
RR
59 wxChar c = (wxChar) 0;
60 for (;;)
61 {
cd6ce4a9 62 if (!m_input) return (wxChar) 0;
191549ed 63 c = m_input.GetC();
cd6ce4a9
VZ
64
65 if (c != wxT('\n') &&
66 c != wxT('\r') &&
67 !m_separators.Contains(c))
68 return c;
cd25b18c 69 }
717b9bf2 70
cd25b18c 71}
fae05df5 72
f6bcfd97 73bool wxTextInputStream::EatEOL(const wxChar &c)
cd25b18c 74{
f6bcfd97 75 if (c == wxT('\n')) return TRUE; // eat on UNIX
cd6ce4a9 76
f6bcfd97 77 if (c == wxT('\r')) // eat on both Mac and DOS
717b9bf2 78 {
f6bcfd97
BP
79 if (!m_input) return TRUE;
80 wxChar c2 = m_input.GetC();
cd6ce4a9 81
f6bcfd97
BP
82 if (c2 != wxT('\n')) m_input.Ungetch( c2 ); // Don't eat on Mac
83 return TRUE;
cd25b18c 84 }
717b9bf2 85
f6bcfd97 86 return FALSE;
191549ed
SB
87}
88
89void wxTextInputStream::SkipIfEndOfLine( wxChar c )
90{
91 if (EatEOL(c)) return;
92 else m_input.Ungetch( c ); // no line terminator
cd25b18c 93}
fae05df5 94
cd25b18c
RR
95wxUint32 wxTextInputStream::Read32()
96{
97 /* I only implemented a simple integer parser */
cd6ce4a9
VZ
98 // VZ: what about using strtol()?? (TODO)
99
cd25b18c
RR
100 int sign;
101 wxInt32 i;
717b9bf2 102
cd25b18c 103 if (!m_input) return 0;
cd6ce4a9 104 int c = NextNonSeparators();
191549ed 105 if (c==(wxChar)0) return 0;
cd25b18c
RR
106
107 i = 0;
223d09f6 108 if (! (c == wxT('-') || c == wxT('+') || isdigit(c)) )
cd25b18c 109 {
191549ed 110 m_input.Ungetch(c);
cd25b18c
RR
111 return 0;
112 }
fae05df5 113
223d09f6 114 if (c == wxT('-'))
cd25b18c
RR
115 {
116 sign = -1;
191549ed 117 c = m_input.GetC();
717b9bf2 118 } else
223d09f6 119 if (c == wxT('+'))
cd25b18c
RR
120 {
121 sign = 1;
191549ed 122 c = m_input.GetC();
717b9bf2 123 } else
cd25b18c
RR
124 {
125 sign = 1;
126 }
fae05df5 127
717b9bf2 128 while (isdigit(c))
cd25b18c 129 {
223d09f6 130 i = i*10 + (c - (int)wxT('0'));
191549ed 131 c = m_input.GetC();
cd25b18c 132 }
fae05df5 133
cd25b18c 134 SkipIfEndOfLine( c );
fae05df5 135
cd25b18c 136 i *= sign;
fae05df5 137
cd25b18c 138 return (wxUint32)i;
fae05df5
GL
139}
140
141wxUint16 wxTextInputStream::Read16()
142{
cd25b18c 143 return (wxUint16)Read32();
fae05df5
GL
144}
145
146wxUint8 wxTextInputStream::Read8()
147{
cd25b18c 148 return (wxUint8)Read32();
fae05df5
GL
149}
150
151double wxTextInputStream::ReadDouble()
152{
f6bcfd97
BP
153 /* I only implemented a simple float parser
154 * VZ: what about using strtod()?? (TODO)
155 */
156
cd25b18c 157 double f;
f6bcfd97
BP
158 int theSign;
159
160 if (!m_input)
161 return 0;
cd25b18c 162
191549ed
SB
163 int c = NextNonSeparators();
164 if (c==(wxChar)0) return 0;
cd25b18c
RR
165
166 f = 0.0;
78e848ca 167 if (! (c == wxT('.') || c == wxT(',') || c == wxT('-') || c == wxT('+') || isdigit(c)) )
cd25b18c 168 {
191549ed 169 m_input.Ungetch(c);
f6bcfd97 170 return 0;
cd25b18c
RR
171 }
172
223d09f6 173 if (c == wxT('-'))
cd25b18c 174 {
f6bcfd97 175 theSign = -1;
191549ed 176 c = m_input.GetC();
717b9bf2 177 } else
223d09f6 178 if (c == wxT('+'))
cd25b18c 179 {
f6bcfd97 180 theSign = 1;
191549ed 181 c = m_input.GetC();
717b9bf2
DW
182 }
183 else
cd25b18c 184 {
f6bcfd97 185 theSign = 1;
cd25b18c
RR
186 }
187
717b9bf2 188 while (isdigit(c))
cd25b18c 189 {
223d09f6 190 f = f*10 + (c - wxT('0'));
191549ed 191 c = m_input.GetC();
fae05df5
GL
192 }
193
78e848ca 194 if (c == wxT('.') || c == wxT(','))
cd25b18c
RR
195 {
196 double f_multiplicator = (double) 0.1;
fae05df5 197
191549ed 198 c = m_input.GetC();
fae05df5 199
717b9bf2 200 while (isdigit(c))
cd6ce4a9 201 {
223d09f6 202 f += (c-wxT('0'))*f_multiplicator;
cd25b18c 203 f_multiplicator /= 10;
191549ed 204 c = m_input.GetC();
cd25b18c 205 }
fae05df5 206
223d09f6 207 if (c == wxT('e'))
cd6ce4a9 208 {
cd25b18c
RR
209 double f_multiplicator = 0.0;
210 int i, e;
fae05df5 211
191549ed 212 c = m_input.GetC();
fae05df5 213
717b9bf2 214 switch (c)
cd6ce4a9 215 {
223d09f6 216 case wxT('-'): f_multiplicator = 0.1; break;
cd6ce4a9
VZ
217 case wxT('+'): f_multiplicator = 10.0; break;
218 }
fae05df5 219
cd25b18c
RR
220 e = Read8(); // why only max 256 ?
221
222 for (i=0;i<e;i++)
223 f *= f_multiplicator;
717b9bf2 224 }
cd6ce4a9
VZ
225 else
226 SkipIfEndOfLine( c );
cd25b18c
RR
227 }
228 else
229 {
191549ed 230 m_input.Ungetch(c);
cd25b18c
RR
231 }
232
f6bcfd97 233 f *= theSign;
cd25b18c 234 return f;
fae05df5
GL
235}
236
237wxString wxTextInputStream::ReadString()
9853d977 238{
cd6ce4a9 239 return ReadLine();
9853d977
SB
240}
241
242wxString wxTextInputStream::ReadLine()
fae05df5 243{
cd25b18c
RR
244 wxString line;
245
cd6ce4a9 246 while ( !m_input.Eof() )
cd25b18c 247 {
2b5f62a0
VZ
248#if wxUSE_UNICODE
249 // FIXME: this is only works for single byte encodings
250 // How-to read a single char in an unkown encoding???
251 char buf[10];
252 buf[0] = m_input.GetC();
253 buf[1] = 0;
254
255 wxChar wbuf[2];
256 m_conv.MB2WC( wbuf, buf, 2 );
257 wxChar c = wbuf[0];
258#else
259 char c = m_input.GetC();
260#endif
f6bcfd97 261
cd6ce4a9
VZ
262 if ( !m_input )
263 break;
264
265 if (EatEOL(c))
266 break;
267
cd25b18c
RR
268 line += c;
269 }
717b9bf2 270
cd25b18c 271 return line;
fae05df5 272}
717b9bf2 273
9853d977
SB
274wxString wxTextInputStream::ReadWord()
275{
9853d977 276 wxString word;
9853d977 277
cd6ce4a9
VZ
278 if ( !m_input )
279 return word;
280
281 wxChar c = NextNonSeparators();
282 if ( !c )
283 return word;
284
f6bcfd97
BP
285 word += c;
286
cd6ce4a9 287 while ( !m_input.Eof() )
9853d977 288 {
f6bcfd97
BP
289 c = m_input.GetC();
290
291 if (!m_input)
292 break;
293
cd6ce4a9
VZ
294 if (m_separators.Contains(c))
295 break;
296
297 if (EatEOL(c))
298 break;
299
9853d977 300 word += c;
9853d977
SB
301 }
302
303 return word;
304}
305
306wxTextInputStream& wxTextInputStream::operator>>(wxString& word)
fae05df5 307{
cd6ce4a9
VZ
308 word = ReadWord();
309 return *this;
fae05df5
GL
310}
311
f6bcfd97 312wxTextInputStream& wxTextInputStream::operator>>(char& c)
fae05df5 313{
cd25b18c
RR
314 if (!m_input)
315 {
f6bcfd97 316 c = 0;
cd25b18c
RR
317 return *this;
318 }
717b9bf2 319
191549ed 320 c = m_input.GetC();
717b9bf2 321
f6bcfd97
BP
322 if (EatEOL(c))
323 c = '\n';
324
cd25b18c 325 return *this;
fae05df5
GL
326}
327
328wxTextInputStream& wxTextInputStream::operator>>(wxInt16& i)
329{
cd25b18c
RR
330 i = (wxInt16)Read16();
331 return *this;
fae05df5
GL
332}
333
334wxTextInputStream& wxTextInputStream::operator>>(wxInt32& i)
335{
cd25b18c
RR
336 i = (wxInt32)Read32();
337 return *this;
fae05df5
GL
338}
339
fae05df5
GL
340wxTextInputStream& wxTextInputStream::operator>>(wxUint16& i)
341{
cd25b18c
RR
342 i = Read16();
343 return *this;
fae05df5
GL
344}
345
346wxTextInputStream& wxTextInputStream::operator>>(wxUint32& i)
347{
cd25b18c
RR
348 i = Read32();
349 return *this;
fae05df5
GL
350}
351
352wxTextInputStream& wxTextInputStream::operator>>(double& i)
353{
cd25b18c
RR
354 i = ReadDouble();
355 return *this;
fae05df5
GL
356}
357
358wxTextInputStream& wxTextInputStream::operator>>(float& f)
359{
cd25b18c
RR
360 f = (float)ReadDouble();
361 return *this;
fae05df5
GL
362}
363
2b5f62a0
VZ
364
365
366#if wxUSE_UNICODE
367wxTextOutputStream::wxTextOutputStream(wxOutputStream& s, wxEOL mode, wxMBConv& conv)
368 : m_output(s), m_conv(conv)
369#else
c7a9fa36 370wxTextOutputStream::wxTextOutputStream(wxOutputStream& s, wxEOL mode)
191549ed 371 : m_output(s)
2b5f62a0 372#endif
fae05df5 373{
c7a9fa36
RR
374 m_mode = mode;
375 if (m_mode == wxEOL_NATIVE)
376 {
377#if defined(__WXMSW__) || defined(__WXPM__)
378 m_mode = wxEOL_DOS;
f3ff3813 379#elif defined(__WXMAC__) && !defined(__DARWIN__)
c7a9fa36
RR
380 m_mode = wxEOL_MAC;
381#else
382 m_mode = wxEOL_UNIX;
383#endif
384 }
fae05df5
GL
385}
386
387wxTextOutputStream::~wxTextOutputStream()
388{
389}
390
cd0b1709 391void wxTextOutputStream::SetMode(wxEOL mode)
c7a9fa36
RR
392{
393 m_mode = mode;
394 if (m_mode == wxEOL_NATIVE)
395 {
396#if defined(__WXMSW__) || defined(__WXPM__)
397 m_mode = wxEOL_DOS;
f3ff3813 398#elif defined(__WXMAC__) && !defined(__DARWIN__)
c7a9fa36
RR
399 m_mode = wxEOL_MAC;
400#else
401 m_mode = wxEOL_UNIX;
402#endif
403 }
404}
405
fae05df5
GL
406void wxTextOutputStream::Write32(wxUint32 i)
407{
cd25b18c 408 wxString str;
223d09f6 409 str.Printf(wxT("%u"), i);
717b9bf2 410
cd25b18c 411 WriteString(str);
fae05df5
GL
412}
413
414void wxTextOutputStream::Write16(wxUint16 i)
415{
cd25b18c 416 wxString str;
223d09f6 417 str.Printf(wxT("%u"), i);
717b9bf2 418
cd25b18c 419 WriteString(str);
fae05df5
GL
420}
421
422void wxTextOutputStream::Write8(wxUint8 i)
423{
cd25b18c 424 wxString str;
223d09f6 425 str.Printf(wxT("%u"), i);
717b9bf2 426
cd25b18c 427 WriteString(str);
fae05df5
GL
428}
429
430void wxTextOutputStream::WriteDouble(double d)
431{
cd25b18c 432 wxString str;
fae05df5 433
223d09f6 434 str.Printf(wxT("%f"), d);
cd25b18c 435 WriteString(str);
fae05df5
GL
436}
437
438void wxTextOutputStream::WriteString(const wxString& string)
439{
20ea6894
VZ
440 size_t len = string.length();
441
442 wxString out;
443 out.reserve(len);
444
445 for ( size_t i = 0; i < len; i++ )
cd25b18c 446 {
20ea6894
VZ
447 const wxChar c = string[i];
448 if ( c == wxT('\n') )
cd25b18c 449 {
20ea6894 450 switch ( m_mode )
cd6ce4a9 451 {
20ea6894
VZ
452 case wxEOL_DOS:
453 out << _T("\r\n");
454 continue;
455
456 case wxEOL_MAC:
457 out << _T('\r');
458 continue;
459
460 default:
461 wxFAIL_MSG( _T("unknown EOL mode in wxTextOutputStream") );
462 // fall through
463
464 case wxEOL_UNIX:
465 // don't treat '\n' specially
466 ;
c7a9fa36 467 }
cd25b18c 468 }
20ea6894
VZ
469
470 out << c;
cd25b18c 471 }
20ea6894 472
2b5f62a0
VZ
473 // We must not write the trailing NULL here
474#if wxUSE_UNICODE
475 wxCharBuffer buffer = m_conv.cWC2MB( out );
476 m_output.Write( (const char*) buffer, strlen( (const char*) buffer ) );
477#else
478 m_output.Write(out.c_str(), out.length() );
479#endif
fae05df5
GL
480}
481
482wxTextOutputStream& wxTextOutputStream::operator<<(const wxChar *string)
483{
cd25b18c
RR
484 WriteString( wxString(string) );
485 return *this;
fae05df5
GL
486}
487
488wxTextOutputStream& wxTextOutputStream::operator<<(const wxString& string)
489{
cd25b18c
RR
490 WriteString( string );
491 return *this;
fae05df5
GL
492}
493
f6bcfd97 494wxTextOutputStream& wxTextOutputStream::operator<<(char c)
fae05df5 495{
2b5f62a0
VZ
496 WriteString( wxString::FromAscii(c) );
497
cd25b18c 498 return *this;
fae05df5
GL
499}
500
501wxTextOutputStream& wxTextOutputStream::operator<<(wxInt16 c)
502{
78e848ca
RR
503 wxString str;
504 str.Printf(wxT("%d"), (signed int)c);
505 WriteString(str);
cd6ce4a9 506
cd25b18c 507 return *this;
fae05df5
GL
508}
509
510wxTextOutputStream& wxTextOutputStream::operator<<(wxInt32 c)
511{
78e848ca
RR
512 wxString str;
513 str.Printf(wxT("%ld"), (signed long)c);
514 WriteString(str);
cd6ce4a9 515
cd25b18c 516 return *this;
fae05df5
GL
517}
518
fae05df5
GL
519wxTextOutputStream& wxTextOutputStream::operator<<(wxUint16 c)
520{
78e848ca
RR
521 wxString str;
522 str.Printf(wxT("%u"), (unsigned int)c);
523 WriteString(str);
cd6ce4a9 524
cd25b18c 525 return *this;
fae05df5
GL
526}
527
528wxTextOutputStream& wxTextOutputStream::operator<<(wxUint32 c)
529{
78e848ca
RR
530 wxString str;
531 str.Printf(wxT("%lu"), (unsigned long)c);
532 WriteString(str);
533
cd25b18c 534 return *this;
fae05df5
GL
535}
536
537wxTextOutputStream &wxTextOutputStream::operator<<(double f)
538{
cd25b18c
RR
539 WriteDouble(f);
540 return *this;
fae05df5
GL
541}
542
543wxTextOutputStream& wxTextOutputStream::operator<<(float f)
544{
cd25b18c
RR
545 WriteDouble((double)f);
546 return *this;
fae05df5
GL
547}
548
ed58dbea
RR
549wxTextOutputStream &endl( wxTextOutputStream &stream )
550{
223d09f6 551 return stream << wxT('\n');
ed58dbea
RR
552}
553
fae05df5
GL
554#endif
555 // wxUSE_STREAMS