1<?php 2/** 3 * Renderer for LaTeX output 4 * Copyright (C) ???? Harry Fuecks, Andreas Gohr, Danjer 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 * 21 * @author Harry Fuecks <hfuecks@gmail.com> 22 * @author Andreas Gohr <andi@splitbrain.org> 23 * @author Danjer <danjer@doudouke.org> 24 * 25 */ 26 27if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 28 29if ( !defined('DOKU_LF') ) { 30 // Some whitespace to help View > Source 31 define ('DOKU_LF',"\n"); 32} 33 34if ( !defined('DOKU_TAB') ) { 35 // Some whitespace to help View > Source 36 define ('DOKU_TAB',"\t"); 37} 38 39require_once DOKU_INC . 'inc/parser/renderer.php'; 40require_once DOKU_INC . 'inc/html.php'; 41 42class Doku_Renderer_latex extends Doku_Renderer { 43 44 var $doc = ''; 45 46 47 var $acronyms = array(); 48 var $smileys = array(); 49 var $badwords = array(); 50 var $entities = array(); 51 var $interwiki = array(); 52 var $state = array(); 53 var $latexentities = array(); 54 var $headers = array(); 55 var $dokulinks = array(); 56 var $smileys_ps = array(); 57 var $interwiki_ps = array(); 58 var $_quote_level = 0; 59 var $_section_level = 0; 60 var $_footnotes = array(); 61 var $_footnote_index = 0; 62 var $_num_titles = 0; 63 var $_current_table_mode = NULL; 64 var $_current_table_args = array(); 65 var $_current_table = array(); 66 var $_current_table_maxcols_size = array(); 67 var $_current_table_cols_size = 0; 68 var $_acronyms_used = array(); 69 var $_tmphandle = NULL; 70 var $_tmp_put = array(); 71 72 function label_document() { //For links 73 if (isset($this->info['current_file_id'])) 74 $cleanid = $this->info['current_file_id']; 75 else 76 $cleanid = noNS(cleanID($this->info['current_id'], TRUE)); 77 $this->putcmd("label{" . md5($cleanid) . "}"); 78 if (isset($this->info['current_file_id'])) 79 $this->putnl("%%Start: " . $cleanid . ' => ' 80 . $this->info['current_file_id']); 81 else 82 $this->putnl("%%Start: " . $cleanid . ' => ' . wikiFN($cleanid)); 83 } 84 85 function getFormat() { 86 return 'latex'; 87 } 88 89 function document_start() { 90 // ob_start(); 91 $this->headers = array(); 92 //msg("Memory Usage doc start: ". memory_get_usage(), -1); 93 //memory managment 94 //$this->_tmphandle = tmpfile(); 95 96 } 97 98 function document_end() { 99 // $this->doc .= ob_get_contents(); 100 //ob_end_clean(); 101 // msg("Memory Usage doc close: ". memory_get_usage(), -1); 102 $this->info['dokulinks'] = $this->dokulinks; 103 if (is_null($this->_tmphandle)) 104 return $this->doc; 105 // if (function_exists('stream_get_contents')) { 106 // $this->doc = stream_get_contents($this->_tmphandle, -1, 0); 107 //} else { 108 // msg("tmpfile mode"); 109 rewind($this->_tmphandle); 110 while (!feof($this->_tmphandle)) 111 $this->doc .= fgets($this->_tmphandle); 112 //} 113 fclose($this->_tmphandle); 114 } 115 116 function header($text, $level) { 117 global $conf; 118 $levels = array( 119 1=>'dokutitlelevelone', 120 2=>'dokutitleleveltwo', 121 3=>'dokutitleleveltree', 122 4=>'dokutitlelevelfour', 123 5=>'dokutitlelevelfive', 124 ); 125 126 if ( isset($levels[$level]) ) { 127 $token = $levels[$level]; 128 } else { 129 $token = $levels[1]; 130 } 131 $text = trim($text); 132 $this->nlputcmdnl("$token{" . $this->_latexEntities($text) . "}"); 133 $cleanid = noNS(cleanID($text, TRUE)); 134 if ($conf['maxtoclevel'] >= $level) { // Don't label too high 135 $this->putcmd("label{" . md5($cleanid) . "}"); //label for links on headers 136 $this->putnl("%% " . $cleanid); 137 } 138 if ($this->_num_titles == 0) { //label for links on document/page 139 $this->label_document(); 140 } 141 $this->_num_titles++; 142 if ($level == 1) {//Reset footnotes used each chapter 143 $this->_acronyms_used = array(); 144 $this->_footnote_index = 0; 145 } 146 } 147 148 function section_open($level) { 149 $this->_section_level = $level; 150 } 151 152 function section_close() { 153 154 } 155 156 function cdata($text) { 157 $this->putent($text); 158 } 159 160 function p_open() { 161 162 } 163 164 function p_close() { 165 $this->put(DOKU_LF.DOKU_LF); 166 } 167 168 function linebreak() { 169 $this->put('\\\\ '); 170 } 171 172 function hr() { 173 $this->nlputcmdnl("dokuhline"); 174 $this->putnl(); 175 } 176 177 function strong_open() { 178 $this->putcmd("dokubold{"); 179 } 180 181 function strong_close() { 182 $this->put('}'); 183 } 184 185 function emphasis_open() { 186 $this->putcmd("dokuitalic{"); 187 } 188 189 function emphasis_close() { 190 $this->put('}'); 191 } 192 193 function underline_open() { 194 $this->putcmd("dokuunderline{"); 195 $this->state['format'] = 1; 196 } 197 198 function underline_close() { 199 $this->state['format'] = 0; 200 $this->put('}'); 201 } 202 203 function monospace_open() { 204 $this->putcmd("dokumonospace{"); 205 $this->state['format'] = 1; 206 } 207 208 function monospace_close() { 209 $this->state['format'] = 0; 210 $this->put('}'); 211 } 212 213 function subscript_open() { 214 $this->putcmd("dokusubscript{"); 215 } 216 217 function subscript_close() { 218 $this->put('}'); 219 } 220 221 function superscript_open() { 222 $this->putcmd("dokusupscript{"); 223 } 224 225 function superscript_close() { 226 $this->put('}'); 227 } 228 229 function deleted_open() { 230 $this->putcmd("dokuoverline{"); 231 } 232 233 function deleted_close() { 234 $this->put('}'); 235 } 236 237 function footnote_open() { 238 $this->_footnote_index++; 239 $this->putcmd("dokufootnote{"); 240 } 241 242 function footnote_close() { 243 $this->put('}'); 244 } 245 246 function footnotemark_open() { 247 $this->putcmd("dokufootmark{"); 248 } 249 250 function footnotemark_close() { 251 $this->put('}'); 252 } 253 254 /** 255 * @TODO Problem here with nested lists 256 */ 257 function listu_open() { 258 $this->nlputcmdnl("begin{itemize}"); //need to overload that 259 } 260 261 function listu_close() { 262 $this->putcmdnl("end{itemize}"); 263 } 264 265 function listo_open() { 266 $this->nlputcmd("begin{enumerate}"); //need to overload that 267 } 268 269 function listo_close() { 270 $this->putcmdnl("end{enumerate}"); 271 } 272 273 function listitem_open($level) { 274 $this->putcmd("dokuitem "); 275 } 276 277 function listitem_close() { 278 $this->putnl(); 279 } 280 281 function listcontent_open() { 282 283 } 284 285 function listcontent_close() { 286 287 } 288 289 function unformatted($text) { 290 $this->cdata($text); 291 } 292 293 function php($text) { 294 $this->code("\n<php>\n$text\n</php>\n", 'php'); //Need to do smth ?!? 295 } 296 297 function html($text) { 298 $this->code("\n<html>\n$text\n</html>\n", 'html'); //Any Ideas ? 299 } 300 301 /** 302 * Indent? 303 */ 304 function preformatted($text) { 305 $this->nlputcmdnl("small"); 306 $this->putcmdnl("begin{verbatimtab}"); //need overload 307 $this->put(wordwrap(str_replace('verbatimtab', 'verbatim', 308 $text), $this->info['wrapcodelength'], "\n")); 309 $this->nlputcmdnl("end{verbatimtab}"); //need overload 310 $this->putcmdnl("normalsize"); 311 } 312 313 function file($text) { 314 $this->preformatted($text); 315 } 316 317 /** 318 * Problem here with nested quotes 319 */ 320 function quote_open() { 321 $this->_quote_level++; 322 $this->putcmd_protect("dokuquoting"); 323 } 324 325 function quote_close() { 326 $this->_quote_level--; 327 if ($this->_quote_level == 0) { 328 $this->putnl(); 329 $this->putnl(); 330 } 331 } 332 333 function code($text, $lang = NULL) { 334 if ( !$lang ) { 335 $this->preformatted($text); 336 } else { 337 switch ($lang) { //Latex syntax hightlight is quite old... 338 case "shell": 339 $lang = "sh"; 340 break; 341 case "bash": 342 $lang = "sh"; 343 break; 344 case "latex": 345 $lang = "TeX"; 346 break; 347 } 348 $this->nlputcmdnl("lstset{language=$lang}"); //need overload 349 $this->putcmd("begin{lstlisting}"); //need overload 350 $this->put(wordwrap($text, $this->info['wrapcodelength'], DOKU_LF)); 351 $this->nlputcmdnl("end{lstlisting}"); //need overload 352 } 353 } 354 355 function acronym($acronym) { 356 $this->put($acronym); 357 if (!isset($this->_acronyms_used[$this->acronyms[$acronym]])) { 358 $this->footnote_open(); 359 $this->putent($this->acronyms[$acronym], 1); 360 $this->footnote_close(); 361 $this->_acronyms_used[$this->acronyms[$acronym]] = $this->_footnote_index; 362 } else { 363 $this->footnotemark_open(); 364 $this->put($this->_acronyms_used[$this->acronyms[$acronym]]); 365 $this->footnotemark_close(); 366 } 367 } 368 369 function smiley($smiley) { 370 if ( array_key_exists($smiley, $this->smileys) ) { 371 $this->putcmd("dokusmiley{"); 372 $this->put(DOKU_INC.'lib/images/smileys/'.$this->smileys[$smiley]); 373 $this->put("}"); 374 } else { 375 $this->put($smiley); 376 } 377 } 378 379 function wordblock($word) { 380 $this->put($word); 381 } 382 383 function entity($entity) { 384 $this->put($this->latexentities[$entity], 1); 385 } 386 387 // 640x480 ($x=640, $y=480) 388 function multiplyentity($x, $y) { 389 if ($this->_current_table_mode == 'table_analyse') { //try think something better 390 $this->cdata($x . "x" . $y); 391 return; 392 } 393 $this->put($x); 394 $this->put("{\\texttimes}", 1); //Need Overload 395 $this->put($y); 396 } 397 398 function singlequoteopening() { 399 $this->put("'"); 400 } 401 402 function singlequoteclosing() { 403 $this->put("'"); 404 } 405 406 function apostrophe() { 407 $this->singlequoteopening(); 408 } 409 410 function doublequoteopening() { 411 $this->put('"'); 412 } 413 414 function doublequoteclosing() { 415 $this->put('"'); 416 } 417 418 // $link like 'SomePage' 419 function camelcaselink($link) { 420 $this->put($link); 421 } 422 423 function locallink($hash, $name = NULL) { 424 global $ID; 425 list($page, $section) = split('#', $hash, 2); 426 // $md5 = md5(cleanID($section, TRUE)); 427 $cleanid = noNS(cleanID($hash, TRUE)); 428 $md5 = md5($cleanid); 429 $name = $this->_getLinkTitle($name, $hash, $isImage); 430 $hash = $this->_headerToLink($hash); 431 array_push($this->dokulinks, array('id' => $hash, 'name' => $name, 'type' => 'local', )); 432 $this->putcmd('hyperref[' . $md5 . ']{'); 433 $this->putent($name); 434 $this->put('}'); 435 // $this->putnl('%% '. $cleanid); 436 } 437 438 439 function internallink($id, $name = NULL, $search=NULL, $returnonly=false) { 440 global $ID; 441 // default name is based on $id as given 442 $default = $this->_simpleTitle($id); 443 // now first resolve and clean up the $id 444 $orgname = $name; 445 resolve_pageid(getNS($ID),$id,$exists); 446 $name = $this->_getLinkTitle($name, $default, $isImage, $id); 447 list($page, $section) = split('#', $id, 2); 448 if (isset($section)) 449 $cleanid = noNS(cleanID($section, TRUE)); 450 else 451 $cleanid = noNS(cleanID($id, TRUE)); 452 453 $md5 = md5($cleanid); 454 array_push($this->dokulinks, array('id' => $id, 'name' => $name, 455 'type' => 'internal', 456 'hash' => $md5)); 457 $hash = NULL; 458 $this->putcmd('hyperref['); 459 // if (is_null($hash)) 460 // $this->put(str_replace('_', ' ', $id)); 461 // else 462 // $this->put(str_replace('_', ' ', $hash)); 463 $this->put($md5); 464 $this->put(']{'); 465 $this->putent($name); 466 $this->put('}'); 467 // $this->putnl('%% '. $cleanid); 468 } 469 470 471 // $link like 'wiki:syntax', $title could be an array (media) 472 function internallink_old($link, $title = NULL) { 473 $this->putent('[['.$link.'|'.$title.']]'); 474 } 475 476 function internallink_xhtml($id, $name = NULL, $search=NULL, $returnonly=false) { 477 global $conf; 478 global $ID; 479 // default name is based on $id as given 480 $default = $this->_simpleTitle($id); 481 // now first resolve and clean up the $id 482 resolve_pageid(getNS($ID),$id,$exists); 483 $name = $this->_getLinkTitle($name, $default, $isImage, $id); 484 if ( !$isImage ) { 485 if ( $exists ) { 486 $class='wikilink1'; 487 // do some recurse 488 } else { 489 $class='wikilink2'; 490 } 491 } else { 492 $class='media'; 493 } 494 495 //keep hash anchor 496 list($id,$hash) = split('#',$id,2); 497 if (isset($hash)) { 498 $this->putcmd('href{' . $id . '#' . $hash . '}{' . $name . '}'); 499 } else { 500 $this->putcmd('hyperlink{' . $id . '}{' . $name . '}'); 501 } 502 } 503 504 // $link is full URL with scheme, $title could be an array (media) 505 function externallink($link, $title = NULL) { 506 $title_org = $title; 507 $title = $this->_getLinkTitle($title, $link, $isImage); 508 if ($isImage) { 509 $this->put($title); 510 } else { 511 if ( $title ) { 512 $this->put($this->_formatLink(array('url' => $link, 513 'title' => $title))); 514 } else { 515 $this->putcmd('url{'.$link.'}'); 516 } 517 } 518 } 519 520 // $link is the original link - probably not much use 521 // $wikiName is an indentifier for the wiki 522 // $wikiUri is the URL fragment to append to some known URL 523 function interwikilink($link, $title = NULL, $wikiName, $wikiUri) { 524 if (is_array($title)) { 525 $url = ''; 526 if ( isset($this->interwiki[$wikiName]) ) { 527 $url = $this->interwiki[$wikiName]; 528 } 529 $title['caption'] = $url.$wikiUri; 530 } 531 $linkname = $this->_getLinkTitle($title, $wikiUri, $isImage); 532 if ( !$isImage ) { 533 $class = preg_replace('/[^_\-a-z0-9]+/i','_',$wikiName); 534 $imagefile = DOKU_INC . 'lib/images/interwiki/' . $class . '.gif'; 535 if (!(isset($this->interwiki_ps[$class]) 536 && @file_exists($this->interwiki_ps[$class])) 537 && @file_exists($imagefile)) { 538 $img = new TexItImage($imagefile); 539 if ($img->is_error) { 540 msg('img error: '. $imagefile, -1); 541 $this->unformatted('img error: '. $imagefile); 542 return ; 543 } 544 $filename = $img->get_output_filename(); 545 $this->interwiki_ps[$class] = $filename; 546 } 547 if (isset($this->interwiki_ps[$class])) { 548 $this->putcmd("includegraphics[height=1em]{"); // need config for that 549 $this->put($this->interwiki_ps[$class], 1); 550 $this->put("}", 1); 551 } 552 } else { 553 $this->put($linkname); //link is an image 554## $this->putcmd('breakup'); 555 return ; 556 } 557 if ( isset($this->interwiki[$wikiName]) ) { 558 $url = $this->interwiki[$wikiName]; 559 $this->put($this->_formatLink(array('url' => $url, 560 'title' => $linkname))); 561 } else { 562 $this->putcmd('url{'); 563 $this->put($link); 564 $this->put('}', 1); 565 } 566 567 } 568 569 // Link to file on users OS, $title could be an array (media) 570 function filelink($link, $title = NULL) { 571 array_push($this->dokulinks, array('id' => $link, 'name' => $title, 'type' => 'filelink')); 572 $this->unformatted('[['.$link.'|'.$title.']]'); 573 } 574 575 // Link to a Windows share, , $title could be an array (media) 576 function windowssharelink($link, $title = NULL) { 577 $this->unformatted('[['.$link.'|'.$title.']]'); 578 } 579 580 function emaillink($address, $title = NULL) { 581 $this->putent($address); 582 } 583 584 // @TODO 585 function internalmedialink ( 586 $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL 587 ) { 588 589 } 590 591 // @TODO 592 function externalmedialink( 593 $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL 594 ) { 595 if ( $title ) { 596 $this->doc .= '{{'.$src.'|'.$title.'}}'; 597 } else { 598 $this->doc .= '{{'.$src.'}}'; 599 } 600 } 601 602 // Need analyse table before choose a table mode 603 604 /** 605 * Renders an RSS feed 606 * 607 * @author Andreas Gohr <andi@splitbrain.org> 608 */ 609 function rss ($url,$params){ 610 global $lang; 611 global $conf; 612 613 require_once(DOKU_INC.'inc/FeedParser.php'); 614 $feed = new FeedParser(); 615 $feed->feed_url($url); 616 617 //disable warning while fetching 618 if (!defined('DOKU_E_LEVEL')) { $elvl = error_reporting(E_ERROR); } 619 $rc = $feed->init(); 620 if (!defined('DOKU_E_LEVEL')) { error_reporting($elvl); } 621 622 //decide on start and end 623 if($params['reverse']){ 624 $mod = -1; 625 $start = $feed->get_item_quantity()-1; 626 $end = $start - ($params['max']); 627 $end = ($end < -1) ? -1 : $end; 628 }else{ 629 $mod = 1; 630 $start = 0; 631 $end = $feed->get_item_quantity(); 632 $end = ($end > $params['max']) ? $params['max'] : $end;; 633 } 634 635 //$this->doc .= '<ul class="rss">'; 636 $this->listu_open(); 637 if($rc){ 638 for ($x = $start; $x != $end; $x += $mod) { 639 $item = $feed->get_item($x); 640 //$this->doc .= '<li><div class="li">'; 641 $this->listitem_open(1); 642 $this->externallink($item->get_permalink(), 643 $item->get_title()); 644 if($params['author']){ 645 $author = $item->get_author(0); 646 if($author){ 647 $name = $author->get_name(); 648 if(!$name) $name = $author->get_email(); 649 if($name) 650 $this->cdata(' '.$lang['by'].' '.$name); 651 //$this->doc .= ' '.$lang['by'].' '.$name; 652 } 653 } 654 if($params['date']){ 655 $this->cdata(' ('.$item->get_date($conf['dformat']).')'); 656 //$this->doc .= ' ('.$item->get_date($conf['dformat']).')'; 657 } 658 if($params['details']){ 659 //$this->doc .= '<div class="detail">'; 660 if($htmlok){ 661 $this->cdata($item->get_description()); 662 }else{ 663 $this->cdata(strip_tags($item->get_description())); 664 } 665 //$this->doc .= '</div>'; 666 } 667 668 //$this->doc .= '</div></li>'; 669 $this->listitem_close(); 670 } 671 }else{ 672 //$this->doc .= '<li><div class="li">'; 673 $this->listitem_open(1); 674 $this->emphasis_open(); 675 //$this->doc .= '<em>'.$lang['rssfailed'].'</em>'; 676 $this->cdata($lang['rssfailed']); 677 $this->emphasis_close(); 678 $this->externallink($url); 679// if($conf['allowdebug']){ 680// $this->doc .= '<!--'.hsc($feed->error).'-->'; 681// } 682 // $this->doc .= '</div></li>'; 683 $this->listitem_close(); 684 } 685 // $this->doc .= '</ul>'; 686 $this->listu_close(); 687 } 688 689 function table_open($maxcols = NULL, $numrows = NULL) { 690 $this->_current_table_mode = 'table_analyse'; 691 $table_mode = $this->_current_table_mode . '_open'; 692 $this->$table_mode($maxcols, $numrows); 693 } 694 695 function table_close() { 696 $table_mode = $this->_current_table_mode . '_close'; 697 $this->$table_mode(); 698 } 699 700 function tablerow_open() { 701 $table_mode = $this->_current_table_mode . 'row_open'; 702 $this->$table_mode(); 703 704 } 705 706 function tablerow_close() { 707 $table_mode = $this->_current_table_mode . 'row_close'; 708 $this->$table_mode(); 709 } 710 711 function tableheader_open($colspan = 1, $align = NULL) { 712 $table_mode = $this->_current_table_mode . 'header_open'; 713 $this->$table_mode($colspan, $align); 714 } 715 716 function tableheader_close() { 717 $table_mode = $this->_current_table_mode . 'header_close'; 718 $this->$table_mode(); 719 } 720 721 function tablecell_open($colspan = 1, $align = NULL) { 722 $table_mode = $this->_current_table_mode . 'cell_open'; 723 $this->$table_mode($colspan, $align); 724 } 725 726 function tablecell_close() { 727 $table_mode = $this->_current_table_mode . 'cell_close'; 728 $this->$table_mode(); 729 } 730 731 function table_analyse_open($maxcols = NULL, $numrows = NULL) { 732 $this->_current_table_args = array($maxcols, $numrows); 733 array_push($this->_current_table, 734 array('type' => '_open', 735 'args' => array($maxcols, $numrows))); 736 } 737 738 function table_analyse_size() { //calculate max aprox size of each cell 739 $longest_row = 0; //and find the longest row 740 $row_len = 0; 741 $cell_len = 0; 742 $cell_word = 0; 743 $cell_text = ''; 744 $i = 0; 745 $j = 0; 746 $maxcols_len = NULL; 747 $maxcols_text = NULL; 748 $maxcols_word = NULL; 749 // msg("Memory Usage Table open: ". memory_get_usage(), -1); 750 foreach ( $this->_current_table as $action ) { 751 if ($action['type'] == 'put') { 752 $row_len += $action['size']; 753 $cell_len += $action['size']; 754 $cell_text .= $action['text']; 755 $cell_word = $action['word_size']; 756 } 757 if ($action['type'] == 'row_open') { 758 $row_len = 0; 759 $i++; 760 } 761 if ($action['type'] == 'row_close') { 762 if ($longest_row < $row_len) 763 $longest_row = $row_len; 764 $row_len = 0; 765 $j = 0; 766 } 767 if ($action['type'] == 'cell_open' || $action['type'] == 'header_open') { 768 $j++; 769 } 770 if ($action['type'] == 'cell_close' || $action['type'] == 'header_close') { 771 if ($maxcols_len[$j] < $cell_len) { 772 $maxcols_len[$j] = $cell_len; 773 $maxcols_word[$j] = $this->biggest_word_size($cell_text); 774 $maxcols_text[$j] = trim($cell_text); 775 } 776 $cell_len = 0; 777 $cell_word = 0; 778 $cell_text = ''; 779 } 780 } 781 // msg("longest row: " . $longest_row); 782 list($maxcols, $numrows) = $this->_current_table_args; 783 $max_i = 0; 784 $max = 0; 785 for ($i = 1; $i <= $maxcols; $i++) { // Make some adjustment 786 if ($max < $maxcols_len[$i]) { 787 $max = $maxcols_len[$i]; 788 $max_i = $i; 789 } 790 } 791 $maxcols_word[$max_i] = NULL; 792 $this->_current_table_maxcols_size = $maxcols_word; 793 return $longest_row; 794 } 795 796 function table_analyse_close() { 797 // choose mode 798 $i = 0; 799 $j = 0; 800 list($maxcols, $numrows) = $this->_current_table_args; 801 $longest_row = $this->table_analyse_size(); 802 $this->_current_table_mode = 'tabular'; 803 // msg("Memory Usage Table close: ". memory_get_usage(), -1); 804 if ($numrows > $this->info['tablemaxrows']) { // need config 805 if ($longest_row < $this->info['tablerowlength']) //need config 806 $this->_current_table_mode = 'supertabular'; 807 else 808 $this->_current_table_mode = 'supertabular_landscape'; 809 } else { 810 if ($longest_row < $this->info['tablerowlength']) { //need config 811 $this->_current_table_mode = 'tabular'; 812 } else { 813 $this->_current_table_mode = 'tabularx'; 814 } 815 } 816 $this->putnl("%% Table analyse:"); 817 $this->putnl("%% Numrows: " . $numrows); 818 $this->putnl("%% Longest row size: " . $longest_row); 819 $this->putnl("%% Choose table mode: " . $this->_current_table_mode); 820 821 foreach ( $this->_current_table as $action ) { //Ouput analysed table 822 if ($action['type'] == 'row_open') 823 $i++; 824 if ($action['type'] == 'cell_open' || $action['type'] == 'header_open') { 825 $j++; 826 $this->_current_table_cols_size = $this->_current_table_maxcols_size[$j]; 827 } 828 if ($action['type'] == 'row_close') 829 $j = 0; 830 if ($action['type'] == 'put') { 831 $this->put($action['text']); 832 unset($action['text']); 833 } else { 834 $table_mode = $this->_current_table_mode . $action['type']; 835 list($arg1, $arg2) = $action['args']; 836 $this->$table_mode($arg1, $arg2); 837 } 838 } 839 //msg("Memory Usage B: ". memory_get_usage(), -1); 840 $table_mode = $this->_current_table_mode . '_close'; 841 $this->$table_mode($arg1, $arg2); 842 $this->_current_table_mode = NULL; 843 $this->_current_table_args = array(); 844 $this->_current_table = array(); 845 $this->_current_table_maxcols_size = array(); 846 $this->_current_table_cols_size = 0; 847 } 848 849 function table_analyserow_open() { 850 array_push($this->_current_table, 851 array('type' => 'row_open', 852 'args' => array())); 853 } 854 855 function table_analyserow_close() { 856 array_push($this->_current_table, 857 array('type' => 'row_close', 858 'args' => array())); 859 } 860 861 function table_analyseheader_open($colspan = 1, $align = NULL) { 862 array_push($this->_current_table, 863 array('type' => 'header_open', 864 'args' => array($colspan, $align))); 865 } 866 867 function table_analyseheader_close() { 868 array_push($this->_current_table, 869 array('type' => 'header_close', 870 'args' => array())); 871 } 872 873 function table_analysecell_open($colspan = 1, $align = NULL) { 874 array_push($this->_current_table, 875 array('type' => 'cell_open', 876 'args' => array($colspan, $align))); 877 } 878 879 function table_analysecell_close() { 880 array_push($this->_current_table, 881 array('type' => 'cell_close', 882 'args' => array())); 883 } 884 885 // Table tabular way 886 function tabular_open($maxcols = NULL, $numrows = NULL) { 887 $this->_current_tab_cols = 0; 888 if ($this->info['usetablefigure']) 889 $this->putcmdnl("begin{figure}[h]"); 890 else 891 $this->putcmdnl("vspace{0.8em}"); 892 $this->putcmd("begin{tabular}"); 893 $this->put("{"); 894 for ($i = 0; $i < $maxcols; $i++) { 895 $this->put("l"); 896 } 897 $this->putnl("}"); 898 } 899 900 function tabular_close() { 901 $this->putcmdnl("hline"); 902 $this->putcmdnl("end{tabular}"); 903 if ($this->info['usetablefigure']) 904 $this->putcmdnl("end{figure}"); 905 else 906 $this->putcmdnl("vspace{0.8em}"); 907 $this->putnl(); //Prevent Break 908 } 909 910 function tabularrow_open() { 911 $this->putcmdnl("hline"); 912 $this->_current_tab_cols = 0; 913 } 914 915 function tabularrow_close() { 916 $this->linebreak(); 917 $this->putnl(); 918 } 919 920 function tabularheader_open($colspan = 1, $align = NULL) { 921 $this->tablecell_open($colspan, $align); 922 $this->putcmd("dokuheadingstyle{"); 923 $this->putcmd("color{dokuheadingcolor}"); 924 } 925 926 function tabularheader_close() { 927 $this->putcmd("normalcolor"); 928 $this->put("}"); 929 $this->tablecell_close(); 930 } 931 932 function tabularcell_open($colspan = 1, $align = NULL) { 933 if ($this->_current_tab_cols) 934 $this->put("&"); 935 if ($colspan > 0) { 936 $this->_current_tab_colspan = 1; 937 $this->putcmd("multicolumn{". $colspan . "}"); 938 $this->put("{"); 939 if ($this->_current_tab_cols == 0) 940 $this->put("|"); 941 switch ($align) { 942 case "right" : 943 $this->put("r"); 944 break; 945 case "left" : 946 $this->put("l"); 947 break; 948 case "center" : 949 $this->put("c"); 950 break; 951 default: 952 $this->put("l"); 953 } 954 $this->put("|}"); 955 $this->put("{"); 956 } 957 $this->_current_tab_cols++; 958 } 959 960 function tabularcell_close() { 961 if ($this->_current_tab_colspan = 1) { 962 $this->_current_tab_colspan = 0; 963 $this->put("}"); 964 } 965 } 966 967 // Table tabularx way 968 969 function tabularx_open($maxcols = NULL, $numrows = NULL) { 970 $this->_current_tab_cols = 0; 971 if ($this->info['usetablefigure']) 972 $this->putcmdnl("begin{figure}[h]"); 973 else 974 $this->putcmdnl("vspace{0.8em}"); 975 $this->putcmd("begin{tabularx}{"); 976 $this->putcmd("dokutabularwidth"); 977 $this->put("}{|"); 978 for ($i = 1; $i <= $maxcols; $i++) { 979 // $this->put("X|"); 980 if (is_null($this->_current_table_maxcols_size[$i]) 981 || $this->_current_table_maxcols_size[$i] == 0 982 || $this->_current_table_maxcols_size[$i] > $this->info['biggesttableword']) 983 $this->put("X|"); 984 else 985 $this->put("p{" . ($this->_current_table_maxcols_size[$i] * 0.80). "em}|"); 986 } 987 $this->put("}"); 988 $this->put("%% "); 989 for ($i = 1; $i <= $maxcols; $i++) { 990 if (is_null($this->_current_table_maxcols_size[$i])) 991 $this->put("X"); 992 else 993 $this->put($this->_current_table_maxcols_size[$i]); 994 $this->put(" | "); 995 } 996 $this->putnl(); 997 } 998 999 function tabularx_close() { 1000 $this->putcmdnl("hline"); 1001 $this->putcmdnl("end{tabularx}"); 1002 if ($this->info['usetablefigure']) 1003 $this->putcmdnl("end{figure}"); 1004 else 1005 $this->putcmdnl("vspace{0.8em}"); 1006 $this->putnl(); //Prevent Break 1007 } 1008 1009 function tabularxrow_open() { 1010 $this->putcmdnl("hline"); 1011 $this->_current_tab_cols = 0; 1012 } 1013 1014 function tabularxrow_close() { 1015 $this->linebreak(); 1016 $this->putnl(); 1017 } 1018 1019 function tabularxheader_open($colspan = 1, $align = NULL) { 1020 $this->tablecell_open($colspan, $align); 1021 $this->putcmd("dokuheadingstyle{"); 1022 $this->putcmd("color{dokuheadingcolor}"); 1023 } 1024 1025 function tabularxheader_close() { 1026 $this->putcmd("normalcolor"); 1027 $this->put("}"); 1028 $this->tablecell_close(); 1029 } 1030 1031 function tabularxcell_open($colspan = 1, $align = NULL) { 1032 if ($this->_current_tab_cols) 1033 $this->put("&"); 1034 if ($colspan > 1) { 1035 $this->_current_tab_colspan = 1; 1036 $this->putcmd("multicolumn{". $colspan . "}"); 1037 $this->put("{"); 1038 if ($this->_current_tab_cols == 0) 1039 $this->put("|"); 1040 switch ($align) { 1041 case "right" : 1042 $this->put("r"); 1043 break; 1044 case "left" : 1045 $this->put("l"); 1046 break; 1047 case "center" : 1048 $this->put("c"); 1049 break; 1050 default: 1051 $this->put("l"); 1052 } 1053 $this->put("|}"); 1054 $this->put("{"); 1055 } else { 1056 $this->put("{"); 1057 } 1058 $this->_current_tab_cols++; 1059 } 1060 1061 function tabularxcell_close() { 1062 if ($this->_current_tab_colspan = 1) { 1063 $this->_current_tab_colspan = 0; 1064 $this->put("}"); 1065 } 1066 } 1067 1068 // Table supertabular way 1069 1070 function supertabular_open($maxcols = NULL, $numrows = NULL) { 1071 $this->_current_tab_cols = 0; 1072 $this->putcmdnl('par'); 1073 $this->putcmd('tablefirsthead{'); 1074 $this->putcmdnl('hline}'); 1075 $this->putcmd('tablehead{'); 1076 $this->putcmd('hline'); 1077 $this->putcmd('multicolumn{'.($maxcols).'}{|l|}{'); 1078 $this->putcmd('dokusupertabularheadbreak{}'); 1079 $this->put('}'); 1080 $this->linebreak(); 1081 $this->nlputcmd('hline'); 1082 $this->putnl('}'); 1083 $this->putcmd('tabletail{'); 1084 $this->putcmd('hline'); 1085 $this->putcmd('multicolumn{'.($maxcols).'}{|r|}{'); 1086 $this->putcmd('dokusupertabulartailbreak{}'); 1087 $this->put('}'); 1088 $this->linebreak(); 1089 $this->nlputcmd('hline'); 1090 $this->putnl('}'); 1091 $this->putcmdnl('tablelasttail{\hline}'); 1092 $this->putcmdnl('par'); 1093 // $this->putcmd('begin{supertabular}{'); 1094 // for ($i = 0; $i < $maxcols; $i++) { 1095 // $this->put('|p{'.((int)(14 / $maxcols * 1000)).'mm}'); 1096 // } // 14 c'est pour une feuille a4 avec les marges... il faut trouver mieux ca sux 1097 // $this->putnl('|}'); 1098 $this->putcmd("begin{supertabular}"); 1099 $this->put("{"); 1100 for ($i = 0; $i < $maxcols; $i++) { 1101 $this->put("l"); 1102 } 1103 $this->putnl("}"); 1104 } 1105 1106 function supertabular_close() { 1107 $this->putcmdnl("hline"); 1108 $this->putcmdnl("end{supertabular}"); 1109 $this->putcmdnl('par'); 1110 $this->putnl(); //Prevent Break 1111 } 1112 1113 function supertabularrow_open() { 1114 $this->putcmdnl("hline"); 1115 $this->_current_tab_cols = 0; 1116 } 1117 1118 function supertabularrow_close() { 1119 $this->linebreak(); 1120 $this->putnl(); 1121 } 1122 1123 function supertabularheader_open($colspan = 1, $align = NULL) { 1124 $this->tablecell_open($colspan, $align); 1125 $this->putcmd("dokuheadingstyle{"); 1126 $this->putcmd("color{dokuheadingcolor}"); 1127 } 1128 1129 function supertabularheader_close() { 1130 $this->putcmd("normalcolor"); 1131 $this->put("}"); 1132 $this->tablecell_close(); 1133 } 1134 1135 function supertabularcell_open($colspan = 1, $align = NULL) { 1136 if ($this->_current_tab_cols) 1137 $this->put("&"); 1138 if ($colspan > 0) { 1139 $this->_current_tab_colspan = 1; 1140 $this->putcmd("multicolumn{". $colspan . "}"); 1141 $this->put("{"); 1142 if ($this->_current_tab_cols == 0) 1143 $this->put("|"); 1144 switch ($align) { 1145 case "right" : 1146 $this->put("r"); 1147 break; 1148 case "left" : 1149 $this->put("l"); 1150 break; 1151 case "center" : 1152 $this->put("c"); 1153 break; 1154 default: 1155 $this->put("l"); 1156 } 1157 $this->put("|}"); 1158 $this->put("{"); 1159 } 1160 $this->_current_tab_cols++; 1161 } 1162 1163 function supertabularcell_close() { 1164 if ($this->_current_tab_colspan = 1) { 1165 $this->_current_tab_colspan = 0; 1166 $this->put("}"); 1167 } 1168 } 1169 1170 1171 // Table supertabular_landscape way 1172 1173 function supertabular_landscape_open($maxcols = NULL, $numrows = NULL) { 1174 $this->putcmdnl("begin{landscape}"); 1175 $this->supertabular_open($maxcols, $numrows); 1176 } 1177 1178 function supertabular_landscape_close() { 1179 $this->putcmdnl("hline"); 1180 $this->putcmdnl("end{supertabular}"); 1181 $this->putcmdnl("end{landscape}"); 1182 } 1183 1184 function supertabular_landscaperow_open() { 1185 $this->supertabularrow_open(); 1186 } 1187 1188 function supertabular_landscaperow_close() { 1189 $this->supertabularrow_close(); 1190 } 1191 1192 function supertabular_landscapeheader_open($colspan = 1, $align = NULL) { 1193 $this->supertabularheader_open($colspan, $align); 1194 } 1195 1196 function supertabular_landscapeheader_close() { 1197 $this->supertabularheader_close(); 1198 } 1199 1200 function supertabular_landscapecell_open($colspan = 1, $align = NULL) { 1201 $this->supertabularcell_open($colspan, $align); 1202 } 1203 1204 function supertabular_landscapecell_close() { 1205 $this->supertabularcell_close(); 1206 } 1207 1208 function mediatops($filename, $title=NULL, $align=NULL, $width=NULL, 1209 $height=NULL, $cache=NULL, $linking=NULL) { 1210 // if ((is_null($align) || $align == 'center') && is_null($title)) { 1211 if ((is_null($align) || $align == 'center') || !is_null($title)) { 1212 return $this->mediatops_old($filename, $title, $align, $width, $height, 1213 $cache, $linking); 1214 } 1215 $img = new TexItImage($filename); 1216 if ($img->is_error) { 1217 $this->unformatted('img '. $filename . '('. $mime . '=>' . $ext . ')'); 1218 return ; 1219 } 1220 $ps_filename = $img->get_output_filename(); 1221 if ($ps_filename == '') { 1222 $this->unformatted('img '. $filename); 1223 return; 1224 } else { 1225 $this->putcmd("begin{wrapfigure}{", -1); 1226 if ($align == "left") 1227 $align = 'l'; 1228 else if ($align == "right") 1229 $align = 'r'; 1230 else if ($align == "center") 1231 $align = 'c'; 1232 else 1233 $align = 'l'; 1234 $this->putnl($align . "}{0pt}", -1); 1235 $this->putcmd("includegraphics", -1); // need config for that 1236 if ($width || $height) { 1237 $this->put("[", -1); 1238 if ($height) 1239 $this->put("height=" . $height. "pt", -1); 1240 if ($width && $height) 1241 $this->put(",", -1); 1242 if ($width) 1243 $this->put("width=" . $width . "pt", -1); 1244 $this->put("]", -1); 1245 } 1246 $this->put("{", -1); 1247 $this->put($img->get_output_filename(), -1); 1248 $this->put("}\n", -1); 1249 if (isset($title)) { 1250 $this->putcmd("caption{", -1); 1251 if (substr($title, 0, 5) == 'http:') 1252 $this->_formatLink(array('url' => $title, 1253 'title' => $title, 1254 'noflush' => 1)); 1255 else 1256 $this->putent($title, -1); 1257 $this->putnl("}", -1); 1258 } 1259 $this->putcmdnl("end{wrapfigure}", -1); 1260 return $this->put_flush(); 1261 } 1262 } 1263 1264 function mediatops_old($filename, $title=NULL, $align=NULL, $width=NULL, 1265 $height=NULL, $cache=NULL, $linking=NULL) { 1266 if (!empty($align) || !empty($title)) { 1267 $this->putcmdnl("begin{figure*}[h]", -1); 1268 if ($align == "left") { 1269 $align = 'flushleft'; 1270 $this->putcmdnl("raggedright", -1); 1271 } 1272 if ($align == "right") { 1273 $align = 'flushright'; 1274 $this->putcmdnl("raggedleft", -1); 1275 } 1276 if ($align == "center") 1277 $this->putcmdnl("centering", -1); 1278 } 1279 $this->putcmd("includegraphics", -1); // need config for that 1280 if ($width || $height) { 1281 $this->put("[", -1); 1282 if ($height) 1283 $this->put("height=" . $height. "pt", -1); 1284 if ($width && $height) 1285 $this->put(",", -1); 1286 if ($width) 1287 $this->put("width=" . $width . "pt", -1); 1288 $this->put("]", -1); 1289 } 1290 $this->put("{", -1); 1291 $this->put($filename, -1); 1292 $this->put("}\n", -1); 1293 if (!empty($title)) { 1294 $this->putcmd("caption{", -1); 1295 if (substr($title, 0, 5) == 'http:') 1296 $this->_formatLink(array('url' => $title, 1297 'title' => $title, 1298 'noflush' => 1)); 1299 else 1300 $this->putent($title, -1); 1301 $this->putnl("}", -1); 1302 } 1303 if (!empty($align) || !empty($title)) { 1304 // if ($align != 'center') { 1305// $this->putcmdnl("end{" . $align. "}", -1); 1306// $this->putcmdnl("hfill", -1); 1307// } 1308 $this->putcmdnl("end{figure*}", -1); 1309 } 1310 return $this->put_flush(); 1311 } 1312 1313 function internalmedia ($src, $title=NULL, $align=NULL, $width=NULL, 1314 $height=NULL, $cache=NULL, $linking=NULL) { 1315 global $conf; 1316 global $ID; 1317 $filename = mediaFN($src); 1318 resolve_mediaid(getNS($ID),$src, $exists); 1319 list($ext,$mime) = mimetype($src); 1320 if(substr($mime,0,5) == 'image') { 1321 $img = $this->mediatops($filename, $title, $align, $width, 1322 $height, $cache, $linking); 1323 $this->put($img); 1324 return; 1325 } 1326 if ($title == NULL) 1327 $title = basename($filename); 1328 array_push($this->dokulinks, array('id' => $filename , 'name' => $title, 'type' => 'file')); 1329 $this->putcmd('hyperref['); 1330 $this->put(md5($filename)); 1331 $this->put(']{'); 1332 $this->putent($title); 1333 $this->put('}'); 1334 // $this->unformatted('unkown '. $filename . '('. $mime . '=>' . $ext . ')'); 1335 } 1336 1337 /** 1338 * Returns the wanted cachetime in seconds 1339 * 1340 * Resolves named constants 1341 * 1342 * @author Andreas Gohr <andi@splitbrain.org> 1343 */ 1344 function calc_cache($cache) { 1345 global $conf; 1346 1347 if(strtolower($cache) == 'nocache') return 0; //never cache 1348 if(strtolower($cache) == 'recache') return $conf['cachetime']; //use standard cache 1349 return -1; //cache endless 1350 } 1351 1352 /** 1353 * Download a remote file and return local filename 1354 * 1355 * returns false if download fails. Uses cached file if available and 1356 * wanted 1357 * 1358 * @author Andreas Gohr <andi@splitbrain.org> 1359 * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 1360 */ 1361 function get_from_URL($url,$ext,$cache) { 1362 global $conf; 1363 1364 $local = getCacheName(strtolower($url),".media.$ext"); 1365 $mtime = @filemtime($local); // 0 if not exists 1366 1367 //decide if download needed: 1368 if( $cache == 0 || // never cache 1369 ($mtime != 0 && $cache != -1) || // exists but no endless cache 1370 ($mtime == 0) || // not exists 1371 ($cache != -1 && $mtime < time()-$cache) // expired 1372 ) { 1373 if(io_download($url,$local)) { 1374 return $local; 1375 }else{ 1376 return false; 1377 } 1378 } 1379 1380 //if cache exists use it else 1381 if($mtime) return $local; 1382 1383 //else return false 1384 return false; 1385 } 1386 1387 1388 /** 1389 * @todo don't add link for flash 1390 */ 1391 function externalmedia ($src, $title=NULL, $align=NULL, $width=NULL, 1392 $height=NULL, $cache=NULL, $linking=NULL) { 1393 global $conf; 1394 1395 list($ext,$mime) = mimetype($src); 1396 if(substr($mime,0,5) == 'image') { 1397 $filename = $this->get_from_URL($src,$ext,$this->calc_cache($cache)); 1398 if(!$filename) { 1399 //download failed - redirect to original URL 1400 //make default images. 1401 $this->unformatted('externalmedia dnl error: ' . $src . ' ext: ' . $ext. ' cache: '. $cache); 1402 } else { 1403 $img = $this->mediatops($filename, $title, $align, $width, 1404 $height, $cache, $linking); 1405 $this->put($img); 1406 } 1407 return; 1408 }else{ 1409 // add file icons 1410 $this->unformatted('externalmedia ' . $src); 1411 } 1412 1413 //output formatted 1414 if ($linking == 'nolink' || $noLink) $this->doc .= $link['name']; 1415 else $this->doc .= $this->_formatLink($link); 1416 } 1417 1418 1419 /** 1420 * Construct a title and handle images in titles 1421 * 1422 * @author Harry Fuecks <hfuecks@gmail.com> 1423 */ 1424 1425 function _getLinkTitle($title, $default, & $isImage, $id=NULL) { 1426 global $conf; 1427 1428 $isImage = false; 1429 if ( is_null($title) ) { 1430 if ($conf['useheading'] && $id) { 1431 $heading = p_get_first_heading($id); 1432 if ($heading) { 1433 return $this->_latexEntities($heading); 1434 } 1435 } 1436 return $this->_latexEntities($default); 1437 } else if ( is_string($title) ) { 1438 return $this->_latexEntities($title); 1439 } else if ( is_array($title) ) { 1440 $isImage = true; 1441 if (isset($title['caption'])) { 1442 $title['title'] = $title['caption']; 1443 } else { 1444 $title['title'] = $default; 1445 } 1446 $title['align'] = 'center'; 1447 return $this->_imageTitle($title); 1448 } 1449 } 1450 1451 function _xmlEntities($string) { 1452 return htmlspecialchars($string); 1453 } 1454 1455 function _latexEntities($string,$ent=NULL) { 1456 static $doku_ent = NULL; 1457 static $latex_ent = NULL; 1458 if (is_null($ent)) { 1459 $ent = $this->latexentities; 1460 } 1461 if ($doku_ent == NULL && $latex_ent == NULL && is_array($ent)) { 1462 $doku_ent = array_keys($ent); 1463 $latex_ent = array_values($ent); 1464 } 1465 return str_replace($doku_ent, $latex_ent, $string); 1466 } 1467 1468 1469 1470 /** 1471 * Creates a linkid from a headline 1472 * 1473 * @param string $title The headline title 1474 * @param boolean $create Create a new unique ID? 1475 * @author Andreas Gohr <andi@splitbrain.org> 1476 */ 1477 function _headerToLink($title,$create=false) { 1478 $title = str_replace(':','',cleanID($title,true)); //force ASCII 1479 $title = ltrim($title,'0123456789._-'); 1480 if(empty($title)) $title='section'; 1481 1482 if($create) { 1483 // make sure tiles are unique 1484 $num = ''; 1485 while(in_array($title.$num,$this->headers)) { 1486 ($num) ? $num++ : $num = 1; 1487 } 1488 $title = $title.$num; 1489 $this->headers[] = $title; 1490 } 1491 1492 return $title; 1493 } 1494 1495 1496 /** 1497 * Renders internal and external media 1498 * 1499 * @author Andreas Gohr <andi@splitbrain.org> 1500 */ 1501 function _media_test ($src, $title=NULL, $align=NULL, $width=NULL, 1502 $height=NULL, $cache=NULL) { 1503 1504 $ret = ''; 1505 list($ext,$mime) = mimetype($src); 1506 if(substr($mime,0,5) == 'image') { 1507 //add image tag 1508 $ret .= ml($src,array('w'=>$width,'h'=>$height,'cache'=>$cache)); 1509 } elseif(!is_null($title)) { 1510 // well at least we have a title to display 1511 $ret .= $this->_xmlEntities($title); 1512 } else { 1513 // just show the sourcename 1514 $ret .= $this->_xmlEntities(noNS($src)); 1515 } 1516 return $ret; 1517 } 1518 1519 function _media($src, $title=NULL, $align=NULL, $width=NULL, 1520 $height=NULL, $cache=NULL) { 1521 1522 $ret = ''; 1523 list($ext,$mime) = mimetype($src); 1524 if(substr($mime,0,5) == 'image') { 1525 $filename = mediaFN($src); 1526 if (!file_exists($filename)) { 1527 $filename = $this->get_from_URL($src,$ext,$this->calc_cache($cache)); 1528 if(!$filename) { 1529 $this->unformatted('externalmedia dnl error: ' . $src . ' ext: ' . $ext. ' cache: '. $cache); 1530 } 1531 } 1532 $ret .= $this->mediatops_old($filename, $title, $align, $width, 1533 $height, $cache, $linking); 1534 1535 //$ret .= '\\hyperimage{'; 1536 //$ret .= ml($src,array('w'=>$width,'h'=>$height,'cache'=>$cache), true, '&', true); 1537 //$ret .= '}'; 1538 1539 }elseif($mime == 'application/x-shockwave-flash') { 1540 $ret .= ''; 1541 1542 }elseif(!is_null($title)) { 1543 // well at least we have a title to display 1544 $ret .= $this->_latexEntities($title); 1545 }else{ 1546 // just show the sourcename 1547 $ret .= $this->latexEntities(noNS($src)); 1548 } 1549 1550 return $ret; 1551 } 1552 1553 1554 function _media_xhtml ($src, $title=NULL, $align=NULL, $width=NULL, 1555 $height=NULL, $cache=NULL) { 1556 1557 $ret = ''; 1558 1559 list($ext,$mime) = mimetype($src); 1560 if(substr($mime,0,5) == 'image') { 1561 //add image tag 1562 $ret .= '<img src="'.ml($src,array('w'=>$width,'h'=>$height,'cache'=>$cache)).'"'; 1563 $ret .= ' class="media'.$align.'"'; 1564 1565 if (!is_null($title)) { 1566 $ret .= ' title="'.$this->_xmlEntities($title).'"'; 1567 $ret .= ' alt="'.$this->_xmlEntities($title).'"'; 1568 }elseif($ext == 'jpg' || $ext == 'jpeg') { 1569 //try to use the caption from IPTC/EXIF 1570 require_once(DOKU_INC.'inc/JpegMeta.php'); 1571 $jpeg =& new JpegMeta(mediaFN($src)); 1572 if($jpeg !== false) $cap = $jpeg->getTitle(); 1573 if($cap) { 1574 $ret .= ' title="'.$this->_xmlEntities($cap).'"'; 1575 $ret .= ' alt="'.$this->_xmlEntities($cap).'"'; 1576 } 1577 }else{ 1578 $ret .= ' alt=""'; 1579 } 1580 1581 if ( !is_null($width) ) 1582 $ret .= ' width="'.$this->_xmlEntities($width).'"'; 1583 1584 if ( !is_null($height) ) 1585 $ret .= ' height="'.$this->_xmlEntities($height).'"'; 1586 1587 $ret .= ' />'; 1588 1589 }elseif($mime == 'application/x-shockwave-flash') { 1590 $ret .= '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'. 1591 ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"'; 1592 if ( !is_null($width) ) $ret .= ' width="'.$this->_xmlEntities($width).'"'; 1593 if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"'; 1594 $ret .= '>'.DOKU_LF; 1595 $ret .= '<param name="movie" value="'.ml($src).'" />'.DOKU_LF; 1596 $ret .= '<param name="quality" value="high" />'.DOKU_LF; 1597 $ret .= '<embed src="'.ml($src).'"'. 1598 ' quality="high"'; 1599 if ( !is_null($width) ) $ret .= ' width="'.$this->_xmlEntities($width).'"'; 1600 if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"'; 1601 $ret .= ' type="application/x-shockwave-flash"'. 1602 ' pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>'.DOKU_LF; 1603 $ret .= '</object>'.DOKU_LF; 1604 1605 }elseif(!is_null($title)) { 1606 // well at least we have a title to display 1607 $ret .= $this->_xmlEntities($title); 1608 }else{ 1609 // just show the sourcename 1610 $ret .= $this->_xmlEntities(noNS($src)); 1611 } 1612 1613 return $ret; 1614 } 1615 1616 1617 /** 1618 * Build a link 1619 * 1620 * Assembles all parts defined in $link returns HTML for the link 1621 * 1622 * @author Andreas Gohr <andi@splitbrain.org> 1623 */ 1624 function _formatLink_xhtml($link) { 1625 //make sure the url is XHTML compliant (skip mailto) 1626 if(substr($link['url'],0,7) != 'mailto:') { 1627 $link['url'] = str_replace('&','&',$link['url']); 1628 $link['url'] = str_replace('&amp;','&',$link['url']); 1629 } 1630 //remove double encodings in titles 1631 $link['title'] = str_replace('&amp;','&',$link['title']); 1632 1633 // be sure there are no bad chars in url or title 1634 // (we can't do this for name because it can contain an img tag) 1635 $link['url'] = strtr($link['url'],array('>'=>'%3E','<'=>'%3C','"'=>'%22')); 1636 $link['title'] = strtr($link['title'],array('>'=>'>','<'=>'<','"'=>'"')); 1637 1638 $ret = ''; 1639 $ret .= $link['pre']; 1640 $ret .= '<a href="'.$link['url'].'"'; 1641 if($link['class']) $ret .= ' class="'.$link['class'].'"'; 1642 if($link['target']) $ret .= ' target="'.$link['target'].'"'; 1643 if($link['title']) $ret .= ' title="'.$link['title'].'"'; 1644 if($link['style']) $ret .= ' style="'.$link['style'].'"'; 1645 if($link['more']) $ret .= ' '.$link['more']; 1646 $ret .= '>'; 1647 $ret .= $link['name']; 1648 $ret .= '</a>'; 1649 $ret .= $link['suf']; 1650 return $ret; 1651 } 1652 1653 function _formatLink($link) { 1654 //make sure the url is XHTML compliant (skip mailto) 1655 if(substr($link['url'],0,7) != 'mailto:') { 1656 1657 } 1658 1659 $link['url'] = str_replace('#','\#',$link['url']); 1660 1661 $this->putcmd('href{'.$link['url'].'}', -1); 1662 if (isset($link['title'])) { 1663 $this->put('{', -1); 1664 $this->putent($link['title'], -1); 1665 $this->put('}', -1); 1666 } 1667 1668 if (isset($link['noflush']) && $link['noflush'] == 1) 1669 return; 1670 return $this->put_flush(); 1671 } 1672 1673 1674 /** 1675 * Returns an HTML code for images used in link titles 1676 * 1677 * @todo Resolve namespace on internal images 1678 * @author Andreas Gohr <andi@splitbrain.org> 1679 */ 1680 function _imageTitle($img) { 1681 return $this->_media($img['src'], 1682 $img['title'], 1683 $img['align'], 1684 $img['width'], 1685 $img['height'], 1686 $img['cache']); 1687 } 1688 1689 function _simpleTitle($name) { 1690 global $conf; 1691 1692 if($conf['useslash']) { 1693 $nssep = '[:;/]'; 1694 }else{ 1695 $nssep = '[:;]'; 1696 } 1697 $name = preg_replace('!.*'.$nssep.'!','',$name); 1698 //if there is a hash we use the ancor name only 1699 $name = preg_replace('!.*#!','',$name); 1700 return $name; 1701 } 1702 1703 1704 //latex utils 1705 1706 function biggest_word_size($str) { 1707 $m = strlen($str) / 2; 1708 $a = 1; 1709 while ($a < $m) { 1710 $str = str_replace(" "," ",$str); 1711 $a++; 1712 } 1713 $b = explode(" ", $str); 1714 $max = 0; 1715 foreach ($b as $w) { 1716 $len = strlen($w); 1717 if ($max < $len) 1718 $max = $len; 1719 } 1720 return $max; 1721 } 1722 1723 function put_flush() { 1724 $ret = join('', $this->_tmp_put); 1725 $this->_tmp_put = array(); 1726 return $ret; 1727 } 1728 1729 function put($text, $mode=0) { 1730 if ($mode == -1) { 1731 array_push($this->_tmp_put, $text); 1732 return ; 1733 } 1734 if ($this->_current_table_mode == 'table_analyse') { 1735 array_push($this->_current_table, 1736 array('type' => 'put', 1737 'text' => $text, 1738 'size' => $mode == 0 ? strlen($text) : $mode 1739 )); 1740 return; 1741 } 1742 if (is_null($this->_tmphandle)) 1743 $this->doc .= $text; 1744 else 1745 fwrite($this->_tmphandle, $text); 1746 } 1747 function putent($text, $mode=0) { 1748 if ($mode != -1) 1749 $mode = strlen($text); 1750 return $this->put($this->_latexEntities($text), $mode); 1751 } 1752 function putcmd($cmd, $mode=1) { 1753 return $this->put('\\' . $cmd, $mode); 1754 } 1755 function putcmd_protect($cmd, $mode=1) { 1756 return $this->put('{\\' . $cmd . '}', $mode); 1757 } 1758 function putcmdnl($cmd, $mode=1) { 1759 $this->putcmd($cmd . DOKU_LF, $mode); 1760 } 1761 function nlputcmdnl($cmd) { 1762 $this->putnl(); 1763 $this->putcmd($cmd . DOKU_LF); 1764 } 1765 function nlputcmd($cmd) { 1766 $this->putnl(); 1767 $this->putcmd($cmd); 1768 } 1769 function putnl($text = NULL, $mode = 0) { 1770 if (!is_null($text)) { 1771 $this->put($text, $mode); 1772 } 1773 $this->put(DOKU_LF, $mode); 1774 } 1775 function putmathcmd($cmd) { 1776 $this->put('$'. $cmd . '$'); 1777 } 1778 function putverb($text) { 1779 if ($this->state['format'] == 0) 1780 $this->putcmd("begin{verbatim}"); 1781 $this->put($text); 1782 if ($this->state['format'] == 0) 1783 $this->putcmd("end{verbatim}"); 1784 } 1785 1786 function add_command($text) { 1787 $this->info['command_hook'] .= $text; 1788 } 1789 1790 function add_footer($text) { 1791 $this->info['footer_hook'] .= $text; 1792 } 1793 1794 function get_info() { 1795 return $this->info; 1796 } 1797 1798 function get_clevel() { // for include plugins. 1799 return $this->_section_level; 1800 } 1801 1802} 1803 1804 1805