parse($lines);
return $body->toString();
}
// インライン要素の変換
function guiedit_make_link($line)
{
$obj = new InlineConverterEx();
return $obj->convert($line);
}
// 添付ファイルプラグインの変換
function guiedit_convert_ref($args, $div = TRUE) {
$options = htmlspecialchars(join(',', $args));
$filename = array_shift($args);
$_title = array();
$params = array(
'left' => 0, // 左寄せ
'center' => 0, // 中央寄せ
'right' => 0, // 右寄せ
'wrap' => 0, // TABLEで囲む
'nowrap' => 0, // TABLEで囲まない
'around' => 0, // 回り込み
'noicon' => 0, // アイコンを表示しない
'nolink' => 0, // 元ファイルへのリンクを張らない
'noimg' => 0, // 画像を展開しない
'zoom' => 0, // 縦横比を保持する
'_w' => 0, // 幅
'_h' => 0, // 高さ
'_size' => '%'
);
// パラメータ解析
foreach ($args as $arg) {
$s_arg = strtolower($arg);
if (array_key_exists($s_arg, $params)) {
$params[$s_arg] = 1;
} else if (preg_match('/^([0-9]+)x([0-9]+)$/', $arg, $matches)) {
$params['_w'] = $matches[1];
$params['_h'] = $matches[2];
$params['_size'] = 'px';
} else if (preg_match('/^([0-9.]+)%$/', $arg, $matches) && $matches[1] > 0) {
$params['_w'] = $matches[1];
} else {
$_title[] = $arg;
}
}
$align = '';
if ($params['left']) {
$align = 'left';
} else if ($params['center']) {
$align = 'center';
} else if ($params['right']) {
$align = 'right';
}
$alt = !empty($_title) ? htmlspecialchars(join(',', $_title)) : '';
$alt = preg_replace("/^,/", '', $alt);
$attribute = 'class="ref" contenteditable="false"' . ((UA_NAME == MSIE) ? '' : ' style="cursor:default"');
$attribute .= ' _filename="' . $filename . '"';
$attribute .= ' _alt="' . $alt . '"';
$attribute .= ' _width="' . ($params['_w'] ? $params['_w'] : '') . '"';
$attribute .= ' _height="' . ($params['_h'] ? $params['_h'] : '') . '"';
$attribute .= ' _size="' . $params['_size'] . '"';
$attribute .= ' _align="' . $align . '"';
$attribute .= ' _wrap="' . $params['wrap'] . '"';
$attribute .= ' _around="' . $params['around'] . '"';
$attribute .= ' _nolink="' . $params['nolink'] . '"';
$attribute .= ' _noicon="' . $params['noicon'] . '"';
$attribute .= ' _noimg="' . $params['noimg'] . '"';
$attribute .= ' _zoom="' . $params['zoom'] . '"';
if ($div) {
$tags = "
#ref($options)
";
}
else {
$tags = "&ref($options);";
}
return $tags;
}
function guiedit_make_line_rules($line) {
global $guiedit_line_rules, $guiedit_facemark_rules;
global $usefacemark;
static $pattern, $replace;
if (!isset($pattern)) {
if ($usefacemark) {
$guiedit_line_rules += $guiedit_facemark_rules;
}
$pattern = array_map(create_function('$a', 'return \'/\' . $a . \'/\';'), array_keys($guiedit_line_rules));
$replace = array_values($guiedit_line_rules);
unset($guiedit_facemark_rules);
unset($guiedit_line_rules);
}
return preg_replace($pattern, $replace, $line);
}
// インライン変換クラス
class InlineConverterEx {
function convert($line, $link = TRUE, $enc = TRUE) {
if ($enc) {
$line = preg_replace("/&/", "&", $line);
$line = htmlspecialchars($line);
}
// インライン・プラグイン
$pattern = '/&(\w+)(?:\(((?:(?!\)[;{]).)*)\))?(?:\{((?:(?R)|(?!};).)*)\})?;/';
$line = preg_replace_callback($pattern, array(&$this, 'convert_plugin'), $line);
// ルールの変換
$line = guiedit_make_line_rules($line);
// 文字サイズの変換
$pattern = "//";
$line = preg_replace_callback($pattern, array(&$this, 'convert_size'), $line);
// 色の変換
$pattern = "//";
$line = preg_replace_callback($pattern, array(&$this, 'convert_color'), $line);
// 注釈
$line = preg_replace("/\(\(((?:(?R)|(?!\)\)).)*)\)\)/", "", $line);
// 参照文字
$line = preg_replace('/&(#?[a-z0-9]+);/', "&$1;", $line);
// 上付き文字
$line = preg_replace('/SUP{(.*?)}/', "$1", $line);
// 下付き文字・添え字
$line = preg_replace('/SUB{(.*?)}/', "$1", $line);
// リンク
if ($link) {
$pattern = "/\(\(((?:(?R)|(?!\)\)).)*)\)\)/";
$replace = "";
$line = $this->make_link($line);
}
if (preg_match("/^
$/", $line)) {
$line .= "\n ";
}
return $line;
}
// 文からリンクを検出し、link_replace を呼び出す
function make_link($line) {
$link_rules = "/(
(?:\[\[((?:(?!\]\]).)+):)?
((?:https?|ftp|news)(?::\/\/[!~*'();\/?:\@&=+\$,%#\w.-]+))
(?(2)\]\])
|
(\[\[
(?:
(?:((?:(?!\]\]).)+))
(?:>)
)?
(?:
(\#(?:[a-zA-Z][\w-]*)?)
|
((?:(?!\]\]).)*)
)?
\]\])
)/x";
return preg_replace_callback($link_rules, array(&$this,'link_replace'), $line);
}
// make_link で検出したリンクにリンクタグを付加する
function link_replace($matches) {
if ($matches[3] != '') {
if (!$matches[2]) {
return $matches[3];
}
$url = $matches[3];
$alias = empty($matches[2]) ? $url : $matches[2];
return ''.$alias.'';
}
if ($matches[6] != '') {
$str = empty($matches[5]) ? $matches[6] : $matches[5];
return '' . $str.'';
}
if ($matches[7] != '') {
$str = empty($matches[5]) ? $matches[7] : $matches[5];
return '' . $str . '';
}
return $matches[0];
}
// インラインプラグイン処理メソッド
function convert_plugin($matches) {
$aryargs = (!empty($matches[2])) ? explode(',', $matches[2]) : array();
$name = strtolower($matches[1]);
$body = empty($matches[3]) ? '' : $matches[3];
// プラグインが存在しない場合はそのまま返す。
// if (!file_exists(PLUGIN_DIR . $name . '.inc.php')) {
if (!exist_plugin($name)) {
return $matches[0];
}
switch ($name) {
case 'aname':
return ''.$body.'';
case 'br':
return '
';
case 'color':
$color = $aryargs[0];
$bgcolor = $aryargs[1];
if ($body == '')
return '';
if ($color != '' && !preg_match('/^(#[0-9a-f]+|[\w-]+)$/i', $color))
return $body;
if ($bgcolor != '' && !preg_match('/^(#[0-9a-f]+|[\w-]+)$/i', $bgcolor))
return $body;
if ($color != '')
$color = 'color:'.$color;
if ($bgcolor != '')
$bgcolor = ($color ? '; ' : '') . 'background-color:'.$bgcolor;
return '' . $this->convert($body, TRUE, FALSE) . '';
case 'sup':
case 'sub':
return '<'.$name.'>'.$body.''.$name.'>';
case 'size':
$size = $aryargs[0];
if ($size == '' || $body == '')
return '';
if (!preg_match('/^\d+$/', $size))
return $body;
return '' .
$this->convert($body, TRUE, FALSE) . "";
case 'ref':
return guiedit_convert_ref($aryargs, FALSE);
}
if ($body) {
$pattern = array("%%", "''", "[[", "]]", "{", "|", "}");
$replace = array("%%", "''", "[[",
"]]", "{", "|", "}");
$body = str_replace($pattern, $replace, $body);
}
$inner = '&' . $matches[1] . ($matches[2] ? '('.$matches[2].')' : '') . ($body ? '{'.$body.'}' : '') . ';';
$style = (UA_NAME == MSIE) ? '' : ' style="cursor:default"';
return ''.$inner.'';
}
// 色の変換
function convert_color($matches) {
$color = $matches[1];
$bgcolor = $matches[3];
if ($bgcolor && preg_match("/^#[0-9a-z]{3}$/i", $bgcolor)) {
$bgcolor = "; background-color:" . preg_replace('/[0-9a-f]/i', "$0$0", $bgcolor);
}
if (preg_match("/^#[0-9a-z]{3}$/i", $color)) {
$color = preg_replace('/[0-9a-f]/i', "$0$0", $color);
}
// return "";
// UPK
return '';
}
// 文字サイズの変換
function convert_size($matches) {
if ($matches[2]) {
$size = $matches[2];
if ($size <= 8) $size = 8;
else if ($size <= 9) $size = 9;
else if ($size <= 10) $size = 10;
else if ($size <= 11) $size = 11;
else if ($size <= 12) $size = 12;
else if ($size <= 14) $size = 14;
else if ($size <= 16) $size = 16;
else if ($size <= 18) $size = 18;
else if ($size <= 22) $size = 20;
else if ($size <= 26) $size = 24;
else if ($size <= 30) $size = 28;
else if ($size <= 36) $size = 32;
else if ($size <= 44) $size = 40;
else if ($size <= 52) $size = 48;
else $size = 60;
return '';
}
switch ($matches[3]) {
case 1: $size = 'xx-small';
case 2: $size = 'x-small';
case 3: $size = 'small';
case 4: $size = 'medium';
case 5: $size = 'large';
case 6: $size = 'x-large';
case 7: $size = 'xx-large';
}
return '';
}
}
// Block elements
class ElementEx
{
var $parent;
var $elements; // References of childs
var $last; // Insert new one at the back of the $last
function ElementEx()
{
$this->elements = array();
$this->last = & $this;
}
function setParent(& $parent)
{
$this->parent = & $parent;
}
function & add(& $obj)
{
if ($this->canContain($obj)) {
return $this->insert($obj);
} else {
return $this->parent->add($obj);
}
}
function & insert(& $obj)
{
$obj->setParent($this);
$this->elements[] = & $obj;
return $this->last = & $obj->last;
}
function canContain($obj)
{
return TRUE;
}
function wrap($string, $tag, $param = '', $canomit = TRUE)
{
return ($canomit && $string == '') ? '' :
'<' . $tag . $param . '>' . $string . '' . $tag . '>';
}
function toString()
{
$ret = array();
foreach (array_keys($this->elements) as $key)
$ret[] = $this->elements[$key]->toString();
return join("\n", $ret);
}
function dump($indent = 0)
{
$ret = str_repeat(' ', $indent) . get_class($this) . "\n";
$indent += 2;
foreach (array_keys($this->elements) as $key) {
$ret .= is_object($this->elements[$key]) ?
$this->elements[$key]->dump($indent) : '';
//str_repeat(' ', $indent) . $this->elements[$key];
}
return $ret;
}
}
// Returns inline-related object
function & Factory_InlineEx($text)
{
// Check the first letter of the line
if (substr($text, 0, 1) == '~') {
// return new ParagraphEx(' ' . substr($text, 1));
$obj = new ParagraphEx(' ' . substr($text, 1));
} else {
// return new InlineEx($text);
$obj = new InlineEx($text);
}
return $obj;
}
function & Factory_DListEx(& $root, $text)
{
$out = explode('|', ltrim($text), 2);
if (count($out) < 2) {
return Factory_InlineEx($text);
} else {
return new DListEx($out);
}
}
// '|'-separated table
function & Factory_TableEx(& $root, $text)
{
if (! preg_match('/^\|(.+)\|([hHfFcC]?)$/', $text, $out)) {
return Factory_InlineEx($text);
} else {
// return new TableEx($out);
$obj = new TableEx($out);
return $obj;
}
}
// Comma-separated table
function & Factory_YTableEx(& $root, $text)
{
if ($text == ',') {
return Factory_InlineEx($text);
} else {
// return new YTableEx(csv_explode(',', substr($text, 1)));
$obj = new YTableEx(csv_explode(',', substr($text, 1)));
return $obj;
}
}
function & Factory_DivEx(& $root, $text)
{
$matches = array();
// Seems block plugin?
if (PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK) {
// Usual code
if (preg_match('/^\#([^\(]+)(?:\((.*)\))?/', $text, $matches)) {
// return new DivEx($matches);
$obj = new DivEx($matches);
return $obj;
}
} else {
// Hack code
if (preg_match('/^#([^\(\{]+)(?:\(([^\r]*)\))?(\{*)/', $text, $matches)) {
$len = strlen($matches[3]);
$body = array();
if ($len == 0) {
// return new DivEx($matches); // Seems legacy block plugin
$obj = new DivEx($matches);
return $obj;
} else if (preg_match('/\{{' . $len . '}\s*\r(.*)\r\}{' . $len . '}/', $text, $body)) {
$matches[3] .= "\r" . $body[1] . "\r" . str_repeat('}', $len);
// return new DivEx($matches); // Seems multiline-enabled block plugin
$obj = new DivEx($matches);
return $obj;
}
}
}
// return new ParagraphEx($text);
$obj = new ParagraphEx($text);
return $obj;
}
// InlineEx elements
class InlineEx extends ElementEx
{
function InlineEx($text)
{
parent::ElementEx();
$this->elements[] = trim((substr($text, 0, 1) == "\n") ?
$text : guiedit_make_link($text));
}
function & insert(& $obj)
{
$this->elements[] = $obj->elements[0];
return $this;
}
function canContain($obj)
{
return is_a($obj, 'InlineEx');
}
function toString()
{
global $line_break;
return join(($line_break ? '
' . "\n" : "\n"), $this->elements);
}
function & toPara($class = '')
{
$obj = new ParagraphEx('', $class);
$obj->insert($this);
return $obj;
}
}
// ParagraphEx: blank-line-separated sentences
class ParagraphEx extends ElementEx
{
var $param;
function ParagraphEx($text, $param = '')
{
parent::ElementEx();
$this->param = $param;
if ($text == '') return;
if (substr($text, 0, 1) == '~')
$text = ' ' . substr($text, 1);
$this->insert(Factory_InlineEx($text));
}
function canContain($obj)
{
return is_a($obj, 'InlineEx');
}
function toString()
{
return $this->wrap(parent::toString(), 'p', $this->param);
}
}
// * HeadingEx1
// ** HeadingEx2
// *** HeadingEx3
class HeadingEx extends ElementEx
{
var $level;
var $id;
var $msg_top;
function HeadingEx(& $root, $text)
{
parent::ElementEx();
$this->level = min(3, strspn($text, '*'));
$text = substr($text, $this->level);
if (preg_match('/\s*\[#(\w+)\]/', $text, $matches)) {
$this->id = $matches[1];
}
$text = preg_replace('/\s*\[#\w+\]/', '', $text);
$this->insert(Factory_InlineEx($text));
$this->level++; // h2,h3,h4
}
function & insert(& $obj)
{
parent::insert($obj);
return $this->last = & $this;
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
return $this->wrap(parent::toString(),
'h' . $this->level, ' id="' . $this->id . '"');
}
}
// ----
// Horizontal Rule
class HRuleEx extends ElementEx
{
function HRuleEx(& $root, $text)
{
parent::ElementEx();
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
global $hr;
return $hr;
}
}
// Lists (UL, OL, DL)
class ListContainerEx extends ElementEx
{
var $tag;
var $tag2;
var $level;
var $style;
var $margin;
var $left_margin;
function ListContainerEx($tag, $tag2, $head, $text)
{
parent::ElementEx();
$var_margin = '_' . $tag . '_margin';
$var_left_margin = '_' . $tag . '_left_margin';
global $$var_margin, $$var_left_margin;
$this->margin = $$var_margin;
$this->left_margin = $$var_left_margin;
$this->tag = $tag;
$this->tag2 = $tag2;
$this->level = min(3, strspn($text, $head));
$text = ltrim(substr($text, $this->level));
parent::insert(new ListElementEx($this->level, $tag2));
if ($text != '')
$this->last = & $this->last->insert(Factory_InlineEx($text));
}
function canContain(& $obj)
{
return (! is_a($obj, 'ListContainerEx')
|| ($this->tag == $obj->tag && $this->level == $obj->level));
}
function setParent(& $parent)
{
global $_list_pad_str;
parent::setParent($parent);
$step = $this->level;
if (isset($parent->parent) && is_a($parent->parent, 'ListContainerEx'))
$step -= $parent->parent->level;
$margin = $this->margin * $step;
if ($step == $this->level)
$margin += $this->left_margin;
$this->style = sprintf($_list_pad_str, $this->level, $margin, $margin);
}
function & insert(& $obj)
{
if (! is_a($obj, get_class($this)))
return $this->last = & $this->last->insert($obj);
// Break if no elements found (BugTrack/524)
if (count($obj->elements) == 1 && empty($obj->elements[0]->elements))
return $this->last->parent; // up to ListElementEx
// Move elements
foreach(array_keys($obj->elements) as $key)
parent::insert($obj->elements[$key]);
return $this->last;
}
function toString()
{
return $this->wrap(parent::toString(), $this->tag, $this->style);
}
}
class ListElementEx extends ElementEx
{
function ListElementEx($level, $head)
{
parent::ElementEx();
$this->level = $level;
$this->head = $head;
}
function canContain(& $obj)
{
return (! is_a($obj, 'ListContainerEx') || ($obj->level > $this->level));
}
function toString()
{
return $this->wrap(parent::toString(), $this->head);
}
}
// - One
// - Two
// - Three
class UListEx extends ListContainerEx
{
function UListEx(& $root, $text)
{
parent::ListContainerEx('ul', 'li', '-', $text);
}
}
// + One
// + Two
// + Three
class OListEx extends ListContainerEx
{
function OListEx(& $root, $text)
{
parent::ListContainerEx('ol', 'li', '+', $text);
}
}
// : definition1 | description1
// : definition2 | description2
// : definition3 | description3
class DListEx extends ListContainerEx
{
function DListEx($out)
{
parent::ListContainerEx('dl', 'dt', ':', $out[0]);
$this->last = & ElementEx::insert(new ListElementEx($this->level, 'dd'));
if ($out[1] != '')
$this->last = & $this->last->insert(Factory_InlineEx($out[1]));
}
}
// > Someting cited
// > like E-mail text
class BQuoteEx extends ElementEx
{
var $level;
function BQuoteEx(& $root, $text)
{
parent::ElementEx();
$head = substr($text, 0, 1);
$this->level = min(3, strspn($text, $head));
$text = ltrim(substr($text, $this->level));
if ($head == '<') { // Blockquote close
$level = $this->level;
$this->level = 0;
$this->last = & $this->end($root, $level);
if ($text != '')
$this->last = & $this->last->insert(Factory_InlineEx($text));
} else {
$this->insert(Factory_InlineEx($text));
}
}
function canContain(& $obj)
{
return (! is_a($obj, get_class($this)) || $obj->level >= $this->level);
}
function & insert(& $obj)
{
// BugTrack/521, BugTrack/545
if (is_a($obj, 'InlineEx'))
return parent::insert($obj->toPara(' class="quotation"'));
if (is_a($obj, 'BQuoteEx') && $obj->level == $this->level && count($obj->elements)) {
$obj = & $obj->elements[0];
if (is_a($this->last, 'ParagraphEx') && count($obj->elements))
$obj = & $obj->elements[0];
}
return parent::insert($obj);
}
function toString()
{
return $this->wrap(parent::toString(), 'blockquote');
}
function & end(& $root, $level)
{
$parent = & $root->last;
while (is_object($parent)) {
if (is_a($parent, 'BQuoteEx') && $parent->level == $level)
return $parent->parent;
$parent = & $parent->parent;
}
return $this;
}
}
class TableCellEx extends ElementEx
{
var $tag = 'td'; // {td|th}
var $colspan = 1;
var $rowspan = 1;
var $style; // is array('width'=>, 'align'=>...);
var $is_template;
var $hspace = 0;
var $fspace = 0;
function TableCellEx($text, $is_template = FALSE)
{
parent::ElementEx();
$this->style = $matches = array();
$this->is_template = $is_template;
while (preg_match('/^(?:(LEFT|CENTER|RIGHT)|(BG)?COLOR\(([#\w]+)\)|SIZE\((\d+)\)):(.*)$/',
$text, $matches)) {
if ($matches[1]) {
$this->style['align'] = ' align="' . strtolower($matches[1]) . '"';
$text = $matches[5];
} else if ($matches[3]) {
$name = $matches[2] ? 'background-color' : 'color';
$color = $matches[3];
if (preg_match("/^#[0-9a-f]{3}$/i", $color)) {
$color = preg_replace("/[0-9a-f]/i", "$0$0", $color);
}
$this->style[$name] = $name . ':' . htmlspecialchars($color) . ';';
$text = $matches[5];
} else if ($matches[4]) {
$this->style['size'] = 'font-size:' . htmlspecialchars($matches[4]) . 'px;';
$text = $matches[5];
}
}
if ($is_template && is_numeric($text))
$this->style['width'] = ' width="' . $text . '"';
if ($text == '>') {
$this->colspan = 0;
}
if ($is_template) {
$this->tag = 'col';
}
else if ($text == '~') {
$this->rowspan = 0;
} else if (substr($text, 0, 1) == '~') {
$this->tag = 'th';
$text = substr($text, 1);
}
if ($text != '' && $text{0} == '#') {
// Try using DivEx class for this $text
$obj = & Factory_DivEx($this, $text);
if (is_a($obj, 'ParagraphEx'))
$obj = & $obj->elements[0];
} else {
if (preg_match("/^(\s+)?.+?(\s+)?$/", $text, $matches)) {
$this->hspace = isset($matches[1]) ? strlen($matches[1]) : 0;
$this->fspace = isset($matches[2]) ? strlen($matches[2]) : 0;
}
$obj = & Factory_InlineEx($text);
}
$this->insert($obj);
}
function setStyle(& $style)
{
foreach ($style as $key=>$value)
if (! isset($this->style[$key]))
$this->style[$key] = $value;
}
function toString()
{
if ($this->is_template) {
$param = '';
}
else {
if ($this->rowspan == 0 || $this->colspan == 0) return '';
$param = ' class="style_' . $this->tag . '"'
. ' _hspace="' . $this->hspace . '"'
. ' _fspace="' . $this->fspace . '"';
if ($this->rowspan > 1)
$param .= ' rowspan="' . $this->rowspan . '"';
if ($this->colspan > 1) {
$param .= ' colspan="' . $this->colspan . '"';
unset($this->style['width']);
}
}
if (! empty($this->style)) {
foreach($this->style as $key=>$value) {
if ($key == 'align' || $key == 'width') {
$param .= $value;
unset($this->style[$key]);
}
}
$param .= ' style="' . join(' ', $this->style) . '"';
}
return $this->wrap($this->is_template ? '' : parent::toString(), $this->tag, $param, FALSE);
}
}
// | title1 | title2 | title3 |
// | cell1 | cell2 | cell3 |
// | cell4 | cell5 | cell6 |
class TableEx extends ElementEx
{
var $type;
var $types;
var $col; // number of column
function TableEx($out)
{
parent::ElementEx();
$cells = explode('|', $out[1]);
$this->col = count($cells);
$this->type = strtolower($out[2]);
$this->types = array($this->type);
$is_template = ($this->type == 'c');
$row = array();
foreach ($cells as $cell)
$row[] = new TableCellEx($cell, $is_template);
$this->elements[] = $row;
}
function canContain(& $obj)
{
return is_a($obj, 'TableEx') && ($obj->col == $this->col);
}
function & insert(& $obj)
{
$this->elements[] = $obj->elements[0];
$this->types[] = $obj->type;
return $this;
}
function toString()
{
static $parts = array('h'=>'thead', 'f'=>'tfoot', ''=>'tbody');
// Set rowspan (from bottom, to top)
for ($ncol = 0; $ncol < $this->col; $ncol++) {
$rowspan = 1;
foreach (array_reverse(array_keys($this->elements)) as $nrow) {
$row = & $this->elements[$nrow];
if ($row[$ncol]->rowspan == 0) {
++$rowspan;
continue;
}
$row[$ncol]->rowspan = $rowspan;
// Inherits row type
while (--$rowspan)
$this->types[$nrow + $rowspan] = $this->types[$nrow];
$rowspan = 1;
}
}
// Set colspan and style
$stylerow = NULL;
foreach (array_keys($this->elements) as $nrow) {
$row = & $this->elements[$nrow];
$colspan = 1;
if ($this->types[$nrow] == 'c') {
for ($i = count($row) - 2; $i >= 0; $i--) {
if ($row[$i]->colspan == 0) {
$row[$i]->setStyle($row[$i + 1]->style);
}
}
}
foreach (array_keys($row) as $ncol) {
if ($row[$ncol]->colspan == 0) {
++$colspan;
continue;
}
$row[$ncol]->colspan = $colspan;
if ($stylerow !== NULL) {
$row[$ncol]->setStyle($stylerow[$ncol]->style);
// Inherits column style
while (--$colspan)
$row[$ncol - $colspan]->setStyle($stylerow[$ncol]->style);
}
$colspan = 1;
}
}
// toString
$string = '';
$part_string = '';
$old_type = '';
foreach (array_keys($this->elements) as $nrow) {
if (($old_type != $this->types[$nrow]) && ($part_string != '')) {
$string .= ($old_type == 'c') ? $part_string : $this->wrap($part_string, $parts[$old_type]);
$part_string = '';
}
$row = & $this->elements[$nrow];
$row_string = '';
foreach (array_keys($row) as $ncol) {
$row_string .= $row[$ncol]->toString();
}
$part_string .= $this->wrap($row_string, (($this->types[$nrow] == 'c') ? 'colgroup' : 'tr'));
$old_type = $this->types[$nrow];
}
$string .= ($old_type == 'c') ? $part_string : $this->wrap($part_string, $parts[$old_type]);
return $this->wrap($string, 'table', ' class="style_table" cellspacing="1" border="0" align="center"');
}
}
// , title1 , title2 , title3
// , cell1 , cell2 , cell3
// , cell4 , cell5 , cell6
class YTableEx extends ElementEx
{
var $col;
function YTableEx($_value)
{
parent::ElementEx();
$align = $value = $matches = array();
foreach($_value as $val) {
if (preg_match('/^(\s+)?(.+?)(\s+)?$/', $val, $matches)) {
$align[] =($matches[1] != '') ?
((isset($matches[3]) && $matches[3] != '') ?
' align="center"' :
' align="right"'
) : '';
$value[] = $matches[2];
} else {
$align[] = '';
$value[] = $val;
}
}
$this->col = count($value);
$colspan = array();
foreach ($value as $val)
$colspan[] = ($val == '==') ? 0 : 1;
$str = '';
$count = count($value);
for ($i = 0; $i < $count; $i++) {
if ($colspan[$i]) {
while ($i + $colspan[$i] < $count && $value[$i + $colspan[$i]] == '==')
$colspan[$i]++;
$colspan[$i] = ($colspan[$i] > 1) ? ' colspan="' . $colspan[$i] . '"' : '';
$str .= '' . guiedit_make_link($value[$i]) . ' | ';
}
}
$this->elements[] = $str;
}
function canContain(& $obj)
{
return is_a($obj, 'YTableEx') && ($obj->col == $this->col);
}
function & insert(& $obj)
{
$this->elements[] = $obj->elements[0];
return $this;
}
function toString()
{
$rows = '';
foreach ($this->elements as $str)
$rows .= "\n" . '' . $str . '
' . "\n";
$rows = $this->wrap($rows, 'table', ' class="style_table" cellspacing="1" border="0"');
return $this->wrap($rows, 'div', ' class="ie5"');
}
}
// ' 'Space-beginning sentence
// ' 'Space-beginning sentence
// ' 'Space-beginning sentence
class PreEx extends ElementEx
{
function PreEx(& $root, $text)
{
global $preformat_ltrim;
parent::ElementEx();
$this->elements[] = htmlspecialchars(
(! $preformat_ltrim || $text == '' || $text{0} != ' ') ? $text : substr($text, 1));
}
function canContain(& $obj)
{
return is_a($obj, 'PreEx');
}
function & insert(& $obj)
{
$this->elements[] = $obj->elements[0];
return $this;
}
function toString()
{
return $this->wrap(join("
", $this->elements), 'pre');
}
}
// Block plugin: #something (started with '#')
class DivEx extends ElementEx
{
var $text;
var $name;
var $param;
function DivEx($out)
{
parent::ElementEx();
list(, $this->name, $this->param, $this->text) = array_pad($out, 4, '');
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
switch ($this->name) {
case 'br':
return "
\n ";
case 'hr':
return '
';
case 'pagebreak':
return '
';
case 'ref':
$param = ($this->param != '') ? explode(',', $this->param) : array();
return guiedit_convert_ref($param);
}
if ($this->text) {
$this->text = preg_replace("/\r/", "
", $this->text);
}
$inner = "#$this->name" . ($this->param ? "($this->param)" : '') . $this->text;
$style = (UA_NAME == MSIE) ? '' : ' style="cursor:default"';
return $this->wrap($inner, 'div', ' class="plugin" contenteditable="false"' . $style);
}
}
// LEFT:/CENTER:/RIGHT:
class AlignEx extends ElementEx
{
var $align;
function AlignEx($align)
{
parent::ElementEx();
$this->align = $align;
}
function canContain(& $obj)
{
return is_a($obj, 'InlineEx');
}
function toString()
{
return $this->wrap(parent::toString(), 'div', ' style="text-align: ' . $this->align . '"');
}
}
// BodyEx
class BodyEx extends ElementEx
{
var $classes = array(
'-' => 'UListEx',
'+' => 'OListEx',
'>' => 'BQuoteEx',
'<' => 'BQuoteEx');
var $factories = array(
':' => 'DListEx',
'|' => 'TableEx',
',' => 'YTableEx',
'#' => 'DivEx');
var $comments = array();
function BodyEx()
{
parent::ElementEx();
}
function parse(& $lines)
{
$this->last = & $this;
$matches = array();
while (! empty($lines)) {
$line = array_shift($lines);
// Escape comments
if (substr($line, 0, 2) == '//') {
$this->comments[] = substr($line, 2);
$line = '___COMMENT___';
}
if (preg_match('/^(LEFT|CENTER|RIGHT):(.*)$/', $line, $matches)) {
//
$this->last = & $this->last->add(new AlignEx(strtolower($matches[1])));
if ($matches[2] == '') continue;
$line = $matches[2];
}
$line = rtrim($line, "\r\n");
// Empty
if ($line == '') {
$this->last = & $this;
continue;
}
// Horizontal Rule
if (substr($line, 0, 4) == '----') {
$this->insert(new HRuleEx($this, $line));
continue;
}
// Multiline-enabled block plugin
if (! PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK &&
preg_match('/^#[^{]+(\{\{+)\s*$/', $line, $matches)) {
$len = strlen($matches[1]);
$line .= "\r"; // Delimiter
while (! empty($lines)) {
$next_line = preg_replace("/[\r\n]*$/", '', array_shift($lines));
// UPK
$next_line = htmlspecialchars($next_line);
if (preg_match('/\}{' . $len . '}/', $next_line)) {
$line .= $next_line;
break;
} else {
$line .= $next_line .= "\r"; // Delimiter
}
}
}
// The first character
$head = $line{0};
// HeadingEx
if ($head == '*') {
$this->insert(new HeadingEx($this, $line));
continue;
}
// PreEx
if ($head == ' ' || $head == "\t") {
$this->last = & $this->last->add(new PreEx($this, $line));
continue;
}
// Line Break
if (substr($line, -1) == '~')
$line = substr($line, 0, -1) . "\r";
// Other Character
if (isset($this->classes[$head])) {
$classname = $this->classes[$head];
$this->last = & $this->last->add(new $classname($this, $line));
continue;
}
// Other Character
if (isset($this->factories[$head])) {
$factoryname = 'Factory_' . $this->factories[$head];
$this->last = & $this->last->add($factoryname($this, $line));
continue;
}
// Default
$this->last = & $this->last->add(Factory_InlineEx($line));
}
}
function & insert(& $obj)
{
if (is_a($obj, 'InlineEx')) $obj = & $obj->toPara();
return parent::insert($obj);
}
function toString()
{
global $vars;
$text = parent::toString();
$text = preg_replace_callback("/___COMMENT___(\n___COMMENT___)*/", array(&$this, 'comment'), $text);
return $text . "\n";
}
function comment($matches)
{
$comments = explode("\n", $matches[0]);
foreach ($comments as $key=>$comment) {
$comments[$key] = array_shift($this->comments);
}
$comment = join("\n", $comments);
return '
';
}
}
?>