1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleskandars Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
23 #include "docripper.h"
33 // ***** currently only HTML versions of variouse templates available ***** //
35 static const char* HTM_TopTempl
=
37 "<html><body bgcolor=#FFFFFF>\n\
38 \n\n<!------ Automatically Generated by \"wxDocRipper\"------->\n\n\n\
39 <p><h2>$(NAME)</h2><p>\n\
45 static const char* HTM_ContentIdxTempl
=
48 <a name=\"r$(ID)_$(NAME)\">\n\
50 <h2><p>$(NAME)<p></h2>\
56 static const char* HTM_SuperContentTempl
=
59 <a name=\"r$(ID)_$(NAME)\">\n\
61 <p><h2>$(NAME)<p></h2>\
65 static const char* HTM_SubContentTempl
=
68 <a name=\"r$(ID)_$(NAME)\">\n\
70 <p><h3>$(NAME)<p></h3>\
74 static const char* HTM_OutLineTempl
=
78 <b><font color=\"#FF0000\">$(NAME)</font></b><p>\n\
81 static const char* HTM_OutLine1Templ
=
85 <b><i><font color=\"#101010\">$(NAME)</font></i></b>\n\
91 static const char* HTM_RefTempl
=
94 <li><a href=\"#r$(ID)_$(NAME)\">$(NAME)</A>\n\
97 static const char* HTM_DeadRefTempl
=
103 /***** Implementation for class RipperDocGen *****/
105 RipperDocGen::RipperDocGen()
107 : mTopTempl ( HTM_TopTempl
),
108 mContentIdxTempl ( HTM_ContentIdxTempl
),
109 mSuperContentTempl( HTM_SuperContentTempl
),
110 mSubContentTempl ( HTM_SubContentTempl
),
111 mOutLineTempl ( HTM_OutLineTempl
),
112 mOutLine1Templ ( HTM_OutLine1Templ
),
114 mRefTempl ( HTM_RefTempl
),
115 mDeadRefTempl ( HTM_DeadRefTempl
),
119 // topIndex is not referenced
120 mpTopIdx
= new ScriptSection( "Source Code Contents" , "", &mTopTempl
, 0 );
121 mpClassIdx
= new ScriptSection( "Classes Reference" , "", &mContentIdxTempl
, &mRefTempl
);
122 mpEnumIdx
= new ScriptSection( "Enumerations Reference" , "", &mContentIdxTempl
, &mRefTempl
);
123 mpTypeDefIdx
= new ScriptSection( "Type Definitions Reference" , "", &mContentIdxTempl
, &mRefTempl
);
124 mpMacroIdx
= new ScriptSection( "Macros Reference" , "", &mContentIdxTempl
, &mRefTempl
);
125 mpGlobalVarsIdx
= new ScriptSection( "Global Variables Reference" , "", &mContentIdxTempl
, &mRefTempl
);
126 mpGlobalFuncIdx
= new ScriptSection( "Global Functions Reference", "", &mContentIdxTempl
, &mRefTempl
);
127 mpConstIdx
= new ScriptSection( "Constants Reference" , "", &mContentIdxTempl
, &mRefTempl
);
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 );
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
);
148 // create the top-most (interfile) context
149 mpFileBinderCtx
= new spFile();
151 // the default script is HTML
152 mTags
= get_HTML_markup_tags();
154 mpParser
= 0; // no default parser!
157 void RipperDocGen::Init( SourceParserBase
* pParser
)
162 RipperDocGen::~RipperDocGen()
164 delete mpFileBinderCtx
;
167 void RipperDocGen::AppendComments( spContext
& fromContext
, string
& str
)
169 if ( !fromContext
.HasComments() ) return;
171 size_t start
= str
.length();
173 str
+= mTags
[TAG_BOLD
].end
;
174 str
+= mTags
[TAG_PARAGRAPH
].start
;
176 MCommentListT
& lst
= fromContext
.GetCommentList();
178 for( size_t i
= 0; i
!= lst
.size(); ++i
)
183 if ( lst
[i
]->StartsParagraph() )
185 str
+= mTags
[TAG_PARAGRAPH
].start
;
188 str
+= lst
[i
]->m_Text
;
191 // remove new lines, and insert paragraph breaks
193 // if empty lines found
195 size_t len
= str
.length();
197 for( size_t n
= start
; n
!= len
; ++n
)
204 if ( ( str
[n
] == 13 && str
[n
+1] == 10 && // FIXME:: quick-hack
206 ( str
[n
] == 10 && str
[n
+1] == 10 )
209 str
.insert( n
+ 1, "<p>" ); // FIXME:: quick-hack
215 str
+= mTags
[TAG_PARAGRAPH
].end
;
218 void RipperDocGen::AppendMulitilineStr( string
& st
, string
& mlStr
)
220 st
= mTags
[TAG_FIXED_FONT
].start
;
222 st
+= mTags
[TAG_FIXED_FONT
].end
;
225 void RipperDocGen::AppendHighlightedSource( string
& st
, string source
)
227 // FIXME:: below should not be fixed :)
231 // ASSERT( source.length() + 1 < sizeof(buf) );
233 strcpy( buf
, source
.c_str() );
237 mSrcPainter
.ProcessSource( buf
, strlen(buf
) );
238 mSrcPainter
.GetResultString( st
, mTags
);
241 bool RipperDocGen::CheckIfUncommented( spContext
& ctx
, ScriptSection
& toSect
)
243 if ( ctx
.HasComments() ) return 0;
246 new ScriptSection( GetScopedName( ctx
), "", 0, &mDeadRefTempl
)
252 ScriptTemplate
* RipperDocGen::GetRefTemplFor( spContext
& ctx
)
254 if ( ctx
.HasComments() )
257 return &mDeadRefTempl
;
260 wxString
RipperDocGen::GetScopedName( spContext
& ofCtx
)
262 if ( ofCtx
.IsInFile() )
263 return ofCtx
.GetName();
265 return ofCtx
.GetOutterContext()->GetName() +
266 _T("::") + ofCtx
.GetName();
269 void RipperDocGen::AddToCurrentClass( ScriptSection
* pSection
, spContext
& ctx
,
270 const char* subSectionName
)
274 if ( ctx
.mVisibility
== SP_VIS_PROTECTED
)
275 sName
= "Protected members/";
277 if ( ctx
.mVisibility
== SP_VIS_PRIVATE
)
278 sName
= "Private members/";
280 sName
= "Public members/";
282 sName
+= subSectionName
;
284 ScriptSection
* pSect
= mpCurClassSect
->GetSubsection( sName
.c_str() );
286 if ( CheckIfUncommented( ctx
, *pSect
) )
292 pSect
->AddReference( pSection
);
294 mpCurClassSect
->AddSection( pSection
);
297 void RipperDocGen::LinkSuperClassRefs()
301 // collect all classes in the context tree
302 mpFileBinderCtx
->GetContextList( clLst
, SP_CTX_CLASS
);
304 for( size_t i
= 0; i
!= clLst
.size(); ++i
)
306 spClass
& cl
= *((spClass
*)clLst
[i
]);
308 // FIXME:: why sometimes GetUserData() returns NULL?
309 if ( !cl
.GetUserData() )
312 ScriptSection
* pClSect
= (ScriptSection
*)cl
.GetUserData();
313 ScriptSection
* pSuperSect
= pClSect
->GetSubsection("Derived from");
315 for( size_t n
= 0; n
!= cl
.mSuperClassNames
.size(); ++n
)
317 string
& superClName
= cl
.mSuperClassNames
[n
];
319 spClass
* pFound
= NULL
;
321 for( size_t k
= 0; k
!= clLst
.size(); ++k
)
323 if ( clLst
[k
]->GetName() == superClName
)
325 pFound
= (spClass
*)clLst
[k
];
332 ScriptSection
* pNotFound
=
333 new ScriptSection( superClName
, "", 0, &mDeadRefTempl
);
335 pSuperSect
->AddReference( pNotFound
);
338 if ( pFound
->GetUserData() )
340 pSuperSect
->AddReference(
341 (ScriptSection
*)pFound
->GetUserData() );
346 void RipperDocGen::ProcessFile( const char* sourceFile
)
348 wxSTD cout
<< "Processing file " << sourceFile
<< "..." << wxSTD endl
;
350 spFile
* pCtx
= mpParser
->ParseFile( sourceFile
);
354 wxSTD cout
<< "Cannot open file " << sourceFile
<< ", skipped..." << wxSTD endl
;
359 VisitAll( *pCtx
, true );
361 mpFileBinderCtx
->AddMember( pCtx
);
364 // implementations of "visiting procedures"
366 void RipperDocGen::VisitEnumeration( spEnumeration
& en
)
368 // FOR NOW:: do not reference "nameless" enums
369 if ( en
.GetName() == "" ) return;
371 if ( CheckIfUncommented( en
, *mpEnumIdx
) )
375 body
+= mTags
[TAG_BOLD
].start
;
377 AppendMulitilineStr( body
, en
.m_EnumContent
);
379 body
+= mTags
[TAG_BOLD
].end
;
382 AppendHighlightedSource( line
, body
);
383 AppendComments( en
, line
);
385 mpEnumIdx
->AddSection(
386 new ScriptSection( en
.GetName(), line
,
388 GetRefTemplFor( en
) ), 1
392 void RipperDocGen::VisitTypeDef( spTypeDef
& td
)
394 if ( CheckIfUncommented( td
, *mpTypeDefIdx
) )
398 body
+= mTags
[TAG_BOLD
].start
;
400 body
+= mTags
[TAG_BOLD
].end
;
402 AppendMulitilineStr( body
, td
.m_OriginalType
);
403 body
+= td
.m_OriginalType
;
406 body
+= mTags
[TAG_BOLD
].start
;
407 body
+= td
.GetName();
408 body
+= mTags
[TAG_BOLD
].end
;
411 AppendHighlightedSource( line
, body
);
412 AppendComments( td
, line
);
414 mpTypeDefIdx
->AddSection(
415 new ScriptSection( td
.GetName(), line
,
417 GetRefTemplFor( td
) ), true
421 void RipperDocGen::VisitPreprocessorLine( spPreprocessorLine
& pd
)
423 if ( pd
.mDefType
!= SP_PREP_DEF_REDEFINE_SYMBOL
)
426 if ( CheckIfUncommented( pd
, *mpMacroIdx
) )
430 body
+= mTags
[TAG_FIXED_FONT
].start
;
432 wxString coloredLine
= pd
.m_Line
;
433 AppendHighlightedSource( coloredLine
, pd
.m_Line
);
435 AppendMulitilineStr( body
, coloredLine
);
437 body
+= mTags
[TAG_FIXED_FONT
].end
;
439 AppendComments( pd
, body
);
441 mpMacroIdx
->AddSection(
442 new ScriptSection( pd
.GetName(), body
,
444 GetRefTemplFor( pd
) ), true
448 void RipperDocGen::VisitClass( spClass
& cl
)
450 // FOR NOW:: do not document nested classes -
451 // nicier visiting method yet needed
453 if ( cl
.IsInClass() )
455 SkipChildren(); // spVisitor's method
460 AppendComments( cl
, body
);
463 new ScriptSection( cl
.GetName(), body
, &mSuperContentTempl
, &mRefTempl
);
465 // set up reference in the class context, pointing back
466 // to the section where this class is represented
467 cl
.SetUserData( mpCurClassSect
);
469 ScriptSection
* pSuper
= new ScriptSection( "Derived from" ,"", &mOutLine1Templ
,0, 1 );
471 ScriptSection
* pPublic
= new ScriptSection( "Public members" ,"", &mOutLineTempl
,0, 1 );
472 ScriptSection
* pProtected
= new ScriptSection( "Protected members" ,"", &mOutLineTempl
,0, 1 );
473 ScriptSection
* pPrivate
= new ScriptSection( "Private members" ,"", &mOutLineTempl
,0, 1 );
475 pPublic
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
476 pPublic
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
478 pProtected
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
479 pProtected
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
481 pPrivate
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
482 pPrivate
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
484 mpCurClassSect
->AddSection( pSuper
);
485 mpCurClassSect
->AddSection( pPublic
);
486 mpCurClassSect
->AddSection( pProtected
);
487 mpCurClassSect
->AddSection( pPrivate
);
489 mpClassIdx
->AddSection( mpCurClassSect
, true );
492 void RipperDocGen::VisitAttribute( spAttribute
& attr
)
495 body
+= mTags
[TAG_BOLD
].start
;
497 body
+= mTags
[TAG_BOLD
].end
;
499 body
+= mTags
[TAG_ITALIC
].start
;
501 body
+= attr
.GetName();
502 body
+= mTags
[TAG_ITALIC
].end
;
505 AppendHighlightedSource( line
, body
);
506 AppendComments( attr
, line
);
508 ScriptSection
* pSection
=
509 new ScriptSection( GetScopedName( attr
), line
,
511 GetRefTemplFor( attr
) );
513 if ( attr
.mIsConstant
)
514 mpConstIdx
->AddSection( pSection
, true );
516 if ( !attr
.IsInClass() )
518 if ( CheckIfUncommented( attr
, *mpGlobalVarsIdx
) )
520 mpGlobalVarsIdx
->AddSection( pSection
, true );
523 AddToCurrentClass( pSection
, attr
, "Attributes" );
526 void RipperDocGen::VisitOperation( spOperation
& op
)
530 AppendHighlightedSource( body
, op
.GetFullName(mTags
) );
532 AppendComments( op
, body
);
534 ScriptSection
* pSection
=
535 new ScriptSection( GetScopedName( op
), body
,
537 GetRefTemplFor( op
) );
539 if ( !op
.IsInClass() )
541 if ( CheckIfUncommented( op
, *mpGlobalFuncIdx
) )
544 mpGlobalFuncIdx
->AddSection( pSection
, 1 );
547 AddToCurrentClass( pSection
, op
, "Operations" );
550 bool RipperDocGen::OnSaveDocument( ScriptStream
& WXUNUSED(stm
) )
552 LinkSuperClassRefs();
554 // FOR NOW:: doesn't work yet
555 //mpTopIdx->RemoveEmptySections();
557 return 1; // saving can proceed now