00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "docviewprec.h"
00013
00014 #ifdef __BORLANDC__
00015 #pragma hdrstop
00016 #endif
00017
00018 #ifndef WX_PRECOMP
00019 #include "wx/wx.h"
00020 #endif
00021
00022 #include "docviewprivate.h"
00023
00024 #if wxART2D_USE_XMLPARSE
00025
00026 const size_t XMLBUFSIZE = 1024;
00027
00028 #include "wx/wfstream.h"
00029 #include "wx/intl.h"
00030 #include "wx/log.h"
00031 #include "wx/strconv.h"
00032 #include <wx/tokenzr.h>
00033
00034 #include "wx/xmlparse/genxmlpars.h"
00035 #include "wx/xmlparse/xmlencode.h"
00036
00037
00038
00039
00040
00041 a2dIOHandlerXML::a2dIOHandlerXML()
00042 {
00043 m_parser = NULL;
00044 m_buffer = NULL;
00045 m_done = false;
00046 }
00047
00048 void a2dIOHandlerXML::InitializeLoad( )
00049 {
00050 a2dIOHandlerStrIn::InitializeLoad();
00051
00052 assert( m_buffer == NULL );
00053 assert( m_parser == NULL );
00054
00055 m_parser = XML_ParserCreate(NULL);
00056 m_buffer = NULL;
00057
00058 m_done = false;
00059
00060
00061 XML_SetUserData(m_parser, (void*) this );
00062
00063 XML_SetElementHandler(m_parser, BaseStartElementHnd, BaseEndElementHnd);
00064 XML_SetCharacterDataHandler(m_parser, BaseCharacterDataHnd);
00065 XML_SetCommentHandler(m_parser, BaseCommentHnd);
00066 XML_SetDefaultHandler(m_parser, BaseDefaultHnd);
00067 }
00068
00069 void a2dIOHandlerXML::ResetLoad( )
00070 {
00071 a2dIOHandlerStrIn::ResetLoad();
00072
00073 if (m_parser)
00074 {
00075 XML_ParserFree(m_parser);
00076 m_parser = NULL;
00077 }
00078 m_buffer = NULL;
00079 }
00080
00081 a2dIOHandlerXML::~a2dIOHandlerXML()
00082 {
00083 if (m_parser)
00084 XML_ParserFree(m_parser);
00085 }
00086
00087 int a2dIOHandlerXML::GetCurrentColumnNumber()
00088 {
00089 if (m_parser)
00090 return XML_GetCurrentColumnNumber( m_parser );
00091 return 0;
00092 }
00093
00094 int a2dIOHandlerXML::GetCurrentLineNumber()
00095 {
00096 if (m_parser)
00097 return XML_GetCurrentLineNumber( m_parser );
00098 return 0;
00099 }
00100
00101 wxString a2dIOHandlerXML::GetErrorString()
00102 {
00103 if (m_parser)
00104 return XmlDecodeStringToString( XML_ErrorString( XML_GetErrorCode(m_parser) ) );
00105 return wxT("");
00106 }
00107
00108 void a2dIOHandlerXML::BaseStartElementHnd(void *userData, const char* name, const char** atts )
00109 {
00110 a2dIOHandlerXML* parser = (a2dIOHandlerXML*) userData;
00111
00112 a2dXMLTag* tag = new a2dXMLTag( START_TAG, XmlDecodeStringToString( name ) );
00113
00114 int i = 0;
00115 while ( atts[i] )
00116 {
00117 tag->SetAttribute( XmlDecodeStringToString( atts[i]), XmlDecodeStringToString( atts[i+1]) );
00118 i += 2;
00119 }
00120
00121 parser->StartElementHnd( tag );
00122
00123 }
00124
00125 void a2dIOHandlerXML::BaseEndElementHnd(void *userData, const char* name)
00126 {
00127 a2dIOHandlerXML* parser = (a2dIOHandlerXML*) userData;
00128
00129 parser->EndElementHnd( XmlDecodeStringToString( name ) );
00130 }
00131
00132 void a2dIOHandlerXML::BaseCharacterDataHnd(void *userData, const char* s, int len)
00133 {
00134 a2dIOHandlerXML* parser = (a2dIOHandlerXML*) userData;
00135
00136 char *buf = new char[len + 1];
00137
00138 buf[len] = wxT('\0');
00139 memcpy(buf, s, (size_t)len);
00140
00141 parser->CharacterDataHnd( XmlDecodeStringToString( buf ) );
00142
00143 delete buf;
00144 }
00145
00146 void a2dIOHandlerXML::BaseCommentHnd(void *userData, const char* data)
00147 {
00148 a2dIOHandlerXML* parser = (a2dIOHandlerXML*) userData;
00149
00150 parser->CommentHnd( XmlDecodeStringToString( data ) );
00151 }
00152
00153 void a2dIOHandlerXML::BaseDefaultHnd(void *userData, const char* s, int len)
00154 {
00155 a2dIOHandlerXML* parser = (a2dIOHandlerXML*) userData;
00156
00157 wxString buf = XmlDecodeStringToString( s, (size_t)len );
00158
00159
00160 if (len > 6 && memcmp(s, "<?xml ", 6) == 0)
00161 {
00162 wxString buf = XmlDecodeStringToString( s, (size_t)len);
00163 int pos;
00164 pos = buf.Find(wxT("encoding="));
00165 if (pos != wxNOT_FOUND)
00166 m_encoding = buf.Mid(pos + 10).BeforeFirst(buf[(size_t)pos+9]);
00167 pos = buf.Find(wxT("version="));
00168 if (pos != wxNOT_FOUND)
00169 m_version = buf.Mid(pos + 9).BeforeFirst(buf[(size_t)pos+8]);
00170 }
00171
00172 parser->DefaultHnd( buf );
00173 }
00174
00175 double a2dIOHandlerXML::ParseDouble( const wxString& buffer, unsigned int& position )
00176 {
00177 const wxChar *start = buffer.c_str() + (long) position;
00178 wxChar *end;
00179 double val = wxStrtod(start, &end);
00180 position = end - buffer.c_str();
00181
00182 if ( start == end )
00183 throw a2dIOHandlerXMLException( wxT("not a number near: "), GetCurrentLineNumber(), GetCurrentColumnNumber() + position );
00184
00185 return val;
00186 }
00187
00188 void a2dIOHandlerXML::SkipCommaSpaces( const wxString& buffer, unsigned int& position )
00189 {
00190 char current;
00191 for(;;)
00192 {
00193 current = buffer[position];
00194 switch (current)
00195 {
00196 default:
00197 return;
00198 case wxT(','): case 0x20: case 0x09: case 0x0D: case 0x0A:
00199 position++;
00200 break;
00201 }
00202 }
00203 }
00204
00205 void a2dIOHandlerXML::SkipSpaces( const wxString& buffer, unsigned int& position )
00206 {
00207 char current;
00208 for(;;)
00209 {
00210 current = buffer[position];
00211 switch (current)
00212 {
00213 default:
00214 return;
00215 case 0x20: case 0x09: case 0x0D: case 0x0A:
00216 position++;
00217 break;
00218 }
00219 }
00220 }
00221
00222
00223
00224
00225
00226 a2dXMLTag::a2dXMLTag( XMLeventType type, wxString tagname )
00227 {
00228 m_tag = tagname;
00229 m_type = type;
00230 m_line = 0;
00231 m_column = 0;
00232 m_hasContent = false;
00233 m_hasattributes = false;
00234 }
00235
00236 a2dXMLTag::a2dXMLTag(const a2dXMLTag& other)
00237 {
00238 m_tag = other.m_tag;
00239 m_type = other.m_type;
00240 m_hasContent = false;
00241 m_hasattributes = false;
00242 m_attributes = other.m_attributes;
00243 m_line = 0;
00244 m_column = 0;
00245 }
00246
00247 a2dXMLTag::~a2dXMLTag()
00248 {
00249 }
00250
00251 a2dObject* a2dXMLTag::Clone( CloneOptions WXUNUSED(options) ) const
00252 {
00253 return new a2dXMLTag( *this );
00254 }
00255
00256 bool a2dXMLTag::SetAttribute( const wxString& attributeName, const wxString& Value )
00257 {
00258 a2dAttributeHash::iterator iter = m_attributes.find( attributeName );
00259 m_attributes[ attributeName ] = Value;
00260 return iter != m_attributes.end();
00261 }
00262
00263 wxString* a2dXMLTag::GetAttribute( const wxString& attributeName )
00264 {
00265 a2dAttributeHash::iterator iter = m_attributes.find( attributeName );
00266 if( iter == m_attributes.end() )
00267 return NULL;
00268
00269 return &iter->second;
00270 }
00271
00272 #if wxART2D_USE_CVGIO
00273
00274 void a2dXMLTag::DoSave( wxObject* WXUNUSED(parent), a2dIOHandlerXmlSerOut& WXUNUSED(out), a2dXmlSer_flag WXUNUSED(xmlparts), a2dObjectList* WXUNUSED(towrite) )
00275 {
00276 wxASSERT(0);
00277 }
00278
00279 #endif //wxART2D_USE_CVGIO
00280
00281 #if wxART2D_USE_CVGIO
00282
00283 void a2dXMLTag::DoLoad( wxObject* WXUNUSED(parent), a2dIOHandlerXmlSerIn& WXUNUSED(parser), a2dXmlSer_flag WXUNUSED(xmlparts) )
00284 {
00285 wxASSERT(0);
00286 }
00287
00288 #endif //wxART2D_USE_CVGIO
00289
00290 wxString GetTypeString(const XMLeventType& type)
00291 {
00292 switch ( type )
00293 {
00294 case START_DOCUMENT: { return wxT("START_DOCUMENT"); break; }
00295 case END_DOCUMENT: { return wxT("END_DOCUMENT"); break; }
00296 case START_TAG: { return wxT("START_TAG"); break; }
00297 case END_TAG: { return wxT("END_TAG"); break; }
00298 case CONTENT: { return wxT("CONTENT"); break; }
00299 default: break;
00300 }
00301 return wxT("");
00302 }
00303
00304
00305
00306
00307
00308 wxString a2dIOHandlerXML::m_encoding = wxT("UTF-8");
00309
00310 wxString a2dIOHandlerXML::m_version = wxT("1.0");
00311
00312 a2dIOHandlerXMLPull::a2dIOHandlerXMLPull()
00313 {
00314 m_depth = 0;
00315 m_current = 0 ;
00316 m_startdoc = new a2dXMLTag( START_DOCUMENT, wxT("startdocument") );
00317 m_enddoc = new a2dXMLTag( END_DOCUMENT, wxT("enddocument") );
00318 }
00319
00320 a2dIOHandlerXMLPull::~a2dIOHandlerXMLPull()
00321 {
00322 delete m_startdoc;
00323 delete m_enddoc;
00324 }
00325
00326 void a2dIOHandlerXMLPull::InitializeLoad( )
00327 {
00328 m_depth = 0;
00329 m_current = m_startdoc;
00330 a2dIOHandlerXML::InitializeLoad( );
00331 }
00332
00333 void a2dIOHandlerXMLPull::ResetLoad( )
00334 {
00335 m_elements.clear();
00336 m_current = 0;
00337
00338 a2dIOHandlerXML::ResetLoad( );
00339 }
00340
00341 int a2dIOHandlerXMLPull::GetCurrentColumnNumber()
00342 {
00343 if ( m_current )
00344 return m_current->m_column;
00345 return -1;
00346 }
00347
00348 int a2dIOHandlerXMLPull::GetCurrentLineNumber()
00349 {
00350 if ( m_current )
00351 return m_current->m_line;
00352 return -1;
00353 }
00354
00355 void a2dIOHandlerXMLPull::StartElementHnd( a2dXMLTag* tag )
00356 {
00357 tag->m_line = XML_GetCurrentLineNumber( m_parser );
00358 tag->m_column = XML_GetCurrentColumnNumber( m_parser );
00359 m_elements.push_back( tag );
00360 }
00361
00362 void a2dIOHandlerXMLPull::EndElementHnd( const wxString& name )
00363 {
00364 a2dXMLTag* tag = new a2dXMLTag( END_TAG, name );
00365 m_elements.push_back( tag );
00366 tag->m_line = XML_GetCurrentLineNumber( m_parser );
00367 tag->m_column = XML_GetCurrentColumnNumber( m_parser );
00368 }
00369
00370 void a2dIOHandlerXMLPull::CharacterDataHnd( const wxString& text )
00371 {
00372
00373
00374
00375
00376
00377 if ( !m_elements.empty() )
00378 m_elements.back()->m_text += text;
00379 }
00380
00381 void a2dIOHandlerXMLPull::CommentHnd( const wxString& WXUNUSED(comment) )
00382 {
00383 }
00384
00385 void a2dIOHandlerXMLPull::DefaultHnd( const wxString& WXUNUSED(def) )
00386 {
00387 }
00388
00389 void a2dIOHandlerXMLPull::Require( const XMLeventType& type, wxString name)
00390 {
00391 if ( !m_elements.empty() )
00392 {
00393 if ( m_current->m_type != type || m_current->m_tag != name )
00394 {
00395
00396 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("expected: %s '%s'\ngot %s '%s' at line %d"), GetTypeString(type).c_str(), name.c_str(),
00397 GetTypeString(m_current->m_type).c_str(), m_current->m_tag.c_str(), GetCurrentLineNumber());
00398 throw a2dIOHandlerXMLException( wxT("expected:") + name ,GetCurrentLineNumber(), GetCurrentColumnNumber() );
00399 }
00400 return;
00401 }
00402 else
00403 {
00404 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("XML end of file reached at line %d"), GetCurrentLineNumber());
00405 throw a2dIOHandlerXMLException( wxT("XML end of file reached"),GetCurrentLineNumber(), GetCurrentColumnNumber() );
00406 }
00407 }
00408
00409
00410 XMLeventType a2dIOHandlerXMLPull::NextTag()
00411 {
00412 XMLeventType eventType = Next();
00413
00414 if (eventType != START_TAG && eventType != END_TAG)
00415 {
00416 throw a2dIOHandlerXMLException( wxT("expected start or end tag") ,GetCurrentLineNumber(), GetCurrentColumnNumber());
00417 }
00418 return eventType;
00419 }
00420
00421 XMLeventType a2dIOHandlerXMLPull::Next()
00422 {
00423 if ( !m_elements.empty() )
00424 {
00425 m_elements.pop_front();
00426 m_depth--;
00427
00428 if ( !m_elements.empty() )
00429 {
00430 m_depth++;
00431 m_current = m_elements.front();
00432 return m_current->m_type;
00433 }
00434 }
00435
00436 FillQueue();
00437
00438 if ( !m_elements.empty() )
00439 {
00440 m_depth++;
00441 m_current = m_elements.front();
00442 return m_current->m_type;
00443 }
00444
00445 m_current = m_enddoc;
00446 return END_DOCUMENT;
00447 }
00448
00449 wxString a2dIOHandlerXMLPull::GetAttributeValue( const wxString& attrib, const wxString& defaultv )
00450 {
00451 if ( m_current->m_type != START_TAG )
00452 throw a2dIOHandlerXMLException( wxT("GetAttributeValue on non starttag") ,GetCurrentLineNumber(), GetCurrentColumnNumber());
00453
00454 wxString* val = m_current->GetAttribute( attrib );
00455 if ( m_current->GetAttribute( attrib ) )
00456 return *val;
00457 return defaultv;
00458 }
00459
00460 wxString a2dIOHandlerXMLPull::RequireAttributeValue( const wxString& attrib )
00461 {
00462 if ( m_current->m_type != START_TAG )
00463 throw a2dIOHandlerXMLException( wxT("GetAttributeValue on non starttag") ,GetCurrentLineNumber(), GetCurrentColumnNumber());
00464
00465 wxString* val = m_current->GetAttribute( attrib );
00466 if ( val )
00467 return *val;
00468
00469 throw a2dIOHandlerXMLException( wxT("No such attribute: ") + attrib ,GetCurrentLineNumber(), GetCurrentColumnNumber());
00470 return *val;
00471 }
00472
00473 double a2dIOHandlerXMLPull::GetAttributeValueDouble( const wxString& attrib, double defaultv )
00474 {
00475 wxString s = GetAttributeValue( attrib );
00476 if ( !s.IsEmpty() )
00477 {
00478 double num;
00479 s.ToDouble( &num );
00480 return num;
00481 }
00482
00483 return defaultv;
00484 }
00485
00486 double a2dIOHandlerXMLPull::RequireAttributeValueDouble( const wxString& attrib )
00487 {
00488 wxString s = RequireAttributeValue( attrib );
00489 double num;
00490 s.ToDouble( &num );
00491 return num;
00492 }
00493
00494 int a2dIOHandlerXMLPull::GetAttributeValueInt( const wxString& attrib, int defaultv )
00495 {
00496 wxString s = GetAttributeValue( attrib );
00497 if ( !s.IsEmpty() )
00498 {
00499 long num;
00500 s.ToLong( &num );
00501 return num;
00502 }
00503
00504 return defaultv;
00505 }
00506
00507 int a2dIOHandlerXMLPull::RequireAttributeValueInt( const wxString& attrib )
00508 {
00509 wxString s = RequireAttributeValue( attrib );
00510 long num;
00511 s.ToLong( &num );
00512 return num;
00513 }
00514
00515 long a2dIOHandlerXMLPull::GetAttributeValueLong( const wxString& attrib, long defaultv )
00516 {
00517 wxString s = GetAttributeValue( attrib );
00518 if ( !s.IsEmpty() )
00519 {
00520 long num;
00521 s.ToLong( &num );
00522 return num;
00523 }
00524
00525 return defaultv;
00526 }
00527
00528 long a2dIOHandlerXMLPull::RequireAttributeValueLong( const wxString& attrib )
00529 {
00530 wxString s = RequireAttributeValue( attrib );
00531 long num;
00532 s.ToLong( &num );
00533 return num;
00534 }
00535
00536 bool a2dIOHandlerXMLPull::GetAttributeValueBool( const wxString& attrib, bool defaultv )
00537 {
00538 wxString s = GetAttributeValue( attrib );
00539 if ( !s.IsEmpty() )
00540 {
00541 if ( s.MakeLower() == wxT("true") )
00542 return true;
00543 else
00544 return false;
00545 }
00546
00547 return defaultv;
00548 }
00549
00550 bool a2dIOHandlerXMLPull::RequireAttributeValueBool( const wxString& attrib )
00551 {
00552 wxString s = RequireAttributeValue( attrib );
00553 if ( s.MakeLower() == wxT("true") )
00554 return true;
00555 else
00556 return false;
00557 }
00558
00559 bool a2dIOHandlerXMLPull::HasAttribute( const wxString& attrib )
00560 {
00561 return m_current->GetAttribute( attrib ) != NULL;
00562 }
00563
00564 wxString a2dIOHandlerXMLPull::GetTagName()
00565 {
00566 return m_current->m_tag;
00567 }
00568
00569 wxString a2dIOHandlerXMLPull::GetContent()
00570 {
00571
00572
00573
00574
00575
00576 while( m_elements.size() <= 1 && !m_done )
00577 {
00578
00579 size_t bytes_read;
00580 m_buffer = (char*) XML_GetBuffer( m_parser, XMLBUFSIZE);
00581 if (m_buffer == NULL)
00582 {
00583 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("XML couldnot allocate buffer") );
00584 throw a2dIOHandlerXMLException( a2dIOHandlerXML::GetErrorString() );
00585 }
00586 bytes_read = Read( m_buffer, XMLBUFSIZE);
00587 if (bytes_read < 0)
00588 {
00589
00590 }
00591
00592 m_done = ( bytes_read < XMLBUFSIZE);
00593
00594 if (!XML_ParseBuffer( m_parser, bytes_read, m_done ))
00595 {
00596 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("XML parsing error: '%s' at line %d"), a2dIOHandlerXML::GetErrorString().c_str(), a2dIOHandlerXML::GetCurrentLineNumber() );
00597 throw a2dIOHandlerXMLException( a2dIOHandlerXML::GetErrorString(),a2dIOHandlerXML::GetCurrentLineNumber(), a2dIOHandlerXML::GetCurrentColumnNumber() );
00598 }
00599 }
00600
00601 return m_current->m_text;
00602 }
00603
00604 XMLeventType a2dIOHandlerXMLPull::GetEventType()
00605 {
00606 return m_current->m_type;
00607 }
00608
00609 void a2dIOHandlerXMLPull::FillQueue()
00610 {
00611
00612
00613 while( m_elements.empty() && !m_done )
00614 {
00615
00616 size_t bytes_read;
00617 m_buffer = (char*) XML_GetBuffer( m_parser, XMLBUFSIZE);
00618 if (m_buffer == NULL)
00619 {
00620 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("XML couldnot allocate buffer") );
00621 throw a2dIOHandlerXMLException( a2dIOHandlerXML::GetErrorString() );
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 bytes_read = Read( m_buffer, XMLBUFSIZE);
00633
00634 if (bytes_read < 0)
00635 {
00636
00637 }
00638
00639 m_done = ( bytes_read < XMLBUFSIZE);
00640
00641 if (!XML_ParseBuffer( m_parser, bytes_read, m_done ))
00642 {
00643 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("XML parsing error: '%s' at line %d"), a2dIOHandlerXML::GetErrorString().c_str(), a2dIOHandlerXML::GetCurrentLineNumber() );
00644 throw a2dIOHandlerXMLException( a2dIOHandlerXML::GetErrorString(),a2dIOHandlerXML::GetCurrentLineNumber(), a2dIOHandlerXML::GetCurrentColumnNumber() );
00645 }
00646 }
00647 }
00648
00649 void a2dIOHandlerXMLPull::SkipSubTree()
00650 {
00651 int sublevel = 1;
00652
00653 while(sublevel > 0)
00654 {
00655 XMLeventType type = Next();
00656 switch(type)
00657 {
00658 case START_TAG:
00659 ++sublevel;
00660 break;
00661 case END_TAG:
00662 --sublevel;
00663 break;
00664 default:
00665 break;
00666 }
00667 }
00668 }
00669
00670
00671
00672
00673
00674 a2dIOHandlerXMLWrite::a2dIOHandlerXMLWrite()
00675 {
00676 m_format = wxT("%g");
00677 m_indentSize = 4;
00678 m_indent = 0;
00679 m_depth = 0;
00680 m_current = 0 ;
00681 m_startdoc = new a2dXMLTag( START_DOCUMENT, wxT("startdocument") );
00682 m_enddoc = new a2dXMLTag( END_DOCUMENT, wxT("enddocument") );
00683 }
00684
00685 a2dIOHandlerXMLWrite::~a2dIOHandlerXMLWrite()
00686 {
00687 delete m_startdoc;
00688 delete m_enddoc;
00689 }
00690
00691 void a2dIOHandlerXMLWrite::InitializeSave( )
00692 {
00693 m_indentSize = 4;
00694 m_indent = 0;
00695 m_depth = 0;
00696 m_current = m_startdoc;
00697 a2dIOHandlerStrOut::InitializeSave( );
00698 }
00699
00700 void a2dIOHandlerXMLWrite::ResetSave( )
00701 {
00702 a2dIOHandlerStrOut::ResetSave( );
00703
00704 m_current = 0;
00705 }
00706
00707 int a2dIOHandlerXMLWrite::GetCurrentColumnNumber()
00708 {
00709 return m_current->m_column;
00710 }
00711
00712 int a2dIOHandlerXMLWrite::GetCurrentLineNumber()
00713 {
00714 return m_current->m_line;
00715 }
00716
00717
00718
00719
00720 void a2dIOHandlerXMLWrite::WriteStartDocument( const wxString& version, const wxString& encoding, bool standalone )
00721 {
00722 m_depth = 0;
00723 *this << wxT("<?xml version=\"") << version << wxT("\" encoding=\"") << encoding << wxT("\"");
00724 *this << wxT(" standalone=\"") << (standalone ? wxT("yes") : wxT("no")) << wxT("\"?>\n");
00725 }
00726
00727 void a2dIOHandlerXMLWrite::WriteEndDocument()
00728 {
00729 wxASSERT_MSG( m_elements.empty(), wxT("not end of document, still elements open") );
00730 wxASSERT_MSG( m_current == m_enddoc, wxT("unBalanced") );
00731 }
00732
00733
00734
00735 void a2dIOHandlerXMLWrite::WriteStartElement( const wxString& name, bool newLine )
00736 {
00737
00738 m_current->m_hasContent = true;
00739
00740 if ( newLine )
00741 WriteNewLine();
00742
00743 m_current = new a2dXMLTag( START_TAG, name );
00744 m_elements.push_front( m_current );
00745
00746
00747 m_depth++;
00748 m_indent = m_depth;
00749
00750 *this << wxT("<") << name << wxT(">");
00751 }
00752
00753
00754 void a2dIOHandlerXMLWrite::WriteStartElementAttributes( const wxString& name, bool newLine )
00755 {
00756
00757 m_current->m_hasContent = true;
00758
00759 if ( newLine )
00760 WriteNewLine();
00761
00762 m_current = new a2dXMLTag( START_TAG, name );
00763 m_current->m_hasattributes = true;
00764 m_elements.push_front( m_current );
00765
00766
00767 m_depth++;
00768 m_indent = m_depth;
00769 *this << wxT("<") << name;
00770 }
00771
00772
00773 void a2dIOHandlerXMLWrite::WriteStartElement( const a2dXMLTag& tag, bool newLine )
00774 {
00775
00776 m_current->m_hasContent = true;
00777
00778 if ( newLine )
00779 WriteNewLine();
00780
00781 m_current = new a2dXMLTag( tag );
00782 m_elements.push_front( m_current );
00783
00784 m_current->m_hasattributes = m_current->m_attributes.size() != 0;
00785
00786 m_depth++;
00787 m_indent = m_depth;
00788 *this << wxT("<") << m_current->m_tag << wxT(">");
00789 }
00790
00791 void a2dIOHandlerXMLWrite::WriteElement( const wxString& name, const wxString& content, bool newLine )
00792 {
00793 if ( newLine )
00794 WriteNewLine();
00795
00796 *this << wxT("<") << name << wxT(">") << content << wxT("</") << name << wxT(">");
00797
00798 m_indent = m_depth;
00799 }
00800
00801 void a2dIOHandlerXMLWrite::WriteAttribute( const wxString& name, bool value, bool onlyIfTrue )
00802 {
00803 wxString error = wxT("Wrong start tag") + m_current->m_tag;
00804 wxASSERT_MSG( m_current->m_hasattributes , error );
00805 if ( (onlyIfTrue && value) || !onlyIfTrue )
00806 {
00807 if ( value == true )
00808 *this << wxT(" ") << name << wxT("=\"true\"");
00809 else
00810 *this << wxT(" ") << name << wxT("=\"false\"");
00811 }
00812 }
00813
00814 void a2dIOHandlerXMLWrite::WriteAttribute( const a2dNamedProperty& attribute )
00815 {
00816 wxString error = wxT("Wrong start tag") + m_current->m_tag;
00817 wxASSERT_MSG( m_current->m_hasattributes , error );
00818
00819 *this << wxT(" ") << attribute.GetName() << wxT("=\"") << attribute.StringValueRepresentation();
00820 }
00821
00822 void a2dIOHandlerXMLWrite::WriteAttributeEnt( const wxString& name, const wxString& value )
00823 {
00824 wxString error = wxT("Wrong start tag") + this->m_current->m_tag;
00825 wxASSERT_MSG( this->m_current->m_hasattributes , error );
00826
00827 *this << wxT(" ") << name << wxT("=\"");
00828 WriteStringEnt( value );
00829 *this << wxT("\"");
00830 }
00831
00832 void a2dIOHandlerXMLWrite::WriteEndAttributes(bool close)
00833 {
00834 wxString error = wxT("Wrong start tag") + m_current->m_tag;
00835 wxASSERT_MSG( m_current->m_hasattributes , error );
00836 m_current->m_hasattributes = false;
00837
00838 if (close )
00839 {
00840 m_depth--;
00841
00842 *this << wxT("/>");
00843
00844 m_elements.pop_front();
00845 if ( !m_elements.empty() )
00846 m_current = m_elements.front();
00847 else
00848 m_current = m_enddoc;
00849 }
00850 else
00851 *this << wxT(">");
00852
00853 m_indent = m_depth;
00854 }
00855
00856
00857 void a2dIOHandlerXMLWrite::WriteEndElement( bool newLine )
00858 {
00859 wxString error = wxT("Wrong start tag or attributes not written") + m_current->m_tag;
00860 wxASSERT_MSG( !m_current->m_hasattributes , wxT("Wrong start tag or attributes not written") );
00861
00862 m_depth--;
00863 m_indent = m_depth;
00864
00865 if ( newLine )
00866 WriteNewLine();
00867
00868 m_current = m_elements.front();
00869
00870 *this << wxT("</") << m_current->m_tag << wxT(">");
00871
00872 m_elements.pop_front();
00873 if ( !m_elements.empty() )
00874 m_current = m_elements.front();
00875 else
00876 m_current = m_enddoc;
00877 }
00878
00879 void a2dIOHandlerXMLWrite::WriteContent( const wxString& content )
00880 {
00881 m_indent = m_depth;
00882 *this << content;
00883 }
00884
00885 void a2dIOHandlerXMLWrite::WriteNewLine()
00886 {
00887
00888 WriteIndent();
00889 }
00890
00891
00892 void a2dIOHandlerXMLWrite::WriteIndent()
00893 {
00894 wxString str = wxT("\n");
00895 for (int i = 0; i < m_indent; i++)
00896 for (int i = 0; i < m_indentSize; i++)
00897 str << wxT(" ");
00898
00899 if (str.IsEmpty()) return;
00900
00901 WriteString( str );
00902 }
00903
00904 void a2dIOHandlerXMLWrite::EndlWriteString(const wxString& string)
00905 {
00906 WriteNewLine();
00907 WriteString( string );
00908 }
00909
00910 void a2dIOHandlerXMLWrite::WriteStringEnt(const wxString& string )
00911 {
00912 wxString buf;
00913 size_t i, last, len;
00914 wxChar c;
00915
00916 len = string.Len();
00917 last = 0;
00918 for (i = 0; i < len; i++)
00919 {
00920 c = string.GetChar(i);
00921 if (c == wxT('<') || c == wxT('>') ||
00922 (c == wxT('&') && string.Mid(i+1, 4) != wxT("amp;")) ||
00923 ( c == wxT('"')) )
00924 {
00925 a2dIOHandlerStrOut::WriteString( string.Mid(last, i - last) );
00926 switch (c)
00927 {
00928 case wxT('<'):
00929 a2dIOHandlerStrOut::WriteString( wxT("<"));
00930 break;
00931 case wxT('>'):
00932 a2dIOHandlerStrOut::WriteString( wxT(">"));
00933 break;
00934 case wxT('&'):
00935 a2dIOHandlerStrOut::WriteString( wxT("&"));
00936 break;
00937 case wxT('"'):
00938 a2dIOHandlerStrOut::WriteString( wxT("""));
00939 break;
00940 default:
00941 break;
00942 }
00943 last = i + 1;
00944 }
00945 }
00946 a2dIOHandlerStrOut::WriteString( string.Mid(last, i - last) );
00947 }
00948
00949 void a2dIOHandlerXMLWrite::XmlEncodeStringToStream(
00950 const wxChar *string,
00951 size_t len
00952 )
00953 {
00954 #if wxUSE_UNICODE
00955
00956 for( const wxChar *pos = string; *pos; pos++ )
00957 {
00958 if( *pos>=32 && *pos<=126 && *pos!=wxChar('<') && *pos!=wxChar('>')
00959 && *pos!=wxChar('&') && *pos!=wxChar('\"') )
00960 *this << (char) *pos;
00961 else
00962 *this << wxT("&#") << (unsigned int)(wxUChar)(*pos) << wxT(";");
00963 }
00964
00965 #else
00966 size_t nLen = (len != wxSTRING_MAXLEN)
00967 ? len
00968 : wxConvLocal.MB2WC((wchar_t*) NULL, string, 0);
00969
00970 if( nLen == (size_t)-1 )
00971 {
00972
00973 unsigned i=0;
00974
00975 for( const wxChar *pos = string; *pos && i<nLen; pos++, i++ )
00976 {
00977 if( *pos>=32 && *pos<=126 && *pos!='<' && *pos!='>' && *pos!='&' && *pos!='\"' )
00978 *this << (char) *pos;
00979 else
00980 *this << "&#" << (unsigned int)(wchar_t)(*pos) << ";";
00981 }
00982 }
00983
00984 wchar_t *buf = new wchar_t[nLen+1];
00985 wxConvLocal.MB2WC(buf, string, nLen);
00986 buf[nLen] = 0;
00987
00988 for( const wchar_t *pos = buf; *pos; pos++ )
00989 {
00990 if( *pos>=32 && *pos<=126 && *pos!='<' && *pos!='>' && *pos!='&' && *pos!='\"' )
00991 *this << (char) *pos;
00992 else
00993 *this << wxT("&#") << (unsigned int)(wchar_t)(*pos) << wxT(";");
00994 }
00995
00996 delete[] buf;
00997 #endif
00998
00999 }
01000
01001 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const wxChar *string)
01002 {
01003 WriteString( wxString(string) );
01004 return *this;
01005 }
01006
01007 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const wxString& string)
01008 {
01009 WriteString( string );
01010 return *this;
01011 }
01012
01013 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(char c)
01014 {
01015 WriteString( wxString::FromAscii(c) );
01016
01017 return *this;
01018 }
01019
01020 #if wxUSE_UNICODE && wxWCHAR_T_IS_REAL_TYPE
01021
01022 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(wchar_t wc)
01023 {
01024 WriteString( wxString(&wc, m_conv, 1) );
01025
01026 return *this;
01027 }
01028
01029 #endif // wxUSE_UNICODE
01030
01031 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const wxInt16 & c)
01032 {
01033 wxString str;
01034 str.Printf(wxT("%d"), (signed int)c);
01035 WriteString(str);
01036
01037 return *this;
01038 }
01039
01040 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const wxInt32 & c)
01041 {
01042 wxString str;
01043 str.Printf(wxT("%ld"), (signed long)c);
01044 WriteString(str);
01045
01046 return *this;
01047 }
01048
01049 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const wxInt64 & c)
01050 {
01051 wxString str;
01052 str.Printf(wxT("%lld"), (unsigned long long) c);
01053 WriteString(str);
01054
01055 return *this;
01056 }
01057
01058 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const wxUint16 & c)
01059 {
01060 wxString str;
01061 str.Printf(wxT("%u"), (unsigned int)c);
01062 WriteString(str);
01063
01064 return *this;
01065 }
01066
01067 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const wxUint32 & c)
01068 {
01069 wxString str;
01070 str.Printf(wxT("%lu"), (unsigned long)c);
01071 WriteString(str);
01072
01073 return *this;
01074 }
01075
01076 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const wxUint64 & c)
01077 {
01078 wxString str;
01079 str.Printf(wxT("%llu"), (unsigned long long)c);
01080 WriteString(str);
01081
01082 return *this;
01083 }
01084
01085 a2dIOHandlerXMLWrite &a2dIOHandlerXMLWrite::operator<<(const double & f)
01086 {
01087 WriteDouble(f);
01088 return *this;
01089 }
01090
01091 a2dIOHandlerXMLWrite& a2dIOHandlerXMLWrite::operator<<(const float & f)
01092 {
01093 WriteDouble((double)f);
01094 return *this;
01095 }
01096
01097 #if wxART2D_USE_CVGIO
01098
01099
01100
01101
01102
01103 a2dIOHandlerXmlSerIn::a2dIOHandlerXmlSerIn()
01104 {
01105 }
01106
01107
01108 a2dIOHandlerXmlSerIn::~a2dIOHandlerXmlSerIn()
01109 {
01110 }
01111
01112 bool a2dIOHandlerXmlSerIn::CanLoad(a2dDocumentInputStream& stream, const wxObject* obj, wxClassInfo* docClassInfo )
01113 {
01114 SeekI( 0 );
01115 char cheader[7];
01116 cheader[6] = 0;
01117 Read(cheader, 6);
01118 SeekI( 0 );
01119
01120
01121
01122 return ( memcmp(cheader, "<?xml ", 6) == 0);
01123 }
01124
01125 bool a2dIOHandlerXmlSerIn::Load( a2dDocumentInputStream& stream , wxObject* doc )
01126 {
01127 m_streami = &stream;
01128 m_doc = doc;
01129
01130 InitializeLoad();
01131
01132 bool oke = true;
01133
01134 try
01135 {
01136 a2dResolveIdList toResolve;
01137 ((a2dObject*)m_doc)->Load( NULL, *this );
01138
01139
01140
01141 LinkReferences();
01142
01143 }
01144 catch (const a2dIOHandlerXMLException& e)
01145 {
01146 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("CVG parsing error: '%s' at line %d"), e.getMessage().c_str(), e.getLineNumber(), e.getColumnNumber());
01147 oke = false;
01148 }
01149
01150 ResetLoad();
01151
01152 return oke;
01153 }
01154
01155
01156
01157
01158
01159 a2dIOHandlerXmlSerOut::a2dIOHandlerXmlSerOut()
01160 {
01161 }
01162
01163
01164 a2dIOHandlerXmlSerOut::~a2dIOHandlerXmlSerOut()
01165 {
01166 }
01167
01168 bool a2dIOHandlerXmlSerOut::Save( a2dDocumentOutputStream& stream, const wxObject* doc)
01169 {
01170 m_doc = (wxObject*) doc;
01171 m_streamo = &stream;
01172
01173 if ( !IsOk() )
01174 {
01175 a2dGeneralGlobals->ReportErrorF( a2dError_FileCouldNotOpen, _("Sorry, could not open stream for saving") );
01176 return false;
01177 }
01178
01179 InitializeSave();
01180
01181 ((a2dObject*)m_doc)->Save( NULL, *this, NULL );
01182
01183 ResetSave();
01184
01185 return true;
01186 }
01187 #endif //wxART2D_USE_CVGIO
01188
01189
01190
01191
01192
01193
01194 a2dXmlString::a2dXmlString( const wxString& str )
01195 {
01196 m_streamo = &m_strstream;
01197 InitializeSave();
01198 WriteString( str );
01199 }
01200
01201
01202 a2dXmlString::~a2dXmlString()
01203 {
01204 ResetSave();
01205 }
01206
01207 void a2dXmlString::Reset()
01208 {
01209
01210 }
01211
01212 void a2dXmlString::WriteCommand( const wxString& name, bool close )
01213 {
01214 WriteStartElementAttributes( _T("command"), false );
01215 WriteAttribute( _T("name"), name );
01216 if ( close )
01217 WriteEndAttributes(true);
01218 }
01219
01220
01221
01222 #endif