1<?php
2/**
3 * texit Rendering Class
4 * Copyright (C) 2006   Danjer <danjer@doudouke.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 * --------------------------------------------------------------------
20 * @author Danjer <danjer@doudouke.org>
21 * @version v0.2
22 * @package TeXitrender
23 *
24 */
25
26if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
27if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
28if(!defined('PLUGIN_TEXIT')) define('PLUGIN_TEXIT',DOKU_PLUGIN.'texit/');
29require_once(PLUGIN_TEXIT.'config.php');
30require_once(PLUGIN_TEXIT.'latex.php');
31
32class texitrender_plugin_texit {
33  // =======================================================================
34  // Variable Definitions
35  // =======================================================================
36  var $_inputs = NULL;
37  var $_texit_conf;
38  var $_p_get_count = 0;
39  var $_p_get_parsermodes = null;
40  var $_Parser = null;
41  var $doc_infos;
42  var $texit;
43  /**
44   * Initializes the class
45   *
46   * @param $texit_obj : a texit object (defined in config.php)
47   */
48  //function texitrender_plugin_texit($pageid = NULL) {
49  function __construct($texit_obj) {
50    $this->texit = $texit_obj;
51    $this->_pageid = cleanID($pageid);
52    $this->_doku_file = wikiFN($this->_pageid);
53    $this->_texit_conf = &$this->texit->conf;
54  }
55
56  /**
57   * Main public function:
58   *
59   * @param $id    : the id of the page
60   * @param $basefn: the base page filename
61   * @param $destfn: the destination (tex) filename
62   */
63  function process($basefn, $destfn) {
64    // an array with several fields set during document analyzing,
65    // useful for rendering.
66    // doc_infos is document dependant, so we reinitalize it with default values
67    // at each call
68    // filling with default values:
69    $doc_infos = array(
70      'usetablefigure'   => 'off',
71      'tablerowlength'   => 80,
72      'tablemaxrows'     => 30,
73      'wrapcodelength'   => 100,
74      'biggesttableword' => 15,
75      );
76    // TODO: recursion doesn't work with that code (I should use p_locale_latex instead)
77    $text = file_get_contents($basefn) or die("can't open file $basefn for reading");
78    $parsed = $this->p_render_latex_text($text, $info);
79    file_put_contents($destfn, $parsed) or die("can't open file $destfn for writing");
80  }
81
82  // ========================================================================
83  // public functions
84  // ========================================================================
85
86  function add_inputs($data) {
87    if (is_null($this->_inputs)) {
88      $this->_inputs = $data;
89    } else {
90      $this->_inputs .= $data;
91    }
92  }
93
94  function render_inputs() {
95    if (is_null($this->_inputs))
96      return '';
97    return $this->_inputs;
98  }
99
100  function add_data($state, $data) {
101    $array = preg_split("/\r?\n/", trim($data));
102    $this->remove_outfile();
103    if (!is_array($this->_data[$state])) {
104      $this->_data[$state] = $array;
105      return true;
106    }
107    array_push($this->_data[$state], $array);
108    return false;
109  }
110
111  // =========================================================================
112  // private method
113  // =========================================================================
114
115  function generate_tex() {
116    $error = 0;
117    $begin = new texitConfig('begin');
118    $cmd = new texitConfig('command');
119    $doc = new texitConfig('document');
120    $foot = new texitConfig('footer');
121    $begin_doc = $begin->read();
122    if ($begin->is_error())
123      $error = 1;
124    $cmd_doc .= $cmd->read();
125    if ($cmd->is_error())
126      $error = 1;
127    if (!$error) {
128      $info_doc .= $this->generate_latex_info();
129    }
130    $tex_doc[] = $doc->read();
131    if ($doc->is_error())
132      $error = 1;
133    if (!$error) {
134      $latex = $this->p_locale_latex();
135      foreach ($latex as $part) {
136        array_push($tex_doc, $part);
137      }
138    }
139
140  }
141
142
143
144  function p_get_instructions(&$text){
145    // Dokuwiki Get instruction
146    // Original parser use
147    //    return p_get_instructions($text);
148
149    // texit Get instruction with low memory usage
150    // Use only one parser object and little bit faster
151    return $this->p_get_instructions_texit($text);
152  }
153
154
155/**
156 * turns a page into a list of instructions
157 *
158 * @author Harry Fuecks <hfuecks@gmail.com>
159 * @author Andreas Gohr <andi@splitbrain.org>
160 */
161  function p_get_instructions_texit(&$text){
162    if (is_null($this->_p_get_parsermodes)) {
163      $this->_p_get_parsermodes = p_get_parsermodes();
164      //add modes to parser
165    }
166    if (is_null($this->_Parser)) {
167      $this->_Parser = & new Doku_Parser();
168    }
169    // TODO: this leaves room for optimization, as the same
170    // handler could be used several times instead of being
171    // reinstanciated (as is the case now). The problem is
172    // that there is no reset() function on handlers and all
173    // attempts to do it by hand failes... patch welcome!
174    $this->_Parser->Handler = new Doku_Handler();
175    if (count($this->_Parser->modes) == 0) {
176      foreach($this->_p_get_parsermodes as $mode){
177        $this->_Parser->addMode($mode['mode'],$mode['obj']);
178      }
179    }
180    $p = $this->_Parser->parse($text);
181    return $p;
182  }
183
184  function p_render_latex_text(& $text, & $info){
185//     error_log("p_get_instructions[start]:" . $this->_p_get_count);
186    $ins = $this->p_get_instructions($text);
187
188    unset($text);
189    $parsed = $this->p_render('latex', $ins, $info);
190//     error_log("p_get_instructions[end]:" . $this->_p_get_count++);
191    $ins = null;
192    return $parsed;
193  }
194
195  function p_render_latex($id, & $info){
196    $info['current_id'] = $id;
197    $filename = wikiFN($id);
198    if (!file_exists($filename)) {
199      msg("$filename: Not exists", -1);
200    }
201    if (!is_readable($filename)) {
202      msg("$filename: Can't read", -1);
203    }
204    $text = rawWiki($id);
205    $parsed = $this->p_render_latex_text($text, $info);
206    return $parsed;
207  }
208
209  function p_locale_latex($id=NULL){
210    $latex = array();
211    $do_recurse = 0;
212    $do_recurse_file = 0;
213    if (is_null($id)) {
214      $id = $this->_pageid;
215    }
216    //fetch parsed locale
217    $latex[] = $this->p_render_latex($id, $this->doc_info);
218    //    msg("Memory Sub Usage First: ". memory_get_usage(), -1);
219    if ($this->_texit_conf['recurse'] == "on"
220    || $this->_texit_conf['recurse'] == "appendix"
221    || $this->_texit_conf['recurse'] == "chapter")
222      $do_recurse = 1;
223    if ($this->_texit_conf['recurse_file'] == "on")
224      $do_recurse_file = 1;
225    if ($do_recurse || $do_recurse_file) {
226      if ($this->_texit_conf['recurse'] != "chapter")
227    $latex[] = "\n\\appendix\n";
228      if (is_array($info['dokulinks']) ) {
229        $hash = NULL;
230        foreach ( $info['dokulinks'] as $link ) {
231          if (!isset($hash[$link['id']]) && $link['id'] != $id) {
232            if ($do_recurse
233            && ($link['type'] == 'local' || $link['type'] == 'internal')
234            && @file_exists(wikiFN($link['id']))) {
235              $subinfo = $this->doc_info;
236              error_log("render_link " . $link['id']);
237              $latex[] = $this->p_render_latex($link['id'], $subinfo);
238              error_log("render_end " . $link['id']);
239            }
240            if ($do_recurse_file && $link['type'] == 'file'
241            && @file_exists($link['id'])) {
242              $subinfo = $this->doc_info;
243              $subinfo['current_file_id'] = $link['id'];
244              $text = '====== ' . $link['name'] . "======\n";
245              $text .= "<file>\n";
246              $text .= io_readFile($link['id']);
247              $text .= "</file>\n";
248              $latex[] = $this->p_render_latex_text($text, $subinfo);
249            }
250            $hash[$link['id']] = 1;
251          }
252        }
253      }
254    }
255    return $latex;
256  }
257
258  function p_render($mode,$instructions, &$info){
259    if(is_null($instructions)) return '';
260    //    msg("Memory Usage p_render start: ". memory_get_usage(), -1);
261    //    require_once DOKU_INC."inc/parser/$mode.php";
262    $rclass = "Doku_Renderer_$mode";
263    if ( !class_exists($rclass) ) {
264      trigger_error("Unable to resolve render class $rclass",E_USER_ERROR);
265    }
266    $Renderer = & new $rclass(); #FIXME any way to check for class existance?
267    $Renderer->smileys = getSmileys();
268    $Renderer->entities = getEntities();
269    $Renderer->latexentities = $this->_texit_conf['latexentities'];
270    $Renderer->acronyms = getAcronyms();
271    $Renderer->interwiki = getInterwiki();
272    $Renderer->info = $info;
273
274    // Loop through the instructions
275    foreach ( $instructions as $instruction ) {
276      // Execute the callback against the Renderer
277      call_user_func_array(array(&$Renderer, $instruction[0]),$instruction[1]);
278    }
279    //set info array
280    $info = $Renderer->info;
281    //    msg("Memory Usage p_render end: ". memory_get_usage(), -1);
282    // Return the output
283    return $Renderer->doc;
284  }
285
286/**
287 * Builds a hash from a configfile
288 *
289 * If $lower is set to true all hash keys are converted to
290 * lower case.
291 *
292 * Modified to be able to use # character.
293 *
294 * @author Harry Fuecks <hfuecks@gmail.com>
295 * @author Andreas Gohr <andi@splitbrain.org>
296 */
297  function confToHash($file,$lower=false) {
298    $conf = array();
299    $lines = @file( $file );
300    if ( !$lines ) return $conf;
301
302    foreach ( $lines as $line ) {
303      $line = trim($line);
304      if(empty($line)) continue;
305      $line = preg_split('/\s+/',$line,2);
306      // Build the associative array
307      if($lower){
308    $conf[strtolower($line[0])] = $line[1];
309      }else{
310    $conf[$line[0]] = $line[1];
311      }
312    }
313    return $conf;
314  }
315
316  function buildfilelink($ext, $prefix = '') {
317    $ret['id'] = $prefix . $this->_pageid . '.' . $ext;
318    $ret['file'] = mediaFN($ret['id']);
319    $ret['link'] = ml($ret['id']);
320    return $ret;
321  }
322}
323
324?>
325