OSDN Git Service

fix for FreeBSD 11.1.
[hmh/hhml.git] / wiki / wikiformat.cc
index f99f1df..18b5f88 100644 (file)
@@ -1,4 +1,5 @@
 #include "wikiformat.h"
+#include "config.h"
 #include "wikiline.h"
 #include "wikitable.h"
 #include "wikicmd.h"
 #include "ustring.h"
 #include <boost/ptr_container/ptr_vector.hpp>
 
-#define TABLECOMPATFLAG        1
+/*
+  WIKIMOTORPRE: セットすると,フォーマット済みテキストブロックの中でインライン要素の解釈を行う。
+  UTF8JP: セットすると,条件によりパラグラフ内の改行を空白に置き換えない。
+  WIKITABLECOMPATFLAG: セットすると,旧形式の表の継続記号もゆるす。
+*/
 
 #define  kComment      "//"
 #define  kWikiP                '^'
 #define  kWikiQUOTE    '>'
 #define  kWikiQUOTE_e  '<'
 #define  kWikiDIV      '{'
+#define  uWikiDIV      "{div:"
+#define  uWikiFORM     "{form:"
+#define  uWikiELEMENT  "{element:"
 #define  kWikiDIV_e    '}'
 #define  kWikiHR       '-'
 #define  kWikiCmd      '$'
+#define  uWikiCmd      "$"
 
 #define  uP    "<p>"
 #define  uPe   "</p>\n"
 //#define  unbsp       "&nbsp;"
 
 ustring  uWiki (CharConst ("wiki_"));
+ustring  uAWiki (CharConst ("@wiki_"));
 
 /*DOC:
+$premode:1
 ==テキストの整形ルール==
 
 */
@@ -108,500 +119,6 @@ void  WikiMotorOutputString::flush (bool fsuper) {
 }
 
 /* ============================================================ */
-bool  WikiAttrib1::readAttrib1 (WikiMotorObjVec* cell, bool& rc) {
-    ustring  key;
-    WikiMotorObjVec  vval;
-    bool  ferr = false;
-
-    if (cell->size () == 0) {
-       if (fwhole)
-           return true;
-       else
-           return false;
-    }
-    if (cell->splitChar_keyword ('=', key, vval)) {
-       if (wiki->paramID (key, vval, id, ferr)) {
-       } else if (wiki->paramClass (key, vval, classlist, ferr)) {
-       } else if (wiki->paramOnClickCheck (key)) {
-           if (! checkScript (vval, onclick, ferr)) {
-               wiki->errorMsg.append (cell->dump ()).append (CharConst (": link script error.\n"));
-               ferr = true;
-           }
-       } else if ((selector & SEL_TARGET) && wiki->paramTargetCheck (key)) {
-           wiki->paramTargetBody (key, vval.textOut (wiki), target, ferr);
-       } else if (readAttribMore (key, vval, ferr)) {
-       } else {
-           if (fwhole) {
-               wiki->errorMsg.append (cell->dump ()).append (CharConst (": bad attribute.\n"));
-               rc = false;
-           }
-           return false;
-       }
-    } else {
-       if (selector & SEL_CLASS2) {
-           wiki->paramClassValue (*cell, classlist, ferr);
-       } else if (selector & SEL_TARGET2) {
-           wiki->paramTargetBody (uEmpty, cell->textOut (wiki), target, ferr);
-       } else if ((selector & SEL_ONCLICK2) && checkScript (*cell, onclick, ferr)) {
-       } else if ((selector & SEL_MULTIPLE2) && match (key, CharConst ("multiple"))) {
-           fmultiple = true;
-       } else if ((selector & SEL_DEFAULT2) && match (key, CharConst ("default"))) {
-           fdefault = true;
-       } else if ((selector & SEL_SCRIPT2) && checkScript (*cell, script, ferr)) {
-       } else if (readAttribMore2 (key, *cell, ferr)) {
-       } else {
-           if (fwhole) {
-               wiki->errorMsg.append (cell->dump ()).append (CharConst (": bad attribute.\n"));
-               rc = false;
-           }
-           return false;
-       }
-    }
-    if (ferr) {
-       rc = false;
-       return false;
-    } else {
-       return true;
-    }
-}
-
-bool  WikiAttrib1::shiftAttrib (WikiMotorObjVecPtr& vec) {
-    bool  rc = true;
-    WikiMotorObjVecPtr  v2;
-
-    while (vec->size () > 0) {
-       WikiMotorObjVec  cell;
-
-       v2 = WikiMotorObjVecPtr (new WikiMotorObjVec);
-       if (vec->splitChar (':', cell, *v2) || fwhole) {
-           if (! readAttrib1 (&cell, rc))
-               return rc;
-           vec = v2;
-       } else {
-           return true;
-       }
-    }
-    return true;
-}
-
-void  WikiAttrib1::skipAttrib (WikiMotorObjVecPtr& vec) {
-    WikiMotorObjVecPtr  v2;
-
-    if (vec->size () > 0) {
-       WikiMotorObjVec  cell;
-
-       v2 = WikiMotorObjVecPtr (new WikiMotorObjVec);
-       if (vec->splitChar (':', cell, *v2)) {
-           vec = v2;
-       }
-    }
-}
-
-bool  WikiAttrib1::readAttrib (WikiMotorObjVecVec::const_iterator& b, const WikiMotorObjVecVec::const_iterator& e) {
-    bool  rc = true;
-
-    while (b < e) {
-       WikiMotorObjVec*  cell = b->get ();
-       if (! readAttrib1 (cell, rc))
-           return rc;
-       b ++;
-    }
-    return true;
-}
-
-bool  WikiAttrib1::checkScript (WikiMotorObjVec& vec, ustring& scr, bool& ferr) {
-    bool  f = false;
-    int  i;
-    ustring  u;
-    for (i = 0; i < vec.size () && vec[i]->type == WikiMotorObj::wiki_funcLink; i ++) {
-       WikiMotorObjFuncLink*  fn = WikiMotorObjFuncLink_type (&*vec[i]);
-       u = fn->execDefunArgs (wiki);
-       // XXX: 末尾の空白を除去し,セミコロンを確認する。
-       scr.append (u);
-       f = true;
-    }
-    if (f)
-       return true;
-
-    return false;
-}
-
-bool  WikiAttrib1::shiftLink (WikiMotorObjVecPtr& vec, ustring& url, bool& fscript) {
-    bool  ferr = false;
-    bool  rc;
-    WikiMotorObjVec  cell;
-    WikiMotorObjVecPtr  v2 (new WikiMotorObjVec);
-
-    rc = vec->splitChar (':', cell, *v2);
-    if (checkScript (cell, url, ferr)) {
-       fscript = true;
-       vec = v2;
-       return true;
-    } else if (rc && cell.match (CharConst ("http"), CharConst ("https"))) {
-       ustring  proto = cell.dump ();
-       vec = v2;
-       cell.clear ();
-       v2 = WikiMotorObjVecPtr (new WikiMotorObjVec);
-       rc = vec->splitChar (':', cell, *v2);
-       if (! cell.splitURL_2 (wiki, proto, url)) {
-           vec = v2;
-           return false;
-       }
-       vec = v2;
-       if (vec->size () > 0) {
-           cell.clear ();
-           v2 = WikiMotorObjVecPtr (new WikiMotorObjVec);
-           rc = vec->splitChar (':', cell, *v2);
-           if (cell.splitURL_3 (wiki, url, url))
-               vec = v2;
-       }
-       return true;
-    } else if (cell.splitURLPath (wiki, url)) {
-       vec = v2;
-       return true;
-    } else {
-       return false;
-    }
-    return false;
-}
-
-bool  WikiAttrib1::readLink (WikiMotorObjVecVec::const_iterator& b, const WikiMotorObjVecVec::const_iterator& e, ustring& url, bool& fscript, bool noscript) {
-    bool  ferr = false;
-    bool  rc;
-    WikiMotorObjVec*  cell;
-
-    if (b == e)
-       return false;
-    cell = b->get ();
-    rc = (b + 1 < e);
-    if (! noscript && checkScript (*cell, url, ferr)) {
-       fscript = true;
-       b ++;
-       return true;
-    } else if (rc && cell->match (CharConst ("http"), CharConst ("https"))) {
-       ustring  proto = cell->dump ();
-       b ++;
-       cell = b->get ();
-       if (! cell->splitURL_2 (wiki, proto, url)) {
-           b ++;
-           return false;
-       }
-       b ++;
-       if (b < e) {
-           cell = b->get ();
-           if (cell->splitURL_3 (wiki, url, url))
-               b ++;
-       }
-       return true;
-    } else if (cell->splitURLPath (wiki, url)) {
-       b ++;
-       return true;
-    } else {
-       return false;
-    }
-    return false;
-}
-
-bool  WikiAttrib1::shiftName (WikiMotorObjVecPtr& vec, ustring& name) {
-    if (vec->size () > 0) {
-       WikiMotorObjVec  cell;
-       WikiMotorObjVecPtr  v2 (new WikiMotorObjVec);
-
-       vec->splitChar (':', cell, *v2);
-       name = cell.textOut (wiki);
-       vec = v2;
-       return true;
-    } else {
-       return false;
-    }
-}
-
-void  WikiAttrib1::output (MotorOutput* out) {
-    wiki->outputID (out, id);
-    wiki->outputClass (out, classlist);
-    wiki->outputSubmitScript (out, CharConst ("onClick"), onclick);
-    wiki->outputName (out, CharConst ("target"), target);
-//    wiki->outputName (out, CharConst ("size"), elsize);
-    wiki->outputFlag (out, CharConst ("multiple"), fmultiple);
-    // no fdefault
-    outputMore (out);
-}
-
-/* ============================================================ */
-void  WikiAttribTable::init () {
-    fheader = false;
-    halign = HAlignNone;
-    valign = VAlignNone;
-    fnowrap = false;
-    fnoborder = false;
-    cellspacing = -1;
-    cellpadding = -1;
-    fpadding = false;
-//     halign = HAlignNone;
-    fnowhite = false;
-    fturn = false;
-
-    id.resize (0);
-    while (! classlist.empty ())
-       classlist.pop_back ();
-    width.resize (0);
-    height.resize (0);
-    bgcolor.resize (0);
-    onclick.resize (0);
-}
-
-void  WikiAttribTable::copyFrom (WikiAttribTable& b) {
-    int  i;
-
-    id = b.id;
-    for (i = 0; i < b.classlist.size (); i ++)
-       classlist.push_back (b.classlist[i]);
-    onclick = b.onclick;
-    fheader = b.fheader;
-    halign = b.halign;
-    valign = b.valign;
-    width = b.width;
-    height = b.height;
-    bgcolor = b.bgcolor;
-    fnowrap = b.fnowrap;
-}
-
-bool  WikiAttribTable::readAttribMore (const ustring& key, WikiMotorObjVec& vval, bool& ferr) {
-    if (wiki->paramWidth (key, vval, width, ferr)) {
-    } else if (wiki->paramHeight (key, vval, height, ferr)) {
-    } else if (match (key, CharConst ("bgcolor"), CharConst ("bg"))) {
-       wiki->paramColor (vval.textOut (wiki), bgcolor, key);
-    } else {
-       switch (selector2) {
-       case SEL_TABLE:
-           if (match (key, CharConst ("cellspacing"), CharConst ("spc"))) {
-               wiki->paramUNum (vval.textOut (wiki), cellspacing, key);
-           } else if (match (key, CharConst ("cellpadding"))) {
-               wiki->paramUNum (vval.textOut (wiki), cellpadding, key);
-           } else {
-               return false;
-           }
-           break;
-       case SEL_TR:
-       case SEL_TD:
-           return false;
-       default:
-           assert (0);
-       }
-    }
-    return true;
-}
-
-bool  WikiAttribTable::readAttribMore2 (const ustring& key, WikiMotorObjVec& cell, bool& ferr) {
-    if (match (key, CharConst ("left"), CharConst ("l"))) {
-       halign = HAlignLeft;
-    } else if (match (key, CharConst ("right"), CharConst ("r"))) {
-       halign = HAlignRight;
-    } else if (match (key, CharConst ("center"), CharConst ("c"))) {
-       halign = HAlignCenter;
-    } else {
-       switch (selector2) {
-       case SEL_TABLE:
-           if (match (key, CharConst ("noborder"), CharConst ("nb"))) {
-               fnoborder = true;
-           } else if (match (key, CharConst ("padding"), CharConst ("pad"))) {
-               fpadding = true;
-           } else if (match (key, CharConst ("expanding"), CharConst ("expand"))) {
-               fpadding = false;
-           } else if (match (key, CharConst ("nowhite"), CharConst ("nw"))) {
-               fnowhite = true;
-           } else if (match (key, CharConst ("turn"))) {
-               fturn = true;
-           } else {
-               return false;
-           }
-           break;
-       case SEL_TR:
-       case SEL_TD:
-           if (match (key, CharConst ("header"), CharConst ("h"))) {
-               fheader = true;
-           } else if (match (key, CharConst ("top"), CharConst ("t"))) {
-               valign = VAlignTop;
-           } else if (match (key, CharConst ("middle"), CharConst ("m"))) {
-               valign = VAlignMiddle;
-           } else if (match (key, CharConst ("bottom"), CharConst ("b"))) {
-               valign = VAlignBottom;
-           } else if (match (key, CharConst ("nowrap"), CharConst ("nw"))) {
-               fnowrap = true;
-           } else if (match (key, CharConst ("*"))) {
-               init ();
-           } else {
-               return false;
-           }
-           break;
-       default:
-           assert (0);
-       }
-    }
-
-    return true;
-}
-
-void  WikiAttribTable::outputMore (MotorOutput* out) {
-    switch (halign) {
-    case HAlignLeft:
-       out->out_raw (CharConst (" align=\"left\""));
-       break;
-    case HAlignCenter:
-       out->out_raw (CharConst (" align=\"center\""));
-       break;
-    case HAlignRight:
-       out->out_raw (CharConst (" align=\"right\""));
-       break;
-    }
-    wiki->outputName (out, CharConst ("width"), width);
-    wiki->outputName (out, CharConst ("height"), height);
-    wiki->outputName (out, CharConst ("bgcolor"), bgcolor);
-
-    switch (selector2) {
-    case SEL_TABLE:
-       wiki->outputName (out, CharConst ("border"), fnoborder ? 0 : 1, false);
-       wiki->outputName (out, CharConst ("cellspacing"), cellspacing, false);
-       wiki->outputName (out, CharConst ("cellpadding"), cellpadding, false);
-       break;
-    case SEL_TR:
-    case SEL_TD:
-       switch (valign) {
-       case VAlignTop:
-           out->out_raw (CharConst (" valign=\"top\""));
-           break;
-       case VAlignMiddle:
-           out->out_raw (CharConst (" valign=\"middle\""));
-           break;
-       case VAlignBottom:
-           out->out_raw (CharConst (" valign=\"bottom\""));
-           break;
-       }
-       wiki->outputFlag (out, CharConst ("nowrap"), fnowrap);
-       break;
-    default:
-       assert (0);
-    }
-}
-
-/* ============================================================ */
-bool  WikiAttribImg::readAttribMore (const ustring& key, WikiMotorObjVec& vval, bool& ferr) {
-    if (wiki->paramWidth (key, vval, width, ferr)) {
-    } else if (wiki->paramHeight (key, vval, height, ferr)) {
-    } else if (match (key, CharConst ("alt"))) {
-       alt = vval.textOut (wiki);
-    } else {
-       return false;
-    }
-    return true;
-}
-
-void  WikiAttribImg::outputMore (MotorOutput* out) {
-    wiki->outputName (out, CharConst ("width"), width);
-    wiki->outputName (out, CharConst ("height"), height);
-    // longdesc
-}
-
-/* ============================================================ */
-bool  WikiAttribInput::readAttribMore (const ustring& key, WikiMotorObjVec& vval, bool& ferr) {
-    if ((selector2 & SEL_INPUT) && wiki->paramSize (CharConst ("size"), key, vval, psize, ferr)) {
-    } else if ((selector2 & SEL_ELSIZE) && match (key, CharConst ("size"))) {
-       ustring  v = vval.textOut (wiki);
-       if (match (v, CharConst ("*"))) {
-           elsize = 1;
-       } else if (checkNum (v)) {
-           elsize = to_int32 (v);
-           if (elsize < 0 || elsize > 999) {
-               elsize = 1;
-           }
-       } else {
-           elsize = 1;
-       }
-    } else if (wiki->paramWidth (key, vval, pwidth, ferr)) {
-    } else if ((selector2 & SEL_TEXTAREA) && wiki->paramSize (CharConst ("cols"), key, vval, pcols, ferr)) {
-    } else if ((selector2 & SEL_TEXTAREA) && wiki->paramSize (CharConst ("rows"), key, vval, prows, ferr)) {
-    } else if ((selector2 & SEL_TEXTAREA) && match (key, CharConst ("wrap"))) {
-       ustring  value (vval.textOut (wiki));
-       if (match (value, CharConst ("off"))) {
-           pwrap = W_OFF;
-       } else if (match (value, CharConst ("soft"))) {
-           pwrap = W_SOFT;
-       } else if (match (value, CharConst ("hard"))) {
-           pwrap = W_HARD;
-       } else if (wiki->paramWidth (key, vval, pwidth, ferr)) {
-       } else {
-           wiki->errorMsg.append (key).append (CharConst ("=")).append (vval.dump ()).append (CharConst (": link script error.\n"));
-           ferr = true;
-           return false;
-       }
-    } else {
-       return false;
-    }
-    return true;
-}
-
-bool  WikiAttribInput::readAttribMore2 (const ustring& key, WikiMotorObjVec& cell, bool& ferr) {
-    if (key == uDefault) {
-       pdefault = true;
-    } else if ((selector2 & SEL_CHECK) && match (key, CharConst ("checked"))) {
-       pchecked = true;
-    } else {
-       return false;
-    }
-    return true;
-}
-
-void  WikiAttribInput::outputMore (MotorOutput* out) {
-    wiki->outputName (out, CharConst ("size"), psize);
-    wiki->outputName (out, CharConst ("size"), elsize);
-    if (pwidth.size () > 0)
-       out->out_raw (CharConst (" style=\"width: "))->out_toHTML_noCtrl (pwidth)->out_raw (CharConst (";\""));
-    if (selector2 & SEL_CHECK) {
-       wiki->outputFlag (out, CharConst ("checked"), pchecked);
-    }
-    if (selector2 & SEL_TEXTAREA) {
-       wiki->outputName (out, CharConst ("cols"), pcols, false);
-       wiki->outputName (out, CharConst ("rows"), prows);
-       switch (pwrap) {
-       case W_OFF:
-           out->out_raw (CharConst (" wrap=\"off\""));
-           break;
-       case W_SOFT:
-           out->out_raw (CharConst (" wrap=\"soft\""));
-           //  out->out_raw (CharConst (" wrap=\"virtual\""));
-           break;
-       case W_HARD:
-           out->out_raw (CharConst (" wrap=\"hard\""));
-           //  out->out_raw (CharConst (" wrap=\"physical\""));
-           break;
-       }
-    }
-}
-
-/* ============================================================ */
-bool  WikiAttribButton::readAttrib (WikiMotorObjVecVec::const_iterator& b, const WikiMotorObjVecVec::const_iterator& e) {
-    bool  rc = true;
-
-    if (b < e) {
-       WikiMotorObjVec*  cell = b->get ();
-       bool  bf = fwhole;
-       fwhole = false;
-       if (! readAttrib1 (cell, rc)) {
-           name = cell->textOut (wiki);
-       }
-       fwhole = bf;
-       b ++;
-    }
-    while (b < e) {
-       WikiMotorObjVec*  cell = b->get ();
-       if (! readAttrib1 (cell, rc))
-           return rc;
-       b ++;
-    }
-    return true;
-}
-
-/* ============================================================ */
 void  WikiBlockComplex::outputBlock (MotorOutput* out) {
     for (int i = 0; i < block.size (); i ++) {
        block[i].output (out);
@@ -615,6 +132,19 @@ void  WikiBlockComplex::outputBlock (MotorOutput* out) {
  ^行頭が他のマークアップ文字になるときは,行頭に^を書く。
  
  空行は,段落を分ける。
+ 段落と段落の間に空行を2行以上入れると、「<div class="pggap"></div>」を出力する。
+
+{div:greenbox
+マークアップ文字以外の文字で書き出すと,段落になる。
+^行頭が他のマークアップ文字になるときは,行頭に^を書く。
+
+空行は,段落を分ける。
+
+
+段落と段落の間に空行を2行以上入れると、「<div class="pggap"></div>」を出力する。
+}
 
 */
 bool  WikiBlockParagraph::nextLine (uiterator b, uiterator e) {
@@ -627,47 +157,87 @@ bool  WikiBlockParagraph::nextLine (uiterator b, uiterator e) {
 }
 
 void  WikiBlockParagraph::addLine (uiterator b, uiterator e) {
-    uiterator  it;
-    int  n;
-
-    if (b[0] == kWikiP)
+    if (b[0] == kWikiP) {
        b ++;
+       pflag = true;
+    }
     if (b == e)
        return;
-    if (html.size () == 0) {
-    } else {
-       lastChar (html, it);
-       n = html.end () - it;
-       it = b;
-       nextChar (it, e);
+    {
+       WikiMotorObjVec  o;
+       WikiMotorObjVec::iterator  ob;
+       WikiMotorObjVec::iterator  oe;
+       wiki->wikiMotorInline (b, e, o);
+       if (objv.size () > 0 && o.size () > 0) {
 #ifdef UTF8JP
-       if (n == 3 && it - b == 3) {
-       } else {
-           html.append (uSPC);
-       }
+           WikiMotorObj*  v;
+           WikiMotorObjText*  t1;
+           WikiMotorObjText*  t2;
+           uiterator  i1, i2;
+           int  n;
+           v = &*objv.back ();
+           if (v->type == WikiMotorObj::wiki_text) {
+               t1 = WikiMotorObjText_type (v);
+               v = &*o.front ();
+               if (v->type == WikiMotorObj::wiki_text) {
+                   t2 = WikiMotorObjText_type (v);
+                   if (t1->text.length () > 0 && t2->text.length () > 0) {
+                       lastChar (t1->text, i1);
+                       n = t1->text.end () - i1;
+                       i2 = t2->text.begin ();
+                       nextChar (i2, t2->text.end ());
+                       if (n == 3 && i2 - t2->text.begin () == 3) {
+                       } else {
+                           objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
+                       }
+                   } else {
+                       objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
+                   }
+               } else {
+                   objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
+               }
+           } else {
+               objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
+           }
 #else
-       html.append (uSPC);
+           objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
 #endif
+       }
+       ob = o.begin ();
+       oe = o.end ();
+       for (; ob < oe; ob ++) {
+           objv.push_back (*ob);
+       }
     }
-    html.append (wiki->wikiMotor (b, e));
 }
 
 void  WikiBlockParagraph::addHtml (const ustring& ht) {
-    html.append (ht);
+    objv.push_back (WikiMotorObjPtr (new WikiMotorObjHtml (ht)));
 }
 
 void  WikiBlockParagraph::output (MotorOutput* out) {
-    out->out_raw (CharConst (uP))->out_toText (html)->out_raw (CharConst (uPe));
+    if (singleTag) {
+       out->out_toText (objv.htmlOut (wiki));
+    } else {
+       out->out_raw (CharConst (uP));
+       out->out_toText (objv.htmlOut (wiki));
+       out->out_raw (CharConst (uPe));
+    }
 }
 
 /* ============================================================ */
 /*DOC:
 ===タイトル===
+行頭に=を書くと,タイトルになる。行末の=は,省略可。
+
  =タイトル1=
  ==タイトル2==
  ===タイトル3===#anchor1
-
-行頭に=を書くと,タイトルになる。行末の=は,省略可。
+{div:greenbox
+=タイトル1=
+==タイトル2==
+===タイトル3===#anchor1
+}
 
 */
 
@@ -708,11 +278,13 @@ void  WikiBlockH::addLine (uiterator b, uiterator e) {
 
 WikiBlock::closeType  WikiBlockH::closeLine (uiterator b, uiterator e) {
     if (e - b == 1 && *b == kWikiDIV_e) {
+       // closing point of the div
        int  i;
        for (i = wiki->bstack.size () - 1; i >= 0; i --) {
            switch (wiki->bstack[i]->type) {
            case BlockDiv:
            case BlockForm:
+               // found
                for (i = wiki->bstack.size () - 1; i >= 0; i --) {
                    wiki->pop_block ();
                    switch (wiki->bstack[i]->type) {
@@ -722,10 +294,13 @@ WikiBlock::closeType  WikiBlockH::closeLine (uiterator b, uiterator e) {
                            wiki->cur->close ();
                        wiki->cur = NULL;
                        return CloseTrue;
+                   default:;
                    }
                }
+           default:;
            }
        }
+       // no opening point.
        return CloseFalse;
     } else if (b != e && *b == kWikiH) {
        int  l = wiki->countWikiH (b, e) + wiki->headbase;
@@ -762,9 +337,10 @@ void  WikiBlockH::output (MotorOutput* out) {
     int  i;
 
     assert (0 < level && level <= 6);
-    for (i = level0 + 1; i <= level; i ++) {
-       outputBeginDiv (i, out);
-    }
+    if (checkEmpty ())
+       return;
+
+    outputBeginDiv (level, out);
     switch (level) {
     case 1: out->out_raw (CharConst (uH1)); break;
     case 2: out->out_raw (CharConst (uH2)); break;
@@ -787,13 +363,7 @@ void  WikiBlockH::output (MotorOutput* out) {
     case 6: out->out_raw (CharConst (uH6e)); break;
     }
     outputBlock (out);
-    for (i = level; i > level0; i --) {
-#ifdef DEBUG
-       out->out_raw (CharConst ("</div><!-- hh"))->out_raw (to_ustring (i))->out_raw (CharConst (" -->\n"));
-#else
-       outputEndDiv (out);
-#endif /* DEBUG */
-    }
+    outputEndDiv (level, out);
 }
 
 void  WikiBlockH::outputBeginDiv (int lv, MotorOutput* out) {
@@ -807,8 +377,16 @@ void  WikiBlockH::outputBeginDiv (int lv, MotorOutput* out) {
     }
 }
 
-void  WikiBlockH::outputEndDiv (MotorOutput* out) {
+void  WikiBlockH::outputEndDiv (int lv, MotorOutput* out) {
+#ifdef DEBUG
+    out->out_raw (CharConst ("</div><!-- hh"))->out_raw (to_ustring (lv))->out_raw (CharConst (" -->\n"));
+#else
     out->out_raw (CharConst ("</div>\n"));
+#endif /* DEBUG */
+}
+
+bool  WikiBlockH::checkEmpty () {
+    return title.empty ();
 }
 
 /* ============================================================ */
@@ -816,9 +394,12 @@ void  WikiBlockH::outputEndDiv (MotorOutput* out) {
 ===フォーマット済みテキストブロック===
   行頭に空白文字を書くと,<pre>〜</pre>タグで囲まれます。
 インライン要素の解釈は行われない。
+{div:greenbox
+ 行頭に空白文字を書くと,<pre>〜</pre>タグで囲まれます。
+}
 
 */
-bool  WikiBlockPreformat::nextLine (uiterator b, uiterator e) {
+bool  WikiBlockPreformatRaw::nextLine (uiterator b, uiterator e) {
     if (*b == markup) {
        addLine (b, e);
        return true;
@@ -827,22 +408,23 @@ bool  WikiBlockPreformat::nextLine (uiterator b, uiterator e) {
     }
 }
 
-void  WikiBlockPreformat::addLine (uiterator b, uiterator e) {
+void  WikiBlockPreformatRaw::addLine (uiterator b, uiterator e) {
     markup = *b;
-    if (markup == ' ') {
-//     html.append (wiki->wikiMotor (b + 1, e));
-       text.append (b + 1, e);
+
+    if (markup == ' ')
+       b ++;
+    if (wiki->motorPre) {
+       text.append (wiki->wikiMotor (b, e));
     } else {
-//     html.append (wiki->wikiMotor (b, e));
-       text.append (b, e);
+       MotorOutputString  o;
+       o.out_toHTML (ustring (b, e));
+       text.append (o.ans);
     }
-//    html.append (uLF);
     text.append (uLF);
 }
 
-void  WikiBlockPreformat::output (MotorOutput* out) {
-//    out->out_raw (CharConst ("<pre>"))->out_toText (html)->out_raw (CharConst ("</pre>\n"));
-    out->out_raw (CharConst ("<pre>"))->out_toHTML (text)->out_raw (CharConst ("</pre>\n"));
+void  WikiBlockPreformatRaw::output (MotorOutput* out) {
+    out->out_raw (CharConst ("<pre>"))->out_toText (text)->out_raw (CharConst ("</pre>\n"));
 }
 
 /* ============================================================ */
@@ -891,33 +473,54 @@ void  WikiBlockItemText::output (MotorOutput* out) {
     if (indentHack) {
        outputBlock (out);
     } else {
-       out->out_raw (CharConst ("<li"));
-       attrib.output (out);
-       out->out_raw (CharConst (">"));
-       out->out_toText (html);
-       outputBlock (out);
-       out->out_raw (CharConst ("</li>\n"));
+       if (html.length () > 0) {
+           out->out_raw (CharConst ("<li"));
+           attrib.output (out);
+           out->out_raw (CharConst (">"));
+           out->out_toText (html);
+           outputBlock (out);
+           out->out_raw (CharConst ("</li>\n"));
+       } else {
+           outputBlock (out);
+       }
     }
 }
 
 /* ============================================================ */
 /*DOC:
 ===箇条書き===
-{div:pre
-+&*;項目1
-+&*;*項目1-1
-+&#;ナンバリング1
-+&#;#ナンバリング1-2
-+&+;インデント1
-+&+;+インデント1-1
-+&*;''[OPTION1:OPTION2:...:]''TEXT
-}
+ *項目1
+ **項目1-1
+ #ナンバリング1
+ ##ナンバリング1-2
+ +インデント1
+ ++インデント1-1
+ *''[OPTION1:OPTION2:...:]''TEXT
+ *id=item1:class=style1:onclick=[[ignore:]]:TEXT
+
 行頭に「*」を書くと,<UL>タグによるリスト,「#」を書くと<NL>タグによる番号付きリスト,「+」を書くとnobullクラス指定の<UL>タグによるリスト。
 
-|h:オプション|
-|id=''ID''|
-|class=''CLASS,...''|
-|onclick=''LINK-FUNCTION:PARAM1:...::''|
+オプションパラメータ
+|table:w=100%|t:w=20%|c:w=10%|t:|
+|h:オプション|h:省略形|h:説明|
+|'''id='''''ID''||id属性。|
+|'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
+//|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
+|'''onclick='''''Link''||onclick属性。Javascriptリンク。|
+|'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
+|'''onblur='''''Link''||onblur属性。Javascriptリンク。|
+|'''onchange='''''Link''||onchange属性。Javascriptリンク。|
+|'''start='''''Number''||start属性。OLのみ。|
+
+{div:greenbox
+*項目1
+**項目1-1
+#ナンバリング1
+##ナンバリング1-2
++インデント1
+++インデント1-1
+*id=item1:class=style1:onclick=[[ignore:]]:TEXT
+}
 
 */
 bool  WikiBlockItem::nextLine (uiterator b, uiterator e) {
@@ -945,7 +548,7 @@ void  WikiBlockItem::addLine (uiterator b, uiterator e) {
     assert (b != e && b[0] == ch);
     b ++;
     if (b == e) {
-       wbt = new WikiBlockItemText (wiki);
+       wbt = new WikiBlockItemText (wiki, this);
        block.push_back (wbt);
        wbt->addLine (b, e);
     } else {
@@ -959,7 +562,7 @@ void  WikiBlockItem::addLine (uiterator b, uiterator e) {
            case kWikiOL:       // #
                wbi = new WikiBlockItem (WikiBlock::BlockItemOL, wiki);
                break;
-           case kWikiNL:       // ]
+           case kWikiNL:       // +
                wbi = new WikiBlockItem (WikiBlock::BlockItemNL, wiki);
                break;
            default:
@@ -971,14 +574,14 @@ void  WikiBlockItem::addLine (uiterator b, uiterator e) {
                    wbi->addLine (b, e);
                    wbt->block.push_back (wbi);
                } else {
-                   wbt = new WikiBlockItemText (wiki);
+                   wbt = new WikiBlockItemText (wiki, this);
                    block.push_back (wbt);
                    wbi->addLine (b, e);
                    wbt->block.push_back (wbi);
                    wbt->indentHack = true;
                }
            } else {
-               wbt = new WikiBlockItemText (wiki);
+               wbt = new WikiBlockItemText (wiki, this);
                block.push_back (wbt);
                wbt->addLine (b, e);
            }
@@ -991,17 +594,25 @@ void  WikiBlockItem::output (MotorOutput* out) {
 
     switch (type) {
     case BlockItemUL:
-       out->out_raw (CharConst ("<ul>\n"));
+       out->out_raw (CharConst ("<ul"));
+       attrib.output (out);
+       out->out_raw (CharConst (">\n"));
        outputBlock (out);
        out->out_raw (CharConst ("</ul>\n"));
        break;
     case BlockItemOL:
-       out->out_raw (CharConst ("<ol>\n"));
+       out->out_raw (CharConst ("<ol"));
+       attrib.output (out);
+       out->out_raw (CharConst (">\n"));
        outputBlock (out);
        out->out_raw (CharConst ("</ol>\n"));
        break;
     case BlockItemNL:
-       out->out_raw (CharConst ("<ul class=\"nobull\">\n"));
+       out->out_raw (CharConst ("<ul"));
+       attrib.classlist.push_back (ustring (CharConst ("nobull")));
+       attrib.output (out);
+       attrib.classlist.pop_back ();
+       out->out_raw (CharConst (">\n"));
        outputBlock (out);
        out->out_raw (CharConst ("</ul>\n"));
        break;
@@ -1022,6 +633,10 @@ void  WikiBlockItem::outputBlock (MotorOutput* out) {
 ===定義リスト===
  ;見出し:説明文
 
+{div:greenbox
+;見出し:説明文
+}
+
 */
 bool  WikiBlockItemDL::nextLine (uiterator b, uiterator e) {
     if (*b == kWikiDL) {
@@ -1033,23 +648,25 @@ bool  WikiBlockItemDL::nextLine (uiterator b, uiterator e) {
 }
 
 void  WikiBlockItemDL::addLine (uiterator b, uiterator e) {
-    WikiMotor  motor (b + 1, e, wiki);
     WikiMotorObjVec  objs;
-    ustring  def, desc;
+    WikiMotorObjVec*  def;
+    WikiMotorObjVec*  desc;
 
-    motor.compile (objs);
-    objs.splitChar (wiki, ':', def, desc);
-    html1.push_back (def);
-    html2.push_back (desc);
+    wiki->wikiMotorInline (b + 1, e, objs);
+    def = new WikiMotorObjVec;
+    desc = new WikiMotorObjVec;
+    objv1.push_back (def);
+    objv2.push_back (desc);
+    objs.splitChar (':', *def, *desc);
 }
 
 void  WikiBlockItemDL::output (MotorOutput* out) {
     int  i;
 
     out->out_raw (CharConst ("<dl>\n"));
-    for (i = 0; i < html1.size (); i ++) {
-       out->out_raw (CharConst ("<dt>"))->out_toText (html1[i])->out_raw (CharConst ("</dt>\n"));
-       out->out_raw (CharConst ("<dd>"))->out_toText (html2[i])->out_raw (CharConst ("</dd>\n"));
+    for (i = 0; i < objv1.size (); i ++) {
+       out->out_raw (CharConst ("<dt>"))->out_toText (objv1[i].htmlOut (wiki))->out_raw (CharConst ("</dt>\n"));
+       out->out_raw (CharConst ("<dd>"))->out_toText (objv2[i].htmlOut (wiki))->out_raw (CharConst ("</dd>\n"));
     }
     out->out_raw (CharConst ("</dl>\n"));
 }
@@ -1057,31 +674,37 @@ void  WikiBlockItemDL::output (MotorOutput* out) {
 /* ============================================================ */
 /*DOC:
 ===表===
- |table:w=100%|head:right:||right:|
+ |table:w=100%:数量リスト|head:right:||right:|
  |*:|head:品名|head:数量|
  |1|テレビ|2|
  |2|空気清浄機|3|
 
 +・テーブルセルオプション
-表定義の最初の行の最初のカラムに「table:」を書くと,この行はテーブルオプション指定行になる。2番目以降のカラムは,デフォルトのカラムオプション指定になる。
-
-|table:||c:||
-|h:名前|h:省略形|h:意味|
-|noborder|nb|border="0"を出力する。|
-|cellspacing=''integer''|spc=|cellspacing属性を出力する。|
-|cellpadding=''integer''||cellpadding属性を出力する。|
-|padding|pad|テーブルの最大のカラム数よりカラムが少ない行に,空のカラムを追加する。|
-|expanding|expand|テーブルの最大のカラム数よりカラムが少ない行の最後のカラムを引き延ばす。|
-|center|c|テーブルをセンタリングする。|
-|left|l|テーブルを左寄せする。|
-|right|r|テーブルを右寄せする。|
-|id=''name''||id属性を出力する。|
-|class=''name,name,...''||class属性を出力する。|
-|width=''number'', width=''number''%|w=|width属性を出力する。|
-|bgcolor=#''color''|bg=|bgcolor属性を出力する。|
-|onclick=''fn(arg1,arg2,...)''||onClick属性を出力する。''name''はdefun-wiki-linkで定義したもの。|
-|nowhite|nw||
-|turn||セルの並びの横方向と縦方向を交換する。|
+表定義の最初の行の最初のカラムに「table:」を書くと,この行はテーブルオプション指定行になる。属性指定の後にテキストを書くと,表のキャプションになる。
+2番目以降のカラムは,デフォルトのカラムオプション指定になる。
+
+|table:w=100%:テーブルオプション|t:w=20%|c:w=10%|t:|
+|h:オプション|h:省略形|h:説明|
+|'''id='''''ID''||id属性。|
+|'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
+//|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
+|'''onclick='''''Link''||onclick属性。Javascriptリンク。|
+|'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
+|'''onblur='''''Link''||onblur属性。Javascriptリンク。|
+|'''onchange='''''Link''||onchange属性。Javascriptリンク。|
+|'''width='''''Size''|'''w='''|width属性。単位はpx, pt, in, mm, cm, em, ex。または%。|
+//|'''height='''''Size''|'''h='''|height属性。単位はpx, pt, in, mm, cm, em, ex。または%。|
+|'''bgcolor='''''Color''|'''bg='''|bgcolor属性。|
+|'''cellspacing='''''Integer''|'''spc='''|cellspacing属性。*コンパイル時設定による。|
+|'''cellpadding='''''Integer''||cellpadding属性。*コンパイル時設定による。|
+|'''left'''|'''l'''|align="left"属性。|
+|'''right'''|'''r'''|align="right"属性。|
+|'''center'''|'''c'''|align="center"属性。|
+|'''noborder'''|''nb''|border="0"属性。|
+|'''padding'''|'''pad'''|行のカラム定義が最大カラム数に満たない時,空のカラムを追加する。|
+|'''expanding'''|'''expand'''|行のカラム定義が最大カラム数に満たない時,最終カラムを伸ばす。|
+|'''nowhite'''|'''nw'''|空セルにnbspを出力する。|
+|'''turn'''||表の行と列を入れ替える。|
 
 +・行オプション
  |row:bgcolor=#ff0|&[;&[;Name]]|&[;&[;Value]]|
@@ -1089,25 +712,30 @@ void  WikiBlockItemDL::output (MotorOutput* out) {
 行オプションで指定できる属性はセルオプションと同じものである。
 
 +・セルオプション
- |header:名前|class=big:東武|
- |header:
-|table:||c:||
-|h:名前|h:省略形|h:意味|
-|header|h|ヘッダタグ(<th>)を出力する。|
-|left|l|セル内で左寄せする。|
-|right|r|右寄せする。|
-|center|c|横方向で中央あわせする。|
-|top|t|セル内で上寄せする。|
-|middle|m|縦方向で中央あわせする。|
-|bottom|b|下寄せする。|
-|nowrap|nw|セル内での折り返しを禁止する。|
-|*||デフォルトのセルオプションを含め,全てのセルオプションを破棄する。|
-|id=''name''||セルタグにid属性を付加する。|
-|class=''name,name,...''||セルタグにclass属性を付加する。|
-|width=''number''&|;''number''%||セルタグにwidth属性を付加する。|
-|height=''number''&|;''number''%||セルタグにheight属性を付加する。|
-|bgcolor=#''hex''|bg=|セルタグにbg属性を付加する。|
-|onclick=''fn(arg1,arg2,...)''||onClick属性を出力する。''name''はdefun-wiki-linkで定義したもの。|
+// |header:名前|class=big:東武|
+// |header:
+
+|table:w=100%:行オプション,セルオプション|t:w=20%|c:w=10%|t:|
+|h:オプション|h:省略形|h:説明|
+|'''id='''''ID''||id属性。|
+|'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
+//|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
+|'''onclick='''''Link''||onclick属性。Javascriptリンク。|
+|'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
+|'''onblur='''''Link''||onblur属性。Javascriptリンク。|
+|'''onchange='''''Link''||onchange属性。Javascriptリンク。|
+|'''width='''''Size''|'''w='''|width属性。単位はpx, pt, in, mm, cm, em, ex。または%。|
+|'''height='''''Size''|'''h='''|height属性。単位はpx, pt, in, mm, cm, em, ex。または%。|
+|'''bgcolor='''''Color''|'''bg='''|bgcolor属性。|
+|'''header'''|'''h'''|thタグを出力する。|
+|'''left'''|'''l'''|align="left"属性。|
+|'''right'''|'''r'''|align="right"属性。|
+|'''center'''|'''c'''|align="center"属性。|
+|'''top'''|'''t'''|valign="top"属性。|
+|'''middle'''|'''m'''|valign="middle"属性。|
+|'''bottom'''|'''b'''|valign="bottom"属性。|
+|'''nowrap'''|'''nw'''|nowrap属性。|
+|'''*'''||オプションのクリア。|
 
 |h:結合記号|h:意味|
 |&<;|左のセルと結合する。|
@@ -1186,7 +814,8 @@ void  WikiBlockTable::TableCell::outputTD (WikiFormat* wiki, MotorOutput* out, b
        out->out_raw (CharConst ("<th"));
     else
        out->out_raw (CharConst ("<td"));
-    cellattrib.output (out);
+    bool  foutputwidth = (! fturn && colspan == 1) || (fturn && rowspan == 1);
+    cellattrib.outputCell (out, foutputwidth);
     if (fturn) {
        if (colspan > 1)
            wiki->outputName (out, CharConst ("rowspan"), colspan, false);
@@ -1230,7 +859,7 @@ void  WikiBlockTable::addLine (uiterator b, uiterator e) {
 }
 
 WikiBlock::closeType  WikiBlockTable::closeLine (uiterator b, uiterator e) {
-#ifdef TABLECOMPATFLAG
+#ifdef WIKITABLECOMPATFLAG
     static uregex  re ("^\\}\\}(($)|(\\|)|((!([1-9][0-9]*))?(\\\\|&)$))");
 #else
     static uregex  re ("^\\}\\}(($)|(\\|)|((!([1-9][0-9]*))?(&)$))");
@@ -1284,9 +913,17 @@ void  WikiBlockTable::addLine_head (uiterator b, uiterator e) {
     objv.splitCharA ('|', objvv);
     if (objvv.size () > 0 && objvv.back ()->size () == 0)
        objvv.pop_back ();
-    attrib.shiftAttrib (objvv[0]);
+    if (objvv.size () > 0)
+       attrib.shiftAttrib (objvv[0]);
+
+    cell = new TableCell (wiki, WikiAttrib1::M_NORMAL);
+    if (objvv.size () > 0)
+       cell->cellBody (objvv[0].get (), this, 0);
+    captionHtml = cell->html;
+    delete cell;
+
     for (i = 1; i < objvv.size (); i ++) {
-       cell = new TableCell (wiki, true);
+       cell = new TableCell (wiki, WikiAttrib1::M_ATTRIB);
        cell->cellattrib.shiftAttrib (objvv[i]);
        defaultList.push_back (cell);
     }
@@ -1296,7 +933,7 @@ void  WikiBlockTable::addLine_body (uiterator b, uiterator e) {
     CellList_t*  cols;
     bool  fmorecell = false;
     umatch  m;
-#ifdef TABLECOMPATFLAG
+#ifdef WIKITABLECOMPATFLAG
     static uregex  re ("(!([1-9][0-9]*))?(\\\\|&)$");
 #else
     static uregex  re ("(!([1-9][0-9]*))?(&)$");
@@ -1306,7 +943,6 @@ void  WikiBlockTable::addLine_body (uiterator b, uiterator e) {
        cont = false;
        cols = &ary.back ();
     } else {
-//     cols = new CellList_t;
        cols = new CellList_t (wiki);
        ary.push_back (cols);
     }
@@ -1362,8 +998,10 @@ void  WikiBlockTable::addLine_body (uiterator b, uiterator e) {
                cell = newCell (cols->rowattrib);
            else
                cell = newCell (cols->size ());
-           if (! cell->cellattrib.shiftAttrib (objvv[i]))
+           if (! cell->cellattrib.shiftAttrib (objvv[i])) {
+               delete cell;
                return;
+           }
            if (i == n && fop && objvv[i]->match (brabra)) {
                cols->push_back (cell);
                wiki->push_block (&cell->block);
@@ -1384,7 +1022,7 @@ void  WikiBlockTable::addLine_body (uiterator b, uiterator e) {
 }
 
 WikiBlockTable::TableCell*  WikiBlockTable::newCell (int idx) {
-    TableCell*  ans = new TableCell (wiki, false);
+    TableCell*  ans = new TableCell (wiki, WikiAttrib1::M_NORMAL);
 
     if (idx < defaultList.size ())
        ans->cellattrib.copyFrom (defaultList[idx].cellattrib);
@@ -1392,7 +1030,7 @@ WikiBlockTable::TableCell*  WikiBlockTable::newCell (int idx) {
 }
 
 WikiBlockTable::TableCell*  WikiBlockTable::newCell (WikiAttribTable& rowattrib) {
-    TableCell*  ans = new TableCell (wiki, false);
+    TableCell*  ans = new TableCell (wiki, WikiAttrib1::M_NORMAL);
 
     ans->cellattrib.copyFrom (rowattrib);
     return ans;
@@ -1454,13 +1092,18 @@ void  WikiBlockTable::normalize () {
 void  WikiBlockTable::outputTableTag (MotorOutput* out) {
     int  i;
 
+#ifdef WIKITABLEATTRIB
     if (attrib.cellspacing < 0)
        attrib.cellspacing = 0;
     if (attrib.cellpadding < 0)
        attrib.cellpadding = 0;
+#endif
     out->out_raw (CharConst ("<table"));
     attrib.output (out);
     out->out_raw (CharConst (">\n"));
+    if (captionHtml.length () > 0) {
+       out->out_raw (CharConst ("<caption>"))->out_toText (captionHtml)->out_raw (CharConst ("</caption>\n"));
+    }
 }
 
 void  WikiBlockTable::outputTBody (MotorOutput* out) {
@@ -1504,6 +1147,12 @@ void  WikiBlockTable::outputTBodyCell (WikiFormat* wiki, MotorOutput* out, Table
     if (cell->colspan > 0 && cell->rowspan > 0) {
        cell->outputTD (wiki, out, attrib.fturn);
        if (cell->block.size () > 0) {
+           if (cell->block.size () == 1 && cell->block[0].type == BlockParagraph) {
+               WikiBlockParagraph*  b = WikiBlockParagraph_type (&cell->block[0]);
+               if (! b->pflag) {
+                   b->singleTag = true;
+               }
+           }
            wiki->output (cell->block);
        } else {
            if (cell->html.size () > 0) {
@@ -1524,6 +1173,19 @@ void  WikiBlockTable::outputTBodyCell (WikiFormat* wiki, MotorOutput* out, Table
  |VALUE|
  |LABEL|VALUE|selected|
 
+オプションパラメータ
+|table:w=100%|t:w=20%|c:w=10%|t:|
+|h:オプション|h:省略形|h:説明|
+|'''id='''''ID''||id属性。|
+|'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
+//|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
+|'''onclick='''''Link''||onclick属性。Javascriptリンク。|
+|'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
+|'''onblur='''''Link''||onblur属性。Javascriptリンク。|
+|'''onchange='''''Link''||onchange属性。Javascriptリンク。|
+|'''size='''''Integer''||size属性。|
+|'''multiple'''||multiple属性。|
+
 */
 bool  WikiBlockSelect::nextLine (uiterator b, uiterator e) {
     if (*b == kWikiTABLE) {
@@ -1623,7 +1285,7 @@ void  WikiBlockSelect::output (MotorOutput* out) {
     out->out_raw (CharConst (">\n"));
 
     if (attrib.fdefault)
-       u = wiki->getVar (name);
+       u = wiki->getVar_string (name);
 #ifdef DEBUG2
     std::cerr << "u:" << u << uLF;
 #endif /* DEBUG */
@@ -1680,26 +1342,50 @@ void  WikiBlockQuote::output (MotorOutput* out) {
 /* ============================================================ */
 /*DOC:
 ===DIVタグ===
- {div:SideMenu
+ {div:''ClassName''
  ...
  }
- {div:id=Name:SideMenu:onclick=fn()
+ {div:id=''ID'':''ClassName'':onclick=''LinkFunction''
  ...
  }
 
+オプションパラメータ
+|table:w=100%|t:w=20%|c:w=10%|t:|
+|h:オプション|h:省略形|h:説明|
+|'''id='''''ID''||id属性。|
+|'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
+//|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
+|'''onclick='''''Link''||onclick属性。Javascriptリンク。|
+|'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
+|'''onblur='''''Link''||onblur属性。Javascriptリンク。|
+|'''onchange='''''Link''||onchange属性。Javascriptリンク。|
+|''ClassList''||class=は省略できる。|
+|'''#nop'''||divタグを出力しない。pタグを抑制する。|
+
 */
 bool  WikiBlockDiv::nextLine (uiterator b, uiterator e) {
     return false;
 }
 
 void  WikiBlockDiv::addLine (uiterator b, uiterator e) {
-    bool  rc = matchSkip (b, e, CharConst ("{div:"));
+    bool  rc = matchSkip (b, e, CharConst (uWikiDIV)); // {div:
     assert (rc);
     WikiMotor  motor (b, e, wiki);
     WikiMotorObjVecPtr  vec (new WikiMotorObjVec);
 
     motor.compile (*vec);
     attrib.shiftAttrib (vec);
+    {
+       std::vector<ustring>::const_iterator  b = attrib.directlist.begin ();
+       std::vector<ustring>::const_iterator  e = attrib.directlist.end ();
+       for (; b < e; ++ b) {
+           if (match (*b, CharConst ("#nop"))) {
+               nopflag = true;
+           } else {
+               wiki->errorMsg.append (*b).append (CharConst (": bad attribute.\n"));
+           }
+       }
+    }
 }
 
 WikiBlock::closeType  WikiBlockDiv::closeLine (uiterator b, uiterator e) {
@@ -1713,34 +1399,74 @@ WikiBlock::closeType  WikiBlockDiv::closeLine (uiterator b, uiterator e) {
 }
 
 void  WikiBlockDiv::output (MotorOutput* out) {
-    out->out_raw (CharConst ("<div"));
-    attrib.output (out);
-    out->out_raw (CharConst (">\n"));
+    bool  nonl = false;
+
+    if (nopflag) {
+       boost::ptr_vector<WikiBlock>::iterator  b = block.begin ();
+       boost::ptr_vector<WikiBlock>::iterator  e = block.end ();
+       for (; b < e; ++ b) {
+           if (b->type == BlockParagraph) {
+               WikiBlockParagraph*  p = WikiBlockParagraph_type (&(*b));
+               if (! p->pflag) {
+                   p->singleTag = true;
+                   nonl = true;
+               }
+           }
+       }
+    } else {
+       if (block.size () == 1 && block[0].type == BlockParagraph) {
+           WikiBlockParagraph*  b = WikiBlockParagraph_type (&block[0]);
+           if (! b->pflag) {
+               b->singleTag = true;
+               nonl = true;
+           }
+       }
+       out->out_raw (CharConst ("<div"));
+       attrib.output (out);
+       if (nonl)
+           out->out_raw (CharConst (">"));
+       else
+           out->out_raw (CharConst (">\n"));
+    }
     outputBlock (out);
-    out->out_raw (CharConst ("</div>\n"));
+    if (! nopflag) {
+       out->out_raw (CharConst ("</div>\n"));
+    } else {
+       out->out_raw (uLF);
+    }
 }
 
 /* ============================================================ */
 /*DOC:
 ===FORMタグ===
- {form:POST:post.hml
+ {form:POST:''URL''
  ...
  }
-// {form:POST:id=form1:class=formclass:post.hml
-// {form:POST:post.hml:id=form1:class=formclass
- {form:POST:post.hml:target=target_window:id=form1:class=formclass
+ {form:POST:''URL'':target=''TargetWindow'':id=''ID'':class=''ClassName''
  ...
  }
 
+オプションパラメータ
+|table:w=100%|t:w=20%|c:w=10%|t:|
+|h:オプション|h:省略形|h:説明|
+|'''id='''''ID''||id属性。|
+|'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
+//|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
+|'''onclick='''''Link''||onclick属性。Javascriptリンク。|
+|'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
+|'''onblur='''''Link''||onblur属性。Javascriptリンク。|
+|'''onchange='''''Link''||onchange属性。Javascriptリンク。|
+|'''target='''''Window''||target属性。|
+
 */
 bool  WikiBlockForm::nextLine (uiterator b, uiterator e) {
     return false;
 }
 
 void  WikiBlockForm::addLine (uiterator b, uiterator e) {
-    bool  rc = matchSkip (b, e, CharConst ("{form:"));
+//    bool  rc = matchSkip (b, e, CharConst ("{form:"));
+    bool  rc = matchSkip (b, e, CharConst (uWikiFORM));
     assert (rc);
-
     WikiMotor  motor (b, e, wiki);
     WikiMotorObjVecPtr  vec (new WikiMotorObjVec);
     ustring  key;
@@ -1787,7 +1513,7 @@ void  WikiBlockForm::output (MotorOutput* out) {
     }
     if (fscript) {
        wiki->outputName (out, CharConst ("action"), ustring (CharConst ("#")), false);
-       wiki->outputSubmitScript (out, CharConst ("onSubmit"), url);
+       wiki->outputSubmitScript (out, CharConst ("onsubmit"), url, true);
     } else {
        wiki->outputName (out, CharConst ("action"), url, false);
     }
@@ -1801,6 +1527,54 @@ void  WikiBlockForm::output (MotorOutput* out) {
 
 /* ============================================================ */
 /*DOC:
+===Elementブロック===
+ {element:''Name''
+ ...
+ }
+
+Wikiテキストの名前付きブロック。
+
+*/
+bool  WikiBlockElement::nextLine (uiterator b, uiterator e) {
+    return false;
+}
+
+void  WikiBlockElement::addLine (uiterator b, uiterator e) {
+    bool  rc = matchSkip (b, e, CharConst (uWikiELEMENT));
+    assert (rc);
+    WikiMotor  motor (b, e, wiki);
+    WikiMotorObjVecPtr  vec (new WikiMotorObjVec);
+    WikiMotorObjVecPtr  v2 (new WikiMotorObjVec);
+
+    motor.compile (*vec);
+    vec->splitChar_keyword (':', name, *v2);
+    if (name.size () == 0) {
+       wiki->errorMsg.append (CharConst ("missing name in the element block."));
+    }
+    if (v2->size () > 0) {
+       wiki->errorMsg.append (v2->dump ()).append (CharConst (": bad attribute.\n"));
+    }
+    if (name.size () > 0) {
+       wiki->elementMap.put (name, this);
+    }
+}
+
+WikiBlock::closeType  WikiBlockElement::closeLine (uiterator b, uiterator e) {
+    if (e - b == 1 && *b == kWikiDIV_e) {
+       wiki->pop_block ();
+       wiki->cur = NULL;
+       return CloseTrue;
+    } else {
+       return CloseFalse;
+    }
+}
+
+void  WikiBlockElement::output (MotorOutput* out) {
+//***    outputBlock (out);
+}
+
+/* ============================================================ */
+/*DOC:
 ===水平線===
  ----
 
@@ -1818,30 +1592,106 @@ void  WikiBlockHR::output (MotorOutput* out) {
 }
 
 /* ============================================================ */
+bool  WikiBlockRaw::nextLine (uiterator b, uiterator e) {
+    return false;
+}
+
+void  WikiBlockRaw::addLine (uiterator b, uiterator e) {
+    text.assign (b, e);
+}
+
+void  WikiBlockRaw::output (MotorOutput* out) {
+    out->out_toText (text);
+}
+
+/* ============================================================ */
+bool  WikiBlockBlank::nextLine (uiterator b, uiterator e) {
+    if (b == e) {
+       count ++;
+       return true;
+    } else {
+       switch (*b) {           // paragraph以外の全て
+       case kWikiH:
+       case kWikiPRE:
+       case kWikiPRE2:
+       case kWikiUL:
+       case kWikiOL:
+       case kWikiNL:
+       case kWikiDL:
+       case kWikiTABLE:
+           count = 0;
+           break;
+       default:
+           if ((*b == kWikiQUOTE && e - b == 1) ||
+               matchHead (b, e, CharConst (uWikiDIV)) ||
+               (wiki->curform == NULL && matchHead (b, e, CharConst (uWikiFORM))) ||
+               (wiki->curform == NULL && matchHead (b, e, CharConst (uWikiELEMENT))) ||
+               matchHead (b, e, CharConst ("----"))) {
+               count = 0;
+           } else {
+               if (count >= 2)
+                   enable = true;
+           }
+       }
+       return false;
+    }
+}
+
+void  WikiBlockBlank::addLine (uiterator b, uiterator e) {
+    count ++;
+}
+
+void  WikiBlockBlank::output (MotorOutput* out) {
+    if (enable) {
+       out->out_raw (CharConst ("<div class=\"pggap\"></div>\n"));
+    }
+}
+
+/* ============================================================ */
 void  WikiFormat::pass1 (const ustring& text, WikiLine::linevec* block, bool fsuper) {
-    Splitter  sp (text, re_nl);
+    SplitterNL  sp (text);
 
     pass1_1 (sp, NULL, NULL, block, NULL, NULL, NULL, fsuper);
 }
 
+static bool  findCmdSep (uiterator& b, uiterator e, uiterator& u) {
+    int  c;
+    uiterator  p = b;
+    for (; p < e; ++ p) {
+       c = *p;
+       if (c == ':') {
+           b = p;
+           u = b + 1;
+           return true;
+       } else if (c == ' ' || c == '\t') {
+           b = p;
+           u = b;
+           do {
+               ++ u;
+           } while (u < e && ((c = *u) == ' ' || c == '\t'));
+           return true;
+       }
+    }
+    b = p;
+    u = e;
+    return true;
+}
+
 int  WikiFormat::pass1_1 (Splitter& sp, ustring* elseword, ustring* endword, WikiLine::linevec* block, uiterator* elsebegin0, uiterator* elsebegin, uiterator* elseend, bool fsuper) {
     uiterator  b, e, t, u, v;
-    umatch  m;
 
     while (sp.next ()) {
        b = sp.begin ();
        e = sp.end ();
-       while (b < e && b[0] == '\t')
+       while (b < e && b[0] == '\t')   // TABを無視
            b ++;
        if (matchSkip (b, e, CharConst (kComment))) {
            // comment
        } else if (b != e && b[0] == kWikiCmd) {
-           if (usearch (b, e, m, re_wikicmdsep)) {
-               t = b;
-               u = m[0].first;
-               v = m[0].second;
+           t = b;
+           u = b;
+           if (findCmdSep (u, e, v)) {
            } else {
-               t = b;
                u = e;
                v = e;
            }
@@ -1936,6 +1786,30 @@ bool  WikiFormat::pass1_2 (Splitter& sp, uiterator& b, uiterator& e, uiterator&
            // nonblock
        }
        return true;
+    } else if (t < u && *t == kWikiCmd) {
+       bool  fx = true;
+       MNode*  wf;
+       ustring  name (t + 1, u);                       // '$'を取り除く
+       if (protectMode && ! fsuper && ! env->wikienv->wikiGuestFunc.get (name))
+           fx = false;
+       if (fx && (wf = env->wikienv->wikiCmd2.getVar (name))) { // Wiki Command
+           ustring  endword;
+           endword.assign (CharConst (uWikiCmd "end")).append (name);  // $end...
+           block->push_back (wl = new WikiLine (b, e, fsuper));
+           wl->fn = wc_call_defun;
+           wl->block = new WikiLine::linevec;
+           rc = pass1_1 (sp, NULL, &endword, wl->block, NULL, NULL, NULL, fsuper);
+           if (rc == 0) {
+               // no end line error
+               if (endword.length () > 0) {
+                   errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
+               }
+           } else if (rc == 2) {
+               assert (wl->block2 == NULL);
+               wl->block2 = new WikiLine (sp.begin (), sp.end (), false);
+           }
+           return true;
+       }
     }
 
     return false;
@@ -1999,6 +1873,15 @@ void  WikiFormat::compile (const ustring& text, bool fsuper) {
     }
 }
 
+void  WikiFormat::outputElement (const ustring& elementName) {
+    WikiBlockElement*  b;
+    
+    b = elementMap.get (elementName);
+    if (b) {
+       output (b->block);
+    }
+}
+
 void  WikiFormat::output (boost::ptr_vector<WikiBlock>& ary) {
     int  i;
 
@@ -2029,6 +1912,7 @@ bool  WikiFormat::checkClose (uiterator b, uiterator e) {
            return true;
        case WikiBlock::CloseFalse:
            return false;
+       default:;
        }
     }
     return false;
@@ -2038,17 +1922,28 @@ void  WikiFormat::compileLine (WikiLineScanner& scanner) {
     WikiLine*  wl = scanner.cur ();
     if (! wl)
        return;
-
-    uiterator  b = wl->begin;
-    uiterator  e = wl->end;
-
     if (wl->fn) {
        wl->fn (wl, this);
     } else {
+       uiterator  b = wl->begin;
+       uiterator  e = wl->end;
+
        if (b == e) {           // empty line
            if (cur) {
-               cur->close ();
-               cur = NULL;
+               switch (cur->type) {
+               case WikiBlock::BlockParagraph:
+                   cur->close ();
+                   cur = new WikiBlockBlank (this);
+                   blockp->push_back (cur);
+                   cur->addLine (b, e);
+                   break;
+               case WikiBlock::BlockBlank:
+                   cur->addLine (b, e);
+                   break;
+               default:
+                   cur->close ();
+                   cur = NULL;
+               }
            }
        } else if (matchSkip (b, e, CharConst ("//"))) {        // comment
        } else if (checkClose (b, e)) {
@@ -2066,12 +1961,17 @@ void  WikiFormat::compileLine (WikiLineScanner& scanner) {
            cur = obj = new WikiBlockH (this);
            blockp->push_back (cur);
            cur->addLine (b, e);
-           push_block (&obj->block);
+           if (obj->checkEmpty ()) {
+               cur->close ();
+               cur = NULL;
+           } else {
+               push_block (&obj->block);
+           }
        } else if (b[0] == kWikiPRE     // SPC
                   || b[0] == kWikiPRE2) {      // TAB
            if (cur)
                cur->close ();
-           cur = new WikiBlockPreformat (this);
+           cur = new WikiBlockPreformatRaw (this);
            blockp->push_back (cur);
            cur->addLine (b, e);
        } else if (b[0] == kWikiUL) {   // *
@@ -2088,7 +1988,7 @@ void  WikiFormat::compileLine (WikiLineScanner& scanner) {
            cur = obj = new WikiBlockItem (WikiBlock::BlockItemOL, this);
            blockp->push_back (cur);
            obj->addLine (b, e);
-       } else if (b[0] == kWikiNL) {   // ]
+       } else if (b[0] == kWikiNL) {   // +
            WikiBlockItem*  obj;
            if (cur)
                cur->close ();
@@ -2109,7 +2009,7 @@ void  WikiFormat::compileLine (WikiLineScanner& scanner) {
                cur = new WikiBlockParagraph (this);
                blockp->push_back (cur);
            }
-           push_block (NULL);
+           push_block (blockp);
            cur = new WikiBlockSelect (this);
            cur->addLine (b, e);
        } else if (b[0] == kWikiTABLE) {        // |
@@ -2126,7 +2026,8 @@ void  WikiFormat::compileLine (WikiLineScanner& scanner) {
            cur = obj = new WikiBlockQuote (this);
            blockp->push_back (cur);
            push_block (&obj->block);
-       } else if (matchHead (b, e, CharConst ("{div:"))) {
+//     } else if (matchHead (b, e, CharConst ("{div:"))) {
+       } else if (matchHead (b, e, CharConst (uWikiDIV))) {
            WikiBlockComplex*  obj;
            if (cur)
                cur->close ();
@@ -2134,7 +2035,7 @@ void  WikiFormat::compileLine (WikiLineScanner& scanner) {
            blockp->push_back (cur);
            cur->addLine (b, e);
            push_block (&obj->block);
-       } else if (curform == NULL && matchHead (b, e, CharConst ("{form:"))) {
+       } else if (curform == NULL && matchHead (b, e, CharConst (uWikiFORM))) {
            WikiBlockComplex*  obj;
            if (cur)
                cur->close ();
@@ -2142,6 +2043,14 @@ void  WikiFormat::compileLine (WikiLineScanner& scanner) {
            blockp->push_back (cur);
            cur->addLine (b, e);
            push_block (&obj->block);
+       } else if (curform == NULL && matchHead (b, e, CharConst (uWikiELEMENT))) {
+           WikiBlockComplex*  obj;
+           if (cur)
+               cur->close ();
+           cur = obj = new WikiBlockElement (this);
+           blockp->push_back (cur);
+           cur->addLine (b, e);
+           push_block (&obj->block);
        } else if (matchHead (b, e, CharConst ("----"))) { // ----
            if (cur)
                cur->close ();
@@ -2166,7 +2075,7 @@ void  WikiFormat::compileLine (WikiLineScanner& scanner) {
 void  WikiFormat::compileLines (WikiLineScanner& scanner, bool (*fn)(WikiLine& spp, WikiLineScanner& scanner, WikiFormat* wiki, void* par), void* par) {
     WikiLine*  wl;
 
-    while (wl = scanner.next ()) {
+    while ((wl = scanner.next ())) {
        if (fn && fn (*scanner.cur (), scanner, this, par)) {
            break;
        } else {
@@ -2175,6 +2084,14 @@ void  WikiFormat::compileLines (WikiLineScanner& scanner, bool (*fn)(WikiLine& s
     }
 }
 
+void  WikiFormat::pushBlockRaw (uiterator b, uiterator e) {
+    WikiBlockRaw*  obj;
+
+    obj = new WikiBlockRaw (this);
+    blockp->push_back (obj);
+    obj->addLine (b, e);
+}
+
 int  WikiFormat::countWikiH (uiterator& b, uiterator e) {
     int  ans = 0;
 
@@ -2187,148 +2104,6 @@ int  WikiFormat::countWikiH (uiterator& b, uiterator e) {
     return ans;
 }
 
-bool  WikiFormat::paramID (const ustring& key, WikiMotorObjVec& vval, ustring& var_id, bool& ferr) {
-    if (match (key, CharConst ("id"))) {
-       ustring  value (vval.textOut (this));
-       if (value.length () > 0) {
-           if (checkWikiID (value)) {
-               var_id = value;
-               ferr = false;
-           } else {
-               errorMsg.append (key).append (uEq).append (value).append (CharConst (": bad id\n"));
-               ferr = true;
-           }
-       }
-       return true;
-    } else {
-       return false;
-    }
-}
-
-bool  WikiFormat::paramClass (const ustring& key, WikiMotorObjVec& vval, std::vector<ustring>& classes, bool& ferr) {
-    if (match (key, CharConst ("class"))) {
-       paramClassValue (vval, classes, ferr);
-       return true;
-    } else {
-       return false;
-    }
-}
-
-void  WikiFormat::paramClassValue (WikiMotorObjVec& vval, std::vector<ustring>& classes, bool& ferr) {
-    WikiMotorObjVecVec  args;
-    ferr = false;
-    vval.splitCharA (',', args);
-    for (int i = 0; i < args.size (); i ++) {
-       ustring  value (args[i]->textOut (this));
-       if (value.length () > 0) {
-           if (checkWikiID (value)) {
-               classes.push_back (value);
-           } else {
-               errorMsg.append (value).append (CharConst (": bad class name\n"));
-               ferr = true;
-           }
-       }
-    }
-}
-
-bool  WikiFormat::paramName (const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
-    if (match (key, CharConst ("name"))) {
-       ustring  value (vval.textOut (this));
-       if (checkWikiID (value)) {
-           var = value;
-           ferr = false;
-       } else {
-           ferr = true;
-       }
-       return true;
-    } else {
-       return false;
-    }
-}
-
-bool  WikiFormat::paramWidth (const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
-    if (match (key, CharConst ("width"), CharConst ("w"))) {
-       ustring  value (vval.textOut (this));
-       if (checkWidth (value)) {
-           var = value;
-           if (checkNum (value))
-               var.append (CharConst ("px"));
-           ferr = false;
-       } else {
-           ferr = true;
-       }
-       return true;
-    } else {
-       return false;
-    }
-}
-
-bool  WikiFormat::paramHeight (const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
-    if (match (key, CharConst ("height"), CharConst ("h"))) {
-       ustring  value (vval.textOut (this));
-       if (checkWidth (value)) {
-           var = value;
-           ferr = false;
-       } else {
-           errorMsg.append (key).append (uEq).append (value).append (CharConst (": bad value\n"));
-           ferr = true;
-       }
-       return true;
-    } else {
-       return false;
-    }
-}
-
-bool  WikiFormat::paramSize (const char* name, size_t namelen, const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
-    if (match (key, name, namelen)) {
-       ustring  value (vval.textOut (this));
-       if (checkNum (value)) {
-           var = value;
-           ferr = false;
-       } else {
-           ferr = true;
-       }
-       return true;
-    }
-    return false;
-}
-
-void  WikiFormat::paramUNum (const ustring& value, int& var, const ustring& name) {
-    if (checkNum (value)) {
-       var = strtoul (value);
-    } else {
-       errorMsg.append (name).append (uEq).append (value).append (uErrorBadValue).append (uLF);
-    }
-}
-
-void  WikiFormat::paramColor (const ustring& value, ustring& var, const ustring& name) {
-    if (checkColor (value)) {
-       var = value;
-    } else {
-       errorMsg.append (name).append (uEq).append (value).append (uErrorBadValue).append (uLF);
-    }
-}
-
-bool  WikiFormat::paramTargetCheck (const ustring& key) {
-    return match (key, CharConst ("target"));
-}
-
-void  WikiFormat::paramTargetBody (const ustring& key, const ustring& value, ustring& var, bool& ferr) {
-    if (value.length () == 0 || checkWikiID (value)) {
-       var = value;
-    } else {
-       if (key.length () > 0)
-           errorMsg.append (key).append (uEq).append (value).append (CharConst (": bad target name.\n"));
-       else
-           errorMsg.append (value).append (CharConst (": bad target name.\n"));
-       ferr = true;
-    }
-}
-
-bool  WikiFormat::paramOnClickCheck (const ustring& name) {
-    return match (name, CharConst ("onclick"));
-}
-
 void  WikiFormat::outputName (MotorOutput* out, const char* name, size_t len, const ustring& val, bool cond) {
     if (! cond || val.length () > 0)
        out->out_raw (uSPC)
@@ -2375,19 +2150,54 @@ void  WikiFormat::outputClass (MotorOutput* out, std::vector<ustring>& classes)
     }
 }
 
-void  WikiFormat::outputSubmitScript (MotorOutput* out, const char* name, size_t len, const ustring& onclick) {
-    if (onclick.length () > 0)
+void  WikiFormat::outputSubmitScript (MotorOutput* out, const char* name, size_t len, const ustring& onclick, bool scriptcut) {
+    if (onclick.length () > 0) {
        out->out_raw (uSPC)
            ->out_raw (name, len)
            ->out_raw (CharConst ("=\""))
-           ->out_toHTML_noCtrl (onclick)
-           ->out_raw ("return false;\"");
-//         ->out_raw ("\"");
+           ->out_toHTML_noCtrl (onclick);
+       if (scriptcut)
+           out->out_raw (CharConst ("return false;\""));
+       else
+           out->out_raw (CharConst ("\""));
+    }
+}
+
+void  WikiFormat::outputNum (MotorOutput* out, const char* name, size_t len, int val) {
+    out->out_raw (uSPC)
+       ->out_raw (name, len)
+       ->out_raw (CharConst ("="))
+       ->out_raw (to_ustring (val));
+}
+
+MNode*  WikiFormat::arrayToTexp (const ustring& name) {
+    size_t  i, n;
+    MNodeList  e;
+
+    n = mlenv->getArySize (name);
+    for (i = 1; i <= n; i ++) {
+       e.append (mlenv->getAry (name, i));
+    }
+    return mlenv->retval = e ();
+}
+
+MNode*  WikiFormat::evalVar (const ustring& name) {
+    // @NAME → getarray
+    // NAME → getvar
+    ustring  sym;
+    if (checkAry (name, sym)) {
+       return arrayToTexp (sym);
+    } else {
+       return mlenv->getVar (name);
+    }
 }
 
 void  WikiFormat::wikiMotor (uiterator b, uiterator e, WikiMotorObjVec& ans) {
     WikiMotor  motor (b, e, this);
+    AutoInclCount  autoIncl (env->mlenv);
 
+    if (! autoIncl.inc_test ())
+       throw (uErrorInclNest);
     motor.compile (ans, WikiMotor::TMATCH_NONE);
 }
 
@@ -2398,34 +2208,22 @@ ustring  WikiFormat::wikiMotor (uiterator b, uiterator e) {
     return objv.htmlOut (this);
 }
 
-MNode*  WikiFormat::buildArgs (WikiMotorObjVecVec::const_iterator b, WikiMotorObjVecVec::const_iterator e, bool dumpmode) {
+void  WikiFormat::wikiMotorInline (uiterator b, uiterator e, WikiMotorObjVec& ans) {
+    WikiMotorObjVec  objv;
+    WikiMotor  motor (b, e, this);
+
+    motor.compile (objv, WikiMotor::TMATCH_NONE);
+    objv.eval (ans, this);
+}
+
+MNode*  WikiFormat::buildArgs (WikiMotorObjVecVec::const_iterator b, WikiMotorObjVecVec::const_iterator e) {
     MNodeList  ans;
 
-    if (dumpmode) {
-       for (; b < e; b ++) {
-           ans.append (newMNode_str (new ustring ((*b)->dump ())));
-       }
-    } else {
-       for (; b < e; b ++) {
-           ans.append (newMNode_str (new ustring ((*b)->textOut (this))));
-       }
+    for (; b < e; b ++) {
+       ans.append ((*b)->toMNode (this));
     }
     
     return ans.release ();
-#if 0
-    MNode*  ans = NULL;
-    MNode*  a;
-
-    if (b < e) {
-       ans = a = new MNode;
-       a->set_car (newMNode_str (new ustring ((*b)->textOut (this))));
-       for (b ++; b < e; b ++) {
-           newMNodeCdr (a);
-           a->set_car (newMNode_str (new ustring ((*b)->textOut (this))));
-       }
-    }
-    return ans;
-#endif
 }
 
 void  WikiFormat::logLispFunctionError (const ustring& msg, const ustring& cmd) {
@@ -2439,4 +2237,7 @@ void  WikiFormat::logLispFunctionError (const ustring& msg, const ustring& cmd)
     }
 }
 
+/*DOC:
+$premode:
+*/
 /* ============================================================ */