1<?php
2/**
3 * xtermrtf Plugin : like xterm plugin, but with rtf formatting
4 * Syntax:     <xtermrtf> text </xtermrtf>
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     Etienne Mauvais <emauvaisfr@yahoo.fr> based on xterm plugin by Tom Trenker <tom_trenker@yahoo.com>
8 */
9
10if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
12require_once(DOKU_PLUGIN.'syntax.php');
13
14/**
15 * All DokuWiki plugins to extend the parser/rendering mechanism
16 * need to inherit from this class
17 */
18class syntax_plugin_xtermrtf extends DokuWiki_Syntax_Plugin {
19
20    /**
21     * return some info
22     */
23    function getInfo(){
24        return array(
25          'author' => 'Etienne M.',
26          'email'  => 'emauvaisfr@yahoo.fr',
27          'date'   => '2008-10-07',
28          'name'   => 'xtermrtf Plugin',
29          'desc'   => 'Affiche du texte au format RTF sous forme de terminal. Pratique pour reproduire un affichage en couleurs issu de PuTTY. Ce plugin n\'a ete teste qu\'avec du RTF genere par PuTTY (tres basique : pas de tableaux, pas de listes a puces, etc...)
30	               Displays RTF text into a terminal. Good to reproduce color PuTTY display. This plugin has just been tested with RTF paste from PuTTY (very basic: no arrays, no bullet lists, etc...)',
31          'url'    => 'http://www.dokuwiki.org/plugin:xtermrtf',
32        );
33    }
34
35    /**
36     * What kind of syntax are we?
37     */
38    function getType(){
39        return 'disabled';
40    }
41
42    /**
43     * What kind of syntax do we allow (optional)
44     */
45    function getAllowedTypes() {
46        return array('disabled');
47    }
48
49    /**
50     * What about paragraphs? (optional)
51     */
52   function getPType(){
53       return 'normal';
54   }
55
56    /**
57     * Where to sort in?
58     */
59    function getSort(){
60        return 30;
61    }
62
63
64    /**
65     * Connect pattern to lexer
66     */
67    function connectTo($mode) {
68        $this->Lexer->addEntryPattern('\x3Cxtermrtf\x3E(?=.*\x3C/xtermrtf\x3E)',$mode,'plugin_xtermrtf');
69    }
70
71    function postConnect() {
72        $this->Lexer->addExitPattern('\x3C/xtermrtf\x3E', 'plugin_xtermrtf');
73    }
74
75
76    /**
77     * Handle the match
78     */
79    function handle($match, $state, $pos, &$handler){
80        switch ($state) {
81          case DOKU_LEXER_ENTER :
82            break;
83          case DOKU_LEXER_MATCHED :
84            break;
85          case DOKU_LEXER_UNMATCHED :
86            break;
87          case DOKU_LEXER_EXIT :
88            break;
89          case DOKU_LEXER_SPECIAL :
90            break;
91        }
92        return array($match, $state);
93    }
94
95    /**
96     * Create output
97     */
98    function render($mode, &$renderer, $data) {
99        if($mode == 'xhtml'){
100            if ($data[1] == DOKU_LEXER_ENTER){
101                $renderer->doc .= '<pre class="xtermrtf">';       #     <pre><font size=+0>';
102            } else if ($data[1] == DOKU_LEXER_UNMATCHED){
103                //$renderer->doc .= rtf2html($renderer->_xmlEntities($data[0]));
104                $renderer->doc .= rtf2html($data[0]);
105            } else if ($data[1] == DOKU_LEXER_EXIT){
106                $renderer->doc .= '</pre>';   #       '</font></pre>';
107            }
108            return true;
109        }
110        return false;
111    }
112}
113
114
115
116//Conversion du format rtf "de PuTTY" en html
117//Attention : cette fonction n'a ete testee qu'avec des rtf issus de PuTTY. Elle est des plus basiques (ne gere pas les tableaux, les listes a puces, etc...)
118function rtf2html($rtf) {
119  //On recupere la colortbl
120  preg_match("/{\\\colortbl ;(.*?);}/i", $rtf, $colortbl);
121
122  if ($colortbl) {
123    //On recupere les couleurs
124    $couleurs=split(";", $colortbl[1]);
125
126    if ($couleurs) {
127      for ($i=0; $i<sizeof($couleurs); $i++) {
128        preg_match("/.red(.*?).green(.*?).blue(.*?)$/i", $couleurs[$i], $rgb);
129        $r=dechex($rgb[1]);
130        $v=dechex($rgb[2]);
131        $b=dechex($rgb[3]);
132        if (strlen($r)<2) $r="0$r";
133        if (strlen($v)<2) $v="0$v";
134        if (strlen($b)<2) $b="0$b";
135
136        $couleurs[$i]="#$r$v$b";
137      }
138    }
139  }
140
141  //On recupere les donnees "utiles"
142  preg_match("/^[\s\S]*{.colortbl[\s\S]*?}([\s\S]*)}/i",$rtf,$corps);
143
144  $out="<span>";
145  if ($corps) {
146    $corps=$corps[1];
147
148    //On remplace les \'xx par le caractere qui convient
149    $corps=preg_replace("/\\\'(..)/e","chr(hexdec('\\1'))",$corps);
150
151    //On remplace les \\ par *antislash*
152    $corps=preg_replace("/\\\\\\\\/","*antislash*",$corps);
153
154    //On decoupe le corps suivant les \
155    $corps=split("[\\]", $corps);
156
157    $closeSpan=0;
158    $closeFont=0;
159    //On parcourt le corps
160    for ($i=0; $i<sizeof($corps); $i++) {
161      //Si le "mot" est de la forme cf
162      if (preg_match("/^cf(.*)/i",$corps[$i],$val)) {
163        $idx=$val[1]-1;
164        if ($idx==-1) $coul="#BBBBBB";
165        else $coul=$couleurs[$idx];
166        if ($closeFont) $out.="</font>";
167        $out.="<font color=\"$coul\">";
168        $closeFont=1;
169      }
170      //sinon si le "mot" est de la forme highlight
171      else if (preg_match("/^highlight(.*)/i",$corps[$i],$val)) {
172        $idx=$val[1]-1;
173        if ($idx==-1) $coul="#000000";
174        else $coul=$couleurs[$idx];
175        if ($closeSpan) $out.="</span>";
176        $out.="$close<span style=\"border:0px !important; background-color:$coul\">";
177        $closeSpan=1;
178      }
179      //sinon si le "mot" est de la forme par
180      else if (preg_match("/^par/i",$corps[$i],$val)) {
181        $out.="<br />";
182      }
183      //sinon si le "mot" est de la forme ulnone
184      else if (preg_match("/^ulnone/i",$corps[$i],$val)) {
185        $out.="</u>";
186      }
187      //sinon si le "mot" est de la forme ul
188      else if (preg_match("/^ul/i",$corps[$i],$val)) {
189        $out.="<u>";
190      }
191      //sinon si le "mot" est de la forme b0
192      else if (preg_match("/^b0/i",$corps[$i],$val)) {
193        $out.="</b>";
194      }
195      //sinon si le "mot" est de la forme b
196      else if (preg_match("/^b/i",$corps[$i],$val)) {
197        $out.="<b>";
198      }
199      //sinon si le "mot" est de la forme i0
200      else if (preg_match("/^i0/i",$corps[$i],$val)) {
201        $out.="</i>";
202      }
203      //sinon si le "mot" est de la forme ul
204      else if (preg_match("/^i/i",$corps[$i],$val)) {
205        $out.="<i>";
206      }
207      //Sinon (on n'a pas reconnu une mot clef rtf, on affiche le mot (qui perd son \ au passage...)
208      else {
209        $out.=htmlentities($corps[$i]);
210        continue;
211      }
212
213      //Si le mot contient un code rtf _et_ du texte, on recupere le texte et on l'affiche
214      if (preg_match("/^.*? (.*?)$/",$corps[$i],$val)) {
215        $out.=htmlentities($val[1]);
216      }
217    }
218    //On ferme d'�ventuelles balises span ou font
219    if ($closeFont) $out.="</font>";
220    if ($closeSpan) $out.="</span>";
221  }
222  else $out=htmlspecialchars($rtf);
223
224  $out.="</span>";
225  //On remet les \ "du texte" en place
226  $out=preg_replace("/\*antislash\*/","\\",$out);
227
228  return $out;
229}
230