'Troy Rollo', 'email' => 'dokuwiki@troy.rollo.name', 'date' => '2008-06-10', 'name' => 'Complex Lists Plugin', 'desc' => 'Add complex multi-level lists', 'url' => 'http://wiki.splitbrain.org/plugin:complex_lists' ); } function syntax_plugin_complex_lists(){ } function getAllowedTypes() { return array('container', 'paragraphs', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); } function getType(){ return 'container'; } function getPType(){ return 'block'; } function getSort(){ return 15; } function connectTo($mode) { $this->Lexer->addEntryPattern('\n#[^\n#]+\|[^\n#]+#\n', $mode, 'plugin_complex_lists'); } function postConnect() { $this->Lexer->addPattern('\n#\n', 'plugin_complex_lists'); $this->Lexer->addPattern('\n#\+#\n', 'plugin_complex_lists'); $this->Lexer->addPattern('\n#-#\n', 'plugin_complex_lists'); $this->Lexer->addPattern('#:[^#]+#', 'plugin_complex_lists'); $this->Lexer->addExitPattern('\n##\n','plugin_complex_lists'); } function handle($match, $state, $pos, &$handler){ switch ($state) { case DOKU_LEXER_ENTER: return array($state, $this->list_styles = explode('|', trim($match, "#\r\n"))); case DOKU_LEXER_EDIT: return array($state); case DOKU_LEXER_UNMATCHED: $handler->base($match, $state, $pos); return array($state); case DOKU_LEXER_MATCHED: $match = trim($match, "\n"); switch ($match) { case '#': return array($state, 0); case '#+#': return array($state, 1); case '#-#': return array($state, 2); default: /* Bookmark */ return array($state, 3, substr(trim($match, '#'), 1)); } } return array($state); } function romanNum($n) { $r = ''; while ($n >= 1000) { $n -= 1000; $r = $r . 'm'; } if ($n >= 900) { $r = $r . 'cm'; $n -= 900; } if ($n >= 500) { $r = $r . 'd'; $n -= 500; } if ($n > 400) { $r = $r . 'cd'; $n -= 400; } while ($n >= 100) { $r = $r . 'c'; $n -= 100; } if ($n >= 90) { $r = $r . 'xc'; $n -= 90; } if ($n >= '50') { $r = $r . 'l'; $n -= 50; } if ($n >= '40') { $r = $r . 'xl'; $n -= 40; } while ($n >= 10) { $r = $r . 'x'; $n -= 10; } if ($n == 9) { $r = $r . 'ix'; $n = 0; } if ($n >= 5) { $r = $r .'v'; $n -= 5; } if ($n == 4) { $r = $r . 'iv'; $n = 0; } while ($n > 0) { $r = $r . 'i'; --$n; } return $r; } function latinNum($n) { $r = ''; $j=0; while ($n > 0 && $j < 20) { $d = $n % 27; $r = chr(0x60 + $d); $n = ($n - $d) / 27; if ($n > 0) ++$n; ++$j; } return $r; } function getLevelText($counters, $level) { $str = $this->list_styles[$level - 1]; $len = strlen($str); $type = 0; $n = $counters[$level]; for ($loc = 0; $loc < $len; ++$loc) { $type = strpos("01aAiI", substr($str, $loc, 1)); if ($type) break; } switch ($type) { default: return '???'; case 1: $numtext = $n; break; case 2: $numtext = $this->latinNum($n); break; case 3: $numtext = strtoupper($this->latinNum($n)); break; case 4: $numtext = $this->romanNum($n); break; case 5: $numtext = strtoupper($this->romanNum($n)); break; } return htmlspecialchars(substr($str, 0, $loc) . $numtext . substr($str, $loc + 1)); } function getListText() { return $this->getLevelText($this->list_counters, $this->list_level); } function startList() { $this->list_level += 1; $this->list_counters[$this->list_level] = 0; return '' . "\n"; } function startListItem() { $this->list_counters[$this->list_level] += 1; return '\n"; } function endList() { if ($this->list_level > 0) { $this->list_level -= 1; return "
' . $this->getListText() . '' . "\n"; } function endListItem() { if ($this->list_level > 0) return "
\n"; } } function getListLevelNow() { return $this->list_level; } /** * Create output */ function render($mode, &$renderer, $data) { if($mode == 'xhtml'){ $first = 1; switch ($data[0]) { case DOKU_LEXER_UNMATCHED: //$renderer->doc .= "
[$data[1]]
"; return false; case DOKU_LEXER_ENTER: $this->bookmarks = array(); $this->list_styles = $data[1]; $this->list_level = 0; $renderer->doc .= ''; $renderer->doc .= $this->startList() . $this->startListItem(); return true; case DOKU_LEXER_MATCHED: switch ($data[1]) { case 0: $renderer->doc .= $this->endListItem() . $this->startListItem(); break; case 1: $renderer->doc .= $this->startList() . $this->startListItem(); break; case 2: $renderer->doc .= $this->endListItem() . $this->endList(); break; case 3: $this->bookmarks[$data[2]][0] = $this->list_level; $this->bookmarks[$data[2]][1] = $this->list_counters; break; } return true; case DOKU_LEXER_EXIT: while ($this->list_level > 0) { $renderer->doc .= $this->endListItem() . $this->endList(); } $pos = strpos($renderer->doc, ''); $listtext = substr($renderer->doc, $pos + 22); $renderer->doc = substr($renderer->doc, 0, $pos); $level = 1; $lcounters[1] = 0; while ($listtext) { $pos = strpos($listtext, ''); if (!$pos) { $renderer->doc .= 'Catastrophe'; break; } $command = explode('#', substr($listtext, 0, $pos)); $listtext = substr($listtext, $pos + 3); switch ($command[0]) { case 'XREF': $bookmark = $this->bookmarks[$command[2]]; if ($bookmark) { if ($command[1] == 2) { for ($i = 1; $i <= $bookmark[0]; ++$i) $renderer->doc .= $this->getLevelText($bookmark[1], $i); } else { $last = $bookmark[0]; $first = $last; if ($first > $level) $first = $level + 1; for ($i = 1; $i < $first; ++$i) { if ($lcounters[$i] != $bookmark[1][$i]) { $first = $i; break; } } for ($i = $first; $i <= $last; ++$i) $renderer->doc .= $this->getLevelText($bookmark[1], $i); } } else { $renderer->doc .= 'Bookmark not found!'; } break; case 'ENDSUB': --$level; break; case 'ITEM': if ($command[1] > $level) $level = $command[1]; $lcounters[$level] = $command[2]; break; default: $renderer->doc .= 'Bad command: ' . $command[0] . '!'; } } return true; } } return false; } } //Setup VIM: ex: et ts=4 enc=utf-8 : ?>