1<?php
2if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
3if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
4require_once(DOKU_PLUGIN.'action.php');
5global $conf;
6
7$default_english_file = DOKU_PLUGIN . 'fckg/action/lang/en.php';
8require_once($default_english_file);
9
10if(isset($conf['lang']) && $conf['lang'] != 'en' ) {
11  $default_lang_file = DOKU_PLUGIN . 'fckg/action/lang/' . $conf['lang'] . '.php';
12  if(file_exists($default_lang_file)) {
13    @include($default_lang_file);
14  }
15}
16
17/**
18 * @license    GNU GPLv2 version 2 or later (http://www.gnu.org/licenses/gpl.html)
19 *
20 * class       plugin_fckg_edit
21 * @author     Myron Turner <turnermm02@shaw.ca>
22 */
23
24class action_plugin_fckg_edit extends DokuWiki_Action_Plugin {
25    //store the namespaces for sorting
26    var $fck_location = "fckeditor";
27    var $helper = false;
28    var $fckg_bak_file = "";
29    var $debug = false;
30    var $test = false;
31    var $page_from_template;
32    var $draft_found = false;
33    var $draft_text;
34    /**
35     * Constructor
36     */
37    function action_plugin_fckg_edit()
38    {
39        $this->setupLocale();
40        $this->helper = plugin_load('helper', 'fckg');
41    }
42
43
44    function register(Doku_Event_Handler $controller)
45    {
46        if(method_exists($this->helper, 'is_outOfScope') &&  $this->helper->is_outOfScope()) return;
47
48        global $FCKG_show_preview;
49        $FCKG_show_preview = true;
50
51        if(isset($_REQUEST['mode']) && $_REQUEST['mode'] == 'dwiki') {
52          $FCKG_show_preview = true;
53          return;
54        }
55        elseif(isset($_COOKIE['FCKG_USE'])) {
56             preg_match('/_\w+_/',  $_COOKIE['FCKG_USE'], $matches);
57             if($matches[0] == '_false_') {
58                  $FCKG_show_preview = true;
59                   return;
60             }
61        }
62        $Fck_NmSp = "!!NONSET!!";
63        if(isset($_COOKIE['FCK_NmSp'])) {
64          $Fck_NmSp = $_COOKIE['FCK_NmSp'];
65        }
66        $dwedit_ns = @$this->getConf('dwedit_ns');
67        if(isset($dwedit_ns) && $dwedit_ns) {
68            $ns_choices = explode(',',$dwedit_ns);
69            foreach($ns_choices as $ns) {
70              $ns = trim($ns);
71              if(preg_match("/$ns/",$_REQUEST['id']) || preg_match("/$ns/",$Fck_NmSp)) {
72                      $FCKG_show_preview = true;
73                       return;
74             }
75            }
76        }
77        $controller->register_hook('COMMON_PAGE_FROMTEMPLATE', 'AFTER', $this, 'pagefromtemplate', array());
78        $controller->register_hook('COMMON_PAGETPL_LOAD', 'AFTER', $this, 'pagefromtemplate', array());
79
80        $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'fckg_edit');
81        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'fckg_edit_meta');
82    }
83
84   /**
85    * function pagefromtemplate
86    * Capture template text output by Template Event handler instead of pageTemplate()
87	* @author  Myron Turner <turnermm02@shaw.ca>
88    *
89    */
90    function pagefromtemplate(&$event) {
91      if($event->data['tpl']) {
92         $this->page_from_template = $event->data['tpl'];
93      }
94    }
95
96    /**
97     * fckg_edit_meta
98     *
99     * load fck js
100     * @author Pierre Spring <pierre.spring@liip.ch>
101     * @param mixed $event
102     * @access public
103     * @return void
104     */
105    function fckg_edit_meta(&$event)
106    {
107        global $ACT;
108        // we only change the edit behaviour
109        if ($ACT != 'edit'){
110            return;
111        }
112        global $ID;
113        global $REV;
114        global $INFO;
115
116        $event->data['script'][] =
117            array(
118                'type'=>'text/javascript',
119                'charset'=>'utf-8',
120                '_data'=>'',
121                 'src'=>DOKU_BASE.'lib/plugins/fckg/' .$this->fck_location. '/fckeditor.js'
122            );
123
124        $event->data['script'][] =
125            array(
126                'type'=>'text/javascript',
127                'charset'=>'utf-8',
128                '_data'=>'',
129                 'src'=>DOKU_BASE.'lib/plugins/fckg/scripts/vki_kb.js'
130            );
131
132      $ua = strtolower ($_SERVER['HTTP_USER_AGENT']);
133      if(strpos($ua, 'msie') !== false) {
134          echo "\n" . '<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />' ."\n";
135      }
136
137        return;
138    }
139
140    /**
141     * function    fckg_edit
142     * @author     Pierre Spring <pierre.spring@liip.ch>
143     * edit screen using fck
144     *
145     * @param & $event
146     * @access public
147     * @return void
148     */
149    function fckg_edit(&$event)
150    {
151
152        global $INFO;
153
154        // we only change the edit behaviour
155        if ($event->data != 'edit') {
156            return;
157        }
158        // load xml and acl
159        if (!$this->_preprocess()){
160            return;
161        }
162        // print out the edit screen
163        $this->_print();
164        // prevent Dokuwiki normal processing of $ACT (it would clean the variable and destroy our 'index' value.
165        $event->preventDefault();
166        // index command belongs to us, there is no need to hold up Dokuwiki letting other plugins see if its for them
167        $event->stopPropagation();
168    }
169
170   /**
171    * function _preprocess
172	* @author  Myron Turner <turnermm02@shaw.ca>
173    */
174    function _preprocess()
175    {
176        global $ID;
177        global $REV;
178        global $DATE;
179        global $RANGE;
180        global $PRE;
181        global $SUF;
182        global $INFO;
183        global $SUM;
184        global $lang;
185        global $conf;
186        global $fckg_lang;
187        //set summary default
188        if(!$SUM){
189            if($REV){
190                $SUM = $lang['restored'];
191            }elseif(!$INFO['exists']){
192                $SUM = $lang['created'];
193            }
194        }
195
196            if($INFO['exists']){
197                if($RANGE){
198                    list($PRE,$text,$SUF) = rawWikiSlices($RANGE,$ID,$REV);
199                }else{
200                    $text = rawWiki($ID,$REV);
201                }
202            }else{
203                //try to load a pagetemplate
204                 $text = pageTemplate($ID);
205                //Check for text from template event handler
206                 if(!$text && $this->page_from_template) $text = $this->page_from_template;
207            }
208    $text =  str_replace("{{rss>http://", "{ { rss>Feed:",  $text);
209    if($this->getConf('smiley_hack')) {
210        $new_addr = $_SERVER['SERVER_NAME'] . DOKU_BASE;
211        $text=preg_replace("#(?<=http://)(.*?)(?=lib/plugins/fckg/fckeditor/editor/images/smiley/msn)#s", $new_addr,$text);
212     }
213
214    $text = preg_replace_callback('/\[\[\w+>.*?\]\]/ms',
215    create_function(
216        '$matches',
217        'return str_replace("/", "__IWIKI_FSLASH__" ,$matches[0]);'
218    ), $text);
219
220      global $useComplexTables;
221      if($this->getConf('complex_tables') || strrpos($text, '~~COMPLEX_TABLES~~') !== false) {
222          $useComplexTables=true;
223      }
224      else {
225         $useComplexTables=false;
226      }
227      if(strpos($text, '%%') !== false) {
228         $text= preg_replace_callback(
229            "/<(nowiki|code|file)>(.*?)<\/(nowiki|code|file)/ms",
230            function ($matches) {
231                $matches[0] = str_replace('%%', 'DBLPERCENT',$matches[0]);
232                return $matches[0];
233            },
234             $text
235            );
236
237        $text = preg_replace_callback(
238            "/(?<!nowiki>)%%(.*?)%%/ms",
239            function($matches) {
240            return '<nowiki>' . $matches[1] . '</nowiki>';
241            },
242            $text
243        );
244
245        $text =  str_replace('DBLPERCENT','%%',$text);
246      }
247
248      /* convert html tags to entities in indented code blocks*/
249       $text= preg_replace_callback(
250          '/(\n  )((?![\*\-]).*?)(\n)(?!\s)/ms',
251          create_function(
252            '$matches',
253            '$matches[0] = preg_replace("/(\[\[\w+)>/ms","$1__IWIKI__",$matches[0]);
254            $matches[0] = preg_replace("/<(?!\s)/ms", "&lt;", $matches[0]);
255            $matches[0] = preg_replace("/(?<!\s)>/ms", "&gt;", $matches[0]);
256            $matches[0] = preg_replace("/__IWIKI__/ms", ">", $matches[0]);
257            return $matches[0];  '
258          ), $text
259        );
260
261       $pos = strpos($text, '<');
262
263       if($pos !== false) {
264
265           $text = preg_replace_callback(
266            '/(<nowiki>)(.*?)(<\/nowiki>)/ms',
267            create_function(
268                '$matches',
269                 '$needles =  array("[","]", "/",  ".", "*", "_","\'","<",">","%", "{", "}", "\\\");
270                  $replacements = array("&#91;","&#93;","&#47;", "&#46;", "&#42;", "&#95;", "&#39;", "&#60;","&#62;","&#37;", "&#123;","&#125;", "&#92;");
271                  $matches[2] = str_replace($needles, $replacements, $matches[2]);
272                  return  $matches[1] . $matches[2] . $matches[3];'
273            ),
274            $text
275          );
276
277           $text = preg_replace_callback(
278            '/<(code|file)(.*?)(>)(.*?)(<\/\1>)/ms',
279            create_function(
280                '$matches',
281                 'if(preg_match("/\w+/",$matches[2])) {
282                   $matches[4] = str_replace("CHEVRONescC", ">>",$matches[4]);
283                   $matches[4] = str_replace("CHEVRONescO", "<<",$matches[4]);
284                   $matches[4] = preg_replace("/<(?!\s)/ms", "__GESHI_OPEN__", $matches[4]);
285                  }
286                  else {
287                  if( preg_match("/MULTI/",$matches[0])) {
288                     $open = "< ";
289                     $close = " >";
290                  }
291                  else {
292                     $open = "&lt;";
293                     $close = "&gt;";
294                  }
295                  $matches[4] = preg_replace("/<(?!\s)/ms", $open, $matches[4]);
296                  $matches[4] = preg_replace("/(?<!\s)>/ms", $close, $matches[4]);
297                  }
298                  $matches[4] = str_replace("\"", "__GESHI_QUOT__", $matches[4]);
299                  return "<" . $matches[1] . $matches[2] . $matches[3] . $matches[4] . $matches[5];'
300            ),
301            $text
302          );
303
304         /* \n_fckg_NPBBR_\n: the final \n prevents this from iterfering with next in line markups
305            -- in particular tables which require a new line and margin left
306           this may leave an empty paragraph in the xhtml, which is removed below
307         */
308          $text = preg_replace('/<\/(code|file)>(\s*)(?=[^\w])(\s*)/m',"</$1>\n_fckg_NPBBR_\n$2",$text );
309
310          $text = preg_replace_callback(
311            '/(\|\s*)(<code>|<file>)(.*?)(<\/code>|<\/file>)\n_fckg_NPBBR_(?=.*?\|)/ms',
312            create_function(
313                '$matches',
314                 '$matches[2] = preg_replace("/<code>/ms", "TPRE_CODE", $matches[2]);
315                  $matches[2] = preg_replace("/<file>/ms", "TPRE_FILE", $matches[2]);
316                  $matches[4] = "TPRE_CLOSE";
317                  $matches[3] = preg_replace("/^\n+/", "TC_NL",$matches[3]);
318                  $matches[3] = preg_replace("/\n/ms", "TC_NL",$matches[3]);
319                  return $matches[1] . $matches[2] .  trim($matches[3]) .   $matches[4];'
320            ),
321            $text
322          );
323         $text = preg_replace('/TPRE_CLOSE\s+/ms',"TPRE_CLOSE",$text);
324
325         $text = preg_replace('/<(?!code|file|plugin|del|sup|sub|\/\/|\s|\/del|\/code|\/file|\/plugin|\/sup|\/sub)/ms',"//<//",$text);
326
327         $text = str_replace('%%//<//', '&#37;&#37;&#60;', $text);
328
329         $text = preg_replace_callback('/<plugin(.*?)(?=<\/plugin>)/ms',
330                        create_function(
331                          '$matches',
332                           'return str_replace("//","", $matches[0]);'
333                       ),
334                       $text
335                 );
336         $text = str_replace('</plugin>','</plugin> ', $text);
337       }
338	   if($this->getConf('duplicate_notes')) {
339			$text = preg_replace_callback('/\(\(/ms',
340				  create_function(
341				   '$matches',
342				   'static $count = 0;
343				   $count++;
344				   $ins = "FNoteINSert" . $count;
345				   return "(($ins";'
346				 ), $text
347			);
348		}
349       $text = preg_replace('/^\>/ms',"_dwQUOT_",$text);  // dw quotes
350       $text = str_replace('>>','CHEVRONescC',$text);
351       $text = str_replace('<<','CHEVRONescO',$text);
352       $text = preg_replace('/(={3,}.*?)(\{\{.*?\}\})(.*?={3,})/',"$1$3\n$2",$text);
353       $email_regex = '/\/\/\<\/\/(.*?@.*?)>/';
354       $text = preg_replace($email_regex,"<$1>",$text);
355
356       $text = preg_replace('/{{(.*)\.swf(\s*)}}/ms',"SWF$1.swf$2FWS",$text);
357       $this->xhtml = $this->_render_xhtml($text);
358
359       $this->xhtml = str_replace("__IWIKI_FSLASH__", "&frasl;", $this->xhtml);
360	   if($this->getConf('duplicate_notes')) {
361			$this->xhtml = preg_replace("/FNoteINSert\d+/ms", "",$this->xhtml);
362	   }
363
364       $this->xhtml = str_replace("__GESHI_QUOT__", '&#34;', $this->xhtml);
365       $this->xhtml = str_replace("__GESHI_OPEN__", "&#60; ", $this->xhtml);
366       $this->xhtml = str_replace('CHEVRONescC', '>>',$this->xhtml);
367       $this->xhtml = str_replace('CHEVRONescO', '<<',$this->xhtml);
368       $this->xhtml = preg_replace('/_dwQUOT_/ms','>',$this->xhtml);  // dw quotes
369
370       if($pos !== false) {
371       $this->xhtml = preg_replace_callback(
372                '/(TPRE_CODE|TPRE_FILE)(.*?)(TPRE_CLOSE)/ms',
373                create_function(
374                   '$matches',
375                   '$matches[1] = preg_replace("/TPRE_CODE/","<pre class=\'code\'>\n", $matches[1]);
376                    $matches[1] = preg_replace("/TPRE_FILE/","<pre class=\'file\'>\n", $matches[1]);
377                    $matches[2] = preg_replace("/TC_NL/ms", "\n", $matches[2]);
378                    $matches[3] = "</pre>";
379                    return $matches[1] . $matches[2] . $matches[3];'
380                ),
381                $this->xhtml
382              );
383
384       }
385       $this->xhtml = preg_replace_callback(
386            '/(<pre)(.*?)(>)(.*?)(<\/pre>)/ms',
387            create_function(
388                '$matches',
389                  '$matches[4] = preg_replace("/(\||\^)[ ]+(\||\^)/ms","$1 &nbsp; $2" , $matches[4]);
390                  return  $matches[1] . $matches[2] . $matches[3] . $matches[4] . $matches[5];'
391            ),
392            $this->xhtml
393          );
394
395       $cname = getCacheName($INFO['client'].$ID,'.draft.fckl');
396       if(file_exists($cname)) {
397          $cdata =  unserialize(io_readFile($cname,false));
398          $cdata['text'] = urldecode($cdata['text']);
399          preg_match_all("/<\/(.*?)\>/", $cdata['text'],$matches);
400          /* exclude drafts saved from preview mode */
401          if (!in_array('code', $matches[1]) && !in_array('file', $matches[1]) && !in_array('nowiki', $matches[1])) {
402              $this->draft_text = $cdata['text'];
403              $this->draft_found = true;
404              msg($fckg_lang['draft_msg']) ;
405          }
406          unlink($cname);
407       }
408
409        return true;
410    }
411
412   /**
413    * function dw_edit_displayed
414    * @author  Myron Turner
415    * determines whether or not to show  or hide the
416      'DW Edit' button
417   */
418
419   function dw_edit_displayed()
420   {
421        global $INFO;
422
423        $dw_edit_display = @$this->getConf('dw_edit_display');
424        if(!isset($dw_edit_display))return "";  //version 0.
425        if($dw_edit_display != 'all') {
426            $admin_exclusion = false;
427            if($dw_edit_display == 'admin' && ($INFO['isadmin'] || $INFO['ismanager']) ) {
428                    $admin_exclusion = true;
429            }
430            if($dw_edit_display == 'none' || $admin_exclusion === false) {
431              return ' style = "display:none"; ';
432            }
433           return "";
434        }
435        return "";
436
437   }
438
439   /**
440    * function _print
441    * @author  Myron Turner
442    */
443    function _print()
444    {
445        global $INFO;
446        global $lang;
447        global $fckg_lang;
448        global $ID;
449        global $REV;
450        global $DATE;
451        global $PRE;
452        global $SUF;
453        global $SUM;
454        $wr = $INFO['writable'];
455        if($wr){
456           if ($REV) print p_locale_xhtml('editrev');
457           $ro=false;
458        }else{
459            // check pseudo action 'source'
460            if(!actionOK('source')){
461                msg('Command disabled: source',-1);
462                return false;
463            }
464            print p_locale_xhtml('read');
465            $ro='readonly="readonly"';
466        }
467
468        if(!$DATE) $DATE = $INFO['lastmod'];
469        $guest_toolbar = $this->getConf('guest_toolbar');
470        $guest_media  = $this->getConf('guest_media');
471        if(!isset($INFO['userinfo']) && !$guest_toolbar) {
472
473                echo  $this->helper->registerOnLoad(
474                    ' fck = new FCKeditor("wiki__text", "100%", "600");
475                     fck.BasePath = "'.DOKU_BASE.'lib/plugins/fckg/'.$this->fck_location.'/";
476                     fck.ToolbarSet = "DokuwikiNoGuest";
477                     fck.ReplaceTextarea();'
478                     );
479        }
480        else if(!isset($INFO['userinfo']) && !$guest_media) {
481
482            echo  $this->helper->registerOnLoad(
483                ' fck = new FCKeditor("wiki__text", "100%", "600");
484                 fck.BasePath = "'.DOKU_BASE.'lib/plugins/fckg/'.$this->fck_location.'/";
485                 fck.ToolbarSet = "DokuwikiGuest";
486                 fck.ReplaceTextarea();'
487                 );
488        }
489
490        else {
491            echo  $this->helper->registerOnLoad(
492                ' fck = new FCKeditor("wiki__text", "100%", "600");
493                 fck.BasePath = "'.DOKU_BASE.'lib/plugins/fckg/'.$this->fck_location.'/";
494                 fck.ToolbarSet = "Dokuwiki";
495                 fck.ReplaceTextarea();'
496                 );
497        }
498
499
500?>
501
502
503   <form id="dw__editform" method="post" action="<?php echo script()?>"  accept-charset="<?php echo $lang['encoding']?>">
504    <div class="no">
505      <input type="hidden" name="id"   value="<?php echo $ID?>" />
506      <input type="hidden" name="rev"  value="<?php echo $REV?>" />
507      <input type="hidden" name="date" value="<?php echo $DATE?>" />
508      <input type="hidden" name="prefix" value="<?php echo formText($PRE)?>" />
509      <input type="hidden" name="suffix" value="<?php echo formText($SUF)?>" />
510      <input type="hidden" id="fckg_mode_type"  name="mode" value="" />
511      <input type="hidden" id="fck_preview_mode"  name="fck_preview_mode" value="nil" />
512      <input type="hidden" id="fck_wikitext"    name="fck_wikitext" value="__false__" />
513      <?php
514      if(function_exists('formSecurityToken')) {
515           formSecurityToken();
516      }
517      ?>
518    </div>
519
520    <textarea name="wikitext" id="wiki__text" <?php echo $ro?> cols="80" rows="10" class="edit" tabindex="1"><?php echo "\n".$this->xhtml?></textarea>
521
522<?php
523
524$temp=array();
525trigger_event('HTML_EDITFORM_INJECTION', $temp);
526
527$DW_EDIT_disabled = '';
528$guest_perm = auth_quickaclcheck($_REQUEST['id']);
529$guest_group = false;
530$guest_user = false;
531
532if(isset($INFO['userinfo'])&& isset($INFO['userinfo']['grps'])) {
533   $user_groups = $INFO['userinfo']['grps'];
534   if(is_array($user_groups) && $user_groups) {
535      foreach($user_groups as $group) {
536        if (strcasecmp('guest', $group) == 0) {
537          $guest_group = true;
538          break;
539        }
540     }
541   }
542  if($INFO['client'] == 'guest') $guest_user = true;
543}
544
545if(($guest_user || $guest_group) && $guest_perm <= 2) $DW_EDIT_disabled = 'disabled';
546
547
548$DW_EDIT_hide = $this->dw_edit_displayed();
549
550?>
551
552    <div id="wiki__editbar">
553      <div id="size__ctl"></div>
554      <div id = "fck_size__ctl" style="display: none">
555
556       <img src = "<?php echo DOKU_BASE ?>lib/images/smaller.gif"
557                    title="edit window smaller"
558                    onclick="dwfck_size_ctl('smaller');"
559                    />
560       <img src = "<?php echo DOKU_BASE ?>lib/images/larger.gif"
561                    title="edit window larger"
562                    onclick="dwfck_size_ctl('larger');"
563           />
564      </div>
565      <?php if($wr){?>
566         <div class="editButtons">
567            <input type="checkbox" name="fckg" value="fckg" checked="checked" style="display: none"/>
568             <input class="button" type="button"
569                   name="do[save]"
570                   value="<?php echo $lang['btn_save']?>"
571                   title="<?php echo $lang['btn_save']?> "
572                   <?php echo $DW_EDIT_disabled; ?>
573                   onmousedown="parse_wikitext('edbtn__save');"
574                  />
575
576            <input class="button" id="ebtn__delete" type="submit"
577                   <?php echo $DW_EDIT_disabled; ?>
578                   name="do[delete]" value="<?php echo $lang['btn_delete']?>"
579                   title="<?php echo $fckg_lang['title_dw_delete'] ?>"
580                   style = "font-size: 100%;"
581                   onmouseup="draft_delete();"
582                   onclick = "return confirm('<?php echo $fckg_lang['confirm_delete']?>');"
583            />
584
585            <input type="checkbox" name="fckg" value="fckg" style="display: none"/>
586
587             <input class="button"
588                 <?php echo $DW_EDIT_disabled; ?>
589                 <?php echo $DW_EDIT_hide; ?>
590                 style = "font-size: 100%;"
591                 onclick ="setDWEditCookie(2, this);parse_wikitext('edbtn__save');this.form.submit();"
592                 type="submit" name="do[save]" value="<?php echo $fckg_lang['btn_dw_edit']?>"
593                 title="<?php echo $fckg_lang['title_dw_edit']?>"
594                  />
595
596<?php
597
598global $INFO;
599
600  $disabled = 'Disabled';
601  $inline = $this->test ? 'inline' : 'none';
602
603  $backup_btn = isset($fckg_lang['dw_btn_backup'])? $fckg_lang['dw_btn_backup'] : $fckg_lang['dw_btn_refresh'];
604  $backup_title = isset($fckg_lang['title_dw_backup'])? $fckg_lang['title_dw_backup'] : $fckg_lang['title_dw_refresh'];
605  $using_scayt = ($this->getConf('scayt')) == 'on';
606
607?>
608            <input class="button" type="submit"
609                 name="do[draftdel]"
610                 value="<?php echo $lang['btn_cancel']?>"
611                 onmouseup="draft_delete();"
612                 style = "font-size: 100%;"
613                 title = "<?php echo $fckg_lang['title_dw_cancel']?>"
614             />
615
616           <?php if (!$using_scayt): ?>
617            <input class="button" type="button" value = "<?php echo $fckg_lang['dw_btn_lang']?>"
618                   title="<?php echo $fckg_lang['title_dw_lang']?>"
619                   onclick="aspell_window();" />
620            <?php endif;?>
621
622            <input class="button" type="button" value = "Test"
623                   title="Test"
624                   style = 'display:<?php echo $inline ?>;'
625                   onmousedown="parse_wikitext('test');"
626                  />
627
628 <?php if($this->draft_found) { ?>
629             <input class="button"
630                 onclick ="fckg_get_draft();"
631                 style = "background-color: yellow"
632                 id="fckg_draft_btn"
633                 type="button" value="<?php echo $fckg_lang['btn_draft'] ?>"
634                 title="<?php echo $fckg_lang['title_draft'] ?>"
635                  />
636 <?php } else { ?>
637
638
639             <input class="button" type="button"
640                   value="<?php echo $backup_btn ?>"
641                   title="<?php echo $backup_title ?>"
642                   onclick="renewLock(true);"
643                  />
644
645             <input class="button" type="button"
646                   value="<?php echo $fckg_lang['dw_btn_revert']?>"
647                   title="<?php echo $fckg_lang['title_dw_revert']?>"
648                   onclick="revert_to_prev()"
649                  />&nbsp;&nbsp;&nbsp;
650
651 <br />
652
653 <?php }  ?>
654
655 <?php if($this->debug) { ?>
656         <input class="button" type="button" value = "Debug"
657                   title="Debug"
658                   onclick="HTMLParser_debug();"
659                  />
660
661            <br />
662 <?php } ?>
663
664   <div id = "backup_msg" class="backup_msg" style=" display:none;">
665     <table><tr><td class = "backup_msg_td">
666      <div id="backup_msg_area" class="backup_msg_area"></div>
667     <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
668     <td align="right">
669      <a href="javascript:hide_backup_msg();void(0);" class="backup_msg_close">[ close ]</a>&nbsp;&nbsp;&nbsp;
670     </table>
671
672 </div>
673
674
675<input type="checkbox" name="fckg_timer" value="fckg_timer"  id = "fckg_timer"
676                      style = 'display:none'
677                      onclick="disableDokuWikiLockTimer();"
678                      <?php echo $disabled  ?>
679                 /><span id='fckg_timer_label'
680                    style = 'display:none'>Disable editor time-out messsages </span>
681
682     <?php  //global $useComplexTables;  if(!$useComplexTables) { ?>
683     <label class="nowrap" for="complex_tables" >
684        <input type="checkbox" name="complex_tables" value="complex_tables"  id = "complex_tables"
685                          onclick="setComplexTables(1);"
686                     /><span id='complex_tables_label'> <?php echo $fckg_lang['complex_tables'];?> (<a href="https://www.dokuwiki.org/plugin:fckglite#table_handling" target='_blank'><?php echo $fckg_lang['whats_this']?></a>)</span></label>
687     <?php //} ?>
688
689      <input style="display:none;" class="button" id="edbtn__save" type="submit" name="do[save]"
690                      value="<?php echo $lang['btn_save']?>"
691                      onmouseup="draft_delete();"
692                      <?php echo $DW_EDIT_disabled; ?>
693                      title="<?php echo $lang['btn_save']?> "  />
694
695            <!-- Not used by fckgLite but required to prevent null error when DW adds events -->
696            <input type="button" id='edbtn__preview' style="display: none"/>
697
698
699 <div id='saved_wiki_html' style = 'display:none;' ></div>
700 <div id='fckg_draft_html' style = 'display:none;' >
701 <?php echo $this->draft_text; ?>
702 </div>
703
704  <script type="text/javascript">
705//<![CDATA[
706         var embedComplexTableMacro = false;
707
708        <?php  echo 'var backup_empty = "' . $fckg_lang['backup_empty'] .'";'; ?>
709
710        function aspell_window() {
711          var DURL = "<?php echo DOKU_BASE; ?>";
712          window.open( DURL + "/lib/plugins/fckg/fckeditor/aspell.php?dw_conf_lang=<?php global $conf; echo $conf['lang']?>",
713                    "smallwin", "width=600,height=500,scrollbars=yes");
714        }
715
716        if(unsetDokuWikiLockTimer) unsetDokuWikiLockTimer();
717
718        function dwfck_size_ctl(which) {
719           var height = parseInt(document.getElementById('wiki__text___Frame').style.height);
720           if(which == 'smaller') {
721               height -= 50;
722           }
723           else {
724              height += 50;
725           }
726           document.getElementById('wiki__text___Frame').style.height = height + 'px';
727
728        }
729
730
731   setComplexTables = (function() {
732   var on=false;
733
734     return function(b) {
735        if(b) on = !on;
736        embedComplexTableMacro = on;
737        return on;
738     };
739
740     })();
741
742    <?php  global $useComplexTables;  if($useComplexTables) { ?>
743        document.getElementById('complex_tables').click();
744    <?php } ?>
745    <?php  if($this->getConf('complex_tables')) { ?>
746         document.getElementById('complex_tables').disabled = true;
747    <?php } ?>
748
749var fckgLPluginPatterns = new Array();
750
751<?php
752   global $fckgLPluginPatterns;
753   $utf8Chars = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ', 'Œ', 'œ', 'Š', 'š', 'Ÿ', 'ƒ');
754   $utf8Replacments = array( '&Agrave;',  '&Aacute;',  '&Acirc;',  '&Atilde;',  '&Auml;',  '&Aring;',  '&AElig;',  '&Ccedil;',  '&Egrave;',  '&Eacute;',  '&Ecirc;',  '&Euml;',  '&Igrave;',  '&Iacute;',  '&Icirc;',  '&Iuml;',  '&ETH;',  '&Ntilde;',  '&Ograve;',  '&Oacute;',  '&Ocirc;',  '&Otilde;',  '&Ouml;',  '&Oslash;',  '&Ugrave;',  '&Uacute;',  '&Ucirc;',  '&Uuml;',  '&Yacute;',  '&THORN;',  '&szlig;',  '&agrave;',  '&aacute;',  '&acirc;',  '&atilde;',  '&auml;',  '&aring;',  '&aelig;',  '&ccedil;',  '&egrave;',  '&eacute;',  '&ecirc;',  '&euml;',  '&igrave;',  '&iacute;',  '&icirc;',  '&iuml;',  '&eth;',  '&ntilde;',  '&ograve;',  '&oacute;',  '&ocirc;',  '&otilde;',  '&ouml;',  '&oslash;',  '&ugrave;',  '&uacute;',  '&ucirc;',  '&uuml;',  '&yacute;',  '&thorn;',  '&yuml;',  '&OElig;',  '&oelig;',  '&Scaron;',  '&scaron;',  '&Yuml;',  '&fnof;');
755
756   foreach($fckgLPluginPatterns as $pat) {
757     $pat[0] = preg_replace('/\s+$/',"",$pat[0]);
758     $pat[1] = str_replace('&','&amp;', $pat[1]);
759     $pat[0] = str_replace('&','&amp;',$pat[0]);
760     $pat[0] = str_replace('>', '&gt;',$pat[0]);
761     $pat[0] = str_replace('<', '&lt;',$pat[0]);
762     $pat[1] = str_replace('>', '&gt;',$pat[1]);
763     $pat[1] = str_replace('<', '&lt;',$pat[1]);
764     $pat[0] = preg_replace('/\s+/', '\s+',$pat[0]);
765     $pat[0] = str_replace('*', '%%\*%%',$pat[0]);
766     $pat[0] = str_replace($utf8Chars, $utf8Replacments,$pat[0]);
767     $pat[0] = preg_quote($pat[0], "/");
768     echo "fckgLPluginPatterns.push({'pat': '$pat[0]', 'orig': '$pat[1]' });\n";
769
770   }
771
772   global $fckLImmutables;
773   echo "if(!fckLImmutables) var fckLImmutables = new Array();\n";
774
775   for($i=0; $i< count($fckLImmutables); $i++) {
776      echo "fckLImmutables.push('$fckLImmutables[$i]');\n";
777   }
778
779   $pos = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE');
780   if($pos === false) {
781     echo "var isIE = false;";
782   }
783   else {
784     echo "var isIE = true;";
785   }
786
787   echo "var doku_base = '" . DOKU_BASE ."'";
788
789?>
790
791   var fckg_draft_btn = "<?php echo $fckg_lang['btn_exit_draft'] ?>";
792   var fckg_draft_btn_title = "<?php echo $fckg_lang['title_exit_draft']?>";
793   function fckg_get_draft() {
794      var dom = GetE('fckg_draft_html');
795      var draft = dom.innerHTML;
796      var dw_text = oDokuWiki_FCKEditorInstance.GetData( true );
797      oInst = oDokuWiki_FCKEditorInstance.get_FCK();
798      oInst =oInst.EditorDocument.body;
799      oInst.innerHTML = draft;
800      dom.innerHTML = dw_text;
801      var btn = GetE('fckg_draft_btn');
802      var tmp = btn.value;
803      btn.value = fckg_draft_btn;
804      fckg_draft_btn = tmp;
805      tmp = fckg_draft_btn_title;
806      btn.title = fckg_draft_btn_title;
807      fckg_draft_btn_title = tmp;
808   }
809
810
811   function safe_convert(value) {
812
813     if(oDokuWiki_FCKEditorInstance.dwiki_fnencode && oDokuWiki_FCKEditorInstance.dwiki_fnencode == 'safe') {
814      <?php
815       global $updateVersion;
816       if(!isset($updateVersion)) $updateVersion = 0;
817       echo "updateVersion=$updateVersion;";
818       $list = plugin_list('action');
819       $safe_converted = false;
820       if(in_array( 'safefnrecode' , $list)) {
821          $safe_converted = true;
822       }
823
824     ?>
825
826 		if(value.match(/%25/ && value.match(/%25[a-z0-9]/))) {
827                          value = value.replace(/%25/g,"%");
828                          <?php
829                          if($updateVersion > 30 || $safe_converted) {
830                            echo 'value = value.replace(/%5D/g,"]");';
831                          }
832                          ?>
833
834                          value =  dwikiUTF8_decodeFN(value,'safe');
835                       }
836        }
837        return value;
838
839     }
840
841RegExp.escape = function(str)
842{
843    var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
844    return str.replace(specials, "\\$&");
845}
846
847var HTMLParser_DEBUG = "";
848function parse_wikitext(id)
849{
850
851   var useComplexTables = setComplexTables();
852
853    var this_debug;
854
855    <?php if($this->debug) { ?>
856
857    function show_rowspans(rows) {
858
859    if(!useComplexTables) return;
860    var str = "";
861
862    for(var i=0; i < rows.length; i++) {
863       str+="ROW" + i + "\n";
864
865              for(var col=0; col<rows[i].length; col++) {
866                           str += "[" + col + "]";
867                           str+=   "text="+rows[i][col].text + " ";
868                           str+="  type="+rows[i][col].type + " ";
869                           str+= "  rowspan=" +rows[i][col].rowspan + "  ";
870                           str+= "  colspan=" +rows[i][col].colspan + "  ";
871              }
872              str += "\n";
873        }
874
875
876       this_debug(str,'show_rowspans');
877
878         str = "";
879       for(var i=0; i < rows.length; i++) {
880              for(var col=0; col<rows[i].length; col++) {
881                    str+=   "|"+rows[i][col].text + " ";
882              }
883              str += "|\n";
884        }
885        this_debug(str,'show_rowspans');
886
887    }
888
889    function debug_row(rows,row,col,which) {
890
891    var not_found = "";
892    try {
893         this_debug("row:"+row
894                         +",column:"+col
895                         +", rowspans:"+ rows[row][col].rowspan
896                         +", colspans:"+ rows[row][col].colspan
897                         +", text:"+rows[row][col].text,
898                         which);
899        }catch(ex) {
900            not_found+="row:"+row +",column:"+col;
901        }
902        if(not_found) this_debug(not_found,"not_found");
903    }
904    <?php } ?>
905    function check_rowspans(rows,start_row, ini) {
906        var tmp=new Array();
907        for(var i=start_row; i < rows.length; i++) {
908                  for(var col=0; col<rows[i].length; col++) {
909                        if(rows[i][col].rowspan > 0) {
910                              var _text = rows[i][col].text;
911                              tmp.push({row:i,column:col, spans: rows[i][col].rowspan,text:_text});
912                              if(!ini) break;
913                        }
914                  }
915            }
916        return tmp;
917    }
918
919    function insert_rowspan(row,col,spans,rows,shift) {
920
921        var prev_colspans = rows[row][col].colspan ? rows[row][col].colspan: 0;
922        rows[row][col].rowspan = 0;
923          for(i=0; i<spans-1;i++) {
924          //debug_row(rows,row,col,"insert_rowspan start");
925           rows[++row].splice(col, 0,{type:'td', rowspan:0,colspan:prev_colspans,prev_colspan:prev_colspans,text:" ::: "});
926
927          }
928    }
929
930
931
932   function reorder_span_rows(rows) {
933        var tmp_start = check_rowspans(rows,0,true);
934        var num_spans = tmp_start.length;
935        if(!num_spans) return false;
936
937
938        var row =   tmp_start[0].row;
939        var col = tmp_start[0].column;
940        insert_rowspan(row,col,tmp_start[0].spans,rows);
941
942       num_spans--;
943       for(var i=0; i < num_spans; i++) {
944             row++;
945            var tmp = check_rowspans(rows,row,false);
946            if(tmp.length) {
947                insert_rowspan(tmp[0].row,tmp[0].column,tmp[0].spans,rows);
948            }
949       }
950       return true;
951
952   }
953
954   function insert_table(rows) {
955       if(!useComplexTables) return;
956        for(var i=0; i<rows.length;i++) {
957          if(!reorder_span_rows(rows)) break;;
958        }
959
960        results+="\n";
961        for(var i=0; i < rows.length; i++) {
962                  results+="\n";
963                  for(var col=0; col<rows[i].length; col++) {
964                     var type = rows[i][col].type == 'td'? '|': '^';
965                     results+= type;
966                     var align = rows[i][col].align ? rows[i][col].align : false;
967                     if(align == 'center' || align == 'right') {
968                         results += "  ";
969                     }
970
971                     results += rows[i][col].text;
972                     if(align == 'center' || align == 'left') {
973                          results += "  ";
974                     }
975
976                     if(rows[i][col].colspan) {
977                     for(var n=0; n < rows[i][col].colspan-1; n++) {
978                               results+=type;
979                          }
980                     }
981                  }
982
983                   results += '|';
984
985               }
986   }
987
988
989 window.dwfckTextChanged = false;
990 if(id != 'bakup')  draft_delete();
991 var line_break = "\nL_BR_K  \n";
992    var markup = { 'b': '**', 'i':'//', 'em': '//', 'u': '__', 'br':line_break,
993         'del': '<del>', 'strike': '<del>', p: "\n\n" , 'a':'[[', 'img': '\{\{',
994         'h1': "\n====== ", 'h2': "\n===== ", 'h3': "\n==== ", 'h4': "\n=== ", 'h5': "\n== ",
995         'td': "|", 'th': "^", 'tr':" ", 'table': "\n\n", 'ol':"  - ", 'ul': "  * ", 'li': "",
996         'plugin': '<plugin ', 'code': "\'\'",'pre': "\n<", 'hr': "\n\n----\n\n", 'sub': '<sub>',
997         'font': "\n",
998         'sup': '<sup>', 'div':"\n\n", 'span': "\n", 'dl': "\n", 'dd': "\n", 'dt': "\n"
999     };
1000    var markup_end = { 'del': '</del>', 'strike': '</del>', 'p': " ", 'br':" ", 'a': ']]','img': '\}\}',
1001          'h1': " ======\n", 'h2': " =====\n", 'h3': " ====\n", 'h4': " ===\n", 'h5': " ==\n",
1002          'td': " ", 'th': " ", 'tr':"|\n", 'ol':" ", 'ul': " ", 'li': "\n", 'plugin': '</plugin>',
1003           'pre': "\n</",'sub': '</sub>', 'sup': '</sup> ', 'div':"\n\n", 'p': "\n\n",
1004           'font': "</font> "
1005     };
1006
1007    markup['blank'] = "";
1008    markup['fn_start'] = '((';
1009    markup['fn_end'] = '))';
1010    markup['row_span'] = ":::";
1011    markup['p_insert'] = '_PARA__TABLE_INS_';
1012    markup['format_space'] = '_FORMAT_SPACE_';
1013    markup['pre_td'] = '<';  //removes newline from before < which corrupts table
1014    var format_chars = {'b':true, 'i': true, 'em':true,'u':true, 'del':true,'strike':true, 'code':true};
1015
1016    var results="";
1017    var HTMLParser_LBR = false;
1018    var HTMLParser_PRE = false;
1019    var HTMLParser_Geshi = false;
1020    var HTMLParser_TABLE = false;
1021    var HTMLParser_COLSPAN = false;
1022    var HTMLParser_PLUGIN = false;
1023    var HTMLParser_FORMAT_SPACE = false;
1024    var HTMLParser_MULTI_LINE_PLUGIN = false;
1025    var HTMLParser_NOWIKI = false;
1026    var HTMLFormatInList = false;
1027    var HTMLAcroInList = false;
1028    var CurrentTable;
1029
1030    var HTMLParserTopNotes = new Array();
1031    var HTMLParserBottomNotes = new Array();
1032    var HTMLParserOpenAngleBracket = false;
1033    var HTMLParserParaInsert = markup['p_insert'];
1034 //   var geshi_classes = 'br0|co0|co1|co2|co3|coMULTI|es0|kw1|kw2|kw3|kw4|kw5|me1|me2|nu0|re0|re1|re2|re3|re4|st0|sy0|sy1|sy2|sy3|sy4';
1035      var geshi_classes = '(br|co|coMULTI|es|kw|me|nu|re|st|sy)[0-9]';
1036   String.frasl = new RegExp("⁄\|&frasl;\|&#8260;\|&#x2044;",'g');
1037
1038   geshi_classes = new RegExp(geshi_classes);
1039   HTMLParser(oDokuWiki_FCKEditorInstance.GetData( true ), {
1040    attribute: "",
1041    link_title: "",
1042    link_class: "",
1043    image_link_type: "",
1044    td_align: "",
1045    in_td: false,
1046    td_colspan: 0,
1047    td_rowspan: 0,
1048    rowspan_col: 0,
1049    last_column: -1,
1050    row:0,
1051    col:0,
1052   // table_start: false,
1053    td_no: 0,
1054    tr_no: 0,
1055    current_row:false,
1056    in_table: false,
1057    in_multi_plugin: false,
1058    is_rowspan: false,
1059    list_level: 0,
1060    prev_list_level: -1,
1061    list_started: false,
1062    xcl_markup: false,
1063    in_link: false,
1064    link_formats: new Array(),
1065    last_tag: "",
1066    code_type: false,
1067    in_endnotes: false,
1068    is_smiley: false,
1069    geshi: false,
1070    downloadable_code: false,
1071    export_code: false,
1072    code_snippet: false,
1073    downloadable_file: "",
1074    external_mime: false,
1075    in_header: false,
1076    is_acronym: false,
1077    curid: false,
1078    format_in_list: false,
1079    prev_li: new Array(),
1080    immutable_plugin: false,
1081    link_only: false,
1082	in_font: false,
1083	interwiki: false,
1084    bottom_url: false,
1085
1086    backup: function(c1,c2) {
1087        var c1_inx = results.lastIndexOf(c1);     // start position of chars to delete
1088        var c2_inx = results.indexOf(c2,c1_inx);  // position of expected next character
1089        if(c1_inx == -1 || c2_inx == -1) return;
1090        if(c1.length + c2_inx == c2_inx) {
1091            var left_side = results.substring(0,c1_inx); //from 0 up to but not including c1
1092            var right_side = results.substring(c2_inx);  //from c2 to end of string
1093            results = left_side + right_side;
1094            return true;
1095        }
1096        return false;
1097    },
1098
1099    start: function( tag, attrs, unary ) {
1100    this_debug = this.dbg;
1101    if(markup[tag]) {
1102      if(format_chars[tag] && this.in_link) {
1103                  this.link_formats.push(tag);
1104                  return;
1105         }
1106      if(format_chars[tag] && this.in_font) {
1107                  return;
1108         }
1109
1110     else if(tag == 'acronym') {
1111          return;
1112     }
1113        if(tag == 'ol' || tag == 'ul') {
1114            this.prev_list_level = this.list_level;
1115            this.list_level++;
1116            if(this.list_level == 1) this.list_started = false;
1117            if(this.list_started) this.prev_li.push(markup['li']) ;
1118            markup['li'] = markup[tag];
1119
1120            return;
1121        }
1122        else if(!this.list_level) {
1123             markup['li'] = "";
1124             this.prev_li = new Array();
1125        }
1126
1127        if(tag == 'img') {
1128            var img_size="?";
1129            var width;
1130            var height;
1131            var style = false;
1132            var img_align = '';
1133            var alt = "";
1134            var from_clipboard = false;
1135            this.is_smiley = false;
1136			this.in_link = false;
1137        }
1138
1139        if(tag == 'a') {
1140            var local_image = true;
1141            var type = "";
1142            this.xcl_markup = false;  // set to false in end() as well, double sure
1143            this.in_link = true;
1144            this.link_pos = results.length;
1145            this.link_formats = new Array();
1146            this.footnote = false;
1147            var bottom_note = false;
1148            this.id = "";
1149            this.external_mime = false;
1150            var media_class=false;
1151            this.export_code = false;
1152            this.code_snippet = false;
1153            this.downloadable_file = "";
1154            var qs_set = false;
1155            this.link_only = false;
1156            save_url = "";
1157            this.interwiki=false;
1158            this.bottom_url=false;
1159            this.link_class="";
1160        }
1161
1162       if(tag == 'p') {
1163          this.in_link = false;
1164          if(this.in_table) {
1165              tag = 'p_insert';
1166              HTMLParser_TABLE=true;
1167          }
1168       }
1169       else if(tag=='span') {
1170          var font_family = "arial";
1171          var font_size = "9pt";
1172          var font_weight = "normal";
1173          var font_color;
1174          var font_bgcolor;
1175       }
1176
1177       if(tag == 'table') {
1178        this.td_no = 0;
1179        this.tr_no = 0;
1180        this.in_table = true;
1181        this.is_rowspan = false;
1182        this.row=-1;
1183        this.rows = new Array();
1184        CurrentTable = this.rows;
1185        this.table_start = results.length;
1186       }
1187       else if(tag == 'tr') {
1188           this.tr_no++;
1189           this.td_no = 0;
1190           this.col=-1;
1191           this.row++;
1192           this.rows[this.row] = new Array();
1193           this.current_row = this.rows[this.row];
1194       }
1195       else if(tag == 'td' || tag == 'th') {
1196          this.td_no++;
1197          this.col++;
1198          this.current_row[this.col] = {type:tag, rowspan:0,colspan:0,text:""};
1199          this.cell_start = results.length;
1200          this.current_cell = this.current_row[this.col];
1201          if(this.td_rowspan && this.rowspan_col == this.td_no && this.td_no != this.last_column) {
1202               this.is_rowspan = true;
1203               this.td_rowspan --;
1204          }
1205          else {
1206              this.is_rowspan = false;
1207          }
1208
1209
1210       }
1211
1212
1213        var matches;
1214        this.attr=false;
1215        this.format_tag = false;
1216
1217        if(format_chars[tag])this.format_tag = true;
1218        var dwfck_note = false;
1219
1220        for ( var i = 0; i < attrs.length; i++ ) {
1221
1222          // if(!confirm(tag + ' ' + attrs[i].name + '="' + attrs[i].escaped + '"')) exit;
1223             if(tag == 'td' || tag == 'th') {
1224          //   if(!confirm(tag + ' ' + attrs[i].name + '="' + attrs[i].escaped + '"')) exit;
1225                 if(attrs[i].name  =='colspan') {
1226                     this.current_row[this.col].colspan = attrs[i].value;
1227                 }
1228                 if(attrs[i].name  =='class') {
1229                     if((matches=attrs[i].value.match(/(left|center|right)/))) {
1230                        this.current_row[this.col].align = matches[1];
1231                     }
1232                 }
1233             if(attrs[i].name == 'rowspan') {
1234                  this.current_row[this.col].rowspan= attrs[i].value
1235               }
1236            }
1237             if(attrs[i].escaped == 'u' && tag == 'em' ) {
1238                     tag = 'u';
1239                     this.attr='u'
1240                     break;
1241              }
1242
1243            if(tag == 'div') {
1244              if(attrs[i].name == 'class' && attrs[i].value == 'footnotes') {
1245                     tag = 'blank';
1246                     this.in_endnotes = true;
1247              }
1248               break;
1249            }
1250            if(tag == 'dl' && attrs[i].name == 'class' && attrs[i].value == 'file') {
1251                   this.downloadable_code = true;
1252                   HTMLParser_Geshi = true;
1253                   return;
1254            }
1255            if(tag == 'span' && attrs[i].name == 'class') {
1256                 if(attrs[i].value == 'np_break') return;
1257            }
1258
1259            if(tag == 'span' && attrs[i].name == 'class') {
1260                  if(attrs[i].value =='curid') {
1261                    this.curid = true;
1262                    return;
1263                  }
1264                  if(attrs[i].value == 'multi_p_open') {
1265                      this.in_multi_plugin = true;
1266                      HTMLParser_MULTI_LINE_PLUGIN = true;
1267                      return;
1268                  }
1269                  if(attrs[i].value == 'multi_p_close') {
1270                      this.in_multi_plugin = false;
1271                      return;
1272                  }
1273                 if(attrs[i].value.match(geshi_classes)) {
1274                    tag = 'blank';
1275                    this.geshi = true;
1276                    break;
1277                 }
1278            }
1279
1280            if(tag == 'span' && attrs[i].name == 'id') {
1281               if((matches= attrs[i].value.match(/imm_(\d+)/))) {
1282                   this.immutable_plugin = fckLImmutables[matches[1]];
1283               }
1284            }
1285            else if(tag == 'span') {
1286               if(attrs[i].name == 'face') {
1287			   	   this.in_font=true;
1288                   font_family = attrs[i].value;
1289               }
1290               if(attrs[i].name == 'style') {
1291                   matches = attrs[i].value.match(/font-size:\s*(\d+(\w+|%))/);
1292                   if(matches){
1293                     font_size = matches[1];
1294                   }
1295                   matches = attrs[i].value.match(/font-weight:\s*(\w+)/);
1296                   if(matches) {
1297                      font_weight = matches[1];
1298                   }
1299                   matches = attrs[i].value.match(/[^\-]color:\s*([#\w\s\d,\(\)]+);?/);
1300                   if(matches) {
1301                      font_color = matches[1];
1302                   }
1303
1304                 matches = attrs[i].value.match(/background[-]color:\s*([#\w\s\d,\(\)]+);?/i);
1305                   if(matches) {
1306                      font_bgcolor = matches[1];
1307                   }
1308               }
1309               else if(attrs[i].name == 'color') {
1310                    font_color = attrs[i].value;
1311               }
1312            }
1313            if(tag == 'td' || tag == 'th') {
1314              if(tag == 'td') {
1315                 results = results.replace(/\^$/,'|');
1316              }
1317              this.in_td = true;
1318              if(attrs[i].name == 'align') {
1319                 this.td_align =attrs[i].escaped;
1320
1321              }
1322              else if(attrs[i].name == 'class') {
1323                   matches = attrs[i].value.match(/\s+(\w+)align/);
1324                   if(matches) {
1325                       this.td_align = matches[1];
1326                   }
1327              }
1328              else if(attrs[i].name == 'colspan') {
1329                  HTMLParser_COLSPAN = true;
1330                  this.td_colspan =attrs[i].escaped;
1331              }
1332              else if(attrs[i].name == 'rowspan') {
1333                  this.td_rowspan =attrs[i].escaped-1;
1334                  this.rowspan_col = this.td_no;
1335
1336              }
1337
1338                HTMLParser_TABLE=true;
1339            }
1340
1341            if(tag == 'a') {
1342               if(attrs[i].name == 'title') {
1343                  this.link_title = attrs[i].escaped;
1344                  this.link_title =  this.link_title.replace(/\s*\(.*$/,"") ;
1345               }
1346               else if(attrs[i].name == 'class') {
1347                  if(attrs[i].value.match(/fn_top/)) {
1348                     this.footnote = true;
1349                  }
1350                  else if(attrs[i].value.match(/fn_bot/)) {
1351                     bottom_note = true;
1352                  }
1353                  else if(attrs[i].value.match(/mf_(png|gif|jpg|jpeg)/i)) {
1354                     this.link_only=true;
1355                  }
1356
1357                  this.link_class= attrs[i].escaped;
1358                  media_class = this.link_class.match(/mediafile/);
1359               }
1360               else if(attrs[i].name == 'id') {
1361                  this.id = attrs[i].value;
1362               }
1363               else if(attrs[i].name == 'type') {
1364                  type = attrs[i].value;
1365               }
1366
1367              else if(attrs[i].name == 'href' && !this.code_type) {
1368                    var http =  attrs[i].escaped.match(/https*:\/\//) ? true : false;
1369                    if(http) save_url = attrs[i].escaped;
1370                    if(attrs[i].escaped.match(/\/lib\/exe\/detail.php/)) {
1371                        this.image_link_type = 'detail';
1372                    }
1373                    else if(attrs[i].escaped.match(/exe\/fetch.php/)) {
1374                       this.image_link_type = 'direct';
1375                    }
1376                    else {   // nice urls using .htaccess
1377                        var regex = new RegExp(DOKU_BASE + '_detail');
1378                        if(attrs[i].escaped.match(regex)) {
1379                            this.image_link_type = 'detail';
1380                        }
1381                    }
1382
1383                    // required to distinguish external images from external mime types
1384                    // that are on the wiki which also use {{url}}
1385                    var media_type = attrs[i].escaped.match(/fetch\.php.*?media=.*?\.(png|gif|jpg|jpeg)$/i);
1386                    if(media_type) media_type = media_type[1];
1387
1388                    if(attrs[i].escaped.match(/^https*:/)) {
1389                       this.attr = attrs[i].escaped;
1390                       local_image = false;
1391                    }
1392                   if(attrs[i].escaped.match(/^ftp:/)) {
1393                       this.attr = attrs[i].escaped;
1394                       local_image = false;
1395                    }
1396                    else if(attrs[i].escaped.match(/do=export_code/)) {
1397                            this.export_code = true;
1398                    }
1399                    else if(attrs[i].escaped.match(/^nntp:/)) {
1400                       this.attr = attrs[i].escaped;
1401                       local_image = false;
1402                    }
1403                    else if(attrs[i].escaped.match(/^mailto:/)) {
1404                       this.attr = attrs[i].escaped.replace(/mailto:/,"");
1405                       local_image = false;
1406                    }
1407                    else if(attrs[i].escaped.match(/^file:/)) {  //samba share
1408                        var url= attrs[i].value.replace(/file:[\/]+/,"");
1409                        url = url.replace(/[\/]/g,'\\');
1410                        url = '\\\\' + url;
1411                        this.attr = url;
1412                        local_image = false;
1413                    }
1414                        // external mime types after they've been saved first time
1415                   else if(http && !media_type && (matches = attrs[i].escaped.match(/fetch\.php(.*)/)) ) {
1416                         if(matches[1].match(/media=/)) {
1417                            elems = matches[1].split(/=/);
1418                            this.attr = elems[1];
1419                         }
1420                         else {   // nice urls
1421                            matches[1] = matches[1].replace(/^\//,"");
1422                            this.attr = matches[1];
1423                         }
1424                         local_image = false;
1425
1426                          this.attr = decodeURIComponent ? decodeURIComponent(this.attr) : unescape(this.attr);
1427                          if(!this.attr.match(/^:/)) {
1428                               this.attr = ':' +this.attr;
1429                         }
1430                         this.external_mime = true;
1431                   }
1432
1433                    else {
1434                        local_image = false;
1435
1436                        matches = attrs[i].escaped.match(/doku.php\?id=(.*)/);
1437
1438                        if(!matches) {
1439                            matches = attrs[i].escaped.match(/doku.php\/(.*)/);
1440                        }
1441                        /* previously saved internal link with query string
1442                          requires initial ? to be recognized by DW. In Anteater and later */
1443                        if(matches) {
1444                            if(!matches[1].match(/\?/) && matches[1].match(/&amp;/)) {
1445                                  qs_set = true;
1446                                  matches[1] = matches[1].replace(/&amp;/,'?')
1447                            }
1448                        }
1449                        if(matches && matches[1]) {
1450                           if(!matches[1].match(/^:/)) {
1451                               this.attr = ':' + matches[1];
1452                           }
1453                           else {
1454                                this.attr = matches[1];
1455                           }
1456
1457                           if(this.attr.match(/\.\w+$/)) {  // external mime's first access
1458                               if(type && type == 'other_mime') {
1459                                    this.external_mime = true;
1460                               }
1461                               else {
1462                                   for(var n = i+1; n < attrs.length; n++) {
1463                                     if(attrs[n].value.match(/other_mime/))
1464                                        this.external_mime = true;
1465                                        break;
1466                                    }
1467
1468                               }
1469                           }
1470
1471                        }
1472                        else {
1473                          matches = attrs[i].value.match(/\\\\/);   // Windows share
1474                          if(matches) {
1475                            this.attr = attrs[i].escaped;
1476                            local_image = false;
1477                          }
1478                        }
1479                   }
1480
1481                   if(this.link_class == 'media') {
1482                        if(attrs[i].value.match(/http:/)) {
1483                         local_image = false;
1484                        }
1485                    }
1486
1487                   if(!this.attr && this.link_title) {
1488                       if(this.link_class == 'media') {
1489                            this.attr=this.link_title;
1490                            local_image = true;
1491                       }
1492                    }
1493
1494                   if(this.attr.match && this.attr.match(/%[a-fA-F0-9]{2}/)  && (matches = this.attr.match(/userfiles\/file\/(.*)/))) {
1495                      matches[1] = matches[1].replace(/\//g,':');
1496                      if(!matches[1].match(/^:/)) {
1497                         matches[1] = ':' + matches[1];
1498                      }
1499                      this.attr = decodeURIComponent ? decodeURIComponent(matches[1]) : unescape(matches[1]);
1500                      this.attr = decodeURIComponent ? decodeURIComponent(this.attr) : unescape(this.attr);
1501                      this.external_mime = true;
1502
1503                   }
1504
1505                   // alert('title: ' + this.link_title + '  class: ' + this.link_class + ' export: ' +this.export_code);
1506                    if(this.link_title.match(/Snippet/)) this.code_snippet = true;
1507
1508                    /* anchors to current page without prefixing namespace:page */
1509                   if(attrs[i].value.match(/^#/) && this.link_class.match(/wikilink/)) {
1510                          this.attr = attrs[i].value;
1511                          this.link_title = false;
1512                   }
1513
1514                        /* These two conditions catch user_rewrite not caught above */
1515                    if(this.link_class.match(/wikilink/) && this.link_title) {
1516                       this.external_mime = false;
1517                       if(!this.attr){
1518                             this.attr = this.link_title;
1519                       }
1520                       if(!this.attr.match(/^:/)) {
1521                         this.attr = ':' + this.attr;
1522                       }
1523                      if(this.attr.match(/\?.*?=/)){
1524                       var elems = this.attr.split(/\?/);
1525                       elems[0] = elems[0].replace(/\//g,':');
1526                       this.attr = elems[0] + '?' + elems[1];
1527                      }
1528                      else {
1529                          this.attr = this.attr.replace(/\//g,':');
1530                      }
1531
1532                   /* catch query strings attached to internal links for .htacess nice urls  */
1533                      if(!qs_set && attrs[i].name == 'href') {
1534                         if(!this.attr.match(/\?.*?=/) && !attrs[i].value.match(/doku.php/)) {
1535                           var qs = attrs[i].value.match(/(\?.*)$/);
1536                            if(qs && qs[1]) this.attr += qs[1];
1537                         }
1538
1539                      }
1540                    }
1541                   else if(this.link_class.match(/mediafile/) && this.link_title && !this.attr) {
1542                       this.attr =   this.link_title;
1543                       this.external_mime = true;
1544
1545                       if(!this.attr.match(/^:/)) {
1546                         this.attr = ':' + this.attr;
1547                       }
1548                   }
1549                else if(this.link_class.match(/interwiki/)) {
1550                    var iw_type = this.link_class.match(/iw_(\w+)/);
1551                    var iw_title = this.link_title.split(/\//);
1552                     var interwiki_label = iw_title[iw_title.length-1];
1553                     interwiki_label = interwiki_label.replace(String.frasl,"\/");
1554                    this.attr = iw_type[1] + '>' +  interwiki_label;
1555                    this.interwiki=true;
1556				  }
1557
1558                if(this.link_class == 'urlextern') {
1559                    this.attr = save_url;
1560					this.external_mime=false;  // prevents external links to images from being converted to image links
1561                }
1562                   if(this.in_endnotes) {
1563                        if(this.link_title) {
1564                            this.bottom_url= this.link_title;  //save for bottom urls
1565                        }
1566                        else if(this.attr) {
1567                            this.bottom_url= this.attr;
1568                        }
1569                   }
1570                   this.link_title = "";
1571                   this.link_class= "";
1572
1573                 //  break;
1574                 }
1575            }
1576
1577            if(tag == 'plugin') {
1578                  if(isIE) HTMLParser_PLUGIN = true;
1579                  if(attrs[i].name == 'title') {
1580                       this.attr = ' title="' + attrs[i].escaped + '" ';
1581                       break;
1582                  }
1583             }
1584
1585            if(tag == 'sup') {
1586               if(attrs[i].name == 'class') {
1587                   matches = attrs[i].value.split(/\s+/);
1588                   if(matches[0] == 'dwfcknote') {
1589                      this.attr = matches[0];
1590                      tag = 'blank';
1591                      if(oDokuWiki_FCKEditorInstance.oinsertHtmlCodeObj.notes[matches[1]]) {
1592                          dwfck_note = '(('+ oDokuWiki_FCKEditorInstance.oinsertHtmlCodeObj.notes[matches[1]] + '))';
1593                      }
1594                     break;
1595                   }
1596               }
1597             }
1598
1599            if(tag == 'pre') {
1600                if(attrs[i].name == 'class') {
1601
1602                    var elems = attrs[i].escaped.split(/\s+/);
1603                    if(elems.length > 1) {
1604                        this.attr = attrs[i].value;
1605                        this.code_type = elems[0];
1606                    }
1607                    else {
1608                         this.attr = attrs[i].escaped;
1609                         this.code_type = this.attr;
1610                    }
1611                    if(this.downloadable_code) {
1612                         this.attr = this.attr.replace(/\s*code\s*/,"");
1613                         this.code_type='file';
1614                    }
1615                    HTMLParser_PRE = true;
1616                    if(this.in_table) tag = 'pre_td';
1617                    break;
1618                }
1619
1620            }
1621
1622            else if(tag == 'img') {
1623                if(attrs[i].name == 'alt') {
1624                     alt=attrs[i].value;
1625                }
1626                if(attrs[i].name == 'type') {
1627                     this.image_link_type = attrs[i].value;
1628                }
1629
1630                if(attrs[i].name == 'src') {
1631                  //  alert(attrs[i].name + ' = ' + attrs[i].value + ',  fnencode=' + oDokuWiki_FCKEditorInstance.dwiki_fnencode);
1632
1633                    var src = "";
1634                                // fetched by fetch.php
1635                    if(matches = attrs[i].escaped.match(/fetch\.php.*?(media=.*)/)) {
1636                        var elems = matches[1].split('=');
1637                        src = elems[1];
1638                        if(matches = attrs[i].escaped.match(/(media.*)/)) {
1639                            var elems = matches[1].split('=');
1640                            var uri = elems[1];
1641                            src = decodeURIComponent ? decodeURIComponent(uri) : unescape(uri);
1642                        }
1643                         if(!src.match(/https?:/)  && !src.match(/^:/)) src = ':' + src;
1644                     }
1645                     else if(attrs[i].escaped.match(/https?:\/\//)){
1646                              src = attrs[i].escaped;
1647                              src = src.replace(/\?.*?$/,"");
1648                     }
1649                     // url rewrite 1
1650                     else if(matches = attrs[i].escaped.match(/\/_media\/(.*)/)) {
1651                         var elems  = matches[1].split(/\?/);
1652                         src = elems[0];
1653                         src = src.replace(/\//g,':');
1654                         if(!src.match(/^:/)) src = ':' + src;
1655                     }
1656                     // url rewrite 2
1657                     else if(matches = attrs[i].escaped.match(/\/lib\/exe\/fetch.php\/(.*)/)) {
1658                         var elems  = matches[1].split(/\?/);
1659                         src = elems[0];
1660                         if(!src.match(/^:/)) src = ':' + src;
1661                     }
1662
1663                     else {
1664                          // first insertion from media mananger
1665                            matches = attrs[i].escaped.match(/^.*?\/userfiles\/image\/(.*)/);
1666
1667                            if(!matches) {  // windows style
1668                                var regex =  doku_base + 'data/media/';
1669                                regex = regex.replace(/([\/\\])/g, "\\$1");
1670                                regex = '^.*?' + regex + '(.*)';
1671                                regex = new RegExp(regex);
1672                                matches = attrs[i].escaped.match(regex);
1673                            }
1674                            if(matches && matches[1]) {
1675                               src = matches[1].replace(/\//g, ':');
1676                               src = ':' + src;
1677                               src = safe_convert(src);
1678                            }
1679                           else {
1680                               src = decodeURIComponent ? decodeURIComponent(attrs[i].escaped) : unescape(attrs[i].escaped);
1681                               if(src.search(/data:image.*?;base64/) > -1) {
1682                                   from_clipboard = true;
1683                               }
1684                           }
1685                          if(src.match(/lib\/images\/smileys/)) {
1686                                // src = 'http://' + window.location.host + src;
1687                                this.is_smiley = true;
1688                          }
1689                     }
1690
1691                      this.attr = src;
1692                      if(this.attr.match && this.attr.match(/%[a-fA-F0-9]{2}/)) {
1693                        this.attr = decodeURIComponent ? decodeURIComponent(this.attr) : unescape(this.attr);
1694                        this.attr = decodeURIComponent ? decodeURIComponent(this.attr) : unescape(this.attr);
1695                      }
1696
1697
1698
1699                }   // src end
1700
1701                else if (attrs[i].name == 'width' && !style) {
1702                         width=attrs[i].value;
1703
1704                }
1705                else if (attrs[i].name == 'height' && !style) {
1706                        height=attrs[i].value;
1707                }
1708                else if(attrs[i].name == 'style') {
1709                      var match = attrs[i].escaped.match(/width:\s*(\d+)/);
1710                      if(match) {
1711                           width=match[1];
1712                           var match = attrs[i].escaped.match(/height:\s*(\d+)/);
1713                           if(match) height = match[1];
1714                      }
1715                }
1716                else if(attrs[i].name == 'align' || attrs[i].name == 'class') {
1717                    if(attrs[i].escaped.match(/(center|middle)/)) {
1718                        img_align = 'center';
1719                    }
1720                    else if(attrs[i].escaped.match(/right/)) {
1721                          img_align = 'right';
1722                    }
1723                    else if(attrs[i].escaped.match(/left/)) {
1724                          img_align = 'left';
1725                    }
1726                   else {
1727                      img_align = '';
1728                   }
1729                }
1730            }   // End img
1731        }   // End Attributes Loop
1732
1733           if(this.is_smiley) {
1734                if(alt) {
1735                     results += alt + ' ';
1736                     alt = "";
1737                 }
1738                this.is_smiley = false;
1739                return;
1740           }
1741          if(this.link_only) tag = 'img';
1742          if(tag == 'br') {
1743                if(this.in_multi_plugin) {
1744                    results += "\n";
1745                    return;
1746                }
1747
1748                if(!this.code_type) {
1749                   HTMLParser_LBR = true;
1750                }
1751                else if(this.code_type) {
1752                      results += "\n";
1753                      return;
1754                }
1755
1756                if(this.in_table) {
1757                   results += HTMLParserParaInsert;
1758                   return;
1759                }
1760               if(this.list_started) {
1761                   results += '_LIST_EOFL_'; /* enables newlines in lists:   abc \\def */
1762                }
1763                else {
1764                    results += '\\\\  ';
1765                    return;
1766                }
1767          }
1768          else if(tag.match(/^h(\d+|r)/)) {
1769               var str_len = results.length;
1770               if(tag.match(/h(\d+)/)) {
1771                   this.in_header = true;
1772               }
1773               if(str_len) {
1774                  if(results.charCodeAt(str_len -1) == 32) {
1775                    results = results.replace(/\x20+$/,"");
1776                  }
1777               }
1778          }
1779          else if(this.last_col_pipes) {
1780               if(format_chars[tag]) results += markup[tag];
1781               tag = 'blank';
1782          }
1783          else if(dwfck_note) {
1784           results += dwfck_note;
1785           return;
1786         }
1787
1788          if(tag == 'b' || tag == 'i'  && this.list_level) {
1789                 if(results.match(/(\/\/|\*)(\x20)+/)) {
1790                     results = results.replace(/(\/\/|\*)(\x20+)\-/,"$1\n"+"$2-");
1791                  }
1792          }
1793
1794         if(tag == 'li' && this.list_level) {
1795              if(this.list_level == 1 & !this.list_started) {
1796                    results += "\n";
1797                    this.list_started = true;
1798              }
1799              results = results.replace(/[\x20]+$/,"");
1800
1801              for(var s=0; s < this.list_level; s++) {
1802                  // this handles format characters at the ends of list lines
1803                  if(results.match(/_FORMAT_SPACE_\s*$/)) {
1804                      results = results.replace(/_FORMAT_SPACE_\s*$/,"\n");
1805                  }
1806                  results += '  ';
1807              }
1808
1809             if(this.prev_list_level > 0 && markup['li'] == markup['ol']) {
1810                this.prev_list_level = -1;
1811             }
1812          }
1813
1814          if(tag == 'a' &&  local_image) {
1815                 this.xcl_markup = true;
1816                 return;
1817          }
1818          else if(tag == 'a' && (this.export_code || this.code_snippet)) {
1819                return;
1820          }
1821          else if (tag == 'a' && this.footnote) {
1822             tag = 'fn_start';
1823          }
1824          else if(tag == 'a' && bottom_note) {
1825                HTMLParserTopNotes.push(this.id);
1826          }
1827          else if(tag == 'a' && this.external_mime) {
1828               if(this.in_endnotes) {
1829                    this.link_class = 'media';
1830                    return;
1831                 }
1832               results += markup['img'];
1833               if(this.attr) {
1834                   results += this.attr + '|';
1835               }
1836               return;
1837          }
1838          else if(this.in_font || tag == 'font') {
1839              /* <font 18pt:bold/garamond;;color;;background_color>  */
1840			   if(!font_family) {
1841				   return;
1842			   }
1843               if(font_color)  font_color = font_color.replace(/\s+/g,"");
1844               if(font_bgcolor) font_bgcolor = font_bgcolor.replace(/\s+/g,"");
1845               if(!font_color) font_color = "#000000";
1846               if(!font_bgcolor) font_bgcolor = "#ffffff";
1847
1848               if(font_color) font_family = font_family + ';;'+ font_color;
1849               if(font_bgcolor)  {
1850                   font_family = font_family + ';;'+ font_bgcolor;
1851               }
1852               var font_tag = '<font ' + font_size + ':'+ font_weight + '/'+font_family+'>';
1853               results += font_tag ;
1854               return;
1855       }
1856
1857          if(this.in_endnotes && tag == 'a') return;
1858          if(this.code_type && tag == 'span') tag = 'blank';
1859          results += markup[tag];
1860
1861          if(tag == 'td' || tag == 'th' || (this.last_col_pipes && this.td_align == 'center')) {
1862              if(this.is_rowspan) {
1863                results +=  markup['row_span'] + ' | ';
1864                this.is_rowspan = false;
1865             }
1866             if(this.td_align == 'center' || this.td_align == 'right') {
1867                 results += '  ';
1868             }
1869
1870          }
1871          else if(tag == 'a' && this.attr) {
1872              this.attr =  this.attr.replace(/%25/gm,'%');
1873              this.attr =  this.attr.replace(/%25/gm,'%');
1874              this.attr =  this.attr.replace(/%7c/,'%257c');
1875              results += this.attr + '|';
1876          }
1877          else if(tag == 'img') {
1878               var link_type = this.image_link_type;
1879               this.image_link_type="";
1880               if(this.link_only) link_type = 'link_only';
1881               if(!link_type  || from_clipboard){
1882                  link_type = 'nolink';
1883               }
1884               else if(link_type == 'detail') {
1885                    link_type = "";
1886               }
1887
1888               if(link_type == 'link_only') {
1889                    img_size='?linkonly';
1890               }
1891               else if(link_type) {
1892                     img_size += link_type + '&';
1893               }
1894               if(width && height) {
1895                  img_size +=width + 'x' + height;
1896               }
1897               else if(width) {
1898                  img_size +=width;
1899               }
1900               else if(!link_type) {
1901                  img_size="";
1902               }
1903               if(img_align && img_align != 'left') {
1904                  results += '  ';
1905               }
1906               this.attr += img_size;
1907               if(img_align == 'center' || img_align == 'left') {
1908                  this.attr += '  ';
1909               }
1910
1911               results += this.attr + '}}';
1912               this.attr = 'src';
1913          }
1914          else if(tag == 'plugin' || tag == 'pre' || tag == 'pre_td') {
1915               if(this.downloadable_file) this.attr += ' ' +  this.downloadable_file;
1916               if(!this.attr) this.attr = 'code';
1917               results += this.attr + '>';
1918               this.downloadable_file = "";
1919               this.downloadable_code = false;
1920          }
1921
1922        }   // if markup tag
1923    },
1924
1925    end: function( tag ) {
1926
1927     if(format_chars[tag] && this.in_font) {
1928                 results+=' ';
1929                  return;
1930         }
1931    if(this.in_endnotes && tag == 'a') return;
1932    if(this.link_only){
1933       this.link_only=false;
1934       return;
1935    }
1936    if(!markup[tag]) return;
1937
1938     if(tag == 'sup' && this.attr == 'dwfcknote') {
1939         return;
1940     }
1941     if(this.is_smiley) {
1942        this.is_smiley = false;
1943        if(tag !='li') return;
1944     }
1945	 if(tag == 'span' && this.in_font) {
1946	      tag = 'font';
1947		  this.in_font=false;
1948	 }
1949     if(tag == 'span' && this.curid) {
1950             this.curid = false;
1951             return;
1952     }
1953     if(tag == 'dl' && this.downloadable_code) {
1954         this.downloadable_code = false;
1955         return;
1956     }
1957     if(useComplexTables &&  (tag == 'td' || tag == 'th')) {
1958          this.current_cell.text = results.substring(this.cell_start);
1959           this.current_cell.text = this.current_cell.text.replace(/:::/gm,"");
1960           this.current_cell.text = this.current_cell.text.replace(/^[\s\|\^]+/,"");
1961     }
1962     if(tag == 'a' && (this.export_code || this.code_snippet)) {
1963          this.export_code = false;
1964          this.code_snippet = false;
1965          return;
1966      }
1967
1968     if(this.code_type && tag == 'span') tag = 'blank';
1969     var current_tag = tag;
1970     if(this.footnote) {
1971       tag = 'fn_end';
1972      this.footnote = false;
1973     }
1974     else if(tag == 'a' && this.xcl_markup) {
1975         this.xcl_markup = false;
1976         return;
1977     }
1978     else if(tag == 'table') {
1979        this.in_table = false;
1980        if(useComplexTables ) {
1981            results = results.substring(0, this.table_start);
1982            insert_table(this.rows);
1983         }
1984     }
1985
1986     if(tag == 'p' && this.in_table) {
1987              tag = 'p_insert';
1988              HTMLParser_TABLE=true;
1989     }
1990     if(this.geshi) {
1991        this.geshi = false;
1992        return;
1993     }
1994
1995     if(tag == 'code' && ! this.list_started) {     // empty code markup corrupts results
1996           if(results.match(/''\s*$/m)) {
1997             results = results.replace(/''\s*$/, "\n");
1998             return;
1999           }
2000
2001     }
2002
2003    else if(tag == 'a' && this.attr == 'src') {
2004            // if local image without link content, as in <a . . .></a>, delete link markup
2005          if(this.backup('\[\[', '\{')) return;
2006    }
2007
2008    if(tag == 'ol' || tag == 'ul') {
2009            this.list_level--;
2010            if(!this.list_level) this.format_in_list = false;
2011            if(this.prev_li.length) {
2012            markup['li']= this.prev_li.pop();
2013            }
2014            tag = "\n\n";
2015    }
2016    else if(tag == 'a' && this.external_mime) {
2017           tag = '}} ';
2018           this.external_mime = false;
2019    }
2020    else if(tag == 'pre') {
2021          tag = markup_end[tag];
2022          if(this.code_type) {
2023           tag += this.code_type + ">";
2024          }
2025          else {
2026             var codeinx = results.lastIndexOf('code');
2027             var fileinx = results.lastIndexOf('file');
2028             if(fileinx > codeinx) {
2029               this.code_type = 'file';
2030            }
2031            else this.code_type = 'code';
2032            tag += this.code_type + ">";
2033          }
2034         this.code_type = false;
2035
2036    }
2037    else if(markup_end[tag]) {
2038            tag = markup_end[tag];
2039    }
2040    else if(this.attr == 'u' && tag == 'em' ) {
2041            tag = 'u';
2042    }
2043    else if(tag == 'acronym') {
2044    }
2045    else {
2046           tag = markup[tag];
2047     }
2048
2049    if(current_tag == 'tr') {
2050       if(this.last_col_pipes) {
2051            tag = "\n";
2052            this.last_col_pipes = "";
2053       }
2054
2055
2056     if(this.td_rowspan && this.rowspan_col == this.td_no+1) {
2057               this.is_rowspan = false;
2058               this.last_column = this.td_no;
2059               this.td_rowspan --;
2060               tag  = '|' + markup['row_span'] + "|\n";
2061      }
2062    }
2063    else if(current_tag == 'td' || current_tag == 'th') {
2064       this.last_col_pipes = "";
2065       this.in_td = false;
2066    }
2067
2068   else if (current_tag.match(/h\d+/)) {
2069           this.in_header = false;
2070    }
2071
2072
2073    if(markup['li']) {
2074
2075         if(results.match(/\n$/)) {
2076                  tag = "";
2077        }
2078
2079     }
2080
2081     if(this.in_link && format_chars[current_tag] && this.link_formats.length) {
2082           return;
2083     }
2084
2085       results += tag;
2086
2087      if(format_chars[current_tag]) {
2088            if(this.list_level) {
2089                  this.format_in_list = true;
2090                  HTMLFormatInList = true;
2091            }
2092            results += markup['format_space'];
2093            HTMLParser_FORMAT_SPACE =  markup['format_space'];
2094       }
2095        this.last_tag = current_tag;
2096
2097        if(this.td_colspan && !useComplexTables) {
2098            if(this.td_align == 'center') results += ' ';
2099            var _colspan = "|";
2100            if(current_tag == 'th')
2101                   _colspan = '^';
2102            var colspan = _colspan;
2103            for(var i=1; i < this.td_colspan; i++) {
2104                colspan += _colspan;
2105            }
2106            this.last_col_pipes = colspan;
2107            results += colspan;
2108            this.td_colspan = false;
2109          }
2110          else if(this.td_align == 'center') {
2111                results += ' ';
2112               this.td_align = '';
2113          }
2114
2115      if(current_tag == 'a' && this.link_formats.length) {
2116            var end_str = results.substring(this.link_pos);
2117            var start_str =  results.substring(0,this.link_pos);
2118            var start_format = "";
2119            var end_format = "";
2120            for(var i=0; i < this.link_formats.length; i++) {
2121                 var fmt = markup[this.link_formats[i]];
2122                 var endfmt = markup_end[this.link_formats[i]] ? markup_end[this.link_formats[i]]: fmt;
2123                 start_format += markup[this.link_formats[i]];
2124                 end_format = endfmt + end_format;
2125            }
2126
2127            start_str += start_format;
2128            end_str += end_format;
2129            results = start_str + end_str;
2130            this.link_formats = new Array();
2131            this.in_link = false;
2132         }
2133         else if(current_tag == 'a') {
2134            this.link_formats = new Array();
2135            this.in_link = false;
2136
2137         }
2138         else if(current_tag == 'span' ) {
2139                  this.immutable_plugin = false;
2140         }
2141
2142    },
2143
2144    chars: function( text ) {
2145
2146	if(this.interwiki && results.match(/>\w+\s*\|$/)) 	{
2147        text = text.replace(String.frasl,"\/");
2148	    this.interwiki=false;
2149        if(this.attr) {
2150          results+= text;
2151        }
2152	    else  {
2153           results=results.replace(/>\w+\s*\|$/,'>'+text);
2154        }
2155		return;
2156	  }
2157      else if(this.interwiki) {
2158        text = text.replace(String.frasl,"\/");
2159      }
2160     text = text.replace(/^(&gt;)+/,function(match,quotes) {
2161         return(match.replace(/(&gt;)/g, "\__QUOTE__")) ;
2162     }
2163     );
2164      //adjust spacing on multi-formatted strings
2165    results=results.replace(/([\/\*_])_FORMAT_SPACE_([\/\*_]{2})_FORMAT_SPACE_$/,"$1$2");
2166    if(text.match(/^&\w+;/)) {
2167	    results=results.replace(/_FORMAT_SPACE_\s*$/,"");   // remove unwanted space after character entity
2168    }
2169
2170    if(this.link_only) {
2171	    if(text) {
2172	        replacement = '|'+text + '}} ';
2173	        results = results.replace(/\}\}\s*$/,replacement);
2174	    }
2175	    return;
2176	}
2177    if(!this.code_type) {
2178        if(! this.last_col_pipes) {
2179            text = text.replace(/\x20{6,}/, "   ");
2180            text = text.replace(/^(&nbsp;)+\s*$/, '_FCKG_BLANK_TD_');
2181            text = text.replace(/(&nbsp;)+/, ' ');
2182        }
2183        if(this.immutable_plugin) {
2184             text = this.immutable_plugin;
2185             text = text.replace(/\/\/<\/\//g,'<');
2186             this.immutable_plugin = false;
2187        }
2188        if(this.format_tag) {
2189          if(!this.list_started || this.in_table) text = text.replace(/^\s+/, '@@_SP_@@');
2190        }
2191        else if(this.last_tag=='a') {
2192            text=text.replace(/^\s{2,}/," ");
2193        }
2194        else text = text.replace(/^\s+/, '');
2195
2196        if(text.match(/nowiki&gt;/)) {
2197	       HTMLParser_NOWIKI=true;
2198	   }
2199
2200        if(this.is_acronym) {
2201          this.is_acronym = false;
2202        }
2203        if(this.format_in_list ) {
2204           text = text.replace(/^[\n\s]+$/g, '');
2205        }
2206
2207       if(this.in_td && !text) {
2208           text = "_FCKG_BLANK_TD_";
2209           this.in_td = false;
2210       }
2211    }
2212    else {
2213      text = text.replace(/&lt;\s/g, '<');
2214      text = text.replace(/\s&gt;/g, '>');
2215    }
2216
2217    if(this.attr && this.attr == 'dwfcknote') {
2218         if(text.match(/fckgL\d+/)) {
2219             return;
2220         }
2221          if(text.match(/^[\-,:;!_]/)) {
2222            results +=  text;
2223          }
2224          else {
2225            results += ' ' + text;
2226          }
2227          return;
2228    }
2229
2230
2231
2232    if(this.downloadable_code &&  (this.export_code || this.code_snippet)) {
2233          this.downloadable_file = text;
2234          return;
2235    }
2236
2237   /* remove space between link end markup and following punctuation */
2238    if(this.last_tag == 'a' && text.match(/^[\.,;\:\!]/)) {
2239        results=results.replace(/\s$/,"");
2240    }
2241
2242    if(this.in_header) {
2243      text = text.replace(/---/g,'&mdash;');
2244      text = text.replace(/--/g,'&ndash;');
2245    }
2246    if(this.list_started) {
2247	    results=results.replace(/_LIST_EOFL_\s*L_BR_K\s*$/, '_LIST_EOFL_');
2248   }
2249    if(!this.code_type) {   // keep special character literals outside of code block
2250                              // don't touch samba share or Windows path backslashes
2251        if(!results.match(/\[\[\\\\.*?\|$/) && !text.match(/\w:(\\(\w?))+/ ))
2252         {
2253             text = text.replace(/([\*\\])/g, '%%$1%%');
2254
2255         }
2256    }
2257
2258    if(this.in_endnotes && HTMLParserTopNotes.length) {
2259
2260     if(text.match(/\w/) && ! text.match(/^\s*\d\)\s*$/)) {
2261       text= text.replace(/\)\s*$/, "_FN_PAREN_C_");
2262        var index = HTMLParserTopNotes.length-1;
2263        if(this.bottom_url)  {
2264            if(this.link_class && this.link_class == 'media') {
2265                text = '{{' + this.bottom_url + '|' +text +'}}';
2266            }
2267            else text = '[[' + this.bottom_url + '|' +text +']]';
2268         }
2269        if(HTMLParserBottomNotes[HTMLParserTopNotes[index]]) {
2270           HTMLParserBottomNotes[HTMLParserTopNotes[index]] += ' ' + text;
2271     }
2272        else  {
2273              HTMLParserBottomNotes[HTMLParserTopNotes[index]] = text;
2274        }
2275     }
2276     this.bottom_url = false;
2277     return;
2278    }
2279
2280    if(HTMLParser_PLUGIN) {
2281      HTMLParser_PLUGIN=false;
2282      if(results.match(/>\s*<\/plugin>\s*$/)) {
2283        results = results.replace(/\s*<\/plugin>\s*$/, text + '<\/plugin>');
2284        return;
2285      }
2286   }
2287   if(text && text.length) {
2288      results += text;
2289   }
2290   // remove space between formatted character entity and following character string
2291  results=results.replace(/(&\w+;)\s*([\*\/_]{2})_FORMAT_SPACE_(\w+)/,"$1$2$3");
2292
2293   if(this.list_level && this.list_level > 1) {
2294        results = results.replace(/(\[\[.*?\]\])([ ]+[\*\-].*)$/," $1\n$2");
2295   }
2296
2297   try {    // in case regex throws error on dynamic regex creation
2298        var regex = new RegExp('([\*\/\_]{2,})_FORMAT_SPACE_([\*\/\_]{2,})(' + RegExp.escape(text) + ')$');
2299        if(results.match(regex)) {
2300	        // remove left-over space inside multiple format sequences
2301            results = results.replace(regex,"$1$2$3");
2302        }
2303   } catch(ex){}
2304
2305  if(!HTMLParserOpenAngleBracket) {
2306       if(text.match(/&lt;/)) {
2307         HTMLParserOpenAngleBracket = true;
2308       }
2309  }
2310    },
2311
2312    comment: function( text ) {
2313     // results += "<!--" + text + "-->";
2314    },
2315
2316    dbg: function(text, heading) {
2317        <?php if($this->debug) { ?>
2318         if(text.replace) {
2319             text = text.replace(/^\s+/g,"");
2320             text = text.replace(/^\n$/g,"");
2321             if(!text) return;
2322         }
2323         if(heading) {
2324            heading = '<b>'+heading+"</b>\n";
2325         }
2326         HTMLParser_DEBUG += heading + text + "\n__________\n";
2327       <?php } ?>
2328    }
2329
2330    }
2331    );
2332
2333    //show_rowspans(CurrentTable);
2334    for(var i=0; i < fckgLPluginPatterns.length; i++) {
2335      fckgLPluginPatterns[i].pat = fckgLPluginPatterns[i].pat.replace(/\|/g,"\\|");
2336      fckgLPluginPatterns[i].pat = fckgLPluginPatterns[i].pat.replace(/([\(\)\{\}\.\?\[\]])/g, "\\$1");
2337      var pattern = new RegExp(fckgLPluginPatterns[i].pat,"gm");
2338      results = results.replace(pattern, fckgLPluginPatterns[i].orig);
2339    }
2340    /*
2341      we allow escaping of troublesome characters in plugins by enclosing them withinback slashes, as in \*\
2342      the escapes are removed here together with any DW percent escapes
2343   */
2344
2345     results = results.replace(/(\[\[\\\\)(.*?)\]\]/gm, function(match,brackets,block) {
2346          block=block.replace(/\\/g,"_SMB_");
2347          return brackets+block + ']]';
2348     });
2349
2350     results = results.replace(/%*\\%*([^\w]{1})%*\\%*/g, "$1");
2351     results=results.replace(/_SMB_/g, "\\");
2352
2353    if(id == 'test') {
2354      if(!HTMLParser_test_result(results)) return;
2355    }
2356	results = results.replace(/\{ \{ rss&gt;Feed:/mg,'{{rss&gt;http://');
2357    if(HTMLParser_FORMAT_SPACE) {
2358        if(HTMLParser_COLSPAN) {
2359             results =results.replace(/\s*([\|\^]+)((\W\W_FORMAT_SPACE_)+)/gm,function(match,pipes,format) {
2360                 format = format.replace(/_FORMAT_SPACE_/g,"");
2361                 return(format + pipes);
2362             });
2363        }
2364        results = results.replace(/&quot;/g,'"');
2365        var regex = new RegExp(HTMLParser_FORMAT_SPACE + '([\\-]{2,})', "g");
2366        results = results.replace(regex," $1");
2367
2368        var regex = new RegExp("(\\w|\\d)(\\*\\*|\\/\\/|\\'\\'|__|<\/del>)" + HTMLParser_FORMAT_SPACE + '(\\w|\\d)',"g");
2369        results = results.replace(regex,"$1$2$3");
2370
2371        var regex = new RegExp(HTMLParser_FORMAT_SPACE + '@@_SP_@@',"g");
2372        results = results.replace(regex,' ');
2373
2374		    //spacing around entities with double format characters
2375		results=results.replace(/([\*\/_]{2})@@_SP_@@(&\w+;)/g,"$1 $2");
2376
2377        results = results.replace(/\n@@_SP_@@\n/g,'');
2378        results = results.replace(/@@_SP_@@\n/g,'');
2379        results = results.replace(/@@_SP_@@/g,'');
2380
2381        var regex = new RegExp(HTMLParser_FORMAT_SPACE + '([^\\)\\]\\}\\{\\-\\.,;:\\!\?"\x94\x92\u201D\u2019' + "'" + '])',"g");
2382        results = results.replace(regex," $1");
2383        regex = new RegExp(HTMLParser_FORMAT_SPACE,"g");
2384        results = results.replace(regex,'');
2385
2386         if(HTMLFormatInList) {
2387             /* removes extra newlines from lists */
2388             results =  results.replace(/(\s+[\-\*_]\s*)([\*\/_\']{2})(.*?)(\2)([^\n]*)\n+/gm,
2389                        function(match,list_type,format,text, list_type_close, rest) {
2390                           return(list_type+format+text+list_type_close+rest +"\n");
2391             });
2392         }
2393    }
2394
2395    var line_break_final = "\\\\";
2396
2397    if(HTMLParser_LBR) {
2398        results = results.replace(/(L_BR_K)+/g,line_break_final);
2399        results = results.replace(/L_BR_K/gm, line_break_final) ;
2400	    results = results.replace(/(\\\\)\s+/gm, "$1 \n");
2401    }
2402
2403    if(HTMLParser_PRE) {
2404      results = results.replace(/\s+<\/(code|file)>/g, "\n</" + "$1" + ">");
2405      if(HTMLParser_Geshi) {
2406        results = results.replace(/\s+;/mg, ";");
2407        results = results.replace(/&lt;\s+/mg, "<");
2408        results = results.replace(/\s+&gt;/mg, ">");
2409
2410      }
2411    }
2412
2413    if(HTMLParser_TABLE) {
2414     results += "\n" + line_break_final + "\n";
2415     var regex = new RegExp(HTMLParserParaInsert,"g");
2416     results = results.replace(regex, ' ' +line_break_final + ' ');
2417
2418   // fix for colspans which have had text formatting which cause extra empty cells to be created
2419     results = results.replace(/(\||\^)[ ]+(\||\^)\s$/g, "$1\n");
2420     results = results.replace(/(\||\^)[ ]+(\||\^)/g, "$1");
2421
2422     // prevents valid empty td/th cells from being removed above
2423     //results = results.replace(/_FCKG_BLANK_TD_/g, " ");
2424
2425
2426    }
2427    results = results.replace(/_FCKG_BLANK_TD_/g, " ");
2428    if(HTMLParserOpenAngleBracket) {
2429         results = results.replace(/\/\/&lt;\/\/\s*/g,'&lt;');
2430    }
2431   if(HTMLParserTopNotes.length) {
2432        results = results.replace(/\(\(+(\d+)\)\)+/,"(($1))");
2433        for(var i in HTMLParserBottomNotes) {  // re-insert DW's bottom notes at text level
2434            var matches =  i.match(/_(\d+)/);
2435            var pattern = new RegExp('(\<sup\>)*[\(]+' + matches[1] +  '[\)]+(<\/sup>)*');
2436            results = results.replace(pattern,'((' + HTMLParserBottomNotes[i].replace(/_FN_PAREN_C_/g, ") ") +'))');
2437         }
2438       results = results.replace(/<sup><\/sup>/g, "");
2439    }
2440
2441    results = results.replace(/(={3,}.*?)(\{\{.*?\}\})(.*?={3,})/g,"$1$3\n\n$2");
2442    // remove any empty footnote markup left after section re-edits
2443    results = results.replace(/(<sup>)*\s*\[\[\s*\]\]\s*(<\/sup>)*\n*/g,"");
2444
2445    if(HTMLParser_MULTI_LINE_PLUGIN) {
2446        results = results.replace(/<\s+/g, '<');
2447        results = results.replace(/&lt;\s+/g, '<');
2448    }
2449
2450   if(HTMLParser_NOWIKI) {
2451      /* any characters escaped by DW %%<char>%% are replaced by NOWIKI_<char>
2452         <char> is restored in save.php
2453     */
2454      var nowiki_escapes = '%';  //this technique allows for added chars to attach to NOWIKI_$1_
2455      var regex = new RegExp('([' + nowiki_escapes + '])', "g");
2456
2457      results=results.replace(/(&lt;nowiki&gt;)(.*?)(&lt;\/nowiki&gt;)/mg,
2458             function(all,start,mid,close) {
2459                     mid = mid.replace(/%%(.)%%/mg,"NOWIKI_$1_");
2460                     return start + mid.replace(regex,"NOWIKI_$1_") + close;
2461             });
2462    }
2463
2464    results = results.replace(/SWF(\s*)\[*/g,"{{$1");
2465    results = results.replace(/\|.*?\]*(\s*)FWS/g,"$1}}");
2466    results = results.replace(/(\s*)FWS/g,"$1}}");
2467    results = results.replace(/\n{3,}/g,'\n\n');
2468    results = results.replace(/_LIST_EOFL_/gm, " " + line_break_final + " ");
2469
2470    if(embedComplexTableMacro) {
2471        if(results.indexOf('~~COMPLEX_TABLES~~') == -1) {
2472           results += "\n~~COMPLEX_TABLES~~\n"
2473        }
2474    }
2475
2476    if(id == 'test') {
2477      if(HTMLParser_test_result(results)) {
2478         alert(results);
2479      }
2480      return;
2481    }
2482
2483    var dwform = GetE('dw__editform');
2484    dwform.elements.fck_wikitext.value = results;
2485
2486   if(id == 'bakup') {
2487      //alert(results);
2488      return;
2489   }
2490    if(id) {
2491       var dom =  GetE(id);
2492      dom.click();
2493      return true;
2494    }
2495}
2496
2497<?php if($this->debug) { ?>
2498   function HTMLParser_debug() {
2499       HTMLParser_DEBUG = "";
2500       parse_wikitext("");
2501/*
2502      for(var i in oDokuWiki_FCKEditorInstance) {
2503         HTMLParser_DEBUG += i + ' = ' + oDokuWiki_FCKEditorInstance[i] + "\n";;
2504       }
2505*/
2506
2507       var w = window.open();
2508       w.document.write('<pre>' + HTMLParser_DEBUG + '</pre>');
2509       w.document.close();
2510  }
2511<?php } ?>
2512
2513<?php
2514
2515  $url = DOKU_BASE . 'lib/plugins/fckg/scripts/script-cmpr.js';
2516  echo "var script_url = '$url';";
2517//  $safe_url = DOKU_URL . 'lib/plugins/fckg/scripts/safeFN_cmpr.js';
2518?>
2519
2520
2521try {
2522  if(!HTMLParserInstalled){
2523    LoadScript(script_url);
2524  }
2525}
2526catch (ex) {
2527   LoadScript(script_url);
2528}
2529
2530
2531if(window.DWikifnEncode && window.DWikifnEncode == 'safe') {
2532   LoadScript(DOKU_BASE + 'lib/plugins/fckg/scripts/safeFN_cmpr.js' );
2533}
2534
2535
2536 //]]>
2537
2538  </script>
2539
2540
2541         </div>
2542<?php } ?>
2543
2544      <?php if($wr){ ?>
2545        <div class="summary">
2546           <label for="edit__summary" class="nowrap"><?php echo $lang['summary']?>:</label>
2547           <input type="text" class="edit" name="summary" id="edit__summary" size="50" value="<?php echo formText($SUM)?>" tabindex="2" />
2548          <label class="nowrap" for="minoredit"><input type="checkbox" id="minoredit" name="minor" value="1" tabindex="3" /> <span><?php echo $fckg_lang['minor_changes'] ?></span></label>
2549        </div>
2550      <?php }?>
2551  </div>
2552  </form>
2553
2554  <!-- draft messages from DW -->
2555  <div id="draft__status"></div>
2556
2557<?php
2558    }
2559
2560    /**
2561     * Renders a list of instruction to minimal xhtml
2562     *@author Myron Turner <turnermm02@shaw.ca>
2563     */
2564    function _render_xhtml($text){
2565        $mode = 'fckg';
2566
2567       global $Smilies;
2568       $smiley_as_text = @$this->getConf('smiley_as_text');
2569       if($smiley_as_text) {
2570
2571           $Smilies = array('8-)'=>'aSMILEY_1', '8-O'=>'aSMILEY_2',  ':-('=>'aSMILEY_3',  ':-)'=>'aSMILEY_4',
2572             '=)' => 'aSMILEY_5',  ':-/' => 'aSMILEY_6', ':-\\' => 'aSMILEY_7', ':-?' => 'aSMILEY_8',
2573             ':-D'=>'aSMILEY_9',  ':-P'=>'bSMILEY_10',  ':-O'=>'bSMILEY_11',  ':-X'=>'bSMILEY_12',
2574             ':-|'=>'bSMILEY_13',  ';-)'=>'bSMILEY_14',  '^_^'=>'bSMILEY_15',  ':?:'=>'bSMILEY_16',
2575             ':!:'=>'bSMILEY_17',  'LOL'=>'bSMILEY_18',  'FIXME'=>'bSMILEY_19',  'DELETEME'=>'bSMILEY_20');
2576
2577          $s_values = array_values($Smilies);
2578          $s_values_regex = implode('|', $s_values);
2579            $s_keys = array_keys($Smilies);
2580            $s_keys = array_map  ( create_function(
2581               '$k',
2582               'return "(" . preg_quote($k,"/") . ")";'
2583           ) ,
2584            $s_keys );
2585
2586
2587
2588           $s_keys_regex = implode('|', $s_keys);
2589             global $haveDokuSmilies;
2590             $haveDokuSmilies = false;
2591             $text = preg_replace_callback(
2592                '/(' . $s_keys_regex . ')/ms',
2593                 create_function(
2594                '$matches',
2595                'global $Smilies;
2596                 global $haveDokuSmilies;
2597                 $haveDokuSmilies = true;
2598                 return $Smilies[$matches[1]];'
2599                 ), $text
2600             );
2601
2602       }
2603
2604        // try default renderer first:
2605        $file = DOKU_INC."inc/parser/$mode.php";
2606
2607        if(@file_exists($file)){
2608
2609            require_once $file;
2610            $rclass = "Doku_Renderer_$mode";
2611
2612            if ( !class_exists($rclass) ) {
2613                trigger_error("Unable to resolve render class $rclass",E_USER_WARNING);
2614                msg("Renderer for $mode not valid",-1);
2615                return null;
2616            }
2617            $Renderer = new $rclass();
2618        }
2619        else{
2620            // Maybe a plugin is available?
2621            $Renderer = plugin_load('renderer',$mode);
2622            if(is_null($Renderer)){
2623                msg("No renderer for $mode found",-1);
2624                return null;
2625            }
2626        }
2627
2628        // prevents utf8 conversions of quotation marks
2629         $text = str_replace('"',"_fckg_QUOT_",$text);
2630
2631         $text = preg_replace_callback('/(<code|file.*?>)(.*?)(<\/code>)/ms',
2632             create_function(
2633               '$matches',
2634               '$quot =  str_replace("_fckg_QUOT_",\'"\',$matches[2]);
2635                $quot = str_replace("\\\\ ","_fckg_NL",$quot);
2636                return $matches[1] . $quot . $matches[3];'
2637          ), $text);
2638
2639
2640        global $fckgLPluginPatterns;
2641        $fckgLPluginPatterns = array();
2642
2643        $instructions = p_get_instructions("=== header ==="); // loads DOKU_PLUGINS array --M.T. Dec 22 2009
2644
2645        $installed_plugins = $this->get_plugins();
2646        $regexes = $installed_plugins['plugins'];
2647
2648        $text = preg_replace_callback('/('. $regexes .')/',
2649                create_function(
2650                '$matches',
2651                'global $fckgLPluginPatterns;
2652                 $retv =  preg_replace("/([\{\}\@\:&~\?\!<>])/", "$1 ", $matches[0]);
2653                 $fckgLPluginPatterns[] = array($retv, $matches[0]);
2654                 return $retv;'
2655               ),
2656          $text);
2657
2658        global $fckLImmutables;
2659        $fckglImmutables=array();
2660
2661         foreach($installed_plugins['xcl'] as $xcl) {
2662               $text = preg_replace_callback('/'. $xcl . '/',
2663               create_function(
2664               '$matches',
2665              'global $fckLImmutables;
2666               if(preg_match("#//<//font#",$matches[0])) {
2667                   return str_replace("//<//", "<", $matches[0]);
2668               }
2669               $index = count($fckLImmutables);
2670               $fckLImmutables[] = $matches[0];
2671               return "<span id=\'imm_" . "$index\' title=\'imm_" . "$index\' >" . str_replace("//<//", "<", $matches[0]) . "</span>" ;'
2672
2673              ),
2674          $text);
2675
2676          }
2677
2678            global $multi_block;
2679            if(preg_match('/(?=MULTI_PLUGIN_OPEN)(.*?)(?<=MULTI_PLUGIN_CLOSE)/ms', $text, $matches)) {
2680             //file_put_contents('multi_text-2.txt',$matches[1]);
2681             $multi_block = $matches[1];
2682           }
2683
2684
2685
2686        $instructions = p_get_instructions($text);
2687        if(is_null($instructions)) return '';
2688
2689
2690        $Renderer->notoc();
2691        $Renderer->smileys = getSmileys();
2692        $Renderer->entities = getEntities();
2693        $Renderer->acronyms = array();
2694        $Renderer->interwiki = getInterwiki();
2695
2696        // Loop through the instructions
2697        foreach ( $instructions as $instruction ) {
2698            // Execute the callback against the Renderer
2699            call_user_func_array(array(&$Renderer, $instruction[0]),$instruction[1]);
2700        }
2701
2702        //set info array
2703        $info = $Renderer->info;
2704
2705        // Post process and return the output
2706        $data = array($mode,& $Renderer->doc);
2707        trigger_event('RENDERER_CONTENT_POSTPROCESS',$data);
2708        $xhtml = $Renderer->doc;
2709
2710        $pos = strpos($xhtml, 'MULTI_PLUGIN_OPEN');
2711        if($pos !== false) {
2712           $xhtml = preg_replace('/MULTI_PLUGIN_OPEN.*?MULTI_PLUGIN_CLOSE/ms', $multi_block, $xhtml);
2713           $xhtml = preg_replace_callback(
2714            '|MULTI_PLUGIN_OPEN.*?MULTI_PLUGIN_CLOSE|ms',
2715            create_function(
2716                '$matches',
2717                  '$matches[0] = str_replace("//<//", "< ",$matches[0]);
2718                  return preg_replace("/\n/ms","<br />",$matches[0]);'
2719            ),
2720            $xhtml
2721          );
2722
2723           $xhtml = preg_replace('/~\s*~\s*MULTI_PLUGIN_OPEN~\s*~/', "~ ~ MULTI_PLUGIN_OPEN~ ~\n\n<span class='multi_p_open'>\n\n</span>", $xhtml);
2724           $xhtml = preg_replace('/~\s*~\s*MULTI_PLUGIN_CLOSE~\s*~/', "<span class='multi_p_close'>\n\n</span>\n\n~ ~ MULTI_PLUGIN_CLOSE~ ~\n", $xhtml);
2725
2726
2727        }
2728
2729         // remove empty paragraph: see _fckg_NPBBR_ comment above
2730        $xhtml = preg_replace('/<p>\s+_fckg_NPBBR_\s+<\/p>/ms',"\n",$xhtml);
2731        $xhtml = str_replace('_fckg_NPBBR_', "<span class='np_break'>&nbsp;</span>", $xhtml);
2732        $xhtml = str_replace('_fckg_QUOT_', '&quot;', $xhtml);
2733        $xhtml = str_replace('_fckg_NL', "\n", $xhtml);
2734        $xhtml = str_replace('</pre>', "\n\n</pre><p>&nbsp;</p>", $xhtml);
2735        // inserts p before an initial codeblock to enable text entry above block
2736        $xhtml = preg_replace('/^<pre/',"<p>&nbsp;</p><pre",$xhtml);
2737        //remove empty markup remaining after removing marked-up acronyms in lists
2738        $xhtml = preg_replace('/<(em|b|u|i)>\s+<\/(em|b|u|i)>/ms',"",$xhtml);
2739
2740
2741       if($smiley_as_text) {
2742           if($haveDokuSmilies) {
2743                 $s_values = array_values($Smilies);
2744                 $s_values_regex = (implode('|', $s_values));
2745
2746                 $xhtml = preg_replace_callback(
2747                     '/(' . $s_values_regex . ')/ms',
2748                     create_function(
2749                     '$matches',
2750                    'global $Smilies;
2751                     return array_search($matches[1],$Smilies); '
2752                     ), $xhtml
2753                 );
2754            }
2755          }
2756
2757       $ua = strtolower ($_SERVER['HTTP_USER_AGENT']);
2758	  if(strpos($ua,'chrome') !== false) {
2759       $xhtml = preg_replace_callback(
2760             '/(?<=<a )(href=\".*?\")(\s+\w+=\".*?\")(.*?)(?=>)/sm',
2761			 create_function(
2762			 '$matches',
2763			 '$ret_str = " " . trim($matches[3]) . " " . trim($matches[2])  . " " . trim($matches[1]) ;
2764			  return $ret_str;'
2765			 ),
2766			 $xhtml
2767			 );
2768		}
2769
2770        return $xhtml;
2771    }
2772
2773  function write_debug($what) {
2774     return;
2775     $handle = fopen("edit_php.txt", "a");
2776     if(is_array($what)) $what = print_r($what,true);
2777     fwrite($handle,"$what\n");
2778     fclose($handle);
2779  }
2780 /**
2781  *  @author Myron Turner <turnermm02@shaw.ca>
2782  *  Converts FCK extended syntax to native DokuWiki syntax
2783 */
2784  function fck_convert_text(&$event) {
2785  }
2786
2787
2788 function big_file() {
2789 }
2790
2791/**
2792 * get regular expressions for installed plugins
2793 * @author     Myron Turner <turnermm02@shaw.ca>
2794 * return string of regexes suitable for PCRE matching
2795*/
2796 function get_plugins() {
2797 global $DOKU_PLUGINS;
2798
2799 $list = plugin_list('syntax');
2800 $data =  $DOKU_PLUGINS['syntax'][$list[0]]->Lexer->_regexes['base']->_labels;
2801 $patterns = $DOKU_PLUGINS['syntax'][$list[0]]->Lexer->_regexes['base']->_patterns;
2802 $labels = array();
2803 $regex = '~~NOCACHE~~|~~NOTOC~~';
2804 //$regex .= "|\{\{rss>http:\/\/.*?\}\}";
2805
2806 $exclusions = $this->getConf('xcl_plugins');
2807 $exclusions = trim($exclusions, " ,");
2808 $exclusions = explode  (',', $exclusions);
2809 $exclusions[] = 'fckg_font';
2810 $list = array_diff($list,$exclusions);
2811
2812 foreach($list as $plugin) {
2813   if(preg_match('/fckg_dwplugin/',$plugin)) continue;
2814   $plugin = 'plugin_' . $plugin;
2815
2816   $indices = array_keys($data, $plugin);
2817   if(empty($indices)) {
2818       $plugin = '_' . $plugin;
2819
2820      $indices = array_keys($data, $plugin);
2821   }
2822
2823   if(!empty($indices)) {
2824       foreach($indices as $index) {
2825          $labels[] = "$index: " . $patterns[$index];
2826          $pattern = $patterns[$index];
2827          $pattern = preg_replace('/^\(\^/',"(",$pattern);
2828          $regex .= "|$pattern";
2829       }
2830    }
2831
2832 }
2833 $regex = ltrim($regex, '|');
2834
2835 $regex_xcl = array();
2836 foreach($exclusions as $plugin) {
2837   if(preg_match('/fckg_dwplugin/',$plugin)) continue;
2838   $plugin = 'plugin_' . $plugin;
2839
2840   $indices = array_keys($data, $plugin);
2841   if(empty($indices)) {
2842       $plugin = '_' . $plugin;
2843      $indices = array_keys($data, $plugin);
2844   }
2845
2846   if(!empty($indices)) {
2847       foreach($indices as $index) {
2848            $pos = strpos($patterns[$index],'<');
2849            if($pos !== false) {
2850               $pattern = str_replace('<', '\/\/<\/\/', $patterns[$index]);
2851               $pattern = str_replace('?=',"",$pattern);
2852               $regex_xcl[] = $pattern;
2853            }
2854          }
2855       }
2856    }
2857
2858 return array('plugins'=> $regex, 'xcl'=> $regex_xcl);
2859 //return $regex;
2860
2861 }
2862
2863} //end of action class
2864
2865
2866?>
2867