Main Page | Directories | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages | Examples

wizard_table.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2004 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00062 $BACK_PATH='';
00063 require ('init.php');
00064 require ('template.php');
00065 $LANG->includeLLFile('EXT:lang/locallang_wizards.xml');
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00084 class SC_wizard_table {
00085 
00086          // Internal, dynamic:
00087    var $doc;               // Document template object
00088    var $content;           // Content accumulation for the module.
00089    var $include_once=array(); // List of files to include.
00090    var $inputStyle=0;         // True, then <input> fields are shown, not textareas.
00091 
00092 
00093       // Internal, static:
00094    var $xmlStorage=0;         // If set, the string version of the content is interpreted/written as XML instead of the original linebased kind. This variable still needs binding to the wizard parameters - but support is ready!
00095    var $colsFieldName='cols'; // Name of field in parent record which MAY contain the number of columns for the table - here hardcoded to the value of tt_content. Should be set by TCEform parameters (from P)
00096 
00097 
00098       // Internal, static: GPvars
00099    var $P;                 // Wizard parameters, coming from TCEforms linking to the wizard.
00100    var $TABLECFG;          // The array which is constantly submitted by the multidimensional form of this wizard.
00101 
00102 
00103 
00104 
00105 
00106 
00112    function init()   {
00113       global $BACK_PATH;
00114 
00115          // GPvars:
00116       $this->P = t3lib_div::_GP('P');
00117       $this->TABLECFG = t3lib_div::_GP('TABLE');
00118 
00119          // Setting options:
00120       $this->xmlStorage = $this->P['params']['xmlOutput'];
00121 
00122          // Textareas or input fields:
00123       $this->inputStyle=isset($this->TABLECFG['textFields']) ? $this->TABLECFG['textFields'] : 1;
00124 
00125          // Document template object:
00126       $this->doc = t3lib_div::makeInstance('mediumDoc');
00127       $this->doc->docType = 'xhtml_trans';
00128       $this->doc->backPath = $BACK_PATH;
00129       $this->doc->JScode=$this->doc->wrapScriptTags('
00130          function jumpToUrl(URL,formEl)   {  //
00131             document.location = URL;
00132          }
00133       ');
00134 
00135          // Setting form tag:
00136       list($rUri) = explode('#',t3lib_div::getIndpEnv('REQUEST_URI'));
00137       $this->doc->form ='<form action="'.htmlspecialchars($rUri).'" method="post" name="wizardForm">';
00138 
00139          // Start page:
00140       $this->content.=$this->doc->startPage('Table');
00141 
00142          // If save command found, include tcemain:
00143       if ($_POST['savedok_x'] || $_POST['saveandclosedok_x'])  {
00144          $this->include_once[]=PATH_t3lib.'class.t3lib_tcemain.php';
00145       }
00146    }
00147 
00153    function main()   {
00154       global $LANG;
00155 
00156       if ($this->P['table'] && $this->P['field'] && $this->P['uid']) {
00157          $this->content.=$this->doc->section($LANG->getLL('table_title'),$this->tableWizard(),0,1);
00158       } else {
00159          $this->content.=$this->doc->section($LANG->getLL('table_title'),'<span class="typo3-red">'.$LANG->getLL('table_noData',1).'</span>',0,1);
00160       }
00161       $this->content.=$this->doc->endPage();
00162    }
00163 
00169    function printContent() {
00170       echo $this->content;
00171    }
00172 
00178    function tableWizard()  {
00179 
00180          // First, check the references by selecting the record:
00181       $row=t3lib_BEfunc::getRecord($this->P['table'],$this->P['uid']);
00182       if (!is_array($row)) {
00183          t3lib_BEfunc::typo3PrintError ('Wizard Error','No reference to record',0);
00184          exit;
00185       }
00186 
00187          // This will get the content of the form configuration code field to us - possibly cleaned up, saved to database etc. if the form has been submitted in the meantime.
00188       $tableCfgArray = $this->getConfigCode($row);
00189 
00190          // Generation of the Table Wizards HTML code:
00191       $content = $this->getTableHTML($tableCfgArray,$row);
00192 
00193          // Return content:
00194       return $content;
00195    }
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203    /***************************
00204     *
00205     * Helper functions
00206     *
00207     ***************************/
00208 
00217    function getConfigCode($row)  {
00218 
00219          // If some data has been submitted, then construct
00220       if (isset($this->TABLECFG['c'])) {
00221 
00222             // Process incoming:
00223          $this->changeFunc();
00224 
00225 
00226             // Convert to string (either line based or XML):
00227          if ($this->xmlStorage)  {
00228                // Convert the input array to XML:
00229             $bodyText = t3lib_div::array2xml($this->TABLECFG['c'],'',0,'T3TableWizard');
00230 
00231                // Setting cfgArr directly from the input:
00232             $cfgArr = $this->TABLECFG['c'];
00233          } else {
00234                // Convert the input array to a string of configuration code:
00235             $bodyText = $this->cfgArray2CfgString($this->TABLECFG['c']);
00236 
00237                // Create cfgArr from the string based configuration - that way it is cleaned up and any incompatibilities will be removed!
00238             $cfgArr = $this->cfgString2CfgArray($bodyText,$row[$this->colsFieldName]);
00239          }
00240 
00241             // If a save button has been pressed, then save the new field content:
00242          if ($_POST['savedok_x'] || $_POST['saveandclosedok_x'])  {
00243 
00244                // Make TCEmain object:
00245             $tce = t3lib_div::makeInstance('t3lib_TCEmain');
00246             $tce->stripslashes_values=0;
00247 
00248                // Put content into the data array:
00249             $data=array();
00250             $data[$this->P['table']][$this->P['uid']][$this->P['field']]=$bodyText;
00251 
00252                // Perform the update:
00253             $tce->start($data,array());
00254             $tce->process_datamap();
00255 
00256                // If the save/close button was pressed, then redirect the screen:
00257             if ($_POST['saveandclosedok_x']) {
00258                header('Location: '.t3lib_div::locationHeaderUrl($this->P['returnUrl']));
00259                exit;
00260             }
00261          }
00262       } else { // If nothing has been submitted, load the $bodyText variable from the selected database row:
00263          if ($this->xmlStorage)  {
00264             $cfgArr = t3lib_div::xml2array($row[$this->P['field']]);
00265          } else { // Regular linebased table configuration:
00266             $cfgArr = $this->cfgString2CfgArray($row[$this->P['field']],$row[$this->colsFieldName]);
00267          }
00268          $cfgArr = is_array($cfgArr) ? $cfgArr : array();
00269       }
00270 
00271       return $cfgArr;
00272    }
00273 
00282    function getTableHTML($cfgArr,$row) {
00283       global $LANG;
00284 
00285          // Traverse the rows:
00286       $tRows=array();
00287       $k=0;
00288       foreach($cfgArr as $cellArr)  {
00289          if (is_array($cellArr)) {
00290                // Initialize:
00291             $cells=array();
00292             $a=0;
00293 
00294                // Traverse the columns:
00295             foreach($cellArr as $cellContent)   {
00296                if ($this->inputStyle)  {
00297                   $cells[]='<input type="text"'.$this->doc->formWidth(20).' name="TABLE[c]['.(($k+1)*2).']['.(($a+1)*2).']" value="'.htmlspecialchars($cellContent).'" />';
00298                } else {
00299                   $cellContent=eregi_replace('<br[ ]?[\/]?>',chr(10),$cellContent);
00300                   $cells[]='<textarea '.$this->doc->formWidth(20).' rows="5" name="TABLE[c]['.(($k+1)*2).']['.(($a+1)*2).']">'.t3lib_div::formatForTextarea($cellContent).'</textarea>';
00301                }
00302 
00303                   // Increment counter:
00304                $a++;
00305             }
00306 
00307                // CTRL panel for a table row (move up/down/around):
00308             $onClick="document.wizardForm.action+='#ANC_".(($k+1)*2-2)."';";
00309             $onClick=' onclick="'.htmlspecialchars($onClick).'"';
00310             $ctrl='';
00311 
00312             $brTag=$this->inputStyle?'':'<br />';
00313             if ($k!=0)  {
00314                $ctrl.='<input type="image" name="TABLE[row_up]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/pil2up.gif','').$onClick.' title="'.$LANG->getLL('table_up',1).'" />'.$brTag;
00315             } else {
00316                $ctrl.='<input type="image" name="TABLE[row_bottom]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/turn_up.gif','').$onClick.' title="'.$LANG->getLL('table_bottom',1).'" />'.$brTag;
00317             }
00318             $ctrl.='<input type="image" name="TABLE[row_remove]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/garbage.gif','').$onClick.' title="'.$LANG->getLL('table_removeRow',1).'" />'.$brTag;
00319 
00320             if (($k+1)!=count($tLines))   {
00321                $ctrl.='<input type="image" name="TABLE[row_down]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/pil2down.gif','').$onClick.' title="'.$LANG->getLL('table_down',1).'" />'.$brTag;
00322             } else {
00323                $ctrl.='<input type="image" name="TABLE[row_top]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/turn_down.gif','').$onClick.' title="'.$LANG->getLL('table_top',1).'" />'.$brTag;
00324             }
00325             $ctrl.='<input type="image" name="TABLE[row_add]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/add.gif','').$onClick.' title="'.$LANG->getLL('table_addRow',1).'" />'.$brTag;
00326 
00327             $tRows[]='
00328                <tr class="bgColor4">
00329                   <td class="bgColor5"><a name="ANC_'.(($k+1)*2).'"></a><span class="c-wizButtonsV">'.$ctrl.'</span></td>
00330                   <td>'.implode('</td>
00331                   <td>',$cells).'</td>
00332                </tr>';
00333 
00334                // Increment counter:
00335             $k++;
00336          }
00337       }
00338 
00339          // CTRL panel for a table column (move left/right/around/delete)
00340       $cells=array();
00341       $cells[]='';
00342          // Finding first row:
00343       reset($cfgArr);
00344       $firstRow=current($cfgArr);
00345       if (is_array($firstRow))   {
00346 
00347             // Init:
00348          $a=0;
00349          $cols=count($firstRow);
00350 
00351             // Traverse first row:
00352          foreach($firstRow as $temp)   {
00353             $ctrl='';
00354             if ($a!=0)  {
00355                $ctrl.='<input type="image" name="TABLE[col_left]['.(($a+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/pil2left.gif','').' title="'.$LANG->getLL('table_left',1).'" />';
00356             } else {
00357                $ctrl.='<input type="image" name="TABLE[col_end]['.(($a+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/turn_left.gif','').' title="'.$LANG->getLL('table_end',1).'" />';
00358             }
00359             $ctrl.='<input type="image" name="TABLE[col_remove]['.(($a+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/garbage.gif','').' title="'.$LANG->getLL('table_removeColumn',1).'" />';
00360             if (($a+1)!=$cols)   {
00361                $ctrl.='<input type="image" name="TABLE[col_right]['.(($a+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/pil2right.gif','').' title="'.$LANG->getLL('table_right',1).'" />';
00362             } else {
00363                $ctrl.='<input type="image" name="TABLE[col_start]['.(($a+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/turn_right.gif','').' title="'.$LANG->getLL('table_start',1).'" />';
00364             }
00365             $ctrl.='<input type="image" name="TABLE[col_add]['.(($a+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/add.gif','').' title="'.$LANG->getLL('table_addColumn',1).'" />';
00366             $cells[]='<span class="c-wizButtonsH">'.$ctrl.'</span>';
00367 
00368                // Incr. counter:
00369             $a++;
00370          }
00371          $tRows[]='
00372             <tr class="bgColor5">
00373                <td align="center">'.implode('</td>
00374                <td align="center">',$cells).'</td>
00375             </tr>';
00376       }
00377 
00378       $content = '';
00379 
00380          // Add CSH:
00381       $content.= t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'wizard_table_wiz', $GLOBALS['BACK_PATH'],'');
00382 
00383          // Implode all table rows into a string, wrapped in table tags.
00384       $content.= '
00385 
00386 
00387          <!--
00388             Table wizard
00389          -->
00390          <table border="0" cellpadding="0" cellspacing="1" id="typo3-tablewizard">
00391             '.implode('',$tRows).'
00392          </table>';
00393 
00394          // Add saving buttons in the bottom:
00395       $content.= '
00396 
00397          <!--
00398             Save buttons:
00399          -->
00400          <div id="c-saveButtonPanel">';
00401       $content.= '<input type="image" class="c-inputButton" name="savedok"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/savedok.gif','').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:rm.saveDoc',1).'" />';
00402       $content.= '<input type="image" class="c-inputButton" name="saveandclosedok"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/saveandclosedok.gif','').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:rm.saveCloseDoc',1).'" />';
00403       $content.= '<a href="#" onclick="'.htmlspecialchars('jumpToUrl(unescape(\''.rawurlencode($this->P['returnUrl']).'\')); return false;').'">'.
00404                '<img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/closedok.gif','width="21" height="16"').' class="c-inputButton" title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:rm.closeDoc',1).'" alt="" />'.
00405                '</a>';
00406       $content.= '<input type="image" class="c-inputButton" name="_refresh"'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/refresh_n.gif','').' title="'.$LANG->getLL('forms_refresh',1).'" />';
00407       $content.= t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'wizard_table_wiz_buttons', $GLOBALS['BACK_PATH'],'');
00408       $content.= '
00409          </div>
00410          ';
00411 
00412          // Input type checkbox:
00413       $content.= '
00414 
00415          <!--
00416             Input mode check box:
00417          -->
00418          <div id="c-inputMode">
00419             '.
00420             '<input type="hidden" name="TABLE[textFields]" value="0" />'.
00421             '<input type="checkbox" name="TABLE[textFields]" value="1"'.($this->inputStyle?' checked="checked"':'').' /> '.
00422             $LANG->getLL('table_smallFields').'
00423          </div>
00424 
00425          <br /><br />
00426          ';
00427 
00428          // Return content:
00429       return $content;
00430    }
00431 
00438    function changeFunc()   {
00439       if ($this->TABLECFG['col_remove'])  {
00440          $kk = key($this->TABLECFG['col_remove']);
00441          $cmd='col_remove';
00442       } elseif ($this->TABLECFG['col_add'])  {
00443          $kk = key($this->TABLECFG['col_add']);
00444          $cmd='col_add';
00445       } elseif ($this->TABLECFG['col_start'])   {
00446          $kk = key($this->TABLECFG['col_start']);
00447          $cmd='col_start';
00448       } elseif ($this->TABLECFG['col_end'])  {
00449          $kk = key($this->TABLECFG['col_end']);
00450          $cmd='col_end';
00451       } elseif ($this->TABLECFG['col_left']) {
00452          $kk = key($this->TABLECFG['col_left']);
00453          $cmd='col_left';
00454       } elseif ($this->TABLECFG['col_right'])   {
00455          $kk = key($this->TABLECFG['col_right']);
00456          $cmd='col_right';
00457       } elseif ($this->TABLECFG['row_remove'])  {
00458          $kk = key($this->TABLECFG['row_remove']);
00459          $cmd='row_remove';
00460       } elseif ($this->TABLECFG['row_add'])  {
00461          $kk = key($this->TABLECFG['row_add']);
00462          $cmd='row_add';
00463       } elseif ($this->TABLECFG['row_top'])  {
00464          $kk = key($this->TABLECFG['row_top']);
00465          $cmd='row_top';
00466       } elseif ($this->TABLECFG['row_bottom'])  {
00467          $kk = key($this->TABLECFG['row_bottom']);
00468          $cmd='row_bottom';
00469       } elseif ($this->TABLECFG['row_up'])   {
00470          $kk = key($this->TABLECFG['row_up']);
00471          $cmd='row_up';
00472       } elseif ($this->TABLECFG['row_down']) {
00473          $kk = key($this->TABLECFG['row_down']);
00474          $cmd='row_down';
00475       }
00476 
00477       if ($cmd && t3lib_div::testInt($kk)) {
00478          if (substr($cmd,0,4)=='row_') {
00479             switch($cmd)   {
00480                case 'row_remove':
00481                   unset($this->TABLECFG['c'][$kk]);
00482                break;
00483                case 'row_add':
00484                   $this->TABLECFG['c'][$kk+1]=array();
00485                break;
00486                case 'row_top':
00487                   $this->TABLECFG['c'][1]=$this->TABLECFG['c'][$kk];
00488                   unset($this->TABLECFG['c'][$kk]);
00489                break;
00490                case 'row_bottom':
00491                   $this->TABLECFG['c'][10000000]=$this->TABLECFG['c'][$kk];
00492                   unset($this->TABLECFG['c'][$kk]);
00493                break;
00494                case 'row_up':
00495                   $this->TABLECFG['c'][$kk-3]=$this->TABLECFG['c'][$kk];
00496                   unset($this->TABLECFG['c'][$kk]);
00497                break;
00498                case 'row_down':
00499                   $this->TABLECFG['c'][$kk+3]=$this->TABLECFG['c'][$kk];
00500                   unset($this->TABLECFG['c'][$kk]);
00501                break;
00502             }
00503             ksort($this->TABLECFG['c']);
00504          }
00505          if (substr($cmd,0,4)=='col_') {
00506             reset($this->TABLECFG['c']);
00507             while(list($cAK)=each($this->TABLECFG['c'])) {
00508                switch($cmd)   {
00509                   case 'col_remove':
00510                      unset($this->TABLECFG['c'][$cAK][$kk]);
00511                   break;
00512                   case 'col_add':
00513                      $this->TABLECFG['c'][$cAK][$kk+1]='';
00514                   break;
00515                   case 'col_start':
00516                      $this->TABLECFG['c'][$cAK][1]=$this->TABLECFG['c'][$cAK][$kk];
00517                      unset($this->TABLECFG['c'][$cAK][$kk]);
00518                   break;
00519                   case 'col_end':
00520                      $this->TABLECFG['c'][$cAK][1000000]=$this->TABLECFG['c'][$cAK][$kk];
00521                      unset($this->TABLECFG['c'][$cAK][$kk]);
00522                   break;
00523                   case 'col_left':
00524                      $this->TABLECFG['c'][$cAK][$kk-3]=$this->TABLECFG['c'][$cAK][$kk];
00525                      unset($this->TABLECFG['c'][$cAK][$kk]);
00526                   break;
00527                   case 'col_right':
00528                      $this->TABLECFG['c'][$cAK][$kk+3]=$this->TABLECFG['c'][$cAK][$kk];
00529                      unset($this->TABLECFG['c'][$cAK][$kk]);
00530                   break;
00531                }
00532                ksort($this->TABLECFG['c'][$cAK]);
00533             }
00534          }
00535       }
00536 
00537       // Convert line breaks to <br /> tags:
00538       reset($this->TABLECFG['c']);
00539       while(list($a)=each($this->TABLECFG['c']))   {
00540          reset($this->TABLECFG['c'][$a]);
00541          while(list($b)=each($this->TABLECFG['c'][$a]))  {
00542             $this->TABLECFG['c'][$a][$b] = str_replace(chr(10),'<br />',str_replace(chr(13),'',$this->TABLECFG['c'][$a][$b]));
00543          }
00544       }
00545    }
00546 
00554    function cfgArray2CfgString($cfgArr)   {
00555 
00556          // Initialize:
00557       $inLines=array();
00558 
00559          // Traverse the elements of the table wizard and transform the settings into configuration code.
00560       reset($this->TABLECFG['c']);
00561       while(list($a)=each($this->TABLECFG['c']))   {
00562          $thisLine=array();
00563          reset($this->TABLECFG['c'][$a]);
00564          while(list($b)=each($this->TABLECFG['c'][$a]))  {
00565             $thisLine[]=str_replace('|','',$this->TABLECFG['c'][$a][$b]);
00566          }
00567          $inLines[]=implode('|',$thisLine);
00568       }
00569 
00570          // Finally, implode the lines into a string:
00571       $bodyText = implode(chr(10),$inLines);
00572 
00573          // Return the configuration code:
00574       return $bodyText;
00575    }
00576 
00585    function cfgString2CfgArray($cfgStr,$cols)   {
00586 
00587          // Explode lines in the configuration code - each line is a table row.
00588       $tLines=explode(chr(10),$cfgStr);
00589 
00590          // Setting number of columns
00591       if (!$cols && trim($tLines[0]))  {  // auto...
00592          $cols = count(explode('|',$tLines[0]));
00593       }
00594       $cols=$cols?$cols:4;
00595 
00596          // Traverse the number of table elements:
00597       $cfgArr=array();
00598       foreach($tLines as $k => $v)  {
00599 
00600             // Initialize:
00601          $vParts = explode('|',$v);
00602 
00603             // Traverse columns:
00604          for ($a=0;$a<$cols;$a++)   {
00605             $cfgArr[$k][$a]=$vParts[$a];
00606          }
00607       }
00608 
00609          // Return configuration array:
00610       return $cfgArr;
00611    }
00612 }
00613 
00614 // Include extension?
00615 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/wizard_table.php'])  {
00616    include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/wizard_table.php']);
00617 }
00618 
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 // Make instance:
00631 $SOBE = t3lib_div::makeInstance('SC_wizard_table');
00632 $SOBE->init();
00633 
00634 // Include files?
00635 foreach($SOBE->include_once as $INC_FILE) include_once($INC_FILE);
00636 
00637 $SOBE->main();
00638 $SOBE->printContent();
00639 ?>

Generated on Sun Oct 3 01:06:01 2004 for TYPO3core 3.7.0 dev by  doxygen 1.3.8-20040913