Converters
[ class tree: Converters ] [ index: Converters ] [ all elements ]

Source for file CHMdefaultConverter.inc

Documentation is available at CHMdefaultConverter.inc

  1. <?php
  2. /**
  3.  * CHM (Compiled Help Manual) output converter for Smarty Template.
  4.  *
  5.  * phpDocumentor :: automatic documentation generator
  6.  * 
  7.  * PHP versions 4 and 5
  8.  *
  9.  * Copyright (c) 2003-2006 Andrew Eddie, Greg Beaver
  10.  * 
  11.  * LICENSE:
  12.  * 
  13.  * This library is free software; you can redistribute it
  14.  * and/or modify it under the terms of the GNU Lesser General
  15.  * Public License as published by the Free Software Foundation;
  16.  * either version 2.1 of the License, or (at your option) any
  17.  * later version.
  18.  * 
  19.  * This library is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22.  * Lesser General Public License for more details.
  23.  * 
  24.  * You should have received a copy of the GNU Lesser General Public
  25.  * License along with this library; if not, write to the Free Software
  26.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  27.  *
  28.  * @package    Converters
  29.  * @subpackage CHMdefault
  30.  * @author     Joshua Eichorn <jeichorn@phpdoc.org>
  31.  * @author     Greg Beaver <cellog@php.net>
  32.  * @copyright  2000-2006 Joshua Eichorn, Gregory Beaver
  33.  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
  34.  * @version    CVS: $Id: CHMdefaultConverter.inc 234145 2007-04-19 20:20:57Z ashnazg $
  35.  * @filesource
  36.  * @link       http://www.phpdoc.org
  37.  * @link       http://pear.php.net/PhpDocumentor
  38.  * @since      1.0rc1
  39.  */
  40. /**
  41.  * Generates files that MS HTML Help Worshop can use to create a MS Windows
  42.  * compiled help file (CHM)
  43.  *
  44.  * The free MS HTML Help compiler takes the project file (phpdoc.hhp) and reads
  45.  * the table of contents file specified in the project (which is always contents.hhc
  46.  * in phpDocumentor).  When the converter reaches stable state, it will also
  47.  * output an index file index.hhk.  The free download for MS HTML Help Workshop
  48.  * is available below
  49.  * @link http://www.microsoft.com/downloads/release.asp?releaseid=33071 MS HTML Help Workshop download
  50.  * @package Converters
  51.  * @subpackage CHMdefault
  52.  * @author Greg Beaver <cellog@php.net>
  53.  * @since 1.0rc1
  54.  * @version $Revision: 234145 $
  55.  */
  56. class CHMdefaultConverter extends Converter
  57. {
  58.     /**
  59.      * CHMdefaultConverter wants elements sorted by type as well as alphabetically
  60.      * @see Converter::$sort_page_contents_by_type
  61.      * @var boolean 
  62.      */
  63.     var $sort_page_contents_by_type = true;
  64.     /** @var string */
  65.     var $outputformat = 'CHM';
  66.     /** @var string */
  67.     var $name = 'default';
  68.     /**
  69.      * indexes of elements by package that need to be generated
  70.      * @var array 
  71.      */
  72.     var $leftindex = array('classes' => true'pages' => true'functions' => true'defines' => false'globals' => false);
  73.    
  74.     /**
  75.      * output directory for the current procedural page being processed
  76.      * @var string 
  77.      */
  78.     var $page_dir;
  79.    
  80.     /**
  81.      * target directory passed on the command-line.
  82.      * {@link $targetDir} is malleable, always adding package/ and package/subpackage/ subdirectories onto it.
  83.      * @var string 
  84.      */
  85.     var $base_dir;
  86.    
  87.     /**
  88.      * output directory for the current class being processed
  89.      * @var string 
  90.      */
  91.     var $class_dir;
  92.    
  93.     /**
  94.      * array of converted package page names.
  95.      * Used to link to the package page in the left index
  96.      * @var array Format: array(package => 1)
  97.      */
  98.     var $package_pages = array();
  99.    
  100.     /**
  101.      * controls formatting of parser informative output
  102.      * 
  103.      * Converter prints:
  104.      * "Converting /path/to/file.php... Procedural Page Elements... Classes..."
  105.      * Since CHMdefaultConverter outputs files while converting, it needs to send a \n to start a new line.  However, if there
  106.      * is more than one class, output is messy, with multiple \n's just between class file output.  This variable prevents that
  107.      * and is purely cosmetic
  108.      * @var boolean 
  109.      */
  110.     var $juststarted = false;
  111.    
  112.     /**
  113.      * contains all of the template procedural page element loop data needed for the current template
  114.      * @var array 
  115.      */
  116.     var $current;
  117.    
  118.     /**
  119.      * contains all of the template class element loop data needed for the current template
  120.      * @var array 
  121.      */
  122.     var $currentclass;
  123.     var $wrote = false;
  124.     var $ric_set = array();
  125.     /**
  126.      * Table of Contents entry for index.hhk
  127.      * @var array 
  128.      */
  129.     var $KLinks = array();
  130.  
  131.     /**
  132.      * sets {@link $base_dir} to $targetDir
  133.      * @see Converter()
  134.      */
  135.     function CHMdefaultConverter(&$allp&$packp&$classes&$procpages$po$pp$qm$targetDir$templateDir$title)
  136.     {
  137.         Converter::Converter($allp$packp$classes$procpages,$po$pp$qm$targetDir$templateDir$title);
  138.         $this->base_dir = $targetDir;
  139.     }
  140.    
  141.     /**
  142.      * @deprecated in favor of PHP 4.3.0+ tokenizer-based source highlighting
  143.      */
  144.     function unmangle($sourcecode)
  145.     {
  146.         $sourcecode str_replace('<code>','<pre>',$sourcecode);
  147.         $sourcecode str_replace('</code>','</pre>',$sourcecode);
  148.         $sourcecode str_replace('<br />',"\n",$sourcecode);
  149.         $sourcecode str_replace('&nbsp;',' ',$sourcecode);
  150.         $sourcecode str_replace('&lt;','<',$sourcecode);
  151.         $sourcecode str_replace('&gt;','>',$sourcecode);
  152.         $sourcecode str_replace('&amp;','&',$sourcecode);
  153.         return $sourcecode;
  154.     }
  155.  
  156.     /**
  157.      * @param string full path to the source file
  158.      * @param string fully highlighted source code
  159.      */
  160.     function writeSource($path$value)
  161.     {
  162.         $templ &$this->newSmarty();
  163.         $pathinfo $this->proceduralpages->getPathInfo($path$this);
  164.         $templ->assign('source',$value);
  165.         $templ->assign('package',$pathinfo['package']);
  166.         $templ->assign('subpackage',$pathinfo['subpackage']);
  167.         $templ->assign('name',$pathinfo['name']);
  168.         $templ->assign('source_loc',$pathinfo['source_loc']);
  169.         $templ->assign('docs',$pathinfo['docs']);
  170.         $templ->assign("subdir",'../');
  171.         $templ->register_outputfilter('CHMdefault_outputfilter');
  172.         $this->setTargetDir($this->getFileSourcePath($this->base_dir));
  173.         $this->addSourceTOC($pathinfo['name'],$this->getFileSourceName($path),$pathinfo['package'],$pathinfo['subpackage']true);
  174.         phpDocumentor_out("\n");
  175.         $this->setSourcePaths($path);
  176.         $this->writefile($this->getFileSourceName($path).'.html',$templ->fetch('filesource.tpl'));
  177.     }
  178.    
  179.     function writeExample($title$path$source)
  180.     {
  181.         $templ &$this->newSmarty();
  182.         $templ->assign('source',$source);
  183.         if (empty($title))
  184.         {
  185.             $title 'example';
  186.             addWarning(PDERROR_EMPTY_EXAMPLE_TITLE$path$title);
  187.         }
  188.         $templ->assign('title',$title);
  189.         $templ->assign('file',$path);
  190.         $templ->assign("subdir",'../');
  191.         $templ->register_outputfilter('CHMdefault_outputfilter');
  192.         $pathinfo $this->proceduralpages->getPathInfo($path$this);
  193.         $this->setTargetDir($this->base_dir . PATH_DELIMITER '__examplesource');
  194.         $this->addSourceTOC($title,'exsource_'.$path,$pathinfo['package'],$pathinfo['subpackage']false);
  195.         phpDocumentor_out("\n");
  196.         $this->writefile('exsource_'.$path.'.html',$templ->fetch('examplesource.tpl'));
  197.     }
  198.  
  199.     function getExampleLink($path$title)
  200.     {
  201.         return $this->returnLink('../__examplesource' PATH_DELIMITER 'exsource_'.$path.'.html',$title);
  202.     }
  203.    
  204.     function getSourceLink($path)
  205.     {
  206.         return $this->returnLink('../__filesource/' .
  207.         $this->getFileSourceName($path).'.html','Source Code for this file');
  208.     }
  209.  
  210.     /**
  211.      * Retrieve a Converter-specific anchor to a segment of a source code file
  212.      * parsed via a {@tutorial tags.filesource.pkg} tag.
  213.      * @param string full path to source file
  214.      * @param string name of anchor
  215.      * @param string link text, if this is a link
  216.      * @param boolean returns either a link or a destination based on this
  217.      *                 parameter
  218.      * @return string link to an anchor, or the anchor
  219.      */
  220.     function getSourceAnchor($sourcefile,$anchor,$text '',$link false)
  221.     {
  222.         if ($link{
  223.             return $this->returnLink('../__filesource/' .
  224.                 $this->getFileSourceName($sourcefile'.html#a' $anchor$text);
  225.         else {
  226.             return '<a name="a'.$anchor.'"></a>';
  227.         }
  228.     }
  229.    
  230.  
  231.     /**
  232.      * Return a line of highlighted source code with formatted line number
  233.      *
  234.      * If the $path is a full path, then an anchor to the line number will be
  235.      * added as well
  236.      * @param integer line number
  237.      * @param string highlighted source code line
  238.      * @param false|stringfull path to @filesource file this line is a part of,
  239.      *         if this is a single line from a complete file.
  240.      * @return string formatted source code line with line number
  241.      */
  242.     function sourceLine($linenumber$line$path false)
  243.     {
  244.         $extra '';
  245.         if (strlen(str_replace("\n"''$line)) == 0{
  246.             $extra '&nbsp;';
  247.         }
  248.         if ($path)
  249.         {
  250.             return '<li><div class="src-line">' $this->getSourceAnchor($path$linenumber.
  251.                    str_replace("\n",'',$line$extra .
  252.                    "</div></li>\n";
  253.         else
  254.         {
  255.             return '<li><div class="src-line">' str_replace("\n",'',$line.
  256.                 "$extra</div></li>\n";
  257.         }
  258.     }
  259.  
  260.     /**
  261.      * Used to convert the <<code>> tag in a docblock
  262.      * @param string 
  263.      * @param boolean 
  264.      * @return string 
  265.      */
  266.     function ProgramExample($example$tutorial false$inlinesourceparse null/*false*/,
  267.                             $class null/*false*/$linenum null/*false*/$filesourcepath null/*false*/)
  268.     {
  269.         return $this->PreserveWhiteSpace(parent::ProgramExample($example$tutorial$inlinesourceparse$class$linenum$filesourcepath));
  270.     }
  271.    
  272.     /**
  273.      * @param string 
  274.      */
  275.     function TutorialExample($example)
  276.     {
  277.         $trans $this->template_options['desctranslate'];
  278.         $this->template_options['desctranslate'array();
  279.         $example '<ol>' parent::TutorialExample($example)
  280.                .'</ol>';
  281.         $this->template_options['desctranslate'$trans;
  282.         if (!isset($this->template_options['desctranslate'])) return $example;
  283.         if (!isset($this->template_options['desctranslate']['code'])) return $example;
  284.         $example $this->template_options['desctranslate']['code'$example;
  285.         if (!isset($this->template_options['desctranslate']['/code'])) return $example;
  286.         return $example $this->template_options['desctranslate']['/code'];
  287.     }
  288.    
  289.     function getCurrentPageLink()
  290.     {
  291.         return $this->curname '.html';
  292.     }
  293.  
  294.     /**
  295.      * Uses htmlspecialchars() on the input
  296.      */
  297.     function postProcess($text)
  298.     {
  299.         if ($this->highlightingSource{
  300.             return str_replace(array(' ',"\t")array('&nbsp;''&nbsp;&nbsp;&nbsp;'),
  301.                 htmlspecialchars($text));
  302.         }
  303.         return htmlspecialchars($text);
  304.     }
  305.    
  306.     /**
  307.      * Use the template tutorial_toc.tpl to generate a table of contents for HTML
  308.      * @return string table of contents formatted for use in the current output format
  309.      * @param array format: array(array('tagname' => section, 'link' => returnsee link, 'id' => anchor name, 'title' => from title tag),...)
  310.      */
  311.     function formatTutorialTOC($toc)
  312.     {
  313.         $template &$this->newSmarty();
  314.         $template->assign('toc',$toc);
  315.         return $template->fetch('tutorial_toc.tpl');
  316.     }
  317.    
  318.     function &SmartyInit(&$templ)
  319.     {
  320.         if (!isset($this->package_index))
  321.         foreach($this->all_packages as $key => $val)
  322.         {
  323.             if (isset($this->pkg_elements[$key]))
  324.             {
  325.                 if (!isset($start)) $start $key;
  326.                 $this->package_index[array('link' => "li_$key.html"'title' => $key);
  327.             }
  328.         }
  329.         $templ->assign("packageindex",$this->package_index);
  330.         $templ->assign("subdir",'');
  331.         return $templ;
  332.     }
  333.    
  334.    
  335.     /**
  336.      * Writes out the template file of {@link $class_data} and unsets the template to save memory
  337.      * @see registerCurrentClass()
  338.      * @see parent::endClass()
  339.      */
  340.     function endClass()
  341.     {
  342.         $a '../';
  343.         if (!empty($this->subpackage)) $a .= '../';
  344.         if ($this->juststarted)
  345.         {
  346.             $this->juststarted = false;
  347.             phpDocumentor_out("\n");
  348.             flush();
  349.         }
  350.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->class_dir);
  351.         $this->class_data->assign("subdir",$a);
  352.         $this->class_data->register_outputfilter('CHMdefault_outputfilter');
  353.         $this->addTOC($this->class,$this->class,$this->package,$this->subpackagetrue);
  354.         $this->writefile($this->class . '.html',$this->class_data->fetch('class.tpl'));
  355.         unset($this->class_data);
  356.     }
  357.    
  358.     /**
  359.      * Writes out the template file of {@link $page_data} and unsets the template to save memory
  360.      * @see registerCurrent()
  361.      * @see parent::endPage()
  362.      */
  363.     function endPage()
  364.     {
  365.         $this->package = $this->curpage->package;
  366.         $this->subpackage = $this->curpage->subpackage;
  367.         $a '../';
  368.         if (!empty($this->subpackage)) $a .= '../';
  369.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->page_dir);
  370.         $this->page_data->assign("package",$this->package);
  371.         $this->page_data->assign("subdir",$a);
  372.         $this->page_data->register_outputfilter('CHMdefault_outputfilter');
  373.         $this->addTOC($this->curpage->file,$this->page,$this->package,$this->subpackage);
  374.         $this->writefile($this->page . '.html',$this->page_data->fetch('page.tpl'));
  375.         unset($this->page_data);
  376.     }
  377.    
  378.     /**
  379.      * @param string 
  380.      * @param string 
  381.      * @return string &lt;a href="'.$link.'">'.$text.'</a&gt;
  382.      */
  383.     function returnLink($link,$text)
  384.     {
  385.         return '<a href="'.$link.'">'.$text.'</a>';
  386.     }
  387.    
  388.     /**
  389.      * CHMdefaultConverter chooses to format both package indexes and the complete index here
  390.      *
  391.      * This function formats output for the elementindex.html and pkgelementindex.html template files.  It then
  392.      * writes them to the target directory
  393.      * @see generateElementIndex(), generatePkgElementIndex()
  394.      */
  395.     function formatPkgIndex()
  396.     {
  397.         list($package_indexes,$packages,$mletters$this->generatePkgElementIndexes();
  398.         for($i=0;$i<count($package_indexes);$i++)
  399.         {
  400.             $template &$this->newSmarty();
  401.             $this->package = $package_indexes[$i]['package'];
  402.             $this->subpackage = '';
  403.             $template->assign("index",$package_indexes[$i]['pindex']);
  404.             $template->assign("package",$package_indexes[$i]['package']);
  405.             $template->assign("letters",$mletters[$package_indexes[$i]['package']]);
  406.             $template->assign("title","Package ".$package_indexes[$i]['package']." Element Index");
  407.             $template->assign("subdir",'../');
  408.             $template->register_outputfilter('CHMdefault_outputfilter');
  409.             $this->setTargetDir($this->base_dir . PATH_DELIMITER $package_indexes[$i]['package']);
  410.             $this->addTOC($package_indexes[$i]['package']." Alphabetical Index",'elementindex_'.$package_indexes[$i]['package'],$package_indexes[$i]['package'],'');
  411.             $this->writefile('elementindex_'.$package_indexes[$i]['package'].'.html',$template->fetch('pkgelementindex.tpl'));
  412.         }
  413.         phpDocumentor_out("\n");
  414.         flush();
  415.         }
  416.    
  417.     /**
  418.      * CHMdefaultConverter uses this function to format template index.html and packages.html
  419.      *
  420.      * This function generates the package list from {@link $all_packages}, eliminating any
  421.      * packages that don't have any entries in their package index (no files at all, due to @ignore
  422.      * or other factors).  Then it uses the default package name as the first package index to display.
  423.      * It sets the right pane to be either a blank file with instructions on making package-level docs,
  424.      * or the package-level docs for the default package.
  425.      * @global string Used to set the starting package to display
  426.      */
  427.     function formatIndex()
  428.     {
  429.         global $phpDocumentor_DefaultPackageName;
  430.         list($elindex,$mletters$this->generateElementIndex();
  431.         $template &$this->newSmarty();
  432.         $template->assign("index",$elindex);
  433.         $template->assign("letters",$mletters);
  434.         $template->assign("title","Element Index");
  435.         $template->assign("date",date("r",time()));
  436.         $template->register_outputfilter('CHMdefault_outputfilter');
  437.         phpDocumentor_out("\n");
  438.         flush();
  439.         $this->setTargetDir($this->base_dir);
  440.         $this->addTOC("Alphabetical Index Of All Elements",'elementindex',"Index",'');
  441.         $this->writefile('elementindex.html',$template->fetch('elementindex.tpl'));
  442.         usort($this->package_index,"CHMdefault_pindexcmp");
  443.         $index &$this->newSmarty();
  444.         foreach($this->all_packages as $key => $val)
  445.         {
  446.             if (isset($this->pkg_elements[$key]))
  447.             {
  448.                 if (!isset($start)) $start $key;
  449.                 if (!isset($this->package_pages[$key])) $this->writeNewPPage($key);
  450.             }
  451.         }
  452.         $this->setTargetDir($this->base_dir);
  453.         // Created index.html
  454.         if (isset($this->pkg_elements[$phpDocumentor_DefaultPackageName])) $start $phpDocumentor_DefaultPackageName;
  455.         $this->package = $start;
  456.         $this->subpackage = '';
  457.         $setalready false;
  458.         if (isset($this->tutorials[$start]['']['pkg']))
  459.         {
  460.             foreach($this->tutorials[$start]['']['pkg'as $tute)
  461.             {
  462.                 if ($tute->name == $start '.pkg')
  463.                 {
  464.                     $setalready true;
  465.                        $this->addTOC("Start page",$start.'/tutorial_'.$tute->name,"Index",'');
  466.                 }
  467.             }
  468.         }
  469.         if (!$setalready)
  470.         {
  471.             if (isset($this->package_pages[$start]))
  472.             {
  473.                    $this->addTOC("Start page",'package_'.$start,"Index",'');
  474.             }
  475.             else
  476.             {
  477.                 $index->assign("blank","blank");
  478.                 $blank &$this->newSmarty();
  479.                 $blank->assign('package',$phpDocumentor_DefaultPackageName);
  480.                 $this->addTOC("Start page",'blank',"Index",'');
  481.                 $this->writefile("blank.html",$blank->fetch('blank.tpl'));
  482.                 Converter::writefile('index.html',$blank->fetch('tutorial.tpl'));
  483.             }
  484.         }
  485.         phpDocumentor_out("\n");
  486.         flush();
  487.  
  488.         unset($index);
  489.     }
  490.    
  491.     function writeNewPPage($key)
  492.     {
  493.         return;
  494.         $template &$this->newSmarty();
  495.         $this->package = $key;
  496.         $this->subpackage = '';
  497.         $template->assign("date",date("r",time()));
  498.         $template->assign("title",$this->title);
  499.         $template->assign("package",$key);
  500.         $template->register_outputfilter('CHMdefault_outputfilter');
  501.         phpDocumentor_out("\n");
  502.         flush();
  503.         $this->setTargetDir($this->base_dir);
  504.    
  505.         $this->addTOC("$key Index","li_$key",$key,'');
  506.         $this->writefile("li_$key.html",$template->fetch('index.tpl'));
  507.         unset($template);
  508.     }
  509.    
  510.     /**
  511.      * Generate indexes for li_package.html and classtree output files
  512.      *
  513.      * This function generates the li_package.html files from the template file left.html.  It does this by
  514.      * iterating through each of the $page_elements, $class_elements and  $function_elements arrays to retrieve
  515.      * the pre-sorted {@link abstractLink} descendants needed for index generation.  Conversion of these links to
  516.      * text is done by {@link returnSee()}.  The {@link $local} parameter is set to false to ensure that paths are correct.
  517.      * 
  518.      * Then it uses {@link generateFormattedClassTrees()} to create class trees from the template file classtrees.html.  Output
  519.      * filename is classtrees_packagename.html.  This function also unsets {@link $elements} and {@link $pkg_elements} to free
  520.      * up the considerable memory these two class vars use
  521.      * @see $page_elements, $class_elements, $function_elements
  522.      */
  523.     function formatLeftIndex()
  524.     {
  525.         phpDocumentor_out("\n");
  526.         flush();
  527.         $this->setTargetDir($this->base_dir);
  528.         if (0)//!isset($this->left))
  529.         {
  530.             debug("Nothing parsed, check the command-line");
  531.             die();
  532.         }
  533.         foreach($this->all_packages as $package => $rest)
  534.         {
  535.             if (!isset($this->pkg_elements[$package])) continue;
  536.            
  537.             // Create class tree page
  538.             $template &$this->newSmarty();
  539.             $template->assign("classtrees",$this->generateFormattedClassTrees($package));
  540.             $template->assign("package",$package);
  541.             $template->assign("date",date("r",time()));
  542.             $template->register_outputfilter('CHMdefault_outputfilter');
  543.             $this->addTOC("$package Class Trees","classtrees_$package",$package,'');
  544.             $this->writefile("classtrees_$package.html",$template->fetch('classtrees.tpl'));
  545.             phpDocumentor_out("\n");
  546.             flush();
  547.         }
  548.         // free up considerable memory
  549.         unset($this->elements);
  550.         unset($this->pkg_elements);
  551.     }
  552.    
  553.     /**
  554.      * This function takes an {@link abstractLink} descendant and returns an html link
  555.      *
  556.      * @param abstractLink a descendant of abstractlink should be passed, and never text
  557.      * @param string text to display in the link
  558.      * @param boolean this parameter is not used, and is deprecated
  559.      * @param boolean determines whether the returned text is enclosed in an <a> tag
  560.      */
  561.     function returnSee(&$element$eltext false$with_a true)
  562.     {
  563.         if (!$elementreturn false;
  564.         if (!$with_areturn $this->getId($elementfalse);
  565.         if (!$eltext)
  566.         {
  567.             $eltext '';
  568.             switch($element->type)
  569.             {
  570.                 case 'tutorial' :
  571.                 $eltext strip_tags($element->title);
  572.                 break;
  573.                 case 'method' :
  574.                 case 'var' :
  575.                 case 'const' :
  576.                 $eltext .= $element->class.'::';
  577.                 case 'page' :
  578.                 case 'define' :
  579.                 case 'class' :
  580.                 case 'function' :
  581.                 case 'global' :
  582.                 default :
  583.                 $eltext .= $element->name;
  584.                 if ($element->type == 'function' || $element->type == 'method'$eltext .= '()';
  585.                 break;
  586.             }
  587.         }
  588.         return '<a href="'.$this->getId($element).'">'.$eltext.'</a>';
  589.     }
  590.    
  591.     function getId($element$fullpath true)
  592.     {
  593.         if (phpDocumentor_get_class($element== 'parserdata')
  594.         {
  595.             $element $this->addLink($element->parent);
  596.             $elp $element->parent;
  597.         elseif (is_a($element'parserbase'))
  598.         {
  599.             $elp $element;
  600.             $element $this->addLink($element);
  601.         }
  602.         $c '';
  603.         if (!empty($element->subpackage))
  604.         {
  605.             $c '/'.$element->subpackage;
  606.         }
  607.         $b '../';
  608.         switch ($element->type)
  609.         {
  610.             case 'page' :
  611.             if ($fullpath)
  612.             return $b.$element->package.$c.'/'.$element->fileAlias.'.html';
  613.             return 'top';
  614.             break;
  615.             case 'define' :
  616.             case 'global' :
  617.             case 'function' :
  618.             if ($fullpath)
  619.             return $b.$element->package.$c.'/'.$element->fileAlias.'.html#'.$element->type.$element->name;
  620.             return $element->type.$element->name;
  621.             break;
  622.             case 'class' :
  623.             if ($fullpath)
  624.             return $b.$element->package.$c.'/'.$element->name.'.html';
  625.             return 'top';
  626.             break;
  627.             case 'method' :
  628.             case 'var' :
  629.             case 'const' :
  630.             if ($fullpath)
  631.             return $b.$element->package.$c.'/'.$element->class.'.html#'.$element->type.$element->name;
  632.             return $element->type.$element->name;
  633.             break;
  634.             case 'tutorial' :
  635.             $d '';
  636.             if ($element->section)
  637.             {
  638.                 $d '#'.$element->section;
  639.             }
  640.             return $b.$element->package.$c.'/tutorial_'.$element->name.'.html'.$d;
  641.         }
  642.     }
  643.    
  644.     function ConvertTodoList()
  645.     {
  646.         $todolist array();
  647.         foreach($this->todoList as $package => $alltodos)
  648.         {
  649.             foreach($alltodos as $todos)
  650.             {
  651.                 $converted array();
  652.                 $converted['link'$this->returnSee($todos[0]);
  653.                 if (!is_array($todos[1]))
  654.                 {
  655.                     $converted['todos'][$todos[1]->Convert($this);
  656.                 else
  657.                 {
  658.                     foreach($todos[1as $todo)
  659.                     {
  660.                         $converted['todos'][$todo->Convert($this);
  661.                     }
  662.                 }
  663.                 $todolist[$package][$converted;
  664.             }
  665.         }
  666.         $templ &$this->newSmarty();
  667.         $templ->assign('todos',$todolist);
  668.         $templ->register_outputfilter('CHMdefault_outputfilter');
  669.         $this->setTargetDir($this->base_dir);
  670.         $this->addTOC('Todo List','todolist','Index','',false,true);
  671.         $this->addKLink('Todo List''todolist''''Development');
  672.         $this->writefile('todolist.html',$templ->fetch('todolist.tpl'));
  673.     }
  674.    
  675.     /**
  676.      * Convert README/INSTALL/CHANGELOG file contents to output format
  677.      * @param README|INSTALL|CHANGELOG
  678.      * @param string contents of the file
  679.      */
  680.     function Convert_RIC($name$contents)
  681.     {
  682.         $template &$this->newSmarty();
  683.         $template->assign('contents',$contents);
  684.         $template->assign('name',$name);
  685.         $this->setTargetDir($this->base_dir);
  686.         $this->addTOC($name,'ric_'.$name,'Index','',false,true);
  687.         $this->addKLink($name'ric_'.$name'''Development');
  688.         $this->writefile('ric_'.$name '.html',$template->fetch('ric.tpl'));
  689.         $this->ric_set[$nametrue;
  690.     }
  691.    
  692.     /**
  693.      * Create errors.html template file output
  694.      *
  695.      * This method takes all parsing errors and warnings and spits them out ordered by file and line number.
  696.      * @global ErrorTracker We'll be using it's output facility
  697.      */
  698.     function ConvertErrorLog()
  699.     {
  700.         global $phpDocumentor_errors;
  701.         $allfiles array();
  702.         $files array();
  703.         $warnings $phpDocumentor_errors->returnWarnings();
  704.         $errors $phpDocumentor_errors->returnErrors();
  705.         $template &$this->newSmarty();
  706.         foreach($warnings as $warning)
  707.         {
  708.             $file '##none';
  709.             $linenum 'Warning';
  710.             if ($warning->file)
  711.             {
  712.                 $file $warning->file;
  713.                 $allfiles[$file1;
  714.                 $linenum .= ' on line '.$warning->linenum;
  715.             }
  716.             $files[$file]['warnings'][array('name' => $linenum'listing' => $warning->data);
  717.         }
  718.         foreach($errors as $error)
  719.         {
  720.             $file '##none';
  721.             $linenum 'Error';
  722.             if ($error->file)
  723.             {
  724.                 $file $error->file;
  725.                 $allfiles[$file1;
  726.                 $linenum .= ' on line '.$error->linenum;
  727.             }
  728.             $files[$file]['errors'][array('name' => $linenum'listing' => $error->data);
  729.         }
  730.         $i=1;
  731.         $af array();
  732.         foreach($allfiles as $file => $num)
  733.         {
  734.             $af[$i++$file;
  735.         }
  736.         $allfiles $af;
  737.         usort($allfiles,'strnatcasecmp');
  738.         $allfiles[0"Post-parsing";
  739.         foreach($allfiles as $i => $a)
  740.         {
  741.             $allfiles[$iarray('file' => $a);
  742.         }
  743.         $out array();
  744.         foreach($files as $file => $data)
  745.         {
  746.             if ($file == '##none'$file 'Post-parsing';
  747.             $out[$file$data;
  748.         }
  749.         $template->assign("files",$allfiles);
  750.         $template->assign("all",$out);
  751.         $template->assign("title","phpDocumentor Parser Errors and Warnings");
  752.         $this->setTargetDir($this->base_dir);
  753.         $this->writefile("errors.html",$template->fetch('errors.tpl'));
  754.         unset($template);
  755.         phpDocumentor_out("\n\nTo view errors and warnings, look at ".$this->base_dirPATH_DELIMITER "errors.html\n");
  756.         flush();
  757.     }
  758.    
  759.     function getCData($value)
  760.     {
  761.         return '<pre>'.htmlentities($value).'</pre>';
  762.     }
  763.    
  764.     function getTutorialId($package,$subpackage,$tutorial,$id)
  765.     {
  766.         return $id;
  767.     }
  768.  
  769.     /**
  770.      * Converts package page and sets its package as used in {@link $package_pages}
  771.      * @param parserPackagePage 
  772.      */
  773.     function convertPackagepage(&$element)
  774.     {
  775.         phpDocumentor_out("\n");
  776.         flush();
  777.         $this->package = $element->package;
  778.         $this->subpackage = '';
  779.         $contents $element->Convert($this);
  780.         $this->package_pages[$element->packagestr_replace('../','../',$contents);
  781.         phpDocumentor_out("\n");
  782.         flush();
  783.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $element->package);
  784.         $this->addTOC($element->package." Tutorial",'package_'.$element->package,$element->package,'');
  785.         $this->writeFile('package_'.$element->package.'.html',str_replace('../','../',$contents));
  786.         $this->setTargetDir($this->base_dir);
  787.         Converter::writefile('index.html',str_replace('../','',$contents));
  788.         $this->addKLink($element->package." Tutorial"'package_'.$element->package'''Tutorials');
  789.     }
  790.    
  791.     /**
  792.      * @param parserTutorial 
  793.      */
  794.     function convertTutorial(&$element)
  795.     {
  796.         phpDocumentor_out("\n");
  797.         flush();
  798.         $template &parent::convertTutorial($element);
  799.         $a '../';
  800.         if ($element->subpackage$a .= '../';
  801.         $template->assign('subdir',$a);
  802.         $template->register_outputfilter('CHMdefault_outputfilter');
  803.         $contents $template->fetch('tutorial.tpl');
  804.         if ($element->package == $GLOBALS['phpDocumentor_DefaultPackageName'&& empty($element->subpackage&& ($element->name == $element->package '.pkg'))
  805.         {
  806.             $template->assign('subdir','');
  807.             $this->setTargetDir($this->base_dir);
  808.             Converter::writefile('index.html',$template->fetch('tutorial.tpl'));
  809.         }
  810.         $a '';
  811.         if ($element->subpackage$a PATH_DELIMITER $element->subpackage;
  812.         phpDocumentor_out("\n");
  813.         flush();
  814.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $element->package $a);
  815.         $this->addTOC($a strip_tags($element->getTitle($this))'tutorial_'.$element->name,
  816.             $element->package$element->subpackagefalsetrue);
  817.         $this->writeFile('tutorial_'.$element->name.'.html',$contents);
  818.         $this->addKLink($element->getTitle($this)$element->package $a PATH_DELIMITER 'tutorial_'.$element->name,
  819.             '''Tutorials');
  820.     }
  821.    
  822.     /**
  823.      * Converts class for template output
  824.      * @see prepareDocBlock(), generateChildClassList(), generateFormattedClassTree(), getFormattedConflicts()
  825.      * @see getFormattedInheritedMethods(), getFormattedInheritedVars()
  826.      * @param parserClass 
  827.      */
  828.     function convertClass(&$element)
  829.     {
  830.         parent::convertClass($element);
  831.         $this->class_dir = $element->docblock->package;
  832.         if (!empty($element->docblock->subpackage)) $this->class_dir .= PATH_DELIMITER $element->docblock->subpackage;
  833.         $a '../';
  834.         if ($element->docblock->subpackage != ''$a "../$a";
  835.        
  836.         $this->class_data->assign('subdir',$a);
  837.         $this->class_data->assign("title","Docs For Class " $element->getName());
  838.         $this->class_data->assign("page",$element->getName('.html');
  839.         $this->addKLink($element->name$this->class_dir . PATH_DELIMITER $this->class'''Classes');
  840.     }
  841.    
  842.  
  843.     /**
  844.      * Converts class variables for template output
  845.      * @see prepareDocBlock(), getFormattedConflicts()
  846.      * @param parserDefine 
  847.      */
  848.     function convertVar(&$element)
  849.     {
  850.         parent::convertVar($elementarray('var_dest' => $this->getId($element,false)));
  851.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->class_dir);
  852.         $this->addKLink($element->name$this->class_dir . PATH_DELIMITER .$this->class$this->getId($element,false)$element->class.' Properties');
  853.     }
  854.  
  855.     /**
  856.      * Converts class constants for template output
  857.      * @see prepareDocBlock(), getFormattedConflicts()
  858.      * @param parserDefine 
  859.      */
  860.     function convertConst(&$element)
  861.     {
  862.         parent::convertConst($elementarray('const_dest' => $this->getId($element,false)));
  863.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->class_dir);
  864.         $this->addKLink($element->name$this->class_dir . PATH_DELIMITER .$this->class$this->getId($element,false)$element->class.' Constants');
  865.     }
  866.  
  867.     /**
  868.      * Converts class methods for template output
  869.      * @see prepareDocBlock(), getFormattedConflicts()
  870.      * @param parserDefine 
  871.      */
  872.     function convertMethod(&$element)
  873.     {
  874.         parent::convertMethod($elementarray('method_dest' => $this->getId($element,false)));
  875.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->class_dir);
  876.         $this->addKLink($element->name$this->class_dir . PATH_DELIMITER .$this->class$this->getId($element,false)$element->class.' Methods');
  877.     }
  878.    
  879.     /**
  880.      * Converts function for template output
  881.      * @see prepareDocBlock(), parserFunction::getFunctionCall(), getFormattedConflicts()
  882.      * @param parserFunction 
  883.      */
  884.     function convertFunction(&$element)
  885.     {
  886.         $funcloc $this->getId($this->addLink($element));
  887.         parent::convertFunction($element,array('function_dest' => $this->getId($element,false)));
  888.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->page_dir);
  889.         $this->addKLink($element->name$this->page_dir . PATH_DELIMITER $this->page$this->getId($element,false)'Functions');
  890.     }
  891.    
  892.     /**
  893.      * Converts include elements for template output
  894.      * @see prepareDocBlock()
  895.      * @param parserInclude 
  896.      */
  897.     function convertInclude(&$element)
  898.     {
  899.         parent::convertInclude($elementarray('include_file'    => '_'.strtr($element->getValue(),array('"' => ''"'" => '','.' => '_'))));
  900.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->page_dir);
  901.         $this->addKLink(str_replace('"'''$element->getValue())$this->page_dir . PATH_DELIMITER $this->page''ucfirst($element->name));
  902.     }
  903.    
  904.     /**
  905.      * Converts defines for template output
  906.      * @see prepareDocBlock(), getFormattedConflicts()
  907.      * @param parserDefine 
  908.      */
  909.     function convertDefine(&$element)
  910.     {
  911.         parent::convertDefine($elementarray('define_link' => $this->getId($element,false)));
  912.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->page_dir);
  913.         $this->addKLink($element->name$this->page_dir . PATH_DELIMITER $this->page$this->getId($element,false)'Constants');
  914.     }
  915.    
  916.     /**
  917.      * Converts global variables for template output
  918.      * @param parserGlobal 
  919.      */
  920.     function convertGlobal(&$element)
  921.     {
  922.         parent::convertGlobal($elementarray('global_link' => $this->getId($element,false)));
  923.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->page_dir);
  924.         $this->addKLink($element->name$this->page_dir . PATH_DELIMITER $this->page$this->getId($element,false)'Global Variables');
  925.     }
  926.    
  927.     /**
  928.      * converts procedural pages for template output
  929.      * @see prepareDocBlock(), getClassesOnPage()
  930.      * @param parserData 
  931.      */
  932.     function convertPage(&$element)
  933.     {
  934.         parent::convertPage($element);
  935.         $this->juststarted = true;
  936.         $this->page_dir = $element->parent->package;
  937.         if (!empty($element->parent->subpackage)) $this->page_dir .= PATH_DELIMITER $element->parent->subpackage;
  938.         // registering stuff on the template
  939.         $this->page_data->assign("page",$this->getPageName($element'.html');
  940.         $this->page_data->assign("title","Docs for page ".$element->parent->getFile());
  941.         $this->setTargetDir($this->base_dir . PATH_DELIMITER $this->page_dir);
  942.         $this->addKLink($element->parent->file$this->page_dir . PATH_DELIMITER $this->page'''Files');
  943.     }
  944.    
  945.     function getPageName(&$element)
  946.     {
  947.         if (phpDocumentor_get_class($element== 'parserpage'return '_'.$element->getName();
  948.         return '_'.$element->parent->getName();
  949.     }
  950.  
  951.     /**
  952.      * returns an array containing the class inheritance tree from the root object to the class
  953.      *
  954.      * @param parserClass    class variable
  955.      * @return array Format: array(root,child,child,child,...,$class)
  956.      * @uses parserClass::getParentClassTree()
  957.      */
  958.    
  959.     function generateFormattedClassTree($class)
  960.     {
  961.         $tree $class->getParentClassTree($this);
  962.         $out '';
  963.         if (count($tree1)
  964.         {
  965.             $result array($class->getName());
  966.             $parent $tree[$class->getName()];
  967.             $distance['';
  968.             while ($parent)
  969.             {
  970.                 $x $parent;
  971.                 if (is_object($parent))
  972.                 {
  973.                     $subpackage $parent->docblock->subpackage;
  974.                     $package $parent->docblock->package;
  975.                     $x $parent;
  976.                     $x $parent->getLink($this);
  977.                     if (!$x$x $parent->getName();
  978.                 }
  979.                 $result[
  980.                     $x;
  981.                 $distance[=
  982.                     "\n%s|\n" .
  983.                     "%s--";
  984.                 if (is_object($parent))
  985.                 $parent $tree[$parent->getName()];
  986.                 elseif (isset($tree[$parent]))
  987.                 $parent $tree[$parent];
  988.             }
  989.             $nbsp '   ';
  990.             for($i=count($result1;$i>=0;$i--)
  991.             {
  992.                 $my_nbsp '';
  993.                 for($j=0;$j<count($result$i;$j++$my_nbsp .= $nbsp;
  994.                 $distance[$isprintf($distance[$i],$my_nbsp,$my_nbsp);
  995.             }
  996.             return array('classes'=>array_reverse($result),'distance'=>array_reverse($distance));
  997.         else
  998.         {
  999.             return array('classes'=>$class->getName(),'distance'=>array(''));
  1000.         }
  1001.     }
  1002.    
  1003.     /** @access private */
  1004.     function sortVar($a$b)
  1005.     {
  1006.         return strnatcasecmp($a->getName(),$b->getName());
  1007.     }
  1008.    
  1009.     /** @access private */
  1010.     function sortMethod($a$b)
  1011.     {
  1012.         if ($a->isConstructorreturn -1;
  1013.         if ($b->isConstructorreturn 1;
  1014.         return strnatcasecmp($a->getName(),$b->getName());
  1015.     }
  1016.  
  1017.     /**
  1018.      * returns a template-enabled array of class trees
  1019.      * 
  1020.      * @param    string    $package    package to generate a class tree for
  1021.      * @see $roots, HTMLConverter::getRootTree()
  1022.      */
  1023.     function generateFormattedClassTrees($package)
  1024.     {
  1025.         if (!isset($this->roots['normal'][$package]&&
  1026.               !isset($this->roots['special'][$package])) {
  1027.             return array();
  1028.         }
  1029.         $trees array();
  1030.         if (isset($this->roots['normal'][$package])) {
  1031.             $roots $this->roots['normal'][$package];
  1032.             for($i=0;$i<count($roots);$i++)
  1033.             {
  1034.                 $root $this->classes->getClassByPackage($roots[$i]$package);
  1035.                 if ($root && $root->isInterface()) {
  1036.                     continue;
  1037.                 }
  1038.                 $trees[array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n");
  1039.             }
  1040.         }
  1041.         if (isset($this->roots['special'][$package])) {
  1042.             $roots $this->roots['special'][$package];
  1043.             foreach ($roots as $parent => $classes{
  1044.                 $thistree '';
  1045.                 foreach ($classes as $classinfo{
  1046.                     $root $this->classes->getClassByPackage($classinfo$package);
  1047.                     if ($root && $root->isInterface()) {
  1048.                         continue;
  1049.                     }
  1050.                     $thistree .=
  1051.                         $this->getRootTree(
  1052.                             $this->getSortedClassTreeFromClass(
  1053.                                 $classinfo,
  1054.                                 $package,
  1055.                                 ''),
  1056.                             $package,
  1057.                             true);
  1058.                 }
  1059.                 if (!$thistree{
  1060.                     continue;
  1061.                 }
  1062.                 $trees[array(
  1063.                     'class' => $parent,
  1064.                     'class_tree' => "<ul>\n" $thistree "</ul>\n"
  1065.                 );
  1066.             }
  1067.         }
  1068.         return $trees;
  1069.     }
  1070.  
  1071.     /**
  1072.      * returns a template-enabled array of interface inheritance trees
  1073.      * 
  1074.      * @param    string    $package    package to generate a class tree for
  1075.      * @see $roots, HTMLConverter::getRootTree()
  1076.      */
  1077.     function generateFormattedInterfaceTrees($package)
  1078.     {
  1079.         if (!isset($this->roots['normal'][$package]&&
  1080.               !isset($this->roots['special'][$package])) {
  1081.             return array();
  1082.         }
  1083.         $trees array();
  1084.         if (isset($this->roots['normal'][$package])) {
  1085.             $roots $this->roots['normal'][$package];
  1086.             for($i=0;$i<count($roots);$i++)
  1087.             {
  1088.                 $root $this->classes->getClassByPackage($roots[$i]$package);
  1089.                 if ($root && !$root->isInterface()) {
  1090.                     continue;
  1091.                 }
  1092.                 $trees[array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n");
  1093.             }
  1094.         }
  1095.         if (isset($this->roots['special'][$package])) {
  1096.             $roots $this->roots['special'][$package];
  1097.             foreach ($roots as $parent => $classes{
  1098.                 $thistree '';
  1099.                 foreach ($classes as $classinfo{
  1100.                     $root $this->classes->getClassByPackage($classinfo$package);
  1101.                     if ($root && !$root->isInterface()) {
  1102.                         continue;
  1103.                     }
  1104.                     $thistree .=
  1105.                         $this->getRootTree(
  1106.                             $this->getSortedClassTreeFromClass(
  1107.                                 $classinfo,
  1108.                                 $package,
  1109.                                 ''),
  1110.                             $package,
  1111.                             true);
  1112.                 }
  1113.                 if (!$thistree{
  1114.                     continue;
  1115.                 }
  1116.                 $trees[array(
  1117.                     'class' => $parent,
  1118.                     'class_tree' => "<ul>\n" $thistree "</ul>\n"
  1119.                 );
  1120.             }
  1121.         }
  1122.         return $trees;
  1123.     }
  1124.    
  1125.     /**
  1126.      * return formatted class tree for the Class Trees page
  1127.      *
  1128.      * @param array $tree output from {@link getSortedClassTreeFromClass()}
  1129.      * @param string $package  package
  1130.      * @param boolean $nounknownparent if true, an object's parent will not be checked
  1131.      * @see Classes::$definitechild, generateFormattedClassTrees()
  1132.      * @return string 
  1133.      */
  1134.     function getRootTree($tree$package$noparent false)
  1135.     {
  1136.         if (!$treereturn '';
  1137.         $my_tree '';
  1138.         $cur '#root';
  1139.         $lastcur array(false);
  1140.         $kids array();
  1141.         $dopar false;
  1142.         if (!$noparent && $tree[$cur]['parent'])
  1143.         {
  1144.             $dopar true;
  1145.             if (!is_object($tree[$cur]['parent']))
  1146.             {
  1147. //                debug("parent ".$tree[$cur]['parent']." not found");
  1148.                 $my_tree .= '<li>' $tree[$cur]['parent'.'<ul>';
  1149.             }
  1150.             else
  1151.             {
  1152. //                        debug("parent ".$this->returnSee($tree[$cur]['parent'])." in other package");
  1153.                 $my_tree .= '<li>' $this->returnSee($tree[$cur]['parent']);
  1154.                 if ($tree[$cur]['parent']->package != $package$my_tree .= ' <b>(Different package)</b><ul>';
  1155.             }
  1156.         }
  1157.         do
  1158.         {
  1159. //            fancy_debug($cur,$lastcur,$kids);
  1160.             if (count($tree[$cur]['children']))
  1161.             {
  1162. //                debug("$cur has children");
  1163.                 if (!isset($kids[$cur]))
  1164.                 {
  1165. //                    debug("set $cur kids");
  1166.                     $kids[$cur1;
  1167.                     $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link']);
  1168.                     $my_tree .= '<ul>'."\n";
  1169.                 }
  1170.                 array_push($lastcur,$cur);
  1171.                 list(,$cureach($tree[$cur]['children']);
  1172. //                var_dump('listed',$cur);
  1173.                 if ($cur)
  1174.                 {
  1175.                     $cur $cur['package''#' $cur['class'];
  1176. //                    debug("set cur to child $cur");
  1177. //                    $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link']);
  1178.                     continue;
  1179.                 else
  1180.                 {
  1181. //                    debug("end of children for $cur");
  1182.                     $cur array_pop($lastcur);
  1183.                     $cur array_pop($lastcur);
  1184.                     $my_tree .= '</ul></li>'."\n";
  1185.                     if ($dopar && ($cur == '#root' || !$cur)) $my_tree .= '</ul></li>';
  1186.                 }
  1187.             else 
  1188.             {
  1189. //                debug("$cur has no children");
  1190.                 $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link'])."</li>";
  1191.                 if ($dopar && $cur == '#root'$my_tree .= '</ul></li>';
  1192.                 $cur array_pop($lastcur);
  1193.             }
  1194.         while ($cur);
  1195.         return $my_tree;
  1196.     }
  1197.         /**
  1198.          * Generate indexing information for given element
  1199.          * 
  1200.          * @param parserElement descendant of parserElement
  1201.          * @see generateElementIndex()
  1202.          * @return array 
  1203.          */
  1204.         function getIndexInformation($elt)
  1205.         {
  1206.             $Result['type'$elt->type;
  1207.             $Result['file_name'$elt->file;
  1208.             $Result['path'$elt->getPath();
  1209.            
  1210.             if (isset($elt->docblock))
  1211.                         {
  1212.                             $Result['description'$elt->docblock->getSDesc($this);
  1213.                            
  1214.                             if ($elt->docblock->hasaccess)
  1215.                                 $Result['access'$elt->docblock->tags['access'][0]->value;
  1216.                             else
  1217.                                 $Result['access''public';
  1218.  
  1219.                             $Result['abstract'= isset ($elt->docblock->tags['abstract'][0]);
  1220.                         }
  1221.             else
  1222.                 $Result['description''';
  1223.            
  1224.             $aa $Result['description'];
  1225.             if (!empty($aa)) $aa "<br>&nbsp;&nbsp;&nbsp;&nbsp;$aa";
  1226.  
  1227.             switch($elt->type)
  1228.             {
  1229.                     case 'class':
  1230.                             $Result['name'$elt->getName();
  1231.                             $Result['title''Class';
  1232.                             $Result['link'$this->getClassLink($elt->getName(),
  1233.                                                                   $elt->docblock->package,
  1234.                                                                   $elt->getPath(),
  1235.                                                                   $elt->getName());
  1236.                             $Result['listing''in file '.$elt->file.', class '.$Result['link']."$aa";
  1237.                     break;
  1238.                     case 'define':
  1239.                             $Result['name'$elt->getName();
  1240.                             $Result['title''Constant';
  1241.                             $Result['link'$this->getDefineLink($elt->getName(),
  1242.                                                                    $elt->docblock->package,
  1243.                                                                    $elt->getPath(),
  1244.                                                                    $elt->getName());
  1245.                             $Result['listing''in file '.$elt->file.', constant '.$Result['link']."$aa";
  1246.                     break;
  1247.                     case 'global':
  1248.                             $Result['name'$elt->getName();
  1249.                             $Result['title''Global';
  1250.                             $Result['link'$this->getGlobalLink($elt->getName(),
  1251.                                                                    $elt->docblock->package,
  1252.                                                                    $elt->getPath(),
  1253.                                                                    $elt->getName());
  1254.                             $Result['listing''in file '.$elt->file.', global variable '.$Result['link']."$aa";
  1255.                     break;
  1256.                     case 'function':
  1257.                             $Result['name'$elt->getName();
  1258.                             $Result['title''Function';
  1259.                             $Result['link'$this->getFunctionLink($elt->getName(),
  1260.                                                                      $elt->docblock->package,
  1261.                                                                      $elt->getPath(),
  1262.                                                                      $elt->getName().'()');
  1263.                             $Result['listing''in file '.$elt->file.', function '.$Result['link']."$aa";
  1264.                     break;
  1265.                     case 'method':
  1266.                             $Result['name'$elt->getName();
  1267.                             $Result['title''Method';
  1268.                             $Result['link'$this->getMethodLink($elt->getName(),
  1269.                                                                    $elt->class,
  1270.                                                                    $elt->docblock->package,
  1271.                                                                    $elt->getPath(),
  1272.                                                                    $elt->class.'::'.$elt->getName().'()'
  1273.                                                                              );
  1274.                                                         if ($elt->isConstructor$Result['constructor'1;
  1275.                             $Result['listing''in file '.$elt->file.', method '.$Result['link']."$aa";
  1276.                     break;
  1277.                     case 'var':
  1278.                             $Result['name'$elt->getName();
  1279.                             $Result['title''Variable';
  1280.                             $Result['link'$this->getVarLink($elt->getName(),
  1281.                                                                 $elt->class,
  1282.                                                                 $elt->docblock->package,
  1283.                                                                 $elt->getPath(),
  1284.                                                                 $elt->class.'::'.$elt->getName());
  1285.                             $Result['listing''in file '.$elt->file.', variable '.$Result['link']."$aa";
  1286.                     break;
  1287.                     case 'const':
  1288.                             $Result['name'$elt->getName();
  1289.                             $Result['title''Variable';
  1290.                             $Result['link'$this->getConstLink($elt->getName(),
  1291.                                                                 $elt->class,
  1292.                                                                 $elt->docblock->package,
  1293.                                                                 $elt->getPath(),
  1294.                                                                 $elt->class.'::'.$elt->getName());
  1295.                             $Result['listing''in file '.$elt->file.', class constant '.$Result['link']."$aa";
  1296.                     break;
  1297.                     case 'page':
  1298.                             $Result['name'$elt->getFile();
  1299.                             $Result['title''Page';
  1300.                             $Result['link'$this->getPageLink($elt->getFile(),
  1301.                                                                  $elt->package,
  1302.                                                                  $elt->getPath(),
  1303.                                                                  $elt->getFile());
  1304.                             $Result['listing''procedural page '.$Result['link'];
  1305.                     break;
  1306.                     case 'include':
  1307.                             $Result['name'$elt->getName();
  1308.                             $Result['title''Include';
  1309.                             $Result['link'$elt->getValue();
  1310.                             $Result['listing''include '.$Result['name'];
  1311.                     break;
  1312.             }
  1313.  
  1314.             return $Result;
  1315.         }
  1316.     /**
  1317.      * Generate alphabetical index of all elements
  1318.      *
  1319.      * @see $elements, walk()
  1320.      */
  1321.     function generateElementIndex()
  1322.     {
  1323.         $elementindex array();
  1324.         $letters array();
  1325.         $used array();
  1326.         foreach($this->elements as $letter => $nutoh)
  1327.         {
  1328.             foreach($this->elements[$letteras $i => $yuh)
  1329.             {
  1330.                 if ($this->elements[$letter][$i]->type != 'include')
  1331.                 {
  1332.                     if (!isset($used[$letter]))
  1333.                     {
  1334.                         $letters[]['letter'$letter;
  1335.                         $elindex['letter'$letter;
  1336.                         $used[$letter1;
  1337.                     }
  1338.  
  1339.                     $elindex['index'][$this->getIndexInformation($this->elements[$letter][$i]);
  1340.                 }
  1341.             }
  1342.             if (isset($elindex['index']))
  1343.             {
  1344.                 $elementindex[$elindex;
  1345.             else
  1346.             {
  1347.                 unset($letters[count($letters1]);
  1348.             }
  1349.             $elindex array();
  1350.         }
  1351.         return array($elementindex,$letters);
  1352.     }
  1353.    
  1354.     function setTemplateDir($dir)
  1355.     {
  1356.         Converter::setTemplateDir($dir);
  1357.         $this->smarty_dir = $this->templateDir;
  1358.     }
  1359.    
  1360.     function copyMediaRecursively($media,$targetdir,$subdir '')
  1361.     {
  1362.         $versionControlDirectories array ('CVS''media/CVS''media\\CVS''.svn''media/.svn''media\\.svn');
  1363.         if (!is_array($media)) {
  1364.             return;
  1365.         }
  1366.         foreach($media as $dir => $files)
  1367.         {
  1368.             if ($dir === '/')
  1369.             {
  1370.                 $this->copyMediaRecursively($files,$targetdir);
  1371.             else
  1372.             {
  1373.                 if (!is_numeric($dir))
  1374.                 {
  1375.                     if (in_array($dir$versionControlDirectories))
  1376.                     {
  1377.                         // skip it entirely
  1378.                     }
  1379.                     else
  1380.                     {
  1381.                         // create the subdir
  1382.                         phpDocumentor_out("creating $targetdirPATH_DELIMITER "$dir\n");
  1383.                         Converter::setTargetDir($targetdir PATH_DELIMITER $dir);
  1384.                         if (!empty($subdir)) 
  1385.                         {
  1386.                             $subdir .= PATH_DELIMITER;
  1387.                         }
  1388.                         $this->copyMediaRecursively($files,"$targetdir/$dir",$subdir $dir);
  1389.                     }
  1390.                
  1391.                 else
  1392.                 {
  1393.                     // copy the file
  1394.                     phpDocumentor_out("copying $targetdirPATH_DELIMITER $files['file']."\n");
  1395.                     $this->copyFile($files['file'],$subdir);
  1396.                 }
  1397.             }
  1398.         }
  1399.     }
  1400.    
  1401.     /**
  1402.      * calls the converter setTargetDir, and then copies any template images and the stylesheet if they haven't been copied
  1403.      * @see Converter::setTargetDir()
  1404.      */
  1405.     function setTargetDir($dir)
  1406.     {
  1407.         Converter::setTargetDir($dir);
  1408.         if ($this->wrotereturn;
  1409.         $this->wrote = true;
  1410.         $template_images array();
  1411.         $stylesheets array();
  1412.         $tdir $dir;
  1413.         $dir $this->templateDir;
  1414.         $this->templateDir = $this->templateDir.'templates/';
  1415.         $info new Io;
  1416.         $this->copyMediaRecursively($info->getDirTree($this->templateDir.'media',$this->templateDir),$tdir);
  1417.     }
  1418.    
  1419.     /**
  1420.      * Generate alphabetical index of all elements by package and subpackage
  1421.      *
  1422.      * @param string $package name of a package
  1423.      * @see $pkg_elements, walk(), generatePkgElementIndexes()
  1424.      */
  1425.     function generatePkgElementIndex($package)
  1426.     {
  1427. //        var_dump($this->pkg_elements[$package]);
  1428.         $elementindex array();
  1429.         $letters array();
  1430.         $letterind array();
  1431.         $used array();
  1432.         $subp '';
  1433.         foreach($this->pkg_elements[$packageas $subpackage => $els)
  1434.         {
  1435.             if (empty($els)) continue;
  1436.             if (!empty($subpackage)) $subp " (<b>subpackage:</b> $subpackage)"else $subp '';
  1437.             foreach($els as $letter => $yuh)
  1438.             {
  1439.                 foreach($els[$letteras $i => $yuh)
  1440.                 {
  1441.                     if ($els[$letter][$i]->type != 'include')
  1442.                     {
  1443.                         if (!isset($used[$letter]))
  1444.                         {
  1445.                             $letters[]['letter'$letter;
  1446.                             $letterind[$lettercount($letters1;
  1447.                             $used[$letter1;
  1448.                         }
  1449.                         $elindex[$letter]['letter'$letter;
  1450.  
  1451.                         $elindex[$letter]['index'][$this->getIndexInformation($els[$letter][$i]);
  1452.                     }
  1453.                 }
  1454.             }
  1455.         }
  1456.         ksort($elindex);
  1457.         usort($letters,'CHMdefault_lettersort');
  1458.         if (isset($elindex))
  1459.         {
  1460.             while(list($letter,$tempeleach($elindex))
  1461.             {
  1462.                 if (!isset($tempel))
  1463.                 {
  1464.                     unset($letters[$letterind[$tempel['letter']]]);
  1465.                 else
  1466.                 $elementindex[$tempel;
  1467.             }
  1468.         else $letters array();
  1469.         return array($elementindex,$letters);
  1470.     }
  1471.    
  1472.     /**
  1473.      *
  1474.      * @see generatePkgElementIndex()
  1475.      */
  1476.     function generatePkgElementIndexes()
  1477.     {
  1478.         $packages array();
  1479.         $package_names array();
  1480.         $pkg array();
  1481.         $letters array();
  1482.         foreach($this->pkg_elements as $package => $trash)
  1483.         {
  1484.             $pkgs['package'$package;
  1485.             $pkg['package'$package;
  1486.             list($pkg['pindex'],$letters[$package]$this->generatePkgElementIndex($package);
  1487.             if (count($pkg['pindex']))
  1488.             {
  1489.                 $packages[$pkg;
  1490.                 $package_names[$pkgs;
  1491.             }
  1492.             unset($pkgs);
  1493.             unset($pkg);
  1494.         }
  1495.         foreach($packages as $i => $package)
  1496.         {
  1497.             $pnames array();
  1498.             for($j=0;$j<count($package_names);$j++)
  1499.             {
  1500.                 if ($package_names[$j]['package'!= $package['package']$pnames[$package_names[$j];
  1501.             }
  1502.             $packages[$i]['packageindexes'$pnames;
  1503.         }
  1504.         return array($packages,$package_names,$letters);
  1505.     }
  1506.    
  1507.     /**
  1508.      * @param string name of class
  1509.      * @param string package name
  1510.      * @param string full path to look in (used in index generation)
  1511.      * @param boolean deprecated
  1512.      * @param boolean return just the URL, or enclose it in an html a tag
  1513.      * @return mixed false if not found, or an html a link to the class's documentation
  1514.      * @see parent::getClassLink()
  1515.      */
  1516.     function getClassLink($expr,$package$file false,$text false$with_a true)
  1517.     {
  1518.         $a Converter::getClassLink($expr,$package,$file);
  1519.         if (!$areturn false;
  1520.         return $this->returnSee($a$text$with_a);
  1521.     }
  1522.  
  1523.     /**
  1524.      * @param string name of function
  1525.      * @param string package name
  1526.      * @param string full path to look in (used in index generation)
  1527.      * @param boolean deprecated
  1528.      * @param boolean return just the URL, or enclose it in an html a tag
  1529.      * @return mixed false if not found, or an html a link to the function's documentation
  1530.      * @see parent::getFunctionLink()
  1531.      */
  1532.     function getFunctionLink($expr,$package$file false,$text false)
  1533.     {
  1534.         $a Converter::getFunctionLink($expr,$package,$file);
  1535.         if (!$areturn false;
  1536.         return $this->returnSee($a$text);
  1537.     }
  1538.  
  1539.     /**
  1540.      * @param string name of define
  1541.      * @param string package name
  1542.      * @param string full path to look in (used in index generation)
  1543.      * @param boolean deprecated
  1544.      * @param boolean return just the URL, or enclose it in an html a tag
  1545.      * @return mixed false if not found, or an html a link to the define's documentation
  1546.      * @see parent::getDefineLink()
  1547.      */
  1548.     function getDefineLink($expr,$package$file false,$text false)
  1549.     {
  1550.         $a Converter::getDefineLink($expr,$package,$file);
  1551.         if (!$areturn false;
  1552.         return $this->returnSee($a$text);
  1553.     }
  1554.  
  1555.     /**
  1556.      * @param string name of global variable
  1557.      * @param string package name
  1558.      * @param string full path to look in (used in index generation)
  1559.      * @param boolean deprecated
  1560.      * @param boolean return just the URL, or enclose it in an html a tag
  1561.      * @return mixed false if not found, or an html a link to the global variable's documentation
  1562.      * @see parent::getGlobalLink()
  1563.      */
  1564.     function getGlobalLink($expr,$package$file false,$text false)
  1565.     {
  1566.         $a Converter::getGlobalLink($expr,$package,$file);
  1567.         if (!$areturn false;
  1568.         return $this->returnSee($a$text);
  1569.     }
  1570.  
  1571.     /**
  1572.      * @param string name of procedural page
  1573.      * @param string package name
  1574.      * @param string full path to look in (used in index generation)
  1575.      * @param boolean deprecated
  1576.      * @param boolean return just the URL, or enclose it in an html a tag
  1577.      * @return mixed false if not found, or an html a link to the procedural page's documentation
  1578.      * @see parent::getPageLink()
  1579.      */
  1580.     function getPageLink($expr,$package$path false,$text false)
  1581.     {
  1582.         $a Converter::getPageLink($expr,$package,$path);
  1583.         if (!$areturn false;
  1584.         return $this->returnSee($a$text);
  1585.     }
  1586.  
  1587.     /**
  1588.      * @param string name of method
  1589.      * @param string class containing method
  1590.      * @param string package name
  1591.      * @param string full path to look in (used in index generation)
  1592.      * @param boolean deprecated
  1593.      * @param boolean return just the URL, or enclose it in an html a tag
  1594.      * @return mixed false if not found, or an html a link to the method's documentation
  1595.      * @see parent::getMethodLink()
  1596.      */
  1597.     function getMethodLink($expr,$class,$package$file false,$text false)
  1598.     {
  1599.         $a Converter::getMethodLink($expr,$class,$package,$file);
  1600.         if (!$areturn false;
  1601.         return $this->returnSee($a$text);
  1602.     }
  1603.  
  1604.     /**
  1605.      * @param string name of var
  1606.      * @param string class containing var
  1607.      * @param string package name
  1608.      * @param string full path to look in (used in index generation)
  1609.      * @param boolean deprecated
  1610.      * @param boolean return just the URL, or enclose it in an html a tag
  1611.      * @return mixed false if not found, or an html a link to the var's documentation
  1612.      * @see parent::getVarLink()
  1613.      */
  1614.     function getVarLink($expr,$class,$package$file false,$text false)
  1615.     {
  1616.         $a Converter::getVarLink($expr,$class,$package,$file);
  1617.         if (!$areturn false;
  1618.         return $this->returnSee($a$text);
  1619.     }
  1620.  
  1621.     /**
  1622.      * @param string name of class constant
  1623.      * @param string class containing class constant
  1624.      * @param string package name
  1625.      * @param string full path to look in (used in index generation)
  1626.      * @param boolean deprecated
  1627.      * @param boolean return just the URL, or enclose it in an html a tag
  1628.      * @return mixed false if not found, or an html a link to the var's documentation
  1629.      * @see parent::getVarLink()
  1630.      */
  1631.     function getConstLink($expr,$class,$package$file false,$text false)
  1632.     {
  1633.         $a Converter::getConstLink($expr,$class,$package,$file);
  1634.         if (!$areturn false;
  1635.         return $this->returnSee($a$text);
  1636.     }
  1637.    
  1638.     /**
  1639.      * does a nat case sort on the specified second level value of the array
  1640.      *
  1641.      * @param    mixed    $a 
  1642.      * @param    mixed    $b 
  1643.      * @return    int 
  1644.      */
  1645.     function rcNatCmp ($a$b)
  1646.     {
  1647.         $aa strtoupper($a[$this->rcnatcmpkey]);
  1648.         $bb strtoupper($b[$this->rcnatcmpkey]);
  1649.        
  1650.         return strnatcasecmp($aa$bb);
  1651.     }
  1652.    
  1653.     /**
  1654.      * does a nat case sort on the specified second level value of the array.
  1655.      * this one puts constructors first
  1656.      *
  1657.      * @param    mixed    $a 
  1658.      * @param    mixed    $b 
  1659.      * @return    int 
  1660.      */
  1661.     function rcNatCmp1 ($a$b)
  1662.     {
  1663.         $aa strtoupper($a[$this->rcnatcmpkey]);
  1664.         $bb strtoupper($b[$this->rcnatcmpkey]);
  1665.        
  1666.         if (strpos($aa,'CONSTRUCTOR'=== 0)
  1667.         {
  1668.             return -1;
  1669.         }
  1670.         if (strpos($bb,'CONSTRUCTOR'=== 0)
  1671.         {
  1672.             return 1;
  1673.         }
  1674.         if (strpos($aa,strtoupper($this->class)) === 0)
  1675.         {
  1676.             return -1;
  1677.         }
  1678.         if (strpos($bb,strtoupper($this->class)) === 0)
  1679.         {
  1680.             return -1;
  1681.         }
  1682.         return strnatcasecmp($aa$bb);
  1683.     }
  1684.    
  1685.     /**
  1686.      * Write a file to disk, and add it to the {@link $hhp_files} list of files
  1687.      * to include in the generated CHM
  1688.      *
  1689.      * {@source } 
  1690.      */
  1691.     function writefile($file,$contents)
  1692.     {
  1693.         $this->addHHP($this->targetDir . PATH_DELIMITER $file);
  1694.         Converter::writefile($file,$contents);
  1695.     }
  1696.    
  1697.     /**
  1698.      * @uses $hhp_files creates the array by adding parameter $file
  1699.      */
  1700.     function addHHP($file)
  1701.     {
  1702.         $file str_replace($this->base_dir . PATH_DELIMITER''$file);
  1703.         $file str_replace('\\',PATH_DELIMITER,$file);
  1704.         $file str_replace('//',PATH_DELIMITER,$file);
  1705.         $file str_replace(PATH_DELIMITER,'\\',$file);
  1706.         $this->hhp_files[]['name'$file;
  1707.     }
  1708.    
  1709.     function generateTOC()
  1710.     {
  1711.         $comppack '';
  1712.         $templ &$this->newSmarty();
  1713.         foreach($this->TOC as $package => $TOC1)
  1714.         {
  1715.             $comp_subs '';
  1716.             $comp_subs1 false;
  1717.             foreach($TOC1 as $subpackage => $types)
  1718.             {
  1719.                 $comp_types '';
  1720.                 foreach($types as $type => $files)
  1721.                 {
  1722.                     $comp '';
  1723.                     $templ1 &$this->newSmarty();
  1724.                     $templ1->assign('entry'array());
  1725.                     foreach($files as $file)
  1726.                     {
  1727.                     // use book icon for classes
  1728.                         if ($type == 'Classes'{
  1729.                             $templ1->append('entry'array('paramname' => $file[0],'outputfile' => $file[1],'isclass' => 1));
  1730.                         else {
  1731.                             $templ1->append('entry'array('paramname' => $file[0],'outputfile' => $file[1]));
  1732.                         }
  1733.                     }
  1734.                     $templ &$this->newSmarty();
  1735.                     $templ->assign('tocsubentries',$templ1->fetch('tocentry.tpl'));
  1736.                     $templ->assign('entry'array(array('paramname' => $type)));
  1737.                     $comp_types .= $templ->fetch('tocentry.tpl');
  1738.                 }
  1739.                 if (!empty($subpackage))
  1740.                 {
  1741.                     $templ &$this->newSmarty();
  1742.                     $templ->assign('tocsubentries',$comp_types);
  1743.                     $templ->assign('entry'array(array('paramname' => $subpackage)));
  1744.                     $comp_subs .= $templ->fetch('tocentry.tpl');
  1745.                 else
  1746.                 {
  1747.                     $comp_subs1 $comp_types;
  1748.                 }
  1749.             }
  1750.             if ($comp_subs1)
  1751.             $templ->assign('tocsubentries',$comp_subs1);
  1752.             if (!empty($comp_subs))
  1753.             $templ->assign('entry'array(array('paramname' => $package'tocsubentries' => $comp_subs)));
  1754.             else
  1755.             $templ->assign('entry'array(array('paramname' => $package)));
  1756.             $comppack .= $templ->fetch('tocentry.tpl');
  1757.         }
  1758.         return $comppack;
  1759.     }
  1760.    
  1761.     function addSourceTOC($name$file$package$subpackage$source false)
  1762.     {
  1763.         $file str_replace($this->base_dir . PATH_DELIMITER''$this->targetDir)
  1764.              . PATH_DELIMITER $file '.html';
  1765.         $file str_replace('\\',PATH_DELIMITER,$file);
  1766.         $file str_replace('//',PATH_DELIMITER,$file);
  1767.         $file str_replace(PATH_DELIMITER,'\\',$file);
  1768.         $sub $source 'Source Code' 'Examples';
  1769.         $this->TOC[$package][$subpackage][$sub][array($name$file);
  1770.     }
  1771.    
  1772.     function addTOC($name,$file,$package,$subpackage,$class false,$tutorial false)
  1773.     {
  1774.         $file str_replace($this->base_dir . PATH_DELIMITER''$this->targetDir . PATH_DELIMITER)
  1775.              . $file '.html';
  1776.         $file str_replace('\\',PATH_DELIMITER,$file);
  1777.         $file str_replace('//',PATH_DELIMITER,$file);
  1778.         $file str_replace(PATH_DELIMITER,'\\',$file);
  1779.         $file str_replace($this->base_dir . '\\'''$file);
  1780.         $sub $class 'Classes' 'Files';
  1781.         if ($tutorial$sub 'Manual';
  1782.         $this->TOC[$package][$subpackage][$sub][array($name,$file);
  1783.     }
  1784.    
  1785.     /**
  1786.      * Add an item to the index.hhk file
  1787.      * @param string $name index entry name
  1788.      * @param string $file filename containing index
  1789.      * @param string $bookmark html anchor of location in file, if any
  1790.      * @param string $group group this entry with a string
  1791.      * @uses $KLinks tracks the index
  1792.      * @author Andrew Eddie <eddieajau@users.sourceforge.net>
  1793.      */
  1794.     function addKLink($name$file$bookmark=''$group='')
  1795.     {
  1796.         $file $file '.html';
  1797.         $file str_replace('\\',PATH_DELIMITER,$file);
  1798.         $file str_replace('//',PATH_DELIMITER,$file);
  1799.         $file str_replace(PATH_DELIMITER,'\\',$file);
  1800. //        debug("added $name, $file, $bookmark, $group ");
  1801.         $link $file;
  1802.         $link .= $bookmark "#$bookmark:'';
  1803.         if ($group{
  1804.             $this->KLinks[$group]['grouplink'$file;
  1805.             $this->KLinks[$group][array($name,$link);
  1806.         }
  1807.         $this->KLinks[array($name,$link);
  1808.     }
  1809.  
  1810.     /**
  1811.      * Get the table of contents for index.hhk
  1812.      * @return string contents of tocentry.tpl generated from $KLinks
  1813.      * @author Andrew Eddie <eddieajau@users.sourceforge.net>
  1814.      */
  1815.     function generateKLinks()
  1816.     {
  1817.         $templ &$this->newSmarty();
  1818.         $templ->assign('entry'array());
  1819.         foreach($this->KLinks as $group=>$link)
  1820.         {
  1821.             if (isset($link['grouplink'])) {
  1822.                 $templg &$this->newSmarty();
  1823.                 $templg->assign('entry'array());
  1824.                 foreach($link as $k=>$sublink)
  1825.                 {
  1826.                     if ($k != 'grouplink'{
  1827.                         $templg->append('entry'array('paramname' => $sublink[0],'outputfile' => $sublink[1]));
  1828.                     }
  1829.                 }
  1830.                 $templ->append('entry'array('paramname' => $group'outputfile' => $link['grouplink']'tocsubentries' => $templg->fetch('tocentry.tpl') ));
  1831.             else {
  1832.                 $templ->append('entry'array('paramname' => $link[0],'outputfile' => $link[1]));
  1833.             }
  1834.         }
  1835.         return $templ->fetch('tocentry.tpl');
  1836.     }
  1837.    
  1838.     /**
  1839.      * Create the phpdoc.hhp, contents.hhc files needed by MS HTML Help Compiler
  1840.      * to create a CHM file
  1841.      *
  1842.      * The output function generates the table of contents (contents.hhc)
  1843.      * and file list (phpdoc.hhp) files used to create a .CHM by the
  1844.      * free MS HTML Help compiler.
  1845.      * {@internal 
  1846.      * Using {@link $hhp_files}, a list of all separate .html files
  1847.      * is created in CHM format, and written to phpdoc.hhp.  This list was
  1848.      * generated by {@link writefile}.
  1849.      *
  1850.      * Next, a call to the table of contents:
  1851.      *
  1852.      * {@source 12 2}
  1853.      *
  1854.      * finishes things off}}}
  1855.      * @todo use to directly call html help compiler hhc.exe
  1856.      * @link http://www.microsoft.com/downloads/release.asp?releaseid=33071
  1857.      * @uses generateTOC() assigns to the toc template variable
  1858.      */
  1859.     function Output()
  1860.     {
  1861.         $templ &$this->newSmarty();
  1862.         $templ->assign('files',$this->hhp_files);
  1863.         $this->setTargetDir($this->base_dir);
  1864.         Converter::writefile('phpdoc.hhp',$templ->fetch('hhp.tpl'));
  1865.         $templ &$this->newSmarty();
  1866.         $templ->assign('toc',$this->generateTOC());
  1867.         Converter::writefile('contents.hhc',$templ->fetch('contents.hhc.tpl'));
  1868.         $templ->assign('klinks',$this->generateKLinks());
  1869.         Converter::writefile('index.hhk',$templ->fetch('index.hhk.tpl'));
  1870.         phpDocumentor_out("NOTE: to create the documentation.chm file, you must now run Microsoft Help Workshop on phpdoc.hhp\n");
  1871.         phpDocumentor_out("To get the free Microsoft Help Workshop, browse to: http://go.microsoft.com/fwlink/?LinkId=14188\n");
  1872.         flush();
  1873.     }
  1874. }
  1875.  
  1876. /**
  1877.  * @access private
  1878.  * @global string name of the package to set as the first package
  1879.  */
  1880. function CHMdefault_pindexcmp($a$b)
  1881. {
  1882.     global $phpDocumentor_DefaultPackageName;
  1883.     if ($a['title'== $phpDocumentor_DefaultPackageNamereturn -1;
  1884.     if ($b['title'== $phpDocumentor_DefaultPackageNamereturn 1;
  1885.     return strnatcasecmp($a['title'],$b['title']);
  1886. }
  1887.  
  1888. /** @access private */
  1889. function CHMdefault_lettersort($a$b)
  1890. {
  1891.     return strnatcasecmp($a['letter'],$b['letter']);
  1892. }
  1893.  
  1894. /** @access private */
  1895. function CHMdefault_outputfilter($src&$smarty)
  1896. {
  1897.     return str_replace('../',$smarty->_tpl_vars['subdir'],$src);
  1898. }
  1899. ?>
    Поддержать сайт на родительском проекте КГБ