]> git.saurik.com Git - wxWidgets.git/blame - utils/HelpGen/src/docripper.cpp
Moved wxRichTextCtrl to its own library
[wxWidgets.git] / utils / HelpGen / src / docripper.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
23#include "docripper.h"
24
4888e623
GT
25#if wxUSE_IOSTREAMH
26 #include <iostream.h>
27#else
28 #include <iostream>
29#endif
cecfc5e7
VZ
30
31// script templates
32
33// ***** currently only HTML versions of variouse templates available ***** //
34
8ad74db3 35static const char* HTM_TopTempl =
cecfc5e7
VZ
36
37"<html><body bgcolor=#FFFFFF>\n\
38\n\n<!------ Automatically Generated by \"wxDocRipper\"------->\n\n\n\
39<p><h2>$(NAME)</h2><p>\n\
40<ul>\n\
41$(REFLIST)\
42</ul><p>\n\n\
43";
44
8ad74db3 45static const char* HTM_ContentIdxTempl =
cecfc5e7
VZ
46
47"\
48<a name=\"r$(ID)_$(NAME)\">\n\
49<p><hr>\n\
50<h2><p>$(NAME)<p></h2>\
51<ul>\n\
52$(REFLIST)\
53</ul><p>\n\n\
54";
55
8ad74db3 56static const char* HTM_SuperContentTempl =
cecfc5e7
VZ
57
58"\
59<a name=\"r$(ID)_$(NAME)\">\n\
60<p><hr>\n\
61<p><h2>$(NAME)<p></h2>\
62$(BODY)\n\
63";
64
8ad74db3 65static const char* HTM_SubContentTempl =
cecfc5e7
VZ
66
67"\
68<a name=\"r$(ID)_$(NAME)\">\n\
69<p><hr>\n\
70<p><h3>$(NAME)<p></h3>\
71$(BODY)\n\
72";
73
74static const char* HTM_OutLineTempl =
75
76"\
77<p>\n\
78<b><font color=\"#FF0000\">$(NAME)</font></b><p>\n\
79";
80
81static const char* HTM_OutLine1Templ =
82
83"\
84<p>\n\
85<b><i><font color=\"#101010\">$(NAME)</font></i></b>\n\
86<ul>\n\
87$(REFLIST)\
88</ul>\n\n\
89";
90
91static const char* HTM_RefTempl =
92
93"\
94<li><a href=\"#r$(ID)_$(NAME)\">$(NAME)</A>\n\
95";
96
97static const char* HTM_DeadRefTempl =
98
99"\
100<li></b>$(NAME)\n\
101";
102
103/***** Implementation for class RipperDocGen *****/
104
105RipperDocGen::RipperDocGen()
106
8ad74db3
WS
107 : mTopTempl ( HTM_TopTempl ),
108 mContentIdxTempl ( HTM_ContentIdxTempl ),
109 mSuperContentTempl( HTM_SuperContentTempl ),
110 mSubContentTempl ( HTM_SubContentTempl ),
111 mOutLineTempl ( HTM_OutLineTempl ),
112 mOutLine1Templ ( HTM_OutLine1Templ ),
113
114 mRefTempl ( HTM_RefTempl ),
115 mDeadRefTempl ( HTM_DeadRefTempl ),
116
117 mpCurClassSect(0)
118{
119 // topIndex is not referenced
b6317810
WS
120 mpTopIdx = new ScriptSection( "Source Code Contents" , wxEmptyString, &mTopTempl , 0 );
121 mpClassIdx = new ScriptSection( "Classes Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl );
122 mpEnumIdx = new ScriptSection( "Enumerations Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl );
123 mpTypeDefIdx = new ScriptSection( "Type Definitions Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl );
124 mpMacroIdx = new ScriptSection( "Macros Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl );
125 mpGlobalVarsIdx = new ScriptSection( "Global Variables Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl );
126 mpGlobalFuncIdx = new ScriptSection( "Global Functions Reference", wxEmptyString, &mContentIdxTempl, &mRefTempl );
127 mpConstIdx = new ScriptSection( "Constants Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl );
8ad74db3
WS
128
129 // assemble top index
130 mpTopIdx->AddSection( mpClassIdx , 1 );
131 mpTopIdx->AddSection( mpEnumIdx , 1 );
132 mpTopIdx->AddSection( mpTypeDefIdx , 1 );
133 mpTopIdx->AddSection( mpMacroIdx , 1 );
134 mpTopIdx->AddSection( mpGlobalVarsIdx, 1 );
135 mpTopIdx->AddSection( mpGlobalFuncIdx, 1 );
136 mpTopIdx->AddSection( mpConstIdx , 1 );
137
138 // register reserved variables for index and description templates
139 ScriptSection::RegisterTemplate( mTopTempl );
140 ScriptSection::RegisterTemplate( mContentIdxTempl );
141 ScriptSection::RegisterTemplate( mSuperContentTempl );
142 ScriptSection::RegisterTemplate( mSubContentTempl );
143 ScriptSection::RegisterTemplate( mOutLineTempl );
144 ScriptSection::RegisterTemplate( mOutLine1Templ );
145 ScriptSection::RegisterTemplate( mRefTempl );
146 ScriptSection::RegisterTemplate( mDeadRefTempl );
147
148 // create the top-most (interfile) context
149 mpFileBinderCtx = new spFile();
150
151 // the default script is HTML
2af95167 152 m_Tags = get_HTML_markup_tags();
8ad74db3
WS
153
154 mpParser = 0; // no default parser!
cecfc5e7
VZ
155}
156
157void RipperDocGen::Init( SourceParserBase* pParser )
158{
8ad74db3 159 mpParser = pParser;
cecfc5e7
VZ
160}
161
162RipperDocGen::~RipperDocGen()
163{
8ad74db3 164 delete mpFileBinderCtx;
cecfc5e7
VZ
165}
166
16a0cc1d 167void RipperDocGen::AppendComments( spContext& fromContext, wxString& str )
cecfc5e7 168{
8ad74db3 169 if ( !fromContext.HasComments() ) return;
4888e623 170
8ad74db3 171 size_t start = str.length();
4888e623 172
2af95167
WS
173 str += m_Tags[TAG_BOLD].end;
174 str += m_Tags[TAG_PARAGRAPH].start;
4888e623 175
8ad74db3 176 MCommentListT& lst = fromContext.GetCommentList();
4888e623 177
8ad74db3
WS
178 for( size_t i = 0; i != lst.size(); ++i )
179 {
4888e623 180
8ad74db3 181 if ( i != 0 )
4888e623 182
8ad74db3
WS
183 if ( lst[i]->StartsParagraph() )
184 {
2af95167 185 str += m_Tags[TAG_PARAGRAPH].start;
8ad74db3 186 }
4888e623 187
e49cde67 188 str += lst[i]->m_Text;
8ad74db3 189 }
4888e623 190
8ad74db3 191 // remove new lines, and insert paragraph breaks
4888e623 192
8ad74db3 193 // if empty lines found
cecfc5e7 194
8ad74db3 195 size_t len = str.length();
4888e623 196
8ad74db3 197 for( size_t n = start; n != len; ++n )
4888e623 198
8ad74db3
WS
199 if ( str[n] == 10 ||
200 str[n] == 13 )
201 {
202 if ( n + 2 < len )
203 {
204 if ( ( str[n] == 13 && str[n+1] == 10 && // FIXME:: quick-hack
205 str[n+2] == 13 ) ||
206 ( str[n] == 10 && str[n+1] == 10 )
207 )
208 {
16a0cc1d 209 str.insert( n + 1, _T("<p>") ); // FIXME:: quick-hack
8ad74db3
WS
210 len += 3;
211 }
212 }
16a0cc1d 213 str[n] = _T(' ');
8ad74db3 214 }
2af95167 215 str += m_Tags[TAG_PARAGRAPH].end;
cecfc5e7
VZ
216}
217
401af0f8 218void RipperDocGen::AppendMulitilineStr( wxString& st, wxString& mlStr )
cecfc5e7 219{
2af95167 220 st = m_Tags[TAG_FIXED_FONT].start;
8ad74db3 221 st += mlStr;
2af95167 222 st += m_Tags[TAG_FIXED_FONT].end;
cecfc5e7
VZ
223}
224
16a0cc1d 225void RipperDocGen::AppendHighlightedSource( wxString& st, wxString source )
cecfc5e7 226{
8ad74db3 227 // FIXME:: below should not be fixed :)
b6317810 228 wxChar buf[1024*32];
8ad74db3
WS
229
230 // DBG:::
231// ASSERT( source.length() + 1 < sizeof(buf) );
232
b6317810 233 wxStrcpy( buf, source.c_str() );
8ad74db3
WS
234
235 // highlight things
236 mSrcPainter.Init();
237 mSrcPainter.ProcessSource( buf, strlen(buf) );
2af95167 238 mSrcPainter.GetResultString( st, m_Tags );
cecfc5e7
VZ
239}
240
241bool RipperDocGen::CheckIfUncommented( spContext& ctx, ScriptSection& toSect )
242{
8ad74db3 243 if ( ctx.HasComments() ) return 0;
cecfc5e7 244
8ad74db3 245 toSect.AddReference(
b6317810 246 new ScriptSection( GetScopedName( ctx ), wxEmptyString, 0, &mDeadRefTempl )
8ad74db3 247 );
cecfc5e7 248
8ad74db3 249 return 1;
cecfc5e7
VZ
250}
251
252ScriptTemplate* RipperDocGen::GetRefTemplFor( spContext& ctx )
253{
8ad74db3
WS
254 if ( ctx.HasComments() )
255 return &mRefTempl;
256 else
257 return &mDeadRefTempl;
cecfc5e7
VZ
258}
259
41964404 260wxString RipperDocGen::GetScopedName( spContext& ofCtx )
cecfc5e7 261{
8ad74db3
WS
262 if ( ofCtx.IsInFile() )
263 return ofCtx.GetName();
264 else
265 return ofCtx.GetOutterContext()->GetName() +
41964404 266 _T("::") + ofCtx.GetName();
cecfc5e7
VZ
267}
268
8ad74db3
WS
269void RipperDocGen::AddToCurrentClass( ScriptSection* pSection, spContext& ctx,
270 const char* subSectionName )
cecfc5e7 271{
2af95167 272 wxString sName;
cecfc5e7 273
8ad74db3
WS
274 if ( ctx.mVisibility == SP_VIS_PROTECTED )
275 sName = "Protected members/";
276 else
277 if ( ctx.mVisibility == SP_VIS_PRIVATE )
278 sName = "Private members/";
279 else
280 sName = "Public members/";
cecfc5e7 281
8ad74db3 282 sName += subSectionName;
cecfc5e7 283
8ad74db3 284 ScriptSection* pSect = mpCurClassSect->GetSubsection( sName.c_str() );
cecfc5e7 285
8ad74db3
WS
286 if ( CheckIfUncommented( ctx, *pSect ) )
287 {
288 delete pSection;
289 return;
290 }
cecfc5e7 291
8ad74db3 292 pSect->AddReference( pSection );
cecfc5e7 293
8ad74db3 294 mpCurClassSect->AddSection( pSection );
cecfc5e7
VZ
295}
296
297void RipperDocGen::LinkSuperClassRefs()
298{
8ad74db3
WS
299 MMemberListT clLst;
300
301 // collect all classes in the context tree
302 mpFileBinderCtx->GetContextList( clLst, SP_CTX_CLASS );
303
304 for( size_t i = 0; i != clLst.size(); ++i )
305 {
306 spClass& cl = *((spClass*)clLst[i]);
307
308 // FIXME:: why sometimes GetUserData() returns NULL?
309 if ( !cl.GetUserData() )
310 continue;
311
312 ScriptSection* pClSect = (ScriptSection*)cl.GetUserData();
313 ScriptSection* pSuperSect = pClSect->GetSubsection("Derived from");
314
33882d15 315 for( size_t n = 0; n != cl.m_SuperClassNames.size(); ++n )
8ad74db3 316 {
33882d15 317 wxString& superClName = cl.m_SuperClassNames[n];
8ad74db3
WS
318
319 spClass* pFound = NULL;
320
321 for( size_t k = 0; k != clLst.size(); ++k )
322 {
323 if ( clLst[k]->GetName() == superClName )
324 {
325 pFound = (spClass*)clLst[k];
326 break;
327 }
328 }
329
330 if ( !pFound )
331 {
332 ScriptSection* pNotFound =
b6317810 333 new ScriptSection( superClName, wxEmptyString, 0, &mDeadRefTempl );
8ad74db3
WS
334
335 pSuperSect->AddReference( pNotFound );
336 }
337 else
338 if ( pFound->GetUserData() )
339
340 pSuperSect->AddReference(
341 (ScriptSection*)pFound->GetUserData() );
342 }
343 }
cecfc5e7
VZ
344}
345
346void RipperDocGen::ProcessFile( const char* sourceFile )
347{
8ad74db3 348 wxSTD cout << "Processing file " << sourceFile << "..." << wxSTD endl;
cecfc5e7 349
8ad74db3 350 spFile* pCtx = mpParser->ParseFile( sourceFile );
cecfc5e7 351
8ad74db3
WS
352 if ( pCtx == NULL )
353 {
354 wxSTD cout << "Cannot open file " << sourceFile << ", skipped..." << wxSTD endl;
cecfc5e7 355
8ad74db3
WS
356 return;
357 }
cecfc5e7 358
8ad74db3 359 VisitAll( *pCtx, true );
cecfc5e7 360
8ad74db3 361 mpFileBinderCtx->AddMember( pCtx );
cecfc5e7
VZ
362}
363
364// implementations of "visiting procedures"
365
366void RipperDocGen::VisitEnumeration( spEnumeration& en )
367{
8ad74db3 368 // FOR NOW:: do not reference "nameless" enums
b6317810 369 if ( en.GetName().empty() ) return;
cecfc5e7 370
8ad74db3
WS
371 if ( CheckIfUncommented( en, *mpEnumIdx ) )
372 return;
cecfc5e7 373
41964404 374 wxString body;
2af95167 375 body += m_Tags[TAG_BOLD].start;
cecfc5e7 376
c69a7d10 377 AppendMulitilineStr( body, en.m_EnumContent );
cecfc5e7 378
2af95167 379 body += m_Tags[TAG_BOLD].end;
cecfc5e7 380
41964404 381 wxString line;
8ad74db3
WS
382 AppendHighlightedSource( line, body );
383 AppendComments( en, line );
cecfc5e7 384
8ad74db3
WS
385 mpEnumIdx->AddSection(
386 new ScriptSection( en.GetName(), line,
387 &mSubContentTempl,
388 GetRefTemplFor( en ) ), 1
389 );
cecfc5e7
VZ
390}
391
392void RipperDocGen::VisitTypeDef( spTypeDef& td )
393{
8ad74db3
WS
394 if ( CheckIfUncommented( td, *mpTypeDefIdx ) )
395 return;
396
41964404 397 wxString body;
2af95167 398 body += m_Tags[TAG_BOLD].start;
8ad74db3 399 body += "typdef ";
2af95167 400 body += m_Tags[TAG_BOLD].end;
8ad74db3 401
c69a7d10
WS
402 AppendMulitilineStr( body, td.m_OriginalType );
403 body += td.m_OriginalType;
8ad74db3
WS
404 body += ' ';
405
2af95167 406 body += m_Tags[TAG_BOLD].start;
8ad74db3 407 body += td.GetName();
2af95167 408 body += m_Tags[TAG_BOLD].end;
8ad74db3 409
41964404 410 wxString line;
8ad74db3
WS
411 AppendHighlightedSource( line, body );
412 AppendComments( td, line );
413
414 mpTypeDefIdx->AddSection(
415 new ScriptSection( td.GetName(), line,
416 &mSubContentTempl,
417 GetRefTemplFor( td ) ), true
418 );
cecfc5e7
VZ
419}
420
421void RipperDocGen::VisitPreprocessorLine( spPreprocessorLine& pd )
422{
8ad74db3
WS
423 if ( pd.mDefType != SP_PREP_DEF_REDEFINE_SYMBOL )
424 return;
cecfc5e7 425
8ad74db3
WS
426 if ( CheckIfUncommented( pd, *mpMacroIdx ) )
427 return;
4888e623 428
41964404 429 wxString body;
2af95167 430 body += m_Tags[TAG_FIXED_FONT].start;
cecfc5e7 431
41964404 432 wxString coloredLine = pd.m_Line;
c69a7d10 433 AppendHighlightedSource( coloredLine, pd.m_Line );
cecfc5e7 434
8ad74db3 435 AppendMulitilineStr( body, coloredLine );
cecfc5e7 436
2af95167 437 body += m_Tags[TAG_FIXED_FONT].end;
cecfc5e7 438
8ad74db3 439 AppendComments( pd, body );
cecfc5e7 440
8ad74db3
WS
441 mpMacroIdx->AddSection(
442 new ScriptSection( pd.GetName(), body,
443 &mSubContentTempl,
444 GetRefTemplFor( pd ) ), true
445 );
cecfc5e7
VZ
446}
447
448void RipperDocGen::VisitClass( spClass& cl )
449{
8ad74db3
WS
450 // FOR NOW:: do not document nested classes -
451 // nicier visiting method yet needed
cecfc5e7 452
8ad74db3
WS
453 if ( cl.IsInClass() )
454 {
455 SkipChildren(); // spVisitor's method
456 return;
457 }
cecfc5e7 458
41964404 459 wxString body;
8ad74db3 460 AppendComments( cl, body );
cecfc5e7 461
8ad74db3
WS
462 mpCurClassSect =
463 new ScriptSection( cl.GetName(), body, &mSuperContentTempl, &mRefTempl );
cecfc5e7 464
8ad74db3
WS
465 // set up reference in the class context, pointing back
466 // to the section where this class is represented
467 cl.SetUserData( mpCurClassSect );
cecfc5e7 468
b6317810 469 ScriptSection* pSuper = new ScriptSection( "Derived from" ,wxEmptyString, &mOutLine1Templ,0, 1 );
cecfc5e7 470
b6317810
WS
471 ScriptSection* pPublic = new ScriptSection( "Public members" ,wxEmptyString, &mOutLineTempl,0, 1 );
472 ScriptSection* pProtected = new ScriptSection( "Protected members" ,wxEmptyString, &mOutLineTempl,0, 1 );
473 ScriptSection* pPrivate = new ScriptSection( "Private members" ,wxEmptyString, &mOutLineTempl,0, 1 );
cecfc5e7 474
b6317810
WS
475 pPublic->AddSection( new ScriptSection( "Operations", wxEmptyString, &mOutLine1Templ, 0, 1 ) );
476 pPublic->AddSection( new ScriptSection( "Attributes", wxEmptyString, &mOutLine1Templ, 0, 1 ) );
cecfc5e7 477
b6317810
WS
478 pProtected->AddSection( new ScriptSection( "Operations", wxEmptyString, &mOutLine1Templ, 0, 1 ) );
479 pProtected->AddSection( new ScriptSection( "Attributes", wxEmptyString, &mOutLine1Templ, 0, 1 ) );
cecfc5e7 480
b6317810
WS
481 pPrivate->AddSection( new ScriptSection( "Operations", wxEmptyString, &mOutLine1Templ, 0, 1 ) );
482 pPrivate->AddSection( new ScriptSection( "Attributes", wxEmptyString, &mOutLine1Templ, 0, 1 ) );
cecfc5e7 483
8ad74db3
WS
484 mpCurClassSect->AddSection( pSuper );
485 mpCurClassSect->AddSection( pPublic );
486 mpCurClassSect->AddSection( pProtected );
487 mpCurClassSect->AddSection( pPrivate );
cecfc5e7 488
8ad74db3 489 mpClassIdx->AddSection( mpCurClassSect, true );
cecfc5e7
VZ
490}
491
492void RipperDocGen::VisitAttribute( spAttribute& attr )
493{
41964404 494 wxString body;
2af95167 495 body += m_Tags[TAG_BOLD].start;
821d644d 496 body += attr.m_Type;
2af95167 497 body += m_Tags[TAG_BOLD].end;
8ad74db3 498
2af95167 499 body += m_Tags[TAG_ITALIC].start;
8ad74db3
WS
500 body += ' ';
501 body += attr.GetName();
2af95167 502 body += m_Tags[TAG_ITALIC].end;
8ad74db3 503
41964404 504 wxString line;
8ad74db3
WS
505 AppendHighlightedSource( line, body );
506 AppendComments( attr, line );
507
508 ScriptSection* pSection =
509 new ScriptSection( GetScopedName( attr ), line,
510 &mSubContentTempl,
511 GetRefTemplFor( attr ) );
512
513 if ( attr.mIsConstant )
514 mpConstIdx->AddSection( pSection, true );
515 else
516 if ( !attr.IsInClass() )
517 {
518 if ( CheckIfUncommented( attr, *mpGlobalVarsIdx ) )
519 return;
520 mpGlobalVarsIdx->AddSection( pSection, true );
521 }
522 else
523 AddToCurrentClass( pSection, attr, "Attributes" );
cecfc5e7
VZ
524}
525
526void RipperDocGen::VisitOperation( spOperation& op )
527{
41964404 528 wxString body;
cecfc5e7 529
2af95167 530 AppendHighlightedSource( body, op.GetFullName(m_Tags) );
cecfc5e7 531
8ad74db3 532 AppendComments( op, body );
cecfc5e7 533
8ad74db3
WS
534 ScriptSection* pSection =
535 new ScriptSection( GetScopedName( op ), body,
536 &mSubContentTempl,
537 GetRefTemplFor( op ) );
cecfc5e7 538
8ad74db3
WS
539 if ( !op.IsInClass() )
540 {
541 if ( CheckIfUncommented( op, *mpGlobalFuncIdx ) )
542 return;
cecfc5e7 543
8ad74db3
WS
544 mpGlobalFuncIdx->AddSection( pSection, 1 );
545 }
546 else
547 AddToCurrentClass( pSection, op, "Operations" );
cecfc5e7
VZ
548}
549
8ad74db3 550bool RipperDocGen::OnSaveDocument( ScriptStream& WXUNUSED(stm) )
cecfc5e7 551{
8ad74db3 552 LinkSuperClassRefs();
cecfc5e7 553
8ad74db3
WS
554 // FOR NOW:: doesn't work yet
555 //mpTopIdx->RemoveEmptySections();
cecfc5e7 556
8ad74db3 557 return 1; // saving can proceed now
cecfc5e7
VZ
558}
559