source: trunk/MagicSoft/Mars/mbase/MHtml.cc@ 1910

Last change on this file since 1910 was 753, checked in by tbretz, 24 years ago
*** empty log message ***
  • Property svn:executable set to *
File size: 95.8 KB
Line 
1// @(#)root/html:$Name: not supported by cvs2svn $:$Id: MHtml.cc,v 1.2 2001-04-18 15:26:04 tbretz Exp $
2// Author: Nenad Buncic 18/10/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TROOT.h"
13#include "TBaseClass.h"
14#include "TVirtualPad.h"
15#include "TClass.h"
16#include "TClassTable.h"
17#include "TDataMember.h"
18#include "TDataType.h"
19#include "TDatime.h"
20#include "TEnv.h"
21#include "TError.h"
22#include "MHtml.h"
23#include "TMethod.h"
24#include "TSystem.h"
25#include "TString.h"
26#include "TInterpreter.h"
27
28#include <stdlib.h>
29#include <string.h>
30#include <ctype.h>
31#include <fstream.h>
32
33MHtml *gHtml = 0;
34
35const Int_t kSpaceNum = 1;
36const char *formatStr = "%12s %5s %s";
37
38enum ESortType {kCaseInsensitive, kCaseSensitive};
39enum EFileType {kSource, kInclude, kTree};
40
41
42////////////////////////////////////////////////////////////////////////////////
43//
44// This is some kind of clone of the Root THtml class. I didn't change
45// anything, but enhanced the functionality a little bit.
46//
47// The HyperText Markup Language (HTML) is a simple data format used to
48// create hypertext documents that are portable from one platform to another.
49// HTML documents are SGML documents with generic semantics that are
50// appropriate for representing information from a wide range of domains.
51//
52// The MHtml class is designed to provide an easy way for converting ROOT
53// classes, and files as well, into HTML documents. Here is the few rules
54// and suggestions for a configuration, coding and usage.
55//
56//
57// Configuration:
58// -------------
59//
60// The output directory could be specified using the Root.Html.OutputDir
61// environment variable ( default value: "html/" ). Also it is necessary to
62// define Root.Html.SourceDir to point to directories containing .cxx and .h
63// files ( see: TEnv ).
64//
65// Examples:
66// Root.Html.OutputDir: html
67// Root.Html.SourceDir: src:include:.:/usr/user/source
68// Root.Html.Root: http://root.cern.ch/root/html
69//
70//
71// During the conversion, MHtml will look for the certain number of
72// user defined strings, i.e. author's name, copyright note, etc.
73// This could be defined with following environment variables:
74//
75// Root.Html.Author ( default: // Author:)
76// Root.Html.LastUpdate ( default: // @(#))
77// Root.Html.Copyright ( default: * Copyright)
78//
79//
80//
81// Coding rules:
82// ------------
83//
84// A class description block, which must be placed before the first
85// member function, has a following form:
86//
87// ////////////////////////////////////////////////////////////////
88// // //
89// // TMyClass //
90// // //
91// // This is the description block. //
92// // //
93// ////////////////////////////////////////////////////////////////
94//
95// The environment variable Root.Html.Description ( see: TEnv ) contents
96// the delimiter string ( default value: //_________________ ). It means
97// that you can also write your class description block like this:
98//
99// //_____________________________________________________________
100// // A description of the class starts with the line above, and
101// // will take place here !
102// //
103//
104// Note that EVERYTHING until the first non-commented line is considered
105// as a valid class description block.
106//
107// A member function description block starts immediately after '{'
108// and looks like this:
109//
110// void TWorld::HelloWorldFunc( string *text )
111// {
112// // This is an example of description for the
113// // TWorld member function
114//
115// helloWorld.Print( text );
116// }
117//
118// Like in a class description block, EVERYTHING until the first
119// non-commented line is considered as a valid member function
120// description block.
121//
122// ==> The "Begin_Html" and "End_Html" special keywords <=========
123// --------------------------------------------
124// You can insert pure html code in your comment lines. During the
125// generation of the documentation, this code will be inserted as is
126// in the html file.
127// Pure html code must be inserted between the keywords "Begin_Html"
128// and "End_Html" starting/finishing anywhere in the comment lines.
129// Examples of pure html code are given in many Root classes.
130// See for example the classes TDataMember and TMinuit.
131//
132// ==> The escape character
133// --------------------
134// Outside blocks starting with "Begin_Html" and finishing with "End_Html"
135// one can prevent the automatic translation of symbols like "<" and ">"
136// to "&lt;" and "&gt;" by using the escape character in front.
137// The default escape character is backslash and can be changed
138// via the member function SetEscape.
139//
140// Usage:
141// -----
142//
143// Root> gHtml.MakeAll // invoke a make for all classes
144// Root> gHtml.MakeClass( TMyClass ) // create a HTML files for that class only
145// Root> gHtml.MakeIndex() // creates an index files only
146// Root> gHtml.MakeTree( TMyClass ) // creates an inheritance tree for a class
147//
148// Root> gHtml.Convert( hist1.mac, "Histogram example" )
149//
150//
151// Environment variables:
152// ---------------------
153//
154// Root.Html.OutputDir ( default: htmldoc/)
155// Root.Html.SourceDir ( default: .:src/:include/)
156// Root.Html.Author ( default: // Author:)
157// Root.Html.LastUpdate ( default: // @(#))
158// Root.Html.Copyright ( default: * Copyright)
159// Root.Html.Description ( default: //____________________ )
160// Root.Html.HomePage ( URL to the user defined home page )
161// Root.Html.SearchEngine ( link to the search engine )
162//
163////////////////////////////////////////////////////////////////////////////////
164
165ClassImp( MHtml )
166
167//______________________________________________________________________________
168MHtml::MHtml()
169{
170 // Create a MHtml object. Use object directly or via the global
171 // pointer gHtml. In case output directory does not exist an error
172 // will be printed and gHtml stays 0 also zombie bit will be set.
173
174 fLen = 1024;
175 fLine = new char [fLen];
176 fCounter = new char [6];
177 fEscFlag = kFALSE;
178 SetEscape();
179
180 // get prefix for source directory
181 fSourcePrefix = gEnv->GetValue( "Root.Html.SourcePrefix", "");
182
183 // check for source directory
184 fSourceDir = gEnv->GetValue( "Root.Html.SourceDir", "./:src/:include/" );
185
186 // check for output directory
187 fOutputDir = gEnv->GetValue( "Root.Html.OutputDir", "htmldoc/" );
188
189 fXwho = "http://consult.cern.ch/xwho/people?";
190
191 Int_t st;
192 Long_t sId, sSize, sFlags, sModtime;
193 if ((st = gSystem->GetPathInfo(fOutputDir, &sId, &sSize, &sFlags, &sModtime)) ||
194 !(sFlags & 2)) {
195 if (st == 0) {
196 Error("MHtml", "output directory %s is an existing file", fOutputDir);
197 MakeZombie();
198 return;
199 }
200 // Try creating directory
201 if (gSystem->MakeDirectory(fOutputDir) == -1) {
202 Error("MHtml", "output directory %s does not exist", fOutputDir);
203 MakeZombie();
204 return;
205 }
206 }
207
208 // insert html object in the list of special ROOT objects
209 gHtml = this;
210 gROOT->GetListOfSpecials()->Add(gHtml);
211}
212
213
214//______________________________________________________________________________
215MHtml::~MHtml()
216{
217// Default destructor
218
219 if( fLine ) delete [] fLine;
220 if( fCounter ) delete [] fCounter;
221
222 fSourceDir = 0;
223 fLen = 0;
224}
225
226
227//______________________________________________________________________________
228int CaseSensitiveSort( const void *name1, const void *name2 )
229{
230// Friend function for sorting strings, case sensitive
231//
232//
233// Input: name1 - pointer to the first string
234// name2 - pointer to the second string
235//
236// NOTE: This function compares its arguments and returns an integer less
237// than, equal to, or greater than zero, depending on whether name1
238// is lexicographically less than, equal to, or greater than name2.
239//
240//
241
242 return( strcmp( *( (char **) name1 ), *( (char **) name2 )) );
243}
244
245
246//______________________________________________________________________________
247int CaseInsensitiveSort( const void *name1, const void *name2 )
248{
249// Friend function for sorting strings, case insensitive
250//
251//
252// Input: name1 - pointer to the first string
253// name2 - pointer to the second string
254//
255// NOTE: This function compares its arguments and returns an integer less
256// than, equal to, or greater than zero, depending on whether name1
257// is lexicographically less than, equal to, or greater than name2,
258// but characters are forced to lower-case prior to comparison.
259//
260//
261
262 return( strcasecmp( *( (char **) name1 ), *( (char **) name2 )) );
263}
264
265
266//______________________________________________________________________________
267void MHtml::Class2Html( TClass *classPtr, Bool_t force )
268{
269// It creates HTML file for a single class
270//
271//
272// Input: classPtr - pointer to the class
273
274
275 const char *tab = "<!--TAB-->";
276 const char *tab2 = "<!--TAB2--> ";
277 const char *tab4 = "<!--TAB4--> ";
278 const char *tab6 = "<!--TAB6--> ";
279
280 gROOT->GetListOfGlobals( kTRUE );
281
282 // create a filename
283 char *tmp1 = gSystem->ExpandPathName( fOutputDir );
284 char *tmp2 = gSystem->ConcatFileName( tmp1, classPtr->GetName() );
285
286 char *filename = StrDup( tmp2, 6 );
287 strcat( filename, ".html" );
288
289 if( tmp1 ) delete [] tmp1;
290 if( tmp2 ) delete [] tmp2;
291 tmp1 = tmp2 = 0;
292
293 if( IsModified( classPtr, kSource ) || force ) {
294
295 // open class file
296 ofstream classFile;
297 classFile.open( filename, ios::out );
298
299 Bool_t classFlag = kFALSE;
300
301
302 if( classFile.good() ) {
303
304 Printf( formatStr, "", fCounter, filename );
305
306 // write a HTML header for the classFile file
307 WriteHtmlHeader( classFile, classPtr->GetName() );
308
309 // make a link to the description
310 classFile << "<!--BEGIN-->" << endl;
311 classFile << "<center>" << endl;
312 classFile << "<h1>" << classPtr->GetName() << "</h1>" << endl;
313 classFile << "<hr width=300>" << endl;
314 classFile << "<!--SDL--><em><a href=#" << classPtr->GetName()
315 << ":description>class description</a>";
316
317 // make a link to the '.cxx' file
318 classFile << " - <a href=\"src/" << classPtr->GetName() << ".cxx.html\"";
319 classFile << ">source file</a>";
320
321 // make a link to the inheritance tree
322 classFile << " - <a href=\"" << classPtr->GetName() << "_Tree.ps\"";
323 classFile << ">inheritance tree</a>";
324
325
326 classFile << "</em>" << endl;
327 classFile << "<hr width=300>" << endl;
328 classFile << "</center>" << endl;
329
330
331 // make a link to the '.h' file
332 classFile << "<h2>" << "class <a name=\"" << classPtr->GetName() << "\" href=\"";
333 classFile << GetFileName( (const char * ) classPtr->GetDeclFileName() ) << "\"";
334 classFile << ">" << classPtr->GetName() << "</a> ";
335
336 // copy .h file to the Html output directory
337 char *declf = GetSourceFileName(classPtr->GetDeclFileName());
338 CopyHtmlFile(declf);
339 delete [] declf;
340
341 // make a loop on base classes
342 Bool_t first = kTRUE;
343 TBaseClass *inheritFrom;
344 TIter nextBase( classPtr->GetListOfBases() );
345
346 while (( inheritFrom = ( TBaseClass * ) nextBase() )) {
347 if( first ) {
348 classFile << ": ";
349 first = kFALSE;
350 }
351 else classFile << ", ";
352 classFile << "public ";
353
354 // get a class
355 TClass *classInh = GetClass( (const char * ) inheritFrom->GetName() );
356
357 char *htmlFile = GetHtmlFileName( classInh );
358
359 if( htmlFile ) {
360 classFile << "<a href=\"";
361
362 // make a link to the base class
363 classFile << htmlFile;
364 classFile << "\">" << inheritFrom->GetName() << "</a>";
365 delete [] htmlFile;
366 htmlFile = 0;
367 }
368 else classFile << inheritFrom->GetName();
369 }
370
371 classFile << "</h2>" << endl;
372 classFile << "<pre>" << endl;
373
374
375 // make a loop on member functions
376 TMethod *method;
377 TIter nextMethod( classPtr->GetListOfMethods() );
378
379 Int_t len, maxLen[3];
380 len = maxLen[0] = maxLen[1] = maxLen[2] = 0;
381
382 // loop to get a pointers to a method names
383 const Int_t nMethods = classPtr->GetNmethods();
384 const char **methodNames = new const char*[3*2*nMethods];
385
386 Int_t mtype, num[3];
387 mtype = num[0] = num[1] = num[2] = 0;
388
389 while (( method = ( TMethod * ) nextMethod() )) {
390
391 if(
392 !strcmp( method->GetName(), "Dictionary" ) ||
393 !strcmp( method->GetName(), "Class_Version" ) ||
394 !strcmp( method->GetName(), "Class_Name" ) ||
395 !strcmp( method->GetName(), "DeclFileName" ) ||
396 !strcmp( method->GetName(), "DeclFileLine" ) ||
397 !strcmp( method->GetName(), "ImplFileName" ) ||
398 !strcmp( method->GetName(), "ImplFileLine" )
399 ) continue;
400
401
402 if( kIsPrivate & method->Property() )
403 mtype = 0;
404 else if( kIsProtected & method->Property() )
405 mtype = 1;
406 else if( kIsPublic & method->Property() )
407 mtype = 2;
408
409 methodNames[mtype*2*nMethods+2*num[mtype]] = method->GetName();
410
411 if (method->GetReturnTypeName() ) len = strlen( method->GetReturnTypeName() );
412 else len = 0;
413
414 if( kIsVirtual & method->Property() ) len += 8;
415 if( kIsStatic & method->Property() ) len += 7;
416
417 maxLen[mtype] = maxLen[mtype] > len ? maxLen[mtype] : len;
418
419 const char* type = strrchr( method->GetReturnTypeName(), ' ' );
420 if( ! type ) type = method->GetReturnTypeName();
421 else type++;
422
423 if( classPtr && !strcmp( type, classPtr->GetName() ))
424 methodNames[mtype*2*nMethods+2*num[mtype]] = "A00000000";
425
426 // if this is the destructor
427 while( '~' == *methodNames[mtype*2*nMethods+2*num[mtype]] )
428 methodNames[mtype*2*nMethods+2*num[mtype]] = "A00000001";
429
430 methodNames[mtype*2*nMethods+2*num[mtype]+1] = (char *) method;
431
432 num[mtype]++;
433 }
434
435 Int_t i, j;
436
437 for( j = 0; j < 3; j ++ ) {
438 if( *( methodNames+j*2*nMethods ) ) {
439 qsort( methodNames+j*2*nMethods, num[j], 2*sizeof( methodNames ), CaseInsensitiveSort );
440
441 const char *ftitle = 0;
442 switch( j ) {
443 case 0: ftitle = "private:";
444 break;
445 case 1: ftitle = "protected:";
446 break;
447 case 2: ftitle = "public:";
448 break;
449 }
450 if( j ) classFile << endl;
451 classFile << tab4 << "<b>" << ftitle << "</b><br>" << endl;
452
453 for( i = 0; i < num[j]; i++ ) {
454 method = (TMethod *) methodNames[j*2*nMethods+2*i+1];
455
456 if( method ) {
457 Int_t w = 0;
458 if( method->GetReturnTypeName() ) len = strlen( method->GetReturnTypeName() );
459 else len = 0;
460
461 if( kIsVirtual & method->Property() ) len += 8;
462 if( kIsStatic & method->Property() ) len += 7;
463
464 classFile << tab6;
465 for( w = 0; w < ( maxLen[j]-len ); w++ )
466 classFile << " ";
467
468 if( kIsVirtual & method->Property() )
469 classFile << "virtual ";
470
471 if( kIsStatic & method->Property() )
472 classFile << "static ";
473
474 strcpy( fLine, method->GetReturnTypeName() );
475 ExpandKeywords( classFile, fLine, classPtr, classFlag );
476
477 classFile << " " << tab << "<!--BOLD-->";
478 classFile << "<a href=\"#" << classPtr->GetName();
479 classFile << ":";
480 ReplaceSpecialChars( classFile, method->GetName() );
481 classFile << "\">";
482 ReplaceSpecialChars( classFile, method->GetName() );
483 classFile << "</a><!--PLAIN-->";
484
485 strcpy( fLine, method->GetSignature() );
486 ExpandKeywords( classFile, fLine, classPtr, classFlag );
487 classFile << endl;
488 }
489 }
490 }
491 }
492
493 delete [] methodNames;
494
495 // make a loop on data members
496 first = kFALSE;
497 TDataMember *member;
498 TIter nextMember( classPtr->GetListOfDataMembers() );
499
500
501 Int_t len1, len2, maxLen1[3], maxLen2[3];
502 len1 = len2 = maxLen1[0] = maxLen1[1] = maxLen1[2] = 0;
503 maxLen2[0] = maxLen2[1] = maxLen2[2] = 0;
504 mtype = num[0] = num[1] = num[2] = 0;
505
506 Int_t ndata = classPtr->GetNdata();
507
508 // if data member exist
509 if( ndata ) {
510 TDataMember **memberArray = new TDataMember*[3*ndata];
511
512 if( memberArray ) {
513 while (( member = ( TDataMember * ) nextMember() )) {
514
515 if(
516 !strcmp( member->GetName(), "fgIsA" )
517 ) continue;
518
519 if( kIsPrivate & member->Property() )
520 mtype = 0;
521 else if( kIsProtected & member->Property() )
522 mtype = 1;
523 else if( kIsPublic & member->Property() )
524 mtype = 2;
525
526 memberArray[mtype*ndata+num[mtype]] = member;
527 num[mtype]++;
528
529 if( member->GetFullTypeName() )
530 len1 = strlen( (char * ) member->GetFullTypeName() );
531 else len1 = 0;
532 if( member->GetName() )
533 len2 = strlen( member->GetName() );
534 else len2 = 0;
535
536 if( kIsStatic & member->Property() ) len1 += 7;
537
538 // Take in account the room the array index will occupy
539
540 Int_t dim = member->GetArrayDim();
541 Int_t indx = 0;
542 while (indx < dim ){
543 indx++;
544 len2 += Int_t(TMath::Log10(member->GetMaxIndex(indx))) + 3;
545 }
546
547 maxLen1[mtype] = maxLen1[mtype] > len1 ? maxLen1[mtype] : len1;
548 maxLen2[mtype] = maxLen2[mtype] > len2 ? maxLen2[mtype] : len2;
549 }
550
551 classFile << endl;
552 classFile << "<h3>" << tab2 << "<a name=\"";
553 classFile << classPtr->GetName();
554 classFile << ":Data Members\">Data Members</a></h3>" << endl;
555
556 for( j = 0; j < 3; j++ ) {
557 if( memberArray[j*ndata] ) {
558 const char *ftitle = 0;
559 switch( j ) {
560 case 0: ftitle = "private:";
561 break;
562 case 1: ftitle = "protected:";
563 break;
564 case 2: ftitle = "public:";
565 break;
566 }
567 if( j ) classFile << endl;
568 classFile << tab4 << "<b>" << ftitle << "</b><br>" << endl;
569
570 for( i = 0; i < num[j]; i++ ) {
571 Int_t w = 0;
572 member = memberArray[j*ndata+i];
573
574 classFile << tab6;
575 if ( member->GetFullTypeName() ) len1 = strlen( member->GetFullTypeName() );
576 else len1 = 0;
577
578 if( kIsStatic & member->Property() ) len1 += 7;
579
580 for( w = 0; w < ( maxLen1[j]-len1 ); w++ )
581 classFile << " ";
582
583 if( kIsStatic & member->Property() )
584 classFile << "static ";
585
586 strcpy( fLine, member->GetFullTypeName() );
587 ExpandKeywords( classFile, fLine, classPtr, classFlag );
588
589 classFile << " " << tab << "<!--BOLD-->";
590 classFile << "<a name=\"" << classPtr->GetName() << ":";
591 classFile << member->GetName();
592 classFile << "\">" << member->GetName();
593
594 // Add the dimensions to "array" members
595
596 Int_t dim = member->GetArrayDim();
597 Int_t indx = 0;
598 Int_t indxlen = 0;
599 while (indx < dim ){
600 classFile << "[" << member->GetMaxIndex(indx)<<"]";
601 // Take in account the room this index will occupy
602 indxlen += Int_t(TMath::Log10(member->GetMaxIndex(indx))) + 3;
603 indx++;
604 }
605
606 classFile << "</a><!--PLAIN--> ";
607
608 len2 = 0;
609 if( member->GetName() )
610 len2 = strlen( member->GetName() ) + indxlen;
611
612 for( w = 0; w < ( maxLen2[j]-len2 ); w++ )
613 classFile << " ";
614 classFile << " " << tab;
615
616 classFile << "<i><a name=\"Title:";
617 classFile << member->GetName();
618
619 classFile << "\">";
620
621 strcpy( fLine, member->GetTitle() );
622 ReplaceSpecialChars( classFile, fLine );
623 classFile << "</a></i>" << endl;
624 }
625 }
626 }
627 classFile << "</pre>" << endl;
628 delete [] memberArray;
629 }
630 }
631
632 classFile << "<!--END-->" << endl;
633
634 // create a 'See also' part
635 DerivedClasses( classFile, classPtr );
636
637 // process a '.cxx' file
638 ClassDescription( classFile, classPtr, classFlag );
639
640
641 // close a file
642 classFile.close();
643
644 }
645 else Error( "Make", "Can't open file '%s' !", filename );
646 }
647 else Printf( formatStr, "-no change-", fCounter, filename );
648
649 if( filename ) delete [] filename;
650 filename = 0;
651}
652
653
654//______________________________________________________________________________
655void MHtml::ClassDescription( ofstream &out, TClass *classPtr, Bool_t &flag )
656{
657// This function builds the description of the class
658//
659//
660// Input: out - output file stream
661// classPtr - pointer to the class
662// flag - this is a 'begin_html/end_html' flag
663//
664
665 char *ptr, *key;
666 Bool_t tempFlag = kFALSE;
667 char *filename = 0;
668
669
670 // allocate memory
671 char *nextLine = new char [256];
672 char *pattern = new char [80];
673
674 char *lastUpdate = new char [256];
675 char *author = new char [80];
676 char *copyright = new char [80];
677
678
679 char *funcName = new char [64];
680
681 const char *lastUpdateStr;
682 const char *authorStr;
683 const char *copyrightStr;
684 const char *descriptionStr;
685
686
687 // just in case
688 *lastUpdate = *author = *copyright = 0;
689
690
691 // define pattern
692 strcpy( pattern, classPtr->GetName() );
693 strcat( pattern, "::" );
694 Int_t len = strlen( pattern );
695
696
697 // get environment variables
698 lastUpdateStr = gEnv->GetValue( "Root.Html.LastUpdate", "// @(#)" );
699 authorStr = gEnv->GetValue( "Root.Html.Author", "// Author:" );
700 copyrightStr = gEnv->GetValue( "Root.Html.Copyright", " * Copyright" );
701 descriptionStr = gEnv->GetValue( "Root.Html.Description", "//____________________" );
702
703
704 // find a .cxx file
705 char *tmp1 = GetSourceFileName(classPtr->GetImplFileName());
706 char *realFilename = StrDup( tmp1, 16 );
707 if( !realFilename ) Error( "Make", "Can't find file '%s' !", tmp1 );
708
709 if( tmp1 ) delete [] tmp1;
710 tmp1 = 0;
711
712 Bool_t classDescription = kTRUE;
713
714 Bool_t foundLastUpdate = kFALSE;
715 Bool_t foundAuthor = kFALSE;
716 Bool_t foundCopyright = kFALSE;
717
718 Bool_t firstCommentLine = kTRUE;
719 Bool_t extractComments = kFALSE;
720 Bool_t thisLineIsCommented = kFALSE;
721 Bool_t thisLineIsPpLine = kFALSE;
722 Bool_t postponeMemberDescr = kFALSE;
723 Bool_t skipMemberName = kFALSE;
724 Bool_t writeBracket = kFALSE;
725 streampos postponedpos = 0;
726
727 // Class Description Title
728 out << "<hr>" << endl;
729 out << "<!--DESCRIPTION-->";
730 out << "<h2><a name=\"" << classPtr->GetName();
731 out << ":description\">Class Description</a></h2>" << endl;
732
733
734 // open source file
735 ifstream sourceFile;
736 sourceFile.open( realFilename, ios::in );
737
738
739 if( sourceFile.good() ) {
740 // open a .cxx.html file
741 tmp1 = gSystem->ExpandPathName( fOutputDir );
742 char *tmp2 = gSystem->ConcatFileName( tmp1, "src" );
743 char *dirname = StrDup( tmp2 );
744
745 if( tmp1 ) delete [] tmp1;
746 if( tmp2 ) delete [] tmp2;
747 tmp1 = tmp2 = 0;
748
749 // create directory if necessary
750 if( gSystem->AccessPathName( dirname ))
751 gSystem->MakeDirectory( dirname );
752
753 tmp1 = gSystem->ConcatFileName( dirname, classPtr->GetName() );
754 filename = StrDup( tmp1, 16 );
755 strcat( filename, ".cxx.html" );
756
757 ofstream tempFile;
758 tempFile.open( filename, ios::out );
759
760 if( dirname ) delete [] dirname;
761
762 if( tmp1 ) delete [] tmp1;
763 tmp1 = 0;
764
765 if( tempFile.good() ) {
766
767
768 // create an array of method names
769 Int_t i = 0;
770 TMethod *method;
771 TIter nextMethod( classPtr->GetListOfMethods() );
772 Int_t numberOfMethods = classPtr->GetNmethods();
773 const char **methodNames = new const char* [2*numberOfMethods];
774 while (( method = ( TMethod * ) nextMethod() )) {
775 methodNames[2*i] = method->GetName();
776 methodNames[2*i+1] = ( const char * ) method;
777 i++;
778 }
779
780
781 // write a HTML header
782 char *sourceTitle = StrDup( classPtr->GetName(), 16 );
783 strcat( sourceTitle, " - source file" );
784 WriteHtmlHeader( tempFile, sourceTitle );
785 if( sourceTitle ) delete [] sourceTitle;
786
787
788 tempFile << "<pre>" << endl;
789
790 while( !sourceFile.eof() ) {
791
792 sourceFile.getline( fLine, fLen-1 );
793 if( sourceFile.eof() ) break;
794
795
796 // set start & end of the line
797 if (!fLine) {
798 fLine = (char *) " ";
799 Warning("ClassDescription", "found an empty line");
800 }
801 char *startOfLine = fLine;
802 char *endOfLine = fLine + strlen( fLine ) - 1;
803
804
805 // remove leading spaces
806 while( isspace( *startOfLine )) startOfLine++;
807
808 // remove trailing spaces
809 while( isspace( *endOfLine )) endOfLine--;
810 if( *startOfLine == '#' && !tempFlag )
811 thisLineIsPpLine = kTRUE;
812
813 // if this line is a comment line
814 else if( !strncmp( startOfLine, "//", 2 )) {
815
816 thisLineIsCommented = kTRUE;
817 thisLineIsPpLine = kFALSE;
818
819 // remove a repeating characters from the end of the line
820 while( (*endOfLine == *startOfLine ) &&
821 ( endOfLine >= startOfLine )) endOfLine--;
822 endOfLine++;
823 char tempChar = *endOfLine;
824 *endOfLine = 0;
825
826
827 if( extractComments) {
828 if( firstCommentLine ) {
829 out << "<pre>";
830 firstCommentLine = kFALSE;
831 }
832 if( endOfLine >= startOfLine+2 )
833 ExpandKeywords( out, startOfLine+2, classPtr, flag );
834 out << endl;
835 }
836
837 *endOfLine = tempChar;
838
839 // if line is composed of the same characters
840 if( (endOfLine == startOfLine ) && *( startOfLine+2 ) && classDescription ) {
841 extractComments = kTRUE;
842 classDescription = kFALSE;
843 }
844 }
845 else {
846 thisLineIsCommented = kFALSE;
847 if( flag ) {
848 out << fLine << endl;
849 }
850 else {
851 extractComments = kFALSE;
852 if( !firstCommentLine ) {
853 out << "</pre>";
854 firstCommentLine = kTRUE;
855 }
856 }
857 }
858
859
860 // if NOT member function
861 key = strstr( fLine, pattern );
862 if( !key ) {
863 // check for a lastUpdate string
864 if( !foundLastUpdate && lastUpdateStr) {
865 if( !strncmp( fLine, lastUpdateStr, strlen( lastUpdateStr )) ) {
866 strcpy( lastUpdate, fLine+strlen( lastUpdateStr ));
867 foundLastUpdate = kTRUE;
868 }
869 }
870
871 // check for an author string
872 if( !foundAuthor && authorStr) {
873 if( !strncmp( fLine, authorStr, strlen( authorStr )) ) {
874 strcpy( author, fLine+strlen( authorStr ));
875 foundAuthor = kTRUE;
876 }
877 }
878
879 // check for a copyright string
880 if( !foundCopyright && copyrightStr) {
881 if( !strncmp( fLine, copyrightStr, strlen( copyrightStr )) ) {
882 strcpy( copyright, fLine+strlen( copyrightStr ));
883 foundCopyright = kTRUE;
884 }
885 }
886
887 // check for a description comments
888 if( descriptionStr && !strncmp( fLine, descriptionStr, strlen( descriptionStr )) ) {
889 if( classDescription ) {
890 // write description out
891 classDescription = kFALSE;
892 extractComments = kTRUE;
893 }
894 else
895 {
896 postponeMemberDescr = kTRUE;
897 postponedpos = sourceFile.tellg();
898 }
899 }
900 }
901 else {
902 Bool_t found = kFALSE;
903 // find method name
904 char *funcName = key + len;
905
906 while( *funcName && isspace( *funcName ) )
907 funcName++;
908 char *nameEndPtr = funcName;
909
910 // In case of destructor
911 if( *nameEndPtr == '~' ) nameEndPtr++;
912
913 while( *nameEndPtr && IsName( *nameEndPtr ) )
914 nameEndPtr++;
915
916 char c1 = *nameEndPtr;
917 char pe = 0;
918
919 char *params, *paramsEnd;
920 params = nameEndPtr;
921 paramsEnd = NULL;
922
923 while( *params && isspace( *params ) ) params++;
924 if( *params != '(') params = NULL;
925 else params++;
926 paramsEnd = params;
927
928 // if signature exist, try to find the ending character
929 if( paramsEnd ) {
930 Int_t count = 1;
931 while( *paramsEnd ) {
932 if( *paramsEnd == '(') count++;
933 if( *paramsEnd == ')')
934 if( !--count ) break;
935 paramsEnd++;
936 }
937 pe = *paramsEnd;
938 *paramsEnd = 0;
939 }
940 *nameEndPtr = 0;
941
942 // get method
943 TMethod *method;
944 method = classPtr->GetMethodAny( funcName );
945
946 // restore characters
947 if( paramsEnd ) *paramsEnd = pe;
948 if( nameEndPtr ) *nameEndPtr = c1;
949
950 if( method ) {
951
952 if (skipMemberName)
953 {
954 skipMemberName = kFALSE;
955 writeBracket = kTRUE;
956 sourceFile.seekg(postponedpos);
957 }
958 else
959 {
960 char *typeEnd = NULL;
961 char c2 = 0;
962
963 found = kFALSE;
964
965 // try to get type
966 typeEnd = key-1;
967 while( ( typeEnd > fLine ) && (isspace( *typeEnd ) || *typeEnd == '*') )
968 typeEnd--;
969 typeEnd++;
970 c2 = *typeEnd;
971 *typeEnd = 0;
972 char *type = typeEnd - 1;
973 while( IsName( *type ) && ( type > fLine ))
974 type--;
975 if( !IsWord( *type )) type++;
976
977 while( (type > fLine ) && isspace( *( type-1 )) )
978 type--;
979 if( type > fLine ) {
980 if( !strncmp( type-5, "const", 5 ))
981 found = kTRUE;
982 else found = kFALSE;
983 }
984 else if( type == fLine )
985 found = kTRUE;
986
987 if( !strcmp( type, "void" ) && ( *funcName == '~' ) )
988 found = kTRUE;
989
990 *typeEnd = c2;
991
992 if( found ) {
993 ptr = strchr( nameEndPtr, '{');
994 char *semicolon = strchr( nameEndPtr, ';');
995 if( semicolon )
996 if( !ptr || ( semicolon < ptr )) found = kFALSE;
997
998 if( !ptr && found ) {
999 found = kFALSE;
1000 while( sourceFile.getline( nextLine, 255 ) && fLine && nextLine &&
1001 ( strlen( fLine ) < ( fLen-strlen( nextLine )) )) {
1002 strcat( fLine, "\n" );
1003 strcat( fLine, nextLine );
1004 if (( ptr = strchr( fLine, '{') )) {
1005 found = kTRUE;
1006 *ptr = 0;
1007 break;
1008 }
1009 }
1010 }
1011 else if( ptr ) *ptr = 0;
1012
1013 if( found ) {
1014 char *colonPtr = strrchr( fLine, ':');
1015 if( colonPtr > funcName ) *colonPtr = 0;
1016 if( found ) {
1017 out << "<hr>" << endl;
1018 out << "<!--FUNCTION-->";
1019 if( typeEnd ) {
1020 c2 = *typeEnd;
1021 *typeEnd = 0;
1022 ExpandKeywords( out, fLine, classPtr, flag );
1023 *typeEnd = c2;
1024 while( typeEnd < key ) {
1025 if( *typeEnd == '*')
1026 out << *typeEnd;
1027 typeEnd++;
1028 }
1029 }
1030 *nameEndPtr = 0;
1031
1032 out << " <a name=\"" << classPtr->GetName() << ":";
1033 out << funcName << "\" href=\"src/";
1034 out << classPtr->GetName() << ".cxx.html#" << classPtr->GetName() << ":";
1035 ReplaceSpecialChars( out, funcName );
1036 out << "\">";
1037 ReplaceSpecialChars( out, funcName );
1038 out << "</a>";
1039
1040 tempFile << "<a name=\"" << classPtr->GetName() << ":";
1041 ReplaceSpecialChars( tempFile, funcName );
1042 tempFile << "\"> </a>";
1043
1044 // remove this method name from the list of methods
1045 i = 0;
1046 while( i < numberOfMethods ) {
1047 const char *mptr = methodNames[2*i];
1048 if( mptr ) {
1049 while( *mptr == '*') mptr++;
1050 if( !strcmp( mptr, funcName )) {
1051 methodNames[2*i] = NULL;
1052 break;
1053 }
1054 }
1055 i++;
1056 }
1057
1058 *nameEndPtr = c1;
1059 if( colonPtr ) *colonPtr = ':';
1060 ExpandKeywords( out, nameEndPtr, classPtr, flag );
1061 out << "<br>" << endl;
1062
1063 if (postponeMemberDescr)
1064 {
1065 streampos pos = sourceFile.tellg();
1066 sourceFile.seekg(postponedpos);
1067 postponedpos = pos;
1068 skipMemberName = kTRUE;
1069 postponeMemberDescr = kFALSE;
1070 }
1071 extractComments = kTRUE;
1072 }
1073 }
1074 if( ptr ) *ptr = '{';
1075 }
1076 }
1077 }
1078 }
1079
1080 // write to '.cxx.html' file
1081 if (!skipMemberName)
1082 {
1083 if( thisLineIsPpLine )
1084 ExpandPpLine( tempFile, fLine );
1085 else {
1086 if( thisLineIsCommented) tempFile << "<b>";
1087 ExpandKeywords( tempFile, fLine, classPtr, tempFlag, "../" );
1088 if( thisLineIsCommented ) tempFile << "</b>";
1089 }
1090 tempFile << endl;
1091
1092 if (writeBracket)
1093 {
1094 writeBracket = kFALSE;
1095 tempFile << "{" << endl;
1096 }
1097 }
1098
1099 }
1100 tempFile << "</pre>" << endl;
1101
1102 // do some checking
1103 Bool_t inlineFunc = kFALSE;
1104 i = 0;
1105 while( i++ < numberOfMethods ) {
1106 if( methodNames[2*i] ) {
1107 inlineFunc = kTRUE;
1108 break;
1109 }
1110 }
1111
1112
1113 if( inlineFunc ) {
1114 out << "<br><br><br>" << endl;
1115 out << "<h3>Inline Functions</h3>" << endl;
1116 out << "<hr>" << endl;
1117 out << "<pre>" << endl;
1118
1119 Int_t maxlen = 0, len = 0;
1120 for( i = 0; i < numberOfMethods; i++ ) {
1121 if( methodNames[2*i] ) {
1122 method = ( TMethod * ) methodNames[2*i+1];
1123 if ( method->GetReturnTypeName() ) len = strlen( method->GetReturnTypeName() );
1124 else len = 0;
1125 maxlen = len > maxlen ? len : maxlen;
1126 }
1127 }
1128
1129
1130 // write out an inline functions
1131 for( i = 0; i < numberOfMethods; i++ ) {
1132 if( methodNames[2*i] ) {
1133
1134 method = ( TMethod * ) methodNames[2*i+1];
1135
1136 if( method ) {
1137
1138 if(
1139 !strcmp( method->GetName(), "Dictionary" ) ||
1140 !strcmp( method->GetName(), "Class_Version" ) ||
1141 !strcmp( method->GetName(), "Class_Name" ) ||
1142 !strcmp( method->GetName(), "DeclFileName" ) ||
1143 !strcmp( method->GetName(), "DeclFileLine" ) ||
1144 !strcmp( method->GetName(), "ImplFileName" ) ||
1145 !strcmp( method->GetName(), "ImplFileLine" )
1146 ) continue;
1147
1148 out << "<!--INLINE FUNCTION-->";
1149 if(method->GetReturnTypeName() ) len = strlen( method->GetReturnTypeName() );
1150 else len = 0;
1151
1152 out << "<!--TAB6--> ";
1153 while( len++ < maxlen+2 ) out << " ";
1154
1155 char *tmpstr = StrDup( method->GetReturnTypeName() );
1156 if( tmpstr ) {
1157 ExpandKeywords( out, tmpstr, classPtr, flag );
1158 delete [] tmpstr;
1159 }
1160
1161 out << " <a name=\"" << classPtr->GetName();
1162 out << ":" << method->GetName() << "\" href=\"";
1163 out << GetFileName( classPtr->GetDeclFileName() ) << "\">";
1164 out << method->GetName() << "</a>";
1165
1166 strcpy( fLine, method->GetSignature() );
1167 ExpandKeywords( out, fLine, classPtr, flag );
1168 out << endl;
1169 }
1170 }
1171 }
1172 out << "</pre>" << endl;
1173 }
1174
1175
1176 // write tempFile footer
1177 WriteHtmlFooter( tempFile, "../" );
1178
1179 // close a temp file
1180 tempFile.close();
1181
1182 delete [] methodNames;
1183 }
1184 else Error( "MakeClass", "Can't open file '%s' !", filename );
1185
1186 // close a source file
1187 sourceFile.close();
1188
1189 }
1190 else Error( "Make", "Can't open file '%s' !", realFilename );
1191
1192
1193 // write classFile footer
1194 WriteHtmlFooter( out, "", lastUpdate, author, copyright );
1195
1196 // free memory
1197 if( nextLine ) delete [] nextLine;
1198 if( pattern ) delete [] pattern;
1199
1200 if( lastUpdate ) delete [] lastUpdate;
1201 if( author ) delete [] author;
1202 if( copyright ) delete [] copyright;
1203 if( funcName ) delete [] funcName;
1204
1205 if( realFilename ) delete [] realFilename;
1206 if( filename ) delete [] filename;
1207}
1208
1209
1210//______________________________________________________________________________
1211void MHtml::ClassTree( TVirtualPad *psCanvas, TClass *classPtr, Bool_t force )
1212{
1213// It makes a class tree
1214//
1215//
1216// Input: psCanvas - pointer to the current canvas
1217// classPtr - pointer to the class
1218//
1219
1220 if( psCanvas && classPtr ) {
1221 char *tmp1 = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), classPtr->GetName() );
1222 char *filename = StrDup( tmp1 , 16 );
1223
1224 strcat( filename, "_Tree.ps" );
1225
1226 if( tmp1 ) delete [] tmp1;
1227 tmp1 = 0;
1228
1229 if( IsModified( classPtr, kTree ) || force ) {
1230 Printf( formatStr, "", "", filename );
1231 classPtr->Draw( "same" );
1232 psCanvas->SaveAs(filename);
1233 }
1234 else Printf( formatStr, "-no change-", "", filename );
1235
1236 if( filename ) delete [] filename;
1237 }
1238}
1239
1240
1241//______________________________________________________________________________
1242void MHtml::Convert( const char *filename, const char *title, const char *dirname )
1243{
1244// It converts a single text file to HTML
1245//
1246//
1247// Input: filename - name of the file to convert
1248// title - title which will be placed at the top of the HTML file
1249// dirname - optional parameter, if it's not specified, output will
1250// be placed in html/examples directory.
1251//
1252// NOTE: Output file name is the same as filename, but with extension .html
1253//
1254
1255 const char *dir;
1256 char *ptr;
1257
1258 Bool_t isCommentedLine = kFALSE;
1259 Bool_t tempFlag = kFALSE;
1260
1261 // if it's not defined, make the "examples" as a default directory
1262 if( !*dirname ) {
1263 dir = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), "examples" );
1264
1265 // create directory if necessary
1266 if( gSystem->AccessPathName( dir ))
1267 gSystem->MakeDirectory( dir );
1268 }
1269 else dir = dirname;
1270
1271
1272 // find a file
1273 char *realFilename = gSystem->Which( fSourceDir, filename, kReadPermission );
1274
1275 if( realFilename ) {
1276
1277 // open source file
1278 ifstream sourceFile;
1279 sourceFile.open( realFilename, ios::in );
1280
1281 delete [] realFilename;
1282 realFilename = 0;
1283
1284 if( sourceFile.good() ) {
1285
1286 // open temp file with extension '.html'
1287 if( !gSystem->AccessPathName( dir )) {
1288 char *tmp1 = gSystem->ConcatFileName( dir, GetFileName( filename ));
1289 char *htmlFilename = StrDup( tmp1, 16 );
1290 strcat( htmlFilename, ".html" );
1291
1292 if( tmp1 ) delete [] tmp1;
1293 tmp1 = 0;
1294
1295 ofstream tempFile;
1296 tempFile.open( htmlFilename, ios::out );
1297
1298 if( tempFile.good() ) {
1299
1300 Printf( "Convert: %s", htmlFilename );
1301
1302 // write a HTML header
1303 WriteHtmlHeader( tempFile, title );
1304
1305 tempFile << "<h1>" << title << "</h1>" << endl;
1306 tempFile << "<pre>" << endl;
1307
1308 while( !sourceFile.eof() ) {
1309 sourceFile.getline( fLine, fLen-1 );
1310 if( sourceFile.eof() ) break;
1311
1312
1313 // remove leading spaces
1314 ptr = fLine;
1315 while( isspace( *ptr )) ptr++;
1316
1317
1318 // check for a commented line
1319 if( !strncmp( ptr, "//", 2 )) isCommentedLine = kTRUE;
1320 else isCommentedLine = kFALSE;
1321
1322
1323 // write to a '.html' file
1324 if( isCommentedLine ) tempFile << "<b>";
1325 gROOT->GetListOfGlobals(kTRUE); // force update of this list
1326 ExpandKeywords( tempFile, fLine, NULL, tempFlag, "../" );
1327 if( isCommentedLine ) tempFile << "</b>";
1328 tempFile << endl;
1329 }
1330 tempFile << "</pre>" << endl;
1331
1332
1333 // write a HTML footer
1334 WriteHtmlFooter( tempFile, "../" );
1335
1336
1337 // close a temp file
1338 tempFile.close();
1339
1340 }
1341 else Error( "Convert", "Can't open file '%s' !", htmlFilename );
1342
1343 // close a source file
1344 sourceFile.close();
1345 if( htmlFilename ) delete [] htmlFilename;
1346 htmlFilename = 0;
1347 }
1348 else Error( "Convert", "Directory '%s' doesn't exist, or it's write protected !", dir );
1349 }
1350 else Error( "Convert", "Can't open file '%s' !", realFilename );
1351 }
1352 else Error( "Convert", "Can't find file '%s' !", filename );
1353}
1354
1355
1356//______________________________________________________________________________
1357Bool_t MHtml::CopyHtmlFile( const char *sourceName, const char *destName )
1358{
1359// Copy file to HTML directory
1360//
1361//
1362// Input: sourceName - source file name
1363// destName - optional destination name, if not
1364// specified it would be the same
1365// as the source file name
1366//
1367// Output: TRUE if file is successfully copied, or
1368// FALSE if it's not
1369//
1370//
1371// NOTE: The destination directory is always fOutputDir
1372//
1373
1374 Bool_t ret = kFALSE;
1375 Int_t check = 0;
1376
1377 // source file name
1378 char *tmp1 = gSystem->Which( fSourceDir, sourceName, kReadPermission );
1379 char *sourceFile = StrDup( tmp1, 16 );
1380
1381 if( tmp1 ) delete [] tmp1;
1382 tmp1 = 0;
1383
1384 if( sourceFile ) {
1385
1386 // destination file name
1387 char *tmpstr = 0;
1388 if( !*destName ) tmpstr = StrDup( GetFileName( sourceFile ), 16 );
1389 else tmpstr = StrDup( GetFileName( destName ), 16 );
1390 destName = tmpstr;
1391
1392 tmp1 = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), destName );
1393 char *filename = StrDup( tmp1, 16 );
1394
1395 if( tmp1 ) delete [] tmp1;
1396 tmp1 = 0;
1397
1398 // Get info about a file
1399 Long_t sId, sSize, sFlags, sModtime;
1400 Long_t dId, dSize, dFlags, dModtime;
1401 if( !( check = gSystem->GetPathInfo( sourceFile, &sId, &sSize, &sFlags, &sModtime )) )
1402 check = gSystem->GetPathInfo( filename, &dId, &dSize, &dFlags, &dModtime );
1403
1404
1405 if( (sModtime != dModtime ) || check ) {
1406
1407 char *cmd = new char[256];
1408
1409#ifdef R__UNIX
1410 strcpy( cmd, "/bin/cp " );
1411 strcat( cmd, sourceFile );
1412 strcat( cmd, " " );
1413 strcat( cmd, filename );
1414#endif
1415
1416#ifdef WIN32
1417 strcpy( cmd, "copy \"" );
1418 strcat( cmd, sourceFile );
1419 strcat( cmd, "\" \"" );
1420 strcat( cmd, filename );
1421 strcat( cmd, "\"");
1422 char *bptr = 0;
1423 while( bptr = strchr( cmd, '/') )
1424 *bptr = '\\';
1425#endif
1426
1427 ret = !gSystem->Exec( cmd );
1428
1429 delete [] cmd;
1430 delete [] filename;
1431 delete [] tmpstr;
1432 delete [] sourceFile;
1433 }
1434 }
1435 else Error( "Copy", "Can't copy file '%s' to '%s' directory !", sourceName, fOutputDir );
1436
1437 return( ret );
1438}
1439
1440
1441
1442//______________________________________________________________________________
1443void MHtml::CreateIndex( const char **classNames, Int_t numberOfClasses )
1444{
1445// Create an index
1446//
1447//
1448// Input: classNames - pointer to an array of class names
1449// numberOfClasses - number of elements
1450//
1451
1452 Int_t i, len, maxLen = 0;
1453
1454 char *tmp1 = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), "ClassIndex.html" );
1455 char *filename = StrDup( tmp1 );
1456
1457 if( tmp1 ) delete [] tmp1;
1458 tmp1 = 0;
1459
1460 // open indexFile file
1461 ofstream indexFile;
1462 indexFile.open( filename, ios::out );
1463
1464 for( i = 0; i < numberOfClasses; i++ ) {
1465 len = strlen( classNames[i] );
1466 maxLen = maxLen > len ? maxLen : len;
1467 }
1468
1469 if( indexFile.good() ) {
1470
1471 Printf( formatStr, "", fCounter, filename );
1472
1473 // write indexFile header
1474 WriteHtmlHeader( indexFile, "Class Index" );
1475 indexFile << "<h1>Index</h1>" << endl;
1476
1477 // check for a search engine
1478 const char *searchEngine = gEnv->GetValue( "Root.Html.SearchEngine", "" );
1479
1480 // if exists ...
1481 if( *searchEngine ) {
1482
1483 // create link to search engine page
1484 indexFile << "<h2><a href=\"" << searchEngine
1485 << "\">Search the Class Reference Guide</a></h2>" << endl;
1486
1487 }
1488
1489 indexFile << "<hr>" << endl;
1490 indexFile << "<pre>" << endl;
1491 indexFile << "<ul>" << endl;
1492
1493 // loop on all classes
1494 for( i = 0; i < numberOfClasses; i++ ) {
1495
1496 // get class
1497 TClass *classPtr = GetClass( (const char * ) classNames[i] );
1498
1499 indexFile << "<li>";
1500 char *htmlFile = GetHtmlFileName( classPtr );
1501 if( htmlFile ) {
1502 indexFile << "<a name=\"";
1503 indexFile << classNames[i];
1504 indexFile << "\" href=\"";
1505 indexFile << htmlFile;
1506 indexFile << "\">";
1507 indexFile << classNames[i];
1508 indexFile << "</a> ";
1509 delete [] htmlFile;
1510 htmlFile = 0;
1511 }
1512 else indexFile << classNames[i];
1513
1514
1515 // write title
1516 len = strlen( classNames[i] );
1517 for( Int_t w = 0; w < ( maxLen-len+2 ); w++ )
1518 indexFile << ".";
1519 indexFile << " ";
1520
1521 indexFile << "<a name=\"Title:";
1522 indexFile << classPtr->GetName();
1523 indexFile << "\">";
1524 ReplaceSpecialChars( indexFile, classPtr->GetTitle() );
1525 indexFile << "</a>" << endl;
1526 }
1527
1528 indexFile << "</ul>" << endl;
1529 indexFile << "</pre>" << endl;
1530
1531
1532 // write indexFile footer
1533 TDatime date;
1534 WriteHtmlFooter( indexFile, "", date.AsString() );
1535
1536
1537 // close file
1538 indexFile.close();
1539
1540 }
1541 else Error( "MakeIndex", "Can't open file '%s' !", filename );
1542
1543 if( filename ) delete [] filename;
1544}
1545
1546
1547//______________________________________________________________________________
1548void MHtml::CreateIndexByTopic( char **fileNames, Int_t numberOfNames, Int_t maxLen )
1549{
1550// It creates several index files
1551//
1552//
1553// Input: fileNames - pointer to an array of file names
1554// numberOfNames - number of elements in the fileNames array
1555// maxLen - maximum length of a single name
1556//
1557
1558 ofstream outputFile;
1559 char *filename = NULL;
1560 Int_t i;
1561
1562 for( i = 0; i < numberOfNames; i++ ) {
1563 if( !filename ) {
1564
1565 // create a filename
1566 char *tmp1 = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), fileNames[i] );
1567 filename = StrDup( tmp1, 16);
1568
1569 if( tmp1 ) delete [] tmp1;
1570 tmp1 = 0;
1571
1572 char *underlinePtr = strrchr( filename, '_');
1573 *underlinePtr = 0;
1574
1575 strcat( filename, "_Index.html" );
1576
1577 // open a file
1578 outputFile.open( filename, ios::out );
1579
1580 // check if it's OK
1581 if( outputFile.good() ) {
1582
1583 Printf( formatStr, "", fCounter, filename );
1584
1585 // write outputFile header
1586 WriteHtmlHeader( outputFile, "Index" );
1587 outputFile << "<h2>" << "Index" << "</h2><hr>" << endl;
1588 outputFile << "<pre>" << endl;
1589 outputFile << "<ul>" << endl;
1590 }
1591 else Error( "MakeIndex", "Can't open file '%s' !", filename );
1592 delete [] filename;
1593 }
1594
1595 // get a class
1596 TClass *classPtr = GetClass( (const char * ) strrchr( fileNames[i], '_')+1 );
1597 if( classPtr ) {
1598
1599 // write a classname to an index file
1600 outputFile << "<li>";
1601
1602 char *htmlFile = GetHtmlFileName( classPtr );
1603
1604 if( htmlFile ) {
1605 outputFile << "<a name=\"";
1606 outputFile << classPtr->GetName();
1607 outputFile << "\" href=\"";
1608 outputFile << htmlFile;
1609 outputFile << "\">";
1610 outputFile << classPtr->GetName();
1611 outputFile << "</a> ";
1612 delete [] htmlFile;
1613 htmlFile = 0;
1614 }
1615 else outputFile << classPtr->GetName();
1616
1617
1618 // write title
1619 Int_t len = strlen( classPtr->GetName() );
1620 for( Int_t w = 0; w < maxLen-len; w++ )
1621 outputFile << ".";
1622 outputFile << " ";
1623
1624 outputFile << "<a name=\"Title:";
1625 outputFile << classPtr->GetName();
1626 outputFile << "\">";
1627 ReplaceSpecialChars( outputFile, classPtr->GetTitle() );
1628 outputFile << "</a>" << endl;
1629 }
1630 else Error( "MakeIndex", "Unknown class '%s' !", strchr( fileNames[i], '_')+1 );
1631
1632
1633 // first base name
1634 char *first = strrchr( fileNames[i], '_');
1635 if( first ) *first = 0;
1636
1637 // second base name
1638 char *second = NULL;
1639 if( i < ( numberOfNames - 1 )) {
1640 second = strrchr( fileNames[i+1], '_');
1641 if( second ) *second = 0;
1642 }
1643
1644 // check and close the file if necessary
1645 if( !first || !second || strcmp( fileNames[i], fileNames[i+1] )) {
1646
1647 if( outputFile.good() ) {
1648
1649 outputFile << "</ul>" << endl;
1650 outputFile << "</pre>" << endl;
1651
1652 // write outputFile footer
1653 TDatime date;
1654 WriteHtmlFooter( outputFile, "", date.AsString() );
1655
1656 // close file
1657 outputFile.close();
1658
1659 filename = NULL;
1660 }
1661 else Error( "MakeIndex", "Corrupted file '%s' !", filename );
1662 }
1663
1664 if( first ) *first = '_';
1665 if( second ) *second = '_';
1666 }
1667
1668 // free memory
1669 for( i = 0; i < numberOfNames; i++ )
1670 if( *fileNames[i] ) delete [] fileNames[i];
1671}
1672
1673
1674//______________________________________________________________________________
1675void MHtml::CreateListOfTypes()
1676{
1677// Create list of all data types
1678
1679 Int_t maxLen = 0;
1680 Int_t len;
1681
1682 // open file
1683 ofstream typesList;
1684
1685 char *outFile = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), "ListOfTypes.html" );
1686 typesList.open( outFile, ios::out );
1687
1688
1689 if( typesList.good() ) {
1690 Printf( formatStr, "", "", outFile );
1691
1692 // write typesList header
1693 WriteHtmlHeader( typesList, "List of data types" );
1694 typesList << "<h2> List of data types </h2><hr>" << endl;
1695
1696 typesList << "<dl><dd>" << endl;
1697 typesList << "<pre>" << endl;
1698
1699 // make loop on data types
1700 TDataType *type;
1701 TIter nextType( gROOT->GetListOfTypes() );
1702
1703 while (( type = ( TDataType * ) nextType() )) {
1704 if( *type->GetTitle() && !strchr( type->GetName(), '(' ) ) {
1705 if( type->GetName() ) len = strlen( type->GetName() );
1706 else len = 0;
1707 maxLen = maxLen > len ? maxLen : len;
1708 }
1709 }
1710 nextType.Reset();
1711
1712 maxLen += kSpaceNum;
1713
1714 while (( type = ( TDataType * ) nextType() )) {
1715 if( *type->GetTitle() && !strchr( type->GetName(), '(' ) ) {
1716 typesList << "<b><a name=\"";
1717 typesList << type->GetName();
1718 typesList << "\">" << type->GetName();
1719 typesList << "</a></b>";
1720
1721 if( type->GetName() ) len = strlen( type->GetName() );
1722 else len = 0;
1723 typesList << " ";
1724 for( Int_t j = 0; j < ( maxLen-len ); j++ )
1725 typesList << ".";
1726 typesList << " ";
1727
1728 typesList << "<a name=\"Title:";
1729 typesList << type->GetTitle();
1730 typesList << "\">";
1731 char *tempstr = StrDup( type->GetTitle() );
1732 ReplaceSpecialChars( typesList, tempstr );
1733 typesList << "</a>" << endl;
1734
1735 if( tempstr ) delete [] tempstr;
1736 }
1737 }
1738
1739 typesList << "</pre>" << endl;
1740 typesList << "</dl>" << endl;
1741
1742 // write typesList footer
1743 TDatime date;
1744 WriteHtmlFooter( typesList, "", date.AsString() );
1745
1746 // close file
1747 typesList.close();
1748
1749 }
1750 else Error( "Make", "Can't open file '%s' !", outFile );
1751
1752 if (outFile) delete [] outFile;
1753}
1754
1755
1756//______________________________________________________________________________
1757void MHtml::DerivedClasses( ofstream &out, TClass *classPtr )
1758{
1759// It creates a list of derived classes
1760//
1761//
1762// Input: out - output file stream
1763// classPtr - pointer to the class
1764//
1765
1766 Bool_t first = kTRUE;
1767 Bool_t found = kFALSE;
1768
1769
1770 // get total number of classes
1771 Int_t numberOfClasses = gClassTable->Classes();
1772
1773 // start from begining
1774 gClassTable->Init();
1775
1776 // get class names
1777 TClass *derivedClassPtr;
1778 const char *derivedClassName;
1779 for( Int_t i = 0; i < numberOfClasses; i++ ) {
1780
1781 // get class name
1782 derivedClassName = gClassTable->Next();
1783
1784 // get class pointer
1785 derivedClassPtr = GetClass( derivedClassName );
1786
1787 if ( !derivedClassPtr ) {
1788 Warning("DerivedClasses","Can not find a definition for class <%s>",derivedClassName);
1789 continue;
1790 }
1791 // make a loop on base classes
1792 TBaseClass *inheritFrom;
1793 TIter nextBase( derivedClassPtr->GetListOfBases() );
1794
1795 while (( inheritFrom = ( TBaseClass * ) nextBase() )) {
1796 if( !strcmp( inheritFrom->GetName(), classPtr->GetName() )) {
1797 if( first ) {
1798 out << "<br><hr>" << endl;
1799 out << "<!--SEE ALSO-->";
1800 out << "<h2>See also</h2><dl><dd>" << endl;
1801 }
1802 if( !first ) out << ", ";
1803
1804 char *htmlFile = GetHtmlFileName( derivedClassPtr );
1805
1806 if( htmlFile ) {
1807 out << "<a href=\"";
1808 out << htmlFile;
1809 out << "\">";
1810 out << derivedClassPtr->GetName() << "</a>";
1811 delete [] htmlFile;
1812 htmlFile = 0;
1813 }
1814 else out << derivedClassPtr->GetName();
1815
1816 if( first ) {
1817 first = kFALSE;
1818 found = kTRUE;
1819 }
1820 }
1821 }
1822 }
1823 if( found ) out << "</dl>" << endl;
1824}
1825
1826
1827//______________________________________________________________________________
1828void MHtml::ExpandKeywords( ofstream &out, char *text, TClass *ptr2class,
1829 Bool_t &flag, const char *dir )
1830{
1831// Find keywords in text & create URLs
1832//
1833//
1834// Input: out - output file stream
1835// text - pointer to the array of the characters to process
1836// ptr2class - pointer to the class
1837// flag - this is a 'html_begin/html_end' flag
1838// dir - usually "" or "../", depends of current file
1839// directory position
1840//
1841
1842 char *keyword = text;
1843 char *end;
1844 char *funcName;
1845 char *funcNameEnd;
1846 char *funcSig;
1847 char *funcSigEnd;
1848 char c, c2, c3;
1849 char *tempEndPtr;
1850 c2 = c3 = 0;
1851
1852 Bool_t hide;
1853 Bool_t mmf = 0;
1854
1855 do {
1856 tempEndPtr = end = funcName = funcNameEnd = funcSig = funcSigEnd = NULL;
1857
1858 hide = kFALSE;
1859
1860 // skip until start of the word
1861 while( !IsWord( *keyword ) && *keyword ) {
1862 if( !flag ) ReplaceSpecialChars( out, *keyword );
1863 else out << *keyword;
1864 keyword++;
1865 }
1866
1867 // get end of the word
1868 end = keyword;
1869 while( IsName( *end ) && *end ) end++;
1870
1871 // put '\0' at the end of the keyword
1872 c = *end;
1873 *end = 0;
1874
1875 if( strlen( keyword ) > 50 ) {
1876 out << keyword;
1877 *end = c;
1878 keyword = end;
1879 continue;
1880 }
1881
1882 // check if this is a HTML block
1883 if( flag ) {
1884 if( !strcasecmp( keyword, "end_html" ) && *( keyword-1 ) != '\"') {
1885 flag = kFALSE;
1886 hide = kTRUE;
1887 }
1888 }
1889 else {
1890 if( !strcasecmp( keyword, "begin_html" ) && *( keyword-1 ) != '\"') {
1891 flag = kTRUE;
1892 hide = kTRUE;
1893 }
1894 else {
1895 *end = c;
1896 tempEndPtr = end;
1897
1898 // skip leading spaces
1899 while( *tempEndPtr && isspace( *tempEndPtr ) ) tempEndPtr++;
1900
1901
1902 // check if we have a something like a 'name[arg].name'
1903 Int_t count = 0;
1904 if( *tempEndPtr == '[') {
1905 count++;
1906 tempEndPtr++;
1907 }
1908
1909 // wait until the last ']'
1910 while( count && *tempEndPtr ) {
1911 switch( *tempEndPtr ) {
1912 case '[': count++;
1913 break;
1914 case ']': count--;
1915 break;
1916 }
1917 tempEndPtr++;
1918 }
1919
1920 if( !strncmp( tempEndPtr, "::", 2 ) || !strncmp( tempEndPtr, "->", 2 ) || ( *tempEndPtr == '.') ) {
1921 funcName = tempEndPtr;
1922
1923 // skip leading spaces
1924 while( isspace( *funcName )) funcName++;
1925
1926 // check if we have a '.' or '->'
1927 if( *tempEndPtr == '.') funcName++;
1928 else funcName += 2;
1929
1930 if( !strncmp( tempEndPtr, "::", 2 )) mmf = kTRUE;
1931 else mmf = kFALSE;
1932
1933 // skip leading spaces
1934 while( *funcName && isspace( *funcName )) funcName++;
1935
1936 // get the end of the word
1937 if( !IsWord( *funcName )) funcName = NULL;
1938
1939 if( funcName ) {
1940 funcNameEnd = funcName;
1941
1942 // find the end of the function name part
1943 while( IsName( *funcNameEnd ) && *funcNameEnd )
1944 funcNameEnd++;
1945 c2 = *funcNameEnd;
1946 if( !mmf ) {
1947
1948 // try to find a signature
1949 funcSig = funcNameEnd;
1950
1951 // skip leading spaces
1952 while( *funcSig && isspace( *funcSig )) funcSig++;
1953 if( *funcSig != '(') funcSig = NULL;
1954 else funcSig++;
1955 funcSigEnd = funcSig;
1956
1957 // if signature exist, try to find the ending character
1958 if( funcSigEnd ) {
1959 Int_t count = 1;
1960 while( *funcSigEnd ) {
1961 if( *funcSigEnd == '(') count++;
1962 if( *funcSigEnd == ')')
1963 if( !--count ) break;
1964 funcSigEnd++;
1965 }
1966 c3 = *funcSigEnd;
1967 *funcSigEnd = 0;
1968 }
1969 }
1970 *funcNameEnd = 0;
1971 }
1972 }
1973 *end = 0;
1974 }
1975 }
1976
1977 if( !flag && !hide && *keyword ) {
1978
1979 // get class
1980 TClass *classPtr = GetClass( (const char * ) keyword );
1981
1982 if( classPtr ) {
1983
1984 char *htmlFile = GetHtmlFileName( classPtr );
1985
1986 if( htmlFile ) {
1987 out << "<a href=\"";
1988 if( *dir && strncmp( htmlFile, "http://", 7 )) out << dir;
1989 out << htmlFile;
1990
1991 if( funcName && mmf ) {
1992
1993 // make a link to the member function
1994 out << "#" << classPtr->GetName() << ":";
1995 out << funcName;
1996 out << "\">";
1997 out << classPtr->GetName() << "::";
1998 out << funcName;
1999 out << "</a>";
2000
2001 *funcNameEnd = c2;
2002 keyword = funcNameEnd;
2003 }
2004 else {
2005 // make a link to the class
2006 out << "\">";
2007 out << classPtr->GetName();
2008 out << "</a>";
2009
2010 keyword = end;
2011 }
2012 delete [] htmlFile;
2013 htmlFile = 0;
2014
2015 }
2016 else {
2017 out << keyword;
2018 keyword = end;
2019 }
2020 *end = c;
2021 if( funcName ) *funcNameEnd = c2;
2022 if( funcSig ) *funcSigEnd = c3;
2023 }
2024 else {
2025 // get data type
2026 TDataType *type = gROOT->GetType( (const char *) keyword );
2027
2028 if( type ) {
2029
2030 // make a link to the data type
2031 out << "<a href=\"";
2032 if( *dir ) out << dir;
2033 out << "ListOfTypes.html#";
2034 out << keyword << "\">";
2035 out << keyword << "</a>";
2036
2037 *end = c;
2038 keyword = end;
2039 }
2040 else {
2041 // look for '('
2042 Bool_t isfunc = ( (*tempEndPtr == '(') || c == '(')? kTRUE: kFALSE;
2043 if( !isfunc ) {
2044 char *bptr = tempEndPtr + 1;
2045 while( *bptr && isspace( *bptr ) ) bptr++;
2046 if( *bptr == '(') isfunc = kTRUE;
2047 }
2048
2049 if( isfunc && ptr2class && ( ptr2class->GetMethodAny( keyword )) ) {
2050 out << "<a href=\"#";
2051 out << ptr2class->GetName();
2052 out << ":" << keyword << "\">";
2053 out << keyword << "</a>";
2054 *end = c;
2055 keyword = end;
2056 }
2057 else {
2058 const char *anyname = gROOT->FindObjectClassName( keyword );
2059
2060 const char *namePtr = NULL;
2061 TClass *cl = 0;
2062 TClass *cdl = 0;
2063
2064 if( anyname ) {
2065 cl = GetClass( anyname );
2066 namePtr = ( const char * ) anyname;
2067 cdl = cl;
2068 }
2069 else if( ptr2class ) {
2070 cl = ptr2class->GetBaseDataMember( keyword );
2071 if( cl ) {
2072 namePtr = cl->GetName();
2073 TDataMember *member = cl->GetDataMember( keyword );
2074 if( member )
2075 cdl = GetClass( member->GetTypeName() );
2076 }
2077 }
2078
2079 if( cl ) {
2080 char *htmlFile = GetHtmlFileName( cl );
2081
2082 if( htmlFile ) {
2083 out << "<a href=\"";
2084 if( *dir && strncmp( htmlFile, "http://", 7 )) out << dir;
2085 out << htmlFile;
2086 if( cl->GetDataMember( keyword ) ) {
2087 out << "#" << namePtr << ":";
2088 out << keyword;
2089 }
2090 out << "\">";
2091 out << keyword;
2092 out << "</a>";
2093 delete [] htmlFile;
2094 htmlFile = 0;
2095 }
2096 else out << keyword;
2097
2098 if( funcName ) {
2099 char *ptr = end;
2100 ptr++;
2101 ReplaceSpecialChars( out, c );
2102 while( ptr < funcName )
2103 ReplaceSpecialChars( out, *ptr++ );
2104
2105 TMethod *method = NULL;
2106 if( cdl ) method = cdl->GetMethodAny( funcName );
2107 if( method ) {
2108 TClass *cm = method->GetClass();
2109 if( cm ) {
2110 char *htmlFile2 = GetHtmlFileName( cm );
2111 if( htmlFile2 ) {
2112 out << "<a href=\"";
2113 if( *dir && strncmp( htmlFile2, "http://", 7 )) out << dir;
2114 out << htmlFile2;
2115 out << "#" << cm->GetName() << ":";
2116 out << funcName;
2117 out << "\">";
2118 out << funcName;
2119 out << "</a>";
2120 delete [] htmlFile2;
2121 htmlFile2 = 0;
2122 }
2123 else out << funcName;
2124
2125 keyword = funcNameEnd;
2126 }
2127 else keyword = funcName;
2128 }
2129 else keyword = funcName;
2130
2131 *funcNameEnd = c2;
2132 if( funcSig ) *funcSigEnd = c3;
2133 }
2134 else keyword = end;
2135 *end = c;
2136 }
2137 else {
2138 if( funcName ) *funcNameEnd = c2;
2139 if( funcSig ) *funcSigEnd = c3;
2140 out << keyword;
2141 *end = c;
2142 keyword = end;
2143 }
2144 }
2145 }
2146 }
2147 }
2148 else {
2149 if( !hide && *keyword )
2150 out << keyword;
2151 *end = c;
2152 keyword = end;
2153 }
2154 } while( *keyword );
2155}
2156
2157
2158//______________________________________________________________________________
2159void MHtml::ExpandPpLine( ofstream &out, char *line )
2160{
2161// Expand preprocessor statements
2162//
2163//
2164// Input: out - output file stream
2165// line - pointer to the array of characters,
2166// usually one line from the source file
2167//
2168// NOTE: Looks for the #include statements and
2169// creates link to the corresponding file
2170// if such file exists
2171//
2172
2173 const char *ptr;
2174 const char *ptrStart;
2175 const char *ptrEnd;
2176 char *fileName;
2177
2178 Bool_t linkExist = kFALSE;
2179
2180 ptrEnd = strstr( line, "include" );
2181 if( ptrEnd ) {
2182 ptrEnd += 7;
2183 if (( ptrStart = strpbrk( ptrEnd, "<\"" ))) {
2184 ptrStart++;
2185 ptrEnd = strpbrk( ptrStart, ">\"" );
2186 if( ptrEnd ) {
2187 Int_t len = ptrEnd - ptrStart;
2188 fileName = new char [len + 1];
2189 strncpy( fileName, ptrStart, len );
2190
2191 char *tmpstr = gSystem->Which( fSourceDir, fileName, kReadPermission );
2192 if( tmpstr ) {
2193 char *realFileName = StrDup( tmpstr );
2194
2195 if( realFileName ) {
2196 CopyHtmlFile( realFileName );
2197
2198 ptr = line;
2199 while( ptr < ptrStart )
2200 ReplaceSpecialChars( out, *ptr++ );
2201 out << "<a href=\"../" << GetFileName( realFileName ) << "\">";
2202 out << fileName << "</a>";
2203 out << ptrEnd;
2204
2205 linkExist = kTRUE;
2206 }
2207 if( realFileName ) delete [] realFileName;
2208 if( fileName ) delete [] fileName;
2209 delete [] tmpstr;
2210 }
2211 }
2212 }
2213 }
2214
2215 if( !linkExist ) ReplaceSpecialChars( out, line );
2216}
2217
2218//______________________________________________________________________________
2219const char *MHtml::GetFileName( const char *filename )
2220{
2221// It discards any directory information inside filename
2222//
2223//
2224// Input: filename - pointer to the file name
2225//
2226// Output: pointer to the string containing just a file name
2227// without any other directory information, i.e.
2228// '/usr/root/test.dat' will return 'test.dat'
2229//
2230
2231 return( gSystem->BaseName( gSystem->UnixPathName( filename )) );
2232}
2233
2234//______________________________________________________________________________
2235char *MHtml::GetSourceFileName(const char *filename)
2236{
2237 // Find the source file. If filename contains a path it will be used
2238 // together with the possible source prefix. If not found we try
2239 // old algorithm, by stripping off the path and trying to find it in the
2240 // specified source search path. Returned string must be deleted by the
2241 // user. In case filename is not found 0 is returned.
2242
2243 char *tmp1;
2244#ifdef WIN32
2245 if (strchr(filename, '/') || strchr(filename, '\\')) {
2246#else
2247 if (strchr(filename, '/')) {
2248#endif
2249 char *tmp;
2250 if (strlen(fSourcePrefix) > 0)
2251 tmp = gSystem->ConcatFileName(fSourcePrefix, filename);
2252 else
2253 tmp = StrDup(filename);
2254 if ((tmp1 = gSystem->Which(fSourceDir, tmp, kReadPermission))) {
2255 delete [] tmp;
2256 return tmp1;
2257 }
2258 delete [] tmp;
2259 }
2260
2261 if ((tmp1 = gSystem->Which(fSourceDir, GetFileName(filename), kReadPermission)))
2262 return tmp1;
2263
2264 return 0;
2265}
2266
2267//______________________________________________________________________________
2268char *MHtml::GetHtmlFileName( TClass *classPtr )
2269{
2270// Return real HTML filename
2271//
2272//
2273// Input: classPtr - pointer to a class
2274//
2275// Output: pointer to the string containing a full name
2276// of the corresponding HTML file. The string must be deleted by the user.
2277//
2278
2279 char htmlFileName [128];
2280
2281 char *ret = 0;
2282 Bool_t found = kFALSE;
2283
2284 if( classPtr ) {
2285
2286 const char *filename = classPtr->GetImplFileName();
2287
2288 char varName[80];
2289 const char *colon = strchr( filename, ':');
2290
2291
2292 // this should be a prefix
2293 strcpy( varName, "Root.Html." );
2294
2295
2296 if( colon )
2297 strncat( varName, filename, colon-filename );
2298 else strcat( varName, "Root" );
2299
2300 char *tmp;
2301 if( !(tmp = gSystem->Which( fSourceDir, filename, kReadPermission ))) {
2302 strcpy( htmlFileName, gEnv->GetValue( varName, "" ));
2303 if( !*htmlFileName ) found = kFALSE;
2304 else found = kTRUE;
2305 }
2306 else {
2307 strcpy( htmlFileName, "." );
2308 found = kTRUE;
2309 }
2310 delete [] tmp;
2311
2312 if( found ) {
2313 char *tmp1 = gSystem->ConcatFileName( htmlFileName, classPtr->GetName() );
2314 ret = StrDup( tmp1, 16 );
2315 strcat( ret, ".html" );
2316
2317 if( tmp1 ) delete [] tmp1;
2318 tmp1 = 0;
2319 }
2320 else ret = 0;
2321
2322 }
2323
2324 return ret;
2325}
2326
2327//______________________________________________________________________________
2328TClass *MHtml::GetClass(const char *name1, Bool_t load)
2329{
2330//*-*-*-*-*Return pointer to class with name*-*-*-*-*-*-*-*-*-*-*-*-*
2331//*-* =================================
2332 Int_t n = strlen(name1);
2333 char *name = new char[n+1];
2334 strcpy(name, name1);
2335 char *t = name+n-1;
2336 while(*t == ' ') {
2337 *t = 0;
2338 if (t == name) break;
2339 t--;
2340 }
2341 t = name;
2342 while(*t == ' ') t++;
2343
2344 TClass *cl = gROOT->GetClass(t,load);
2345 delete [] name;
2346 return cl;
2347}
2348
2349
2350//______________________________________________________________________________
2351Bool_t MHtml::IsModified( TClass *classPtr, const Int_t type )
2352{
2353// Check if file is modified
2354//
2355//
2356// Input: classPtr - pointer to the class
2357// type - file type to compare with
2358// values: kSource, kInclude, kTree
2359//
2360// Output: TRUE - if file is modified since last time
2361// FALSE - if file is up to date
2362//
2363
2364 Bool_t ret = kTRUE;
2365
2366 char sourceFile[1024], filename[1024];
2367 char *strPtr, *strPtr2;
2368
2369 switch( type ) {
2370 case kSource:
2371 strPtr2 = GetSourceFileName(classPtr->GetImplFileName());
2372 if (strPtr2) strcpy( sourceFile, strPtr2 );
2373 strPtr = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), "src" );
2374 strcpy( filename, strPtr );
2375 delete [] strPtr;
2376 delete [] strPtr2;
2377#ifdef WIN32
2378 strcat( filename, "\\" );
2379#else
2380 strcat( filename, "/" );
2381#endif
2382 strcat( filename, classPtr->GetName() );
2383 strcat( filename, ".cxx.html" );
2384 break;
2385
2386 case kInclude:
2387 strPtr2 = GetSourceFileName(classPtr->GetDeclFileName());
2388 if (strPtr2) strcpy( sourceFile, strPtr2 );
2389 strPtr = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), GetFileName( classPtr->GetDeclFileName() ));
2390 strcpy( filename,strPtr );
2391 delete [] strPtr;
2392 delete [] strPtr2;
2393 break;
2394
2395 case kTree:
2396 strPtr2 = GetSourceFileName(classPtr->GetDeclFileName());
2397 if (strPtr2) strcpy( sourceFile, strPtr2 );
2398 strPtr = gSystem->ConcatFileName( gSystem->ExpandPathName( fOutputDir ), GetFileName( classPtr->GetName() ));
2399 strcpy( filename, strPtr);
2400 delete [] strPtr;
2401 delete [] strPtr2;
2402 strcat( filename, "_Tree.ps" );
2403 break;
2404
2405 default:
2406 Error( "IsModified", "Unknown file type !" );
2407 }
2408
2409 // Get info about a file
2410 Long_t sId, sSize, sFlags, sModtime;
2411 Long_t dId, dSize, dFlags, dModtime;
2412
2413 if( !( gSystem->GetPathInfo( sourceFile, &sId, &sSize, &sFlags, &sModtime )) )
2414 if( !( gSystem->GetPathInfo( filename, &dId, &dSize, &dFlags, &dModtime )) )
2415 ret = ( sModtime > dModtime ) ? kTRUE : kFALSE;
2416
2417 return( ret );
2418}
2419
2420
2421//______________________________________________________________________________
2422Bool_t MHtml::IsName( Int_t c )
2423{
2424// Check if c is a valid C++ name character
2425//
2426//
2427// Input: c - a single character
2428//
2429// Output: TRUE if c is a valid C++ name character
2430// and FALSE if it's not.
2431//
2432// NOTE: Valid name characters are [a..zA..Z0..9_],
2433//
2434
2435 Bool_t ret = kFALSE;
2436
2437 if( isalnum( c ) || c == '_') ret = kTRUE;
2438
2439 return ret;
2440}
2441
2442
2443//______________________________________________________________________________
2444Bool_t MHtml::IsWord( Int_t c )
2445{
2446// Check if c is a valid first character for C++ name
2447//
2448//
2449// Input: c - a single character
2450//
2451// Output: TRUE if c is a valid first character for C++ name,
2452// and FALSE if it's not.
2453//
2454// NOTE: Valid first characters are [a..zA..Z_]
2455//
2456
2457 Bool_t ret = kFALSE;
2458
2459 if( isalpha( c ) || c == '_') ret = kTRUE;
2460
2461 return ret;
2462}
2463
2464
2465//______________________________________________________________________________
2466void MHtml::MakeAll( Bool_t force )
2467{
2468// It makes everything
2469//
2470
2471 Int_t i;
2472
2473 MakeIndex();
2474
2475 Int_t numberOfClasses = gClassTable->Classes();
2476 const char **className = new const char* [numberOfClasses];
2477
2478 // start from begining
2479 gClassTable->Init();
2480
2481
2482 for( i = 0; i < numberOfClasses; i++ )
2483 className[i] = gClassTable->Next();
2484
2485 for( i = 0; i < numberOfClasses; i++ ) {
2486 sprintf( fCounter, "%5d", numberOfClasses - i );
2487 MakeClass( (char * ) className[i], force );
2488 }
2489
2490 *fCounter = 0;
2491
2492 delete [] className;
2493}
2494
2495
2496//______________________________________________________________________________
2497void MHtml::MakeClass(const char *className, Bool_t force )
2498{
2499// Make HTML files for a single class
2500//
2501//
2502// Input: className - name of the class to process
2503//
2504
2505 TClass *classPtr = GetClass( className );
2506
2507 if( classPtr ) {
2508 char *htmlFile = GetHtmlFileName( classPtr );
2509 if( htmlFile && !strncmp( htmlFile, "http://", 7 )) {
2510 delete [] htmlFile;
2511 htmlFile = 0;
2512 }
2513 if( htmlFile ) {
2514 Class2Html( classPtr, force );
2515 MakeTree( className, force );
2516 delete [] htmlFile;
2517 htmlFile = 0;
2518 }
2519 else Printf( formatStr, "-skipped-", fCounter, className );
2520 }
2521 else Error( "MakeClass", "Unknown class '%s' !", className );
2522
2523}
2524
2525
2526//______________________________________________________________________________
2527void MHtml::MakeIndex()
2528{
2529 // It makes an index files
2530
2531 CreateListOfTypes();
2532
2533 // get total number of classes
2534 Int_t numberOfClasses = gClassTable->Classes();
2535
2536
2537 // allocate memory
2538 const char **classNames = new const char *[numberOfClasses];
2539 char **fileNames = new char *[numberOfClasses];
2540
2541 // start from begining
2542 gClassTable->Init();
2543
2544 // get class names
2545 Int_t len = 0;
2546 Int_t maxLen = 0;
2547 Int_t numberOfImpFiles = 0;
2548
2549 for( Int_t i = 0; i < numberOfClasses; i++ ) {
2550
2551 // get class name
2552 classNames[i] = gClassTable->Next();
2553 len = strlen( classNames[i] );
2554 maxLen = maxLen > len ? maxLen : len;
2555
2556 // get class & filename
2557 TClass *classPtr = GetClass( (const char * ) classNames[i] );
2558 const char *impname = classPtr->GetImplFileName();
2559
2560 if( impname ) {
2561 fileNames[numberOfImpFiles] = StrDup( impname, 64 );
2562
2563 char *underline = strchr( fileNames[numberOfImpFiles], '_');
2564 if( underline )
2565 strcpy( underline + 1, classNames[i] );
2566 else {
2567 // for new ROOT install the impl file name has the form: base/src/TROOT.cxx
2568 char *srcdir = strstr(fileNames[numberOfImpFiles], "/src/");
2569 if (srcdir) {
2570 strcpy(srcdir, "_");
2571 for (char *t = fileNames[numberOfImpFiles]; (t[0] = toupper(t[0])); t++) ;
2572 strcat(srcdir, classNames[i]);
2573 } else {
2574 strcpy( fileNames[i], "USER_" );
2575 strcat( fileNames[i], classNames[i] );
2576 }
2577 }
2578 numberOfImpFiles++;
2579 }
2580 else cout << "WARNING class:" << classNames[i] << " has no implementation file name !" << endl;
2581 }
2582 maxLen += kSpaceNum;
2583
2584 // quick sort
2585 SortNames( classNames, numberOfClasses );
2586 SortNames( (const char ** ) fileNames, numberOfImpFiles );
2587
2588 // create an index
2589 CreateIndex( classNames, numberOfClasses );
2590 CreateIndexByTopic( fileNames, numberOfClasses, maxLen );
2591
2592 // free allocated memory
2593 delete [] classNames;
2594 delete [] fileNames;
2595}
2596
2597
2598//______________________________________________________________________________
2599void MHtml::MakeTree(const char *className, Bool_t force )
2600{
2601// Make an inheritance tree
2602//
2603//
2604// Input: className - name of the class to process
2605//
2606
2607 // create canvas & set fill color
2608 TVirtualPad *psCanvas = 0;
2609 gROOT->ProcessLineFast("new TCanvas(\"\",\"psCanvas\",0,0,1000,750);");
2610 psCanvas = gPad->GetVirtCanvas();
2611
2612 TClass *classPtr = GetClass( className );
2613
2614 if( classPtr ) {
2615
2616 char *htmlFile = GetHtmlFileName( classPtr );
2617 if( htmlFile && !strncmp( htmlFile, "http://", 7 )) {
2618 delete [] htmlFile;
2619 htmlFile = 0;
2620 }
2621 if( htmlFile ) {
2622
2623 // make a class tree
2624 ClassTree( psCanvas, classPtr, force );
2625 delete [] htmlFile;
2626 htmlFile = 0;
2627 }
2628 else Printf( formatStr, "-skipped-", "", className );
2629
2630 }
2631 else Error( "MakeTree", "Unknown class '%s' !", className );
2632
2633 // close canvas
2634 psCanvas->Close();
2635 delete psCanvas;
2636
2637}
2638
2639
2640//______________________________________________________________________________
2641void MHtml::ReplaceSpecialChars( ofstream &out, const char c )
2642{
2643// Replace ampersand, less-than and greater-than character
2644//
2645//
2646// Input: out - output file stream
2647// c - single character
2648//
2649
2650 if (fEscFlag) {
2651 out << c;
2652 fEscFlag = kFALSE;
2653 }
2654 else if (c == fEsc)
2655 fEscFlag = kTRUE;
2656 else
2657 {
2658 switch( c ) {
2659 case '<':
2660 out << "&lt;";
2661 break;
2662 case '&':
2663 out << "&amp;";
2664 break;
2665 case '>':
2666 out << "&gt;";
2667 break;
2668 default:
2669 out << c;
2670 }
2671 }
2672}
2673
2674
2675//______________________________________________________________________________
2676void MHtml::ReplaceSpecialChars( ofstream &out, const char *string )
2677{
2678// Replace ampersand, less-than and greater-than characters
2679//
2680//
2681// Input: out - output file stream
2682// string - pointer to an array of characters
2683//
2684
2685 if( string ) {
2686 char *data = StrDup( string );
2687 if( data ) {
2688 char *ptr = NULL;
2689 char *start = data;
2690
2691 while (( ptr = strpbrk( start, "<&>" ))) {
2692 char c = *ptr;
2693 *ptr = 0;
2694 out << start;
2695 ReplaceSpecialChars( out, c );
2696 start = ptr+1;
2697 }
2698 out << start;
2699 delete [] data;
2700 }
2701 }
2702}
2703
2704//______________________________________________________________________________
2705void MHtml::SortNames( const char **strings, Int_t num, Bool_t type )
2706{
2707// Sort strings
2708//
2709//
2710// Input: strings - pointer to an array of strings
2711// type - sort type
2712// values : kCaseInsensitive, kCaseSensitive
2713// default: kCaseInsensitive
2714//
2715
2716 if( type == kCaseSensitive )
2717 qsort( strings, num, sizeof( strings ), CaseSensitiveSort );
2718 else
2719 qsort( strings, num, sizeof( strings ), CaseInsensitiveSort );
2720}
2721
2722
2723//______________________________________________________________________________
2724char *MHtml::StrDup( const char *s1, Int_t n )
2725{
2726// Returns a pointer to a new string which is a duplicate
2727// of the string to which 's1' points. The space for the
2728// new string is obtained using the 'new' operator. The new
2729// string has the length of 'strlen(s1) + n'.
2730
2731
2732 char *str = 0;
2733
2734 if( s1 ) {
2735 if( n < 0 ) n = 0;
2736 str = new char[ strlen( s1 ) + n + 1 ];
2737 if( str ) strcpy( str, s1 );
2738 }
2739
2740 return( str );
2741}
2742
2743//______________________________________________________________________________
2744void MHtml::WriteHtmlHeader( ofstream &out, const char *title )
2745{
2746// Write HTML header
2747//
2748//
2749// Input: out - output file stream
2750// title - title for the HTML page
2751//
2752
2753 TDatime date;
2754
2755 out << "<!DOCTYPE HTML PUBLIC \"-// IETF/DTD HTML 2.0// EN\">" << endl;
2756 out << "<html>" << endl;
2757 out << "<!-- -->" << endl;
2758 out << "<!-- Author: ROOT team (rootdev@hpsalo.cern.ch) -->" << endl;
2759 out << "<!-- -->" << endl;
2760 out << "<!-- Date: "<< date.AsString() << " -->" << endl;
2761 out << "<!-- -->" << endl;
2762 out << "<head>" << endl;
2763 out << "<title>";
2764 ReplaceSpecialChars( out, title );
2765 out << "</title>" << endl;
2766 out << "<link rev=made href=\"mailto:rootdev@root.cern.ch\">" << endl;
2767 out << "<meta name=\"rating\" content=\"General\">" << endl;
2768 out << "<meta name=\"objecttype\" content=\"Manual\">" << endl;
2769 out << "<meta name=\"keywords\" content=\"software development, oo, object oriented, ";
2770 out << "unix, x11, windows, c++, html, rene brun, fons rademakers\">" << endl;
2771 out << "<meta name=\"description\" content=\"ROOT - An Object Oriented Framework For Large Scale Data Analysis.\">" << endl;
2772 out << "</head>" << endl;
2773
2774 out << "<body BGCOLOR=\"#ffffff\" LINK=\"#0000ff\" VLINK=\"#551a8b\" ALINK=\"#ff0000\" TEXT=\"#000000\">" << endl;
2775 out << "<a name=\"TopOfPage\"></a>" << endl;
2776}
2777
2778
2779//______________________________________________________________________________
2780void MHtml::WriteHtmlFooter( ofstream &out, const char *dir, const char *lastUpdate,
2781 const char *author, const char *copyright )
2782{
2783// Write HTML footer
2784//
2785//
2786// Input: out - output file stream
2787// dir - usually equal to "" or "../", depends of
2788// current file directory position, i.e. if
2789// file is in the fOutputDir, then dir will be ""
2790// lastUpdate - last update string
2791// author - author's name
2792// copyright - copyright note
2793//
2794
2795 out << endl;
2796
2797 if( *author || *lastUpdate || *copyright ) out << "<hr><br>" << endl;
2798
2799 out << "<!--SIGNATURE-->" << endl;
2800
2801 // get the author( s )
2802 if( *author ) {
2803
2804 out << "<em>Author: ";
2805
2806 char *auth = StrDup(author);
2807
2808 char *name = strtok( auth, "," );
2809
2810 Bool_t firstAuthor = kTRUE;
2811
2812 do {
2813 char *ptr = name;
2814 char c;
2815
2816 // remove leading spaces
2817 while( *ptr && isspace( *ptr ) ) ptr++;
2818
2819 if( !firstAuthor ) out << ", ";
2820
2821 if( !strncmp( ptr, "Nicolas", 7 ) ) {
2822 out << "<a href=http://pcbrun.cern.ch/nicolas/index.html";
2823 ptr += 12;
2824 } else {
2825 out << "<a href="<<GetXwho();
2826 }
2827 while( *ptr ) {
2828 // Valery's specific case
2829 if( !strncmp( ptr, "Valery", 6 ) ) {
2830 out << "Valeri";
2831 ptr += 6;
2832 }
2833 else if( !strncmp( ptr, "Fine", 4 ) ) {
2834 out << "Faine";
2835 ptr += 4;
2836 }
2837 while( *ptr && !isspace( *ptr ) )
2838 out << *ptr++;
2839
2840 if( isspace( *ptr ) ) {
2841 while( *ptr && isspace( *ptr ) ) ptr++;
2842 if( isalpha( *ptr) ) out << '+';
2843 else break;
2844 }
2845 else break;
2846 }
2847 c = *ptr;
2848 *ptr = 0;
2849 out << ">" << name << "</a>";
2850 *ptr = c;
2851 out << ptr;
2852
2853 firstAuthor = kFALSE;
2854
2855 } while (( name = strtok( NULL, "," )));
2856 out << "</em><br>" << endl;
2857 delete [] auth;
2858 }
2859
2860 if( *lastUpdate ) out << "<em>Last update: " << lastUpdate << "</em><br>" << endl;
2861 if( *copyright ) out << "<em>Copyright " << copyright << "</em><br>" << endl;
2862
2863
2864 // this is a menu
2865 out << "<br>" << endl;
2866 out << "<address>" << endl;
2867 out << "<hr>" << endl;
2868 out << "<center>" << endl;
2869
2870 // link to the ROOT home page
2871 out << "<a href=\"http://root.cern.ch/root/Welcome.html\">ROOT page</a> - ";
2872
2873 // link to the user home page( if exist )
2874 const char *userHomePage = gEnv->GetValue( "Root.Html.HomePage", "" );
2875 if( *userHomePage ) {
2876 out << "<a href=\"";
2877 if( *dir ) {
2878 if( strncmp( userHomePage, "http://", 7 ))
2879 out << dir;
2880 }
2881 out << userHomePage;
2882 out << "\">Home page</a> - ";
2883 }
2884
2885 // link to the index file
2886 out << "<a href=\"";
2887 if( *dir ) out << dir;
2888 out << "ClassIndex.html\">Class index</a> - ";
2889
2890 // link to the top of the page
2891 out << "<a href=\"#TopOfPage\">Top of the page</a><br>" << endl;
2892
2893 out << "</center>" << endl;
2894
2895 out << "<hr>This page has been automatically generated. If you have any comments or suggestions ";
2896 out << "about the page layout send a mail to <a href=\"mailto:rootdev@root.cern.ch\">ROOT support</a>, or ";
2897 out << "contact <a href=\"mailto:rootdev@root.cern.ch\">the developers</a> with any questions or problems regarding ROOT." << endl;
2898 out << "</address>" << endl;
2899 out << "</body>" << endl;
2900 out << "</html>" << endl;
2901}
2902
Note: See TracBrowser for help on using the repository browser.