]> git.saurik.com Git - wxWidgets.git/blame - utils/HelpGen/src/scriptbinder.cpp
changed wxFFileOutput/InputStream ctor 'mode' argument to wxString
[wxWidgets.git] / utils / HelpGen / src / scriptbinder.cpp
CommitLineData
cecfc5e7
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: No names yet.
3// Purpose: Contrib. demo
4// Author: Aleksandras Gluchovas
5// Modified by:
6// Created: 22/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Aleskandars Gluchovas
8ad74db3 9// Licence: wxWindows licence
cecfc5e7
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20#include "wx/wx.h"
21#endif
22
cecfc5e7
VZ
23#include <string.h>
24#include <memory.h>
25
26#include <stdio.h> // import sprintf() (for doubles)
27#include <stdlib.h> // import atoi() (for integers)
28
29#include "scriptbinder.h"
30
31// helper functions
32
5aca3ef4 33static size_t wx_log2(size_t nr)
cecfc5e7 34{
8ad74db3
WS
35 size_t tmp = 0;
36 while (nr >= 2 )
37 {
38 nr /= 2;
39 ++tmp;
40 }
41
42 return tmp;
cecfc5e7
VZ
43}
44
45/***** Implementation for class ScriptStream *****/
46
47ScriptStream::ScriptStream()
2af95167
WS
48 : m_pBuf(0),
49 m_Size(0),
50 m_Capacity(0)
cecfc5e7
VZ
51{}
52
53ScriptStream::~ScriptStream()
54{
2af95167 55 if ( m_pBuf ) delete m_pBuf;
cecfc5e7
VZ
56}
57
58void ScriptStream::WriteBytes( const void* srcBuf, size_t count )
59{
8ad74db3 60 if ( !count ) return;
cecfc5e7 61
8ad74db3 62 // increase the capacity if necessary
2af95167 63 if ( m_Size + count > m_Capacity )
8ad74db3 64 {
2af95167 65 m_Capacity =
5aca3ef4 66 ( 0x2 << (wx_log2( m_Size + count ) + 1 ) );
cecfc5e7 67
2af95167 68 if ( m_Capacity < 128 ) m_Capacity = 128;
cecfc5e7 69
2af95167 70 char* oldBuf = m_pBuf;
cecfc5e7 71
2af95167 72 m_pBuf = new char[m_Capacity];
cecfc5e7 73
8ad74db3
WS
74 if ( oldBuf )
75 {
2af95167 76 memcpy( m_pBuf, oldBuf, m_Size );
8ad74db3
WS
77 delete oldBuf;
78 }
79 }
cecfc5e7 80
8ad74db3 81 // append new data
2af95167 82 memcpy( &m_pBuf[m_Size], srcBuf, count );
cecfc5e7 83
2af95167 84 m_Size += count;
cecfc5e7
VZ
85}
86
87ScriptStream& ScriptStream::operator<<( const char* str )
88{
8ad74db3 89 WriteBytes( str, strlen( str ) );
cecfc5e7 90
8ad74db3 91 return *this;
cecfc5e7
VZ
92}
93
2af95167 94ScriptStream& ScriptStream::operator<<( const wxString& str )
cecfc5e7 95{
8ad74db3
WS
96 if ( str.length() < 512 )
97 {
98 char buf[512];
99 size_t len = str.length();
cecfc5e7 100
8ad74db3
WS
101 for( size_t i = 0; i != len; ++i )
102 buf[i] = str[i];
cecfc5e7 103
8ad74db3
WS
104 WriteBytes( buf, len );
105 }
106 else
107 WriteBytes( str.c_str(), str.length() );
cecfc5e7 108
8ad74db3 109 return *this;
cecfc5e7
VZ
110}
111
112ScriptStream& ScriptStream::operator<<( char ch )
113{
8ad74db3 114 WriteBytes( &ch, 1 );
cecfc5e7 115
8ad74db3 116 return *this;
cecfc5e7
VZ
117}
118
119void ScriptStream::endl()
120{
8ad74db3
WS
121 char ch = '\n';
122 WriteBytes( &ch, 1 );
cecfc5e7
VZ
123}
124
125/***** Implementation for class ScriptTemplate *****/
126
2af95167 127ScriptTemplate::ScriptTemplate( const wxString& templateText )
cecfc5e7 128{
2af95167 129 wxString tmp = templateText;
cecfc5e7 130
2af95167 131 m_TText = (char*)malloc( tmp.length() + 1 );
cecfc5e7 132
2af95167 133 strcpy( m_TText, tmp.c_str() );
cecfc5e7
VZ
134}
135
136ScriptTemplate::~ScriptTemplate()
137{
2af95167 138 for( size_t i = 0; i != m_Vars.size(); ++i )
cecfc5e7 139
2af95167 140 delete m_Vars[i];
cecfc5e7 141
2af95167 142 free( m_TText );
cecfc5e7
VZ
143}
144
145bool ScriptTemplate::HasVar( const char* name )
146{
2af95167 147 for( size_t i = 0; i != m_Vars.size(); ++i )
cecfc5e7 148
2af95167 149 if ( strcmp( m_Vars[i]->m_Name, name ) == 0 )
cecfc5e7 150
8ad74db3 151 return 1;
cecfc5e7 152
8ad74db3 153 return 0;
cecfc5e7
VZ
154}
155
156void ScriptTemplate::AddStringVar ( const char* name, int ofs )
157{
2af95167 158 m_Vars.push_back( new TVarInfo( name, ofs, TVAR_STRING ) );
cecfc5e7
VZ
159}
160
161void ScriptTemplate::AddIntegerVar( const char* name, int ofs )
162{
2af95167 163 m_Vars.push_back( new TVarInfo( name, ofs, TVAR_INTEGER ) );
cecfc5e7
VZ
164}
165
166void ScriptTemplate::AddDoubleVar ( const char* name, int ofs )
167{
2af95167 168 m_Vars.push_back( new TVarInfo( name, ofs, TVAR_DOUBLE ) );
cecfc5e7
VZ
169}
170
171void ScriptTemplate::AddObjectRefArray( const char* name,
8ad74db3
WS
172 int ofsRefToFirstObj,
173 int ofsObjSizeInt,
174 int ofsObjRefTempl
175 )
cecfc5e7 176{
8ad74db3 177 TArrayInfo* pInfo = new TArrayInfo( name );
cecfc5e7 178
2af95167 179 m_Vars.push_back( pInfo );
cecfc5e7 180
2af95167
WS
181 pInfo->m_RefOfs = ofsRefToFirstObj;
182 pInfo->m_SizeIntOfs = ofsObjSizeInt;
183 pInfo->m_ObjRefTemplOfs = ofsObjRefTempl;
cecfc5e7
VZ
184}
185
8ad74db3
WS
186inline void ScriptTemplate::PrintVar( TVarInfo* pInfo,
187 void* dataObj,
188 ScriptStream& stm )
cecfc5e7 189{
8ad74db3
WS
190 char buf[128];
191
821d644d 192 switch ( pInfo->m_Type )
8ad74db3
WS
193 {
194 case TVAR_INTEGER :
195 {
2af95167 196 sprintf(buf, "%d",*( (int*) ((char*)dataObj + pInfo->m_Ofs) ) );
8bc17f14 197
8ad74db3
WS
198 stm.WriteBytes( buf, strlen(buf ) );
199 break;
200 }
201
202 case TVAR_STRING :
203 {
2af95167 204 wxString& str = *( (wxString*) ((char*)dataObj+pInfo->m_Ofs) );
8ad74db3
WS
205
206 const char* cs = str.c_str();
cecfc5e7 207#ifdef DEBUG_WEIRED_OFFSETS
8ad74db3
WS
208 cout << "DBG:: cs address is " << (int)cs << endl;
209 cout << "DBG:: str address is " << (int)(&str) << endl;
210 cout << "DBG:: dataObj points to " << (int)dataObj << endl;
2af95167
WS
211 cout << "DBG:: pInfo->m_Ofs value is " << (int)pInfo->m_Ofs << endl;
212 cout << "DBG:: d+pInfo->m_Ofs is " << (int)((char*)dataObj + pInfo->m_Ofs) << endl;
8bc17f14 213 cout << "DBG:: pInfo->m_Name is " << pInfo->m_Name << endl;
821d644d 214 cout << "DBG:: pInfo->m_Type is " << pInfo->m_Type << endl;
8ad74db3
WS
215 cout << "DBG:: end of dump. " << endl;
216
217 cout << "DBG:: cs value is " << endl << cs << endl;
cecfc5e7 218#endif
8ad74db3
WS
219 stm.WriteBytes( cs, strlen(cs) );
220 break;
221 }
222
223 case TVAR_DOUBLE :
224 {
225 sprintf( buf, "%f",
2af95167 226 *( (double*)( (char*)dataObj+pInfo->m_Ofs) ) );
8ad74db3
WS
227
228 stm.WriteBytes( buf, strlen(buf ) );
229 break;
230 }
231
232 case TVAR_REF_ARRAY :
233 {
234 TArrayInfo& info = *((TArrayInfo*)pInfo);
235
2af95167 236 int sz = *((int*) ( (char*)dataObj+info.m_SizeIntOfs ));
8ad74db3
WS
237 if ( !sz )
238 {
239 // DBG::
240 int u = 0;
241 ++u;
242 break;
243 }
244
2af95167 245 int* array = *((int**)( (char*)dataObj+info.m_RefOfs ));
8bc17f14 246
8ad74db3
WS
247 ScriptTemplate* pRefTempl;
248
249 for( int i = 0; i != sz; ++i )
250 {
251 pRefTempl =
2af95167 252 *((ScriptTemplate**)((char*)(array[i])+info.m_ObjRefTemplOfs));
8ad74db3
WS
253
254 pRefTempl->PrintScript( (void*)array[i], stm );
255 }
256
257 break;
258 }
259
260 default : break;
261 }
cecfc5e7
VZ
262}
263
264void ScriptTemplate::PrintScript( void* dataObj, ScriptStream& stm )
265{
2af95167 266 char* cur = m_TText;
cecfc5e7 267
8ad74db3
WS
268 // template parsing loop
269 do
270 {
271 char* start = cur;
cecfc5e7 272
8ad74db3 273 while( *cur != '\0' && *cur != '$' ) ++cur;
cecfc5e7 274
8ad74db3
WS
275 // flush text collected between variables
276 stm.WriteBytes( start, cur - start );
cecfc5e7 277
8ad74db3 278 if ( *cur == '\0' ) break;
cecfc5e7 279
8ad74db3 280 cur += 2; // skip to the name of the var
cecfc5e7 281
8ad74db3 282 start = cur;
cecfc5e7 283
8ad74db3 284 while( *cur != ')' ) ++cur;
cecfc5e7 285
8ad74db3 286 // put terminating zero temorarely
cecfc5e7 287
8ad74db3 288 *cur = '\0';
cecfc5e7 289
8ad74db3 290 // look up variable
cecfc5e7 291
2af95167 292 size_t sz = m_Vars.size();
8ad74db3 293 // bool found = false;
cecfc5e7 294
8ad74db3
WS
295 for( size_t i = 0; i != sz; ++i )
296 {
2af95167 297 if ( strcmp( m_Vars[i]->m_Name, start ) == 0 )
8ad74db3 298 {
2af95167 299 PrintVar( m_Vars[i], dataObj, stm );
cecfc5e7 300
8ad74db3
WS
301 *cur = ')'; // remove terminating zero
302 ++cur;
303 // found = 1;
304 break;
305 }
306 }
cecfc5e7 307
8ad74db3
WS
308 // variable referred by template script is not
309 // registered to this tempalte object
310 // ASSERT( found );
cecfc5e7 311
8ad74db3 312 } while(1);
cecfc5e7
VZ
313}
314
315/***** implementation for class ScriptSection *****/
316
2af95167 317int ScriptSection::m_IdCounter = 0;
cecfc5e7 318
c826f371
WS
319ScriptSection::ScriptSection( const wxString& name,
320 const wxString& body,
8ad74db3
WS
321 ScriptTemplate* pSectionTemplate,
322 ScriptTemplate* pReferenceTemplate,
323 bool autoHide,
324 bool sorted
325 )
2af95167 326 : m_pParent ( NULL ),
cecfc5e7 327
2af95167
WS
328 m_Name ( name ),
329 m_Body ( body ),
cecfc5e7 330
2af95167
WS
331 m_AutoHide ( autoHide ),
332 m_SortOn ( sorted ),
cecfc5e7 333
2af95167
WS
334 m_pSectTempl( pSectionTemplate ),
335 m_pRefTempl ( pReferenceTemplate ),
cecfc5e7 336
2af95167
WS
337 m_RefCount( 0 ),
338 m_ArrSize( 0 )
cecfc5e7 339{
8ad74db3 340 // generate GUID
cecfc5e7 341
c826f371 342 wxChar buf[32];
2af95167
WS
343 wxSprintf( buf, _T("%d"), ++m_IdCounter );
344 m_Id = buf;
cecfc5e7
VZ
345}
346
347ScriptSection::~ScriptSection()
348{
2af95167 349 SectListT lst = m_Subsections;
cecfc5e7 350
2af95167 351 while( m_Subsections.size() )
cecfc5e7 352
2af95167 353 m_Subsections[0]->RemoveRef();
cecfc5e7 354
2af95167 355 for( size_t i = 0; i != m_References.size(); ++i )
cecfc5e7 356
2af95167 357 m_References[i]->RemoveRef();
cecfc5e7
VZ
358}
359
360void ScriptSection::AddRef()
361{
2af95167 362 ++m_RefCount;
cecfc5e7
VZ
363}
364
365void ScriptSection::RemoveRef()
366{
2af95167 367 if ( !m_RefCount || !(--m_RefCount) )
8ad74db3 368 {
2af95167 369 if (m_pParent)
8ad74db3
WS
370 {
371 // remove ourselves from parent's list
372
2af95167 373 SectListT& lst = m_pParent->m_Subsections;
8ad74db3
WS
374 for( size_t i = 0; i != lst.size(); ++i )
375
376 if ( lst[i] == this )
377 {
378 lst.erase( &lst[i] );
379 break;
380 }
381 }
382
383 delete this;
384 }
cecfc5e7
VZ
385}
386
387ScriptSection* ScriptSection::GetSubsection( const char* name )
388{
8ad74db3
WS
389 // FOR NOW:: fixed section name length
390 char buf[128];
cecfc5e7 391
8ad74db3 392 size_t cur = 0;
cecfc5e7 393
8ad74db3
WS
394 while( name[cur] && name[cur] != '/' )
395 {
396 buf[cur] = name[cur];
397 ++cur;
398 }
cecfc5e7 399
8ad74db3 400 // ASSERT( cur < sizeof(buf) );
cecfc5e7 401
8ad74db3 402 buf[cur] = '\0';
cecfc5e7 403
2af95167 404 size_t sz = m_Subsections.size();
cecfc5e7 405
8ad74db3
WS
406 for( size_t i = 0; i != sz; ++i )
407 {
408 // DBG::
2af95167 409 //ScriptSection& sect = *m_Subsections[i];
cecfc5e7 410
2af95167 411 if ( m_Subsections[i]->m_Name == buf )
8ad74db3
WS
412 {
413 if ( name[cur] == '/' )
cecfc5e7 414
8ad74db3 415 // search recursivelly
2af95167 416 return m_Subsections[i]->GetSubsection( &name[cur+1] );
8ad74db3 417 else
2af95167 418 return m_Subsections[i];
8ad74db3
WS
419 }
420 }
cecfc5e7 421
8ad74db3 422 return 0;
cecfc5e7
VZ
423}
424
425void ScriptSection::AddSection( ScriptSection* pSection,
8ad74db3
WS
426 bool addToReferencesToo
427 )
cecfc5e7 428{
2af95167 429 m_Subsections.push_back( pSection );
cecfc5e7 430
8ad74db3 431 pSection->AddRef();
cecfc5e7 432
8ad74db3 433 // can add section to multiple containers
2af95167 434 // ASSERT( pSection->m_pParent == 0 );
cecfc5e7 435
2af95167 436 pSection->m_pParent = this;
cecfc5e7 437
8ad74db3 438 if ( addToReferencesToo )
cecfc5e7 439
8ad74db3 440 AddReference( pSection );
cecfc5e7
VZ
441}
442
443void ScriptSection::AddReference( ScriptSection* pReferredSection )
444{
2af95167 445 m_References.push_back( pReferredSection );
cecfc5e7 446
8ad74db3 447 pReferredSection->AddRef();
cecfc5e7 448
8ad74db3 449 // set up mandatory fields used by ScriptTemplate
2af95167
WS
450 m_ArrSize = m_References.size();
451 if ( m_ArrSize )
452 m_RefFirst = (void*)&m_References[0];
cecfc5e7
VZ
453}
454
455SectListT& ScriptSection::GetSubsections()
456{
2af95167 457 return m_Subsections;
cecfc5e7
VZ
458}
459
460// static method:
461void ScriptSection::RegisterTemplate( ScriptTemplate& sectionTempalte )
462{
8ad74db3
WS
463 int nameOfs, bodyOfs, idOfs,
464 arrRefOfs, arrSizeOfs, refTemplOfs;
cecfc5e7 465
8ad74db3 466 // obtaining offsets of member vars
8bc17f14
WS
467
468 GET_VAR_OFS( ScriptSection, m_Name, &nameOfs )
2af95167
WS
469 GET_VAR_OFS( ScriptSection, m_Body, &bodyOfs )
470 GET_VAR_OFS( ScriptSection, m_Id, &idOfs )
471 GET_VAR_OFS( ScriptSection, m_RefFirst,&arrRefOfs )
472 GET_VAR_OFS( ScriptSection, m_ArrSize, &arrSizeOfs )
cecfc5e7 473
2af95167 474 GET_VAR_OFS( ScriptSection, m_pRefTempl, &refTemplOfs )
cecfc5e7 475
8ad74db3 476 // registering member variables with given script template
cecfc5e7 477
8ad74db3
WS
478 sectionTempalte.AddStringVar( "NAME", nameOfs );
479 sectionTempalte.AddStringVar( "BODY", bodyOfs );
480 sectionTempalte.AddStringVar( "ID", idOfs );
cecfc5e7 481
8ad74db3
WS
482 sectionTempalte.AddObjectRefArray( "REFLIST",
483 arrRefOfs, arrSizeOfs, refTemplOfs );
cecfc5e7
VZ
484}
485
486void ScriptSection::Print( ScriptStream& stm )
487{
8ad74db3 488 // TBD:: sorting
cecfc5e7 489
8ad74db3 490 // print out this content first
2af95167 491 if ( m_pSectTempl )
cecfc5e7 492
2af95167 493 m_pSectTempl->PrintScript( this, stm );
cecfc5e7 494
8ad74db3 495 // attach contents subsections at the end of this content
cecfc5e7 496
2af95167 497 for( size_t i = 0; i != m_Subsections.size(); ++i )
cecfc5e7 498
2af95167 499 m_Subsections[i]->Print( stm );
cecfc5e7
VZ
500}
501
502void ScriptSection::DoRemoveEmptySections(int& nRemoved, SectListT& removedLst)
503{
2af95167 504 for( size_t i = 0; i != m_Subsections.size(); ++i )
8ad74db3 505 {
2af95167 506 ScriptSection& sect = *m_Subsections[i];
8ad74db3
WS
507
508 sect.DoRemoveEmptySections( nRemoved, removedLst );
509
2af95167 510 if (sect.m_AutoHide )
8bc17f14 511
2af95167 512 if ( sect.m_References.size() == 0 )
8ad74db3
WS
513 {
514 bool found = false;
515 for( size_t k = 0; k != removedLst.size(); ++k )
516
517 if ( removedLst[k] == &sect )
518 {
519 found = 1;
520 break;
521 }
8bc17f14 522
8ad74db3
WS
523 if ( !found )
524 {
525 removedLst.push_back( &sect );
526 ++nRemoved;
527
528 delete &sect;
529 --i;
530 }
531 }
532 }
cecfc5e7
VZ
533}
534
535void ScriptSection::DoRemoveDeadLinks( SectListT& removedLst)
536{
8ad74db3
WS
537 size_t dsz = removedLst.size();
538
2af95167 539 for( size_t i = 0; i != m_Subsections.size(); ++i )
8ad74db3 540 {
2af95167 541 m_Subsections[i]->DoRemoveDeadLinks( removedLst );
8ad74db3
WS
542 }
543
2af95167 544 for( size_t n = 0; n != m_References.size(); ++n )
8ad74db3
WS
545 {
546 for( size_t k = 0; k != dsz; ++k )
547
2af95167 548 if ( removedLst[k] == m_References[n] )
8ad74db3 549 {
2af95167 550 m_References.erase( &m_References[n] );
8ad74db3
WS
551 --n;
552
553 // set up mandatory fields used by ScriptTemplate
2af95167
WS
554 m_ArrSize = m_References.size();
555 if ( m_ArrSize )
556 m_RefFirst = (void*)&m_References[0];
8ad74db3
WS
557
558 break;
559 }
560 }
cecfc5e7
VZ
561}
562
563
564void ScriptSection::RemoveEmptySections()
565{
8ad74db3 566 // FIXME:: this is very_very_very slow alg.! +"doesn't work"
cecfc5e7 567
8ad74db3 568 int nRemoved = 0;
cecfc5e7 569
8ad74db3
WS
570 do
571 {
572 SectListT removedLst;
573 nRemoved = 0;
cecfc5e7 574
8ad74db3 575 DoRemoveEmptySections( nRemoved, removedLst );
cecfc5e7 576
8ad74db3
WS
577 DoRemoveDeadLinks( removedLst );
578 }
579 while( nRemoved );
cecfc5e7
VZ
580}
581
582/***** Iimplementation for class DocGeneratorBase *****/
583
8ad74db3
WS
584bool DocGeneratorBase::SaveDocument( const char* fname,
585 const char* fopenOptions,
586 ScriptSection* pFromSection
587 )
cecfc5e7 588{
8ad74db3 589 FILE* fp = fopen( fname, fopenOptions );
cecfc5e7 590
42389ac7 591 if ( !fp ) return 0;
cecfc5e7 592
8ad74db3 593 ScriptStream stm;
cecfc5e7 594
8ad74db3
WS
595 // check if derived class agrees about saving it
596 if ( !OnSaveDocument( stm ) ) return 0;
cecfc5e7 597
8ad74db3 598 if ( pFromSection )
cecfc5e7 599
8ad74db3
WS
600 pFromSection->Print( stm );
601 else
602 {
603 ScriptSection* pTopSect = GetTopSection();
604 // ASSERT( pTopSect );
605 pTopSect->Print( stm );
606 }
cecfc5e7 607
8ad74db3 608 size_t nWrite = fwrite( stm.GetBuf(), 1, stm.GetBufSize(), fp );
cecfc5e7 609
8ad74db3 610 if ( nWrite != stm.GetBufSize() ) return 0;
cecfc5e7 611
8ad74db3 612 fclose( fp );
cecfc5e7 613
8ad74db3 614 return 1;
cecfc5e7 615
8ad74db3 616 // that^s it
cecfc5e7 617}