1 #include "wikiformat.h"
8 #include "motorconst.h"
10 #include "motoroutput.h"
11 #include "util_const.h"
12 #include "util_check.h"
13 #include "util_string.h"
16 #include <boost/ptr_container/ptr_vector.hpp>
22 #define kWikiPRE2 '\t'
28 #define kWikiTABLE '|'
29 #define kWikiQUOTE '>'
30 #define kWikiQUOTE_e '<'
32 #define kWikiDIV_e '}'
44 #define uH1e "</h1>\n"
45 #define uH2e "</h2>\n"
46 #define uH3e "</h3>\n"
47 #define uH4e "</h4>\n"
48 #define uH5e "</h5>\n"
49 #define uH6e "</h6>\n"
50 #define uHR "<hr />\n"
51 //#define unbsp " "
53 ustring uWiki (CharConst ("wiki_"));
59 /* ============================================================ */
60 void WikiMlEnv::setVar (const ustring& name, MNode* val) {
63 parent->setVar (na, val);
66 void WikiMlEnv::setAry (const ustring& name, size_t i, MNode* val) {
69 parent->setAry (na, i, val);
72 void WikiMlEnv::setArySize (const ustring& name, size_t n) {
75 parent->setArySize (na, n);
78 void WikiMlEnv::setAry (const ustring& name, MNode* list) {
81 parent->setAry (na, list);
84 MNode* WikiMlEnv::getVar (const ustring& name) {
87 return parent->getVar (na);
90 MNode* WikiMlEnv::getAry (const ustring& name, size_t i) {
93 return parent->getAry (na, i);
96 size_t WikiMlEnv::getArySize (const ustring& name) {
99 return parent->getArySize (na);
102 /* ============================================================ */
103 bool WikiAttrib1::readAttrib1 (WikiMotorObjVec* cell, bool& rc) {
105 WikiMotorObjVec vval;
108 if (cell->size () == 0) {
114 if (cell->splitChar_keyword ('=', key, vval)) {
115 if (wiki->paramID (key, vval, id, ferr)) {
116 } else if (wiki->paramClass (key, vval, classlist, ferr)) {
117 } else if (wiki->paramOnClickCheck (key)) {
118 if (! checkScript (vval, onclick, ferr)) {
119 wiki->errorMsg.append (cell->dump ()).append (CharConst (": link script error.\n"));
122 } else if ((selector & SEL_TARGET) && wiki->paramTargetCheck (key)) {
123 wiki->paramTargetBody (key, vval.textOut (wiki), target, ferr);
124 } else if (readAttribMore (key, vval, ferr)) {
127 wiki->errorMsg.append (cell->dump ()).append (CharConst (": bad attribute.\n"));
133 if (selector & SEL_CLASS2) {
134 wiki->paramClassValue (*cell, classlist, ferr);
135 } else if (selector & SEL_TARGET2) {
136 wiki->paramTargetBody (uEmpty, cell->textOut (wiki), target, ferr);
137 } else if ((selector & SEL_ONCLICK2) && checkScript (*cell, onclick, ferr)) {
138 } else if ((selector & SEL_MULTIPLE2) && match (key, CharConst ("multiple"))) {
140 } else if ((selector & SEL_DEFAULT2) && match (key, CharConst ("default"))) {
142 } else if ((selector & SEL_SCRIPT2) && checkScript (*cell, script, ferr)) {
143 } else if (readAttribMore2 (key, *cell, ferr)) {
146 wiki->errorMsg.append (cell->dump ()).append (CharConst (": bad attribute.\n"));
160 bool WikiAttrib1::shiftAttrib (WikiMotorObjVecPtr& vec) {
162 WikiMotorObjVecPtr v2;
164 while (vec->size () > 0) {
165 WikiMotorObjVec cell;
167 v2 = WikiMotorObjVecPtr (new WikiMotorObjVec);
168 if (vec->splitChar (':', cell, *v2) || fwhole) {
169 if (! readAttrib1 (&cell, rc))
179 bool WikiAttrib1::readAttrib (WikiMotorObjVecVec::const_iterator&b, const WikiMotorObjVecVec::const_iterator& e) {
183 WikiMotorObjVec* cell = b->get ();
184 if (! readAttrib1 (cell, rc))
191 bool WikiAttrib1::checkScript (WikiMotorObjVec& vec, ustring& scr, bool& ferr) {
195 for (i = 0; i < vec.size () && vec[i]->type == WikiMotorObj::wiki_funcLink; i ++) {
196 WikiMotorObjFuncLink* fn = WikiMotorObjFuncLink_type (&*vec[i]);
197 u = fn->execDefunArgs (wiki);
198 // XXX: 末尾の空白を除去し,セミコロンを確認する。
208 bool WikiAttrib1::shiftLink (WikiMotorObjVecPtr& vec, ustring& url, bool& fscript) {
211 WikiMotorObjVec cell;
212 WikiMotorObjVecPtr v2 (new WikiMotorObjVec);
214 rc = vec->splitChar (':', cell, *v2);
215 if (checkScript (cell, url, ferr)) {
219 } else if (rc && cell.match (CharConst ("http"), CharConst ("https"))) {
220 ustring proto = cell.dump ();
223 v2 = WikiMotorObjVecPtr (new WikiMotorObjVec);
224 rc = vec->splitChar (':', cell, *v2);
225 if (! cell.splitURL_2 (wiki, proto, url)) {
230 if (vec->size () > 0) {
232 v2 = WikiMotorObjVecPtr (new WikiMotorObjVec);
233 rc = vec->splitChar (':', cell, *v2);
234 if (cell.splitURL_3 (wiki, url, url))
238 } else if (cell.splitURLPath (wiki, url)) {
247 bool WikiAttrib1::readLink (WikiMotorObjVecVec::const_iterator& b, const WikiMotorObjVecVec::const_iterator& e, ustring& url, bool& fscript, bool noscript) {
250 WikiMotorObjVec* cell;
256 if (! noscript && checkScript (*cell, url, ferr)) {
260 } else if (rc && cell->match (CharConst ("http"), CharConst ("https"))) {
261 ustring proto = cell->dump ();
264 if (! cell->splitURL_2 (wiki, proto, url)) {
271 if (cell->splitURL_3 (wiki, url, url))
275 } else if (cell->splitURLPath (wiki, url)) {
284 bool WikiAttrib1::shiftName (WikiMotorObjVecPtr& vec, ustring& name) {
285 if (vec->size () > 0) {
286 WikiMotorObjVec cell;
287 WikiMotorObjVecPtr v2 (new WikiMotorObjVec);
289 vec->splitChar (':', cell, *v2);
290 name = cell.textOut (wiki);
298 void WikiAttrib1::output (MotorOutput* out) {
299 wiki->outputID (out, id);
300 wiki->outputClass (out, classlist);
301 wiki->outputSubmitScript (out, CharConst ("onClick"), onclick);
302 wiki->outputName (out, CharConst ("target"), target);
303 // wiki->outputName (out, CharConst ("size"), elsize);
304 wiki->outputFlag (out, CharConst ("multiple"), fmultiple);
309 /* ============================================================ */
310 void WikiAttribTable::init () {
319 // halign = HAlignNone;
324 while (! classlist.empty ())
325 classlist.pop_back ();
332 void WikiAttribTable::copyFrom (WikiAttribTable& b) {
336 for (i = 0; i < b.classlist.size (); i ++)
337 classlist.push_back (b.classlist[i]);
348 bool WikiAttribTable::readAttribMore (const ustring& key, WikiMotorObjVec& vval, bool& ferr) {
349 if (wiki->paramWidth (key, vval, width, ferr)) {
350 } else if (wiki->paramHeight (key, vval, height, ferr)) {
351 } else if (match (key, CharConst ("bgcolor"), CharConst ("bg"))) {
352 wiki->paramColor (vval.textOut (wiki), bgcolor, key);
356 if (match (key, CharConst ("cellspacing"), CharConst ("spc"))) {
357 wiki->paramUNum (vval.textOut (wiki), cellspacing, key);
358 } else if (match (key, CharConst ("cellpadding"))) {
359 wiki->paramUNum (vval.textOut (wiki), cellpadding, key);
373 bool WikiAttribTable::readAttribMore2 (const ustring& key, WikiMotorObjVec& cell, bool& ferr) {
374 if (match (key, CharConst ("left"), CharConst ("l"))) {
376 } else if (match (key, CharConst ("right"), CharConst ("r"))) {
377 halign = HAlignRight;
378 } else if (match (key, CharConst ("center"), CharConst ("c"))) {
379 halign = HAlignCenter;
383 if (match (key, CharConst ("noborder"), CharConst ("nb"))) {
385 } else if (match (key, CharConst ("padding"), CharConst ("pad"))) {
387 } else if (match (key, CharConst ("expanding"), CharConst ("expand"))) {
389 } else if (match (key, CharConst ("nowhite"), CharConst ("nw"))) {
391 } else if (match (key, CharConst ("turn"))) {
398 if (match (key, CharConst ("header"), CharConst ("h"))) {
400 } else if (match (key, CharConst ("top"), CharConst ("t"))) {
402 } else if (match (key, CharConst ("middle"), CharConst ("m"))) {
403 valign = VAlignMiddle;
404 } else if (match (key, CharConst ("bottom"), CharConst ("b"))) {
405 valign = VAlignBottom;
406 } else if (match (key, CharConst ("nowrap"), CharConst ("nw"))) {
408 } else if (match (key, CharConst ("*"))) {
422 void WikiAttribTable::outputMore (MotorOutput* out) {
425 out->out_raw (CharConst (" align=\"left\""));
428 out->out_raw (CharConst (" align=\"center\""));
431 out->out_raw (CharConst (" align=\"right\""));
434 wiki->outputName (out, CharConst ("width"), width);
435 wiki->outputName (out, CharConst ("height"), height);
436 wiki->outputName (out, CharConst ("bgcolor"), bgcolor);
440 wiki->outputName (out, CharConst ("border"), fnoborder ? 0 : 1, false);
441 wiki->outputName (out, CharConst ("cellspacing"), cellspacing, false);
442 wiki->outputName (out, CharConst ("cellpadding"), cellpadding, false);
447 out->out_raw (CharConst (" valign=\"top\""));
450 out->out_raw (CharConst (" valign=\"middle\""));
453 out->out_raw (CharConst (" valign=\"bottom\""));
456 wiki->outputFlag (out, CharConst ("nowrap"), fnowrap);
463 /* ============================================================ */
464 bool WikiAttribImg::readAttribMore (const ustring& key, WikiMotorObjVec& vval, bool& ferr) {
465 if (wiki->paramWidth (key, vval, width, ferr)) {
466 } else if (wiki->paramHeight (key, vval, height, ferr)) {
467 } else if (match (key, CharConst ("alt"))) {
468 alt = vval.textOut (wiki);
475 void WikiAttribImg::outputMore (MotorOutput* out) {
476 wiki->outputName (out, CharConst ("width"), width);
477 wiki->outputName (out, CharConst ("height"), height);
481 /* ============================================================ */
482 bool WikiAttribInput::readAttribMore (const ustring& key, WikiMotorObjVec& vval, bool& ferr) {
483 if ((selector2 & SEL_INPUT) && wiki->paramSize (CharConst ("size"), key, vval, psize, ferr)) {
484 } else if ((selector2 & SEL_ELSIZE) && match (key, CharConst ("size"))) {
485 ustring v = vval.textOut (wiki);
486 if (match (v, CharConst ("*"))) {
488 } else if (checkNum (v)) {
489 elsize = to_int32 (v);
490 if (elsize < 0 || elsize > 999) {
496 } else if (wiki->paramWidth (key, vval, pwidth, ferr)) {
497 } else if ((selector2 & SEL_TEXTAREA) && wiki->paramSize (CharConst ("cols"), key, vval, pcols, ferr)) {
498 } else if ((selector2 & SEL_TEXTAREA) && wiki->paramSize (CharConst ("rows"), key, vval, prows, ferr)) {
499 } else if ((selector2 & SEL_TEXTAREA) && match (key, CharConst ("wrap"))) {
500 ustring value (vval.textOut (wiki));
501 if (match (value, CharConst ("off"))) {
503 } else if (match (value, CharConst ("soft"))) {
505 } else if (match (value, CharConst ("hard"))) {
507 } else if (wiki->paramWidth (key, vval, pwidth, ferr)) {
509 wiki->errorMsg.append (key).append (CharConst ("=")).append (vval.dump ()).append (CharConst (": link script error.\n"));
519 bool WikiAttribInput::readAttribMore2 (const ustring& key, WikiMotorObjVec& cell, bool& ferr) {
520 if (key == uDefault) {
522 } else if ((selector2 & SEL_CHECK) && match (key, CharConst ("checked"))) {
530 void WikiAttribInput::outputMore (MotorOutput* out) {
531 wiki->outputName (out, CharConst ("size"), psize);
532 wiki->outputName (out, CharConst ("size"), elsize);
533 if (pwidth.size () > 0)
534 out->out_raw (CharConst (" style=\"width: "))->out_toHTML_noCtrl (pwidth)->out_raw (CharConst (";\""));
535 if (selector2 & SEL_CHECK) {
536 wiki->outputFlag (out, CharConst ("checked"), pchecked);
538 if (selector2 & SEL_TEXTAREA) {
539 wiki->outputName (out, CharConst ("cols"), pcols, false);
540 wiki->outputName (out, CharConst ("rows"), prows);
543 out->out_raw (CharConst (" wrap=\"off\""));
546 out->out_raw (CharConst (" wrap=\"soft\""));
547 // out->out_raw (CharConst (" wrap=\"virtual\""));
550 out->out_raw (CharConst (" wrap=\"hard\""));
551 // out->out_raw (CharConst (" wrap=\"physical\""));
557 /* ============================================================ */
558 bool WikiAttribButton::readAttrib (WikiMotorObjVecVec::const_iterator& b, const WikiMotorObjVecVec::const_iterator& e) {
562 WikiMotorObjVec* cell = b->get ();
565 if (! readAttrib1 (cell, rc)) {
566 name = cell->textOut (wiki);
572 WikiMotorObjVec* cell = b->get ();
573 if (! readAttrib1 (cell, rc))
580 /* ============================================================ */
581 void WikiBlockComplex::outputBlock (MotorOutput* out) {
582 for (int i = 0; i < block.size (); i ++) {
583 block[i].output (out);
587 /* ============================================================ */
590 マークアップ文字以外の文字で書き出すと,段落になる。
591 ^行頭が他のマークアップ文字になるときは,行頭に^を書く。
596 bool WikiBlockParagraph::nextLine (uiterator b, uiterator e) {
605 void WikiBlockParagraph::addLine (uiterator b, uiterator e) {
613 if (html.size () == 0) {
616 n = html.end () - it;
620 if (n == 3 && it - b == 3) {
628 html.append (wiki->wikiMotor (b, e));
631 void WikiBlockParagraph::addHtml (const ustring& ht) {
635 void WikiBlockParagraph::output (MotorOutput* out) {
636 out->out_raw (CharConst (uP))->out_toText (html)->out_raw (CharConst (uPe));
639 /* ============================================================ */
646 行頭に=を書くと,タイトルになる。行末の=は,省略可。
650 bool WikiBlockH::nextLine (uiterator b, uiterator e) {
654 void WikiBlockH::addLine (uiterator b, uiterator e) {
658 static uregex re ("(=+)#([a-zA-Z0-9_-]+)$");
660 cn = wiki->countWikiH (b, e);
661 level = cn + wiki->headbase;
664 level0 = wiki->hlevel;
666 for (; b < e && *b == ' '; b ++) {}
667 if (usearch (b, e, m, re)) {
669 n = m[1].second - m[1].first - cn;
673 for (; b < u && u[-1] == ' '; u --) {}
674 title = wiki->wikiMotor (b, u);
675 anchor = ustring (m[2].first, m[2].second);
678 for (n = cn; n > 0 && b < u && u[-1] == '='; u --, n --) {}
679 for (; b < u && u[-1] == ' '; u --) {}
680 title = wiki->wikiMotor (b, u);
682 wiki->hlevel = level;
685 WikiBlock::closeType WikiBlockH::closeLine (uiterator b, uiterator e) {
686 if (e - b == 1 && *b == kWikiDIV_e) {
688 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
689 switch (wiki->bstack[i]->type) {
692 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
694 switch (wiki->bstack[i]->type) {
706 } else if (b != e && *b == kWikiH) {
707 int l = wiki->countWikiH (b, e) + wiki->headbase;
712 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
713 if (wiki->bstack[i]->type == BlockH) {
714 obj = (WikiBlockH*)wiki->bstack[i];
715 if (obj->level >= l) {
733 void WikiBlockH::close () {
734 wiki->hlevel = level0;
737 void WikiBlockH::output (MotorOutput* out) {
740 assert (0 < level && level <= 6);
741 for (i = level0 + 1; i <= level; i ++) {
742 outputBeginDiv (i, out);
745 case 1: out->out_raw (CharConst (uH1)); break;
746 case 2: out->out_raw (CharConst (uH2)); break;
747 case 3: out->out_raw (CharConst (uH3)); break;
748 case 4: out->out_raw (CharConst (uH4)); break;
749 case 5: out->out_raw (CharConst (uH5)); break;
750 case 6: out->out_raw (CharConst (uH6)); break;
752 if (anchor.size () > 0) {
753 out->out_raw (CharConst ("<a name=\""))->out_toHTML_noCtrl (anchor)->out_raw (CharConst ("\">"))->out_toText (title)->out_raw (CharConst ("</a>"));
755 out->out_noCtrl (title);
758 case 1: out->out_raw (CharConst (uH1e)); break;
759 case 2: out->out_raw (CharConst (uH2e)); break;
760 case 3: out->out_raw (CharConst (uH3e)); break;
761 case 4: out->out_raw (CharConst (uH4e)); break;
762 case 5: out->out_raw (CharConst (uH5e)); break;
763 case 6: out->out_raw (CharConst (uH6e)); break;
766 for (i = level; i > level0; i --) {
768 out->out_raw (CharConst ("</div><!-- hh"))->out_raw (to_ustring (i))->out_raw (CharConst (" -->\n"));
775 void WikiBlockH::outputBeginDiv (int lv, MotorOutput* out) {
777 case 1: out->out_raw (CharConst ("<div class=\"hh1\">\n")); break;
778 case 2: out->out_raw (CharConst ("<div class=\"hh2\">\n")); break;
779 case 3: out->out_raw (CharConst ("<div class=\"hh3\">\n")); break;
780 case 4: out->out_raw (CharConst ("<div class=\"hh4\">\n")); break;
781 case 5: out->out_raw (CharConst ("<div class=\"hh5\">\n")); break;
782 case 6: out->out_raw (CharConst ("<div class=\"hh6\">\n")); break;
786 void WikiBlockH::outputEndDiv (MotorOutput* out) {
787 out->out_raw (CharConst ("</div>\n"));
790 /* ============================================================ */
792 ===フォーマット済みテキストブロック===
793 行頭に空白文字を書くと,<pre>〜</pre>タグで囲まれます。
797 bool WikiBlockPreformat::nextLine (uiterator b, uiterator e) {
806 void WikiBlockPreformat::addLine (uiterator b, uiterator e) {
809 // html.append (wiki->wikiMotor (b + 1, e));
810 text.append (b + 1, e);
812 // html.append (wiki->wikiMotor (b, e));
815 // html.append (uLF);
819 void WikiBlockPreformat::output (MotorOutput* out) {
820 // out->out_raw (CharConst ("<pre>"))->out_toText (html)->out_raw (CharConst ("</pre>\n"));
821 out->out_raw (CharConst ("<pre>"))->out_toHTML (text)->out_raw (CharConst ("</pre>\n"));
824 /* ============================================================ */
825 bool WikiBlockItemText::nextLine (uiterator b, uiterator e) {
829 void WikiBlockItemText::addLine (uiterator b, uiterator e) {
830 WikiMotor motor (b, e, wiki);
831 WikiMotorObjVecPtr v1 (new WikiMotorObjVec);
834 if (! attrib.shiftAttrib (v1))
836 html.append (v1->htmlOut (wiki));
839 bool WikiBlockItemText::checkAddLine (uiterator b, uiterator e) {
847 if (block.size () > 0) {
848 obj = &block.back ();
853 wbi = (WikiBlockItem*)obj;
866 void WikiBlockItemText::output (MotorOutput* out) {
870 out->out_raw (CharConst ("<li"));
872 out->out_raw (CharConst (">"));
873 out->out_toText (html);
875 out->out_raw (CharConst ("</li>\n"));
879 /* ============================================================ */
889 +&*;''[OPTION1:OPTION2:...:]''TEXT
891 行頭に「*」を書くと,<UL>タグによるリスト,「#」を書くと<NL>タグによる番号付きリスト,「+」を書くとnobullクラス指定の<UL>タグによるリスト。
895 |class=''CLASS,...''|
896 |onclick=''LINK-FUNCTION:PARAM1:...::''|
899 bool WikiBlockItem::nextLine (uiterator b, uiterator e) {
908 void WikiBlockItem::setChar (char c) {
913 void WikiBlockItem::addLine (uiterator b, uiterator e) {
916 WikiBlockItemText* wbt;
921 assert (b != e && b[0] == ch);
924 wbt = new WikiBlockItemText (wiki);
925 block.push_back (wbt);
929 if (block.size () > 0 && block.back ().checkAddLine (b, e)) {
933 wbi = new WikiBlockItem (WikiBlock::BlockItemUL, wiki);
936 wbi = new WikiBlockItem (WikiBlock::BlockItemOL, wiki);
939 wbi = new WikiBlockItem (WikiBlock::BlockItemNL, wiki);
945 if (block.size () > 0) {
946 wbt = &block.back ();
948 wbt->block.push_back (wbi);
950 wbt = new WikiBlockItemText (wiki);
951 block.push_back (wbt);
953 wbt->block.push_back (wbi);
954 wbt->indentHack = true;
957 wbt = new WikiBlockItemText (wiki);
958 block.push_back (wbt);
965 void WikiBlockItem::output (MotorOutput* out) {
970 out->out_raw (CharConst ("<ul>\n"));
972 out->out_raw (CharConst ("</ul>\n"));
975 out->out_raw (CharConst ("<ol>\n"));
977 out->out_raw (CharConst ("</ol>\n"));
980 out->out_raw (CharConst ("<ul class=\"nobull\">\n"));
982 out->out_raw (CharConst ("</ul>\n"));
985 std::cerr << "type:" << type << uLF;
990 void WikiBlockItem::outputBlock (MotorOutput* out) {
991 for (int i = 0; i < block.size (); i ++) {
992 block[i].output (out);
996 /* ============================================================ */
1002 bool WikiBlockItemDL::nextLine (uiterator b, uiterator e) {
1003 if (*b == kWikiDL) {
1011 void WikiBlockItemDL::addLine (uiterator b, uiterator e) {
1012 WikiMotor motor (b + 1, e, wiki);
1013 WikiMotorObjVec objs;
1016 motor.compile (objs);
1017 objs.splitChar (wiki, ':', def, desc);
1018 html1.push_back (def);
1019 html2.push_back (desc);
1022 void WikiBlockItemDL::output (MotorOutput* out) {
1025 out->out_raw (CharConst ("<dl>\n"));
1026 for (i = 0; i < html1.size (); i ++) {
1027 out->out_raw (CharConst ("<dt>"))->out_toText (html1[i])->out_raw (CharConst ("</dt>\n"));
1028 out->out_raw (CharConst ("<dd>"))->out_toText (html2[i])->out_raw (CharConst ("</dd>\n"));
1030 out->out_raw (CharConst ("</dl>\n"));
1033 /* ============================================================ */
1036 |table:w=100%|head:right:||right:|
1037 |*:|head:品名|head:数量|
1042 表定義の最初の行の最初のカラムに「table:」を書くと,この行はテーブルオプション指定行になる。2番目以降のカラムは,デフォルトのカラムオプション指定になる。
1046 |noborder|nb|border="0"を出力する。|
1047 |cellspacing=''integer''|spc=|cellspacing属性を出力する。|
1048 |cellpadding=''integer''||cellpadding属性を出力する。|
1049 |padding|pad|テーブルの最大のカラム数よりカラムが少ない行に,空のカラムを追加する。|
1050 |expanding|expand|テーブルの最大のカラム数よりカラムが少ない行の最後のカラムを引き延ばす。|
1051 |center|c|テーブルをセンタリングする。|
1052 |left|l|テーブルを左寄せする。|
1053 |right|r|テーブルを右寄せする。|
1054 |id=''name''||id属性を出力する。|
1055 |class=''name,name,...''||class属性を出力する。|
1056 |width=''number'', width=''number''%|w=|width属性を出力する。|
1057 |bgcolor=#''color''|bg=|bgcolor属性を出力する。|
1058 |onclick=''fn(arg1,arg2,...)''||onClick属性を出力する。''name''はdefun-wiki-linkで定義したもの。|
1060 |turn||セルの並びの横方向と縦方向を交換する。|
1063 |header:名前|class=big:東武|
1067 |header|h|ヘッダタグ(<th>)を出力する。|
1070 |center|c|横方向で中央あわせする。|
1072 |middle|m|縦方向で中央あわせする。|
1074 |nowrap|nw|セル内での折り返しを禁止する。|
1075 |*||デフォルトのセルオプションを含め,全てのセルオプションを破棄する。|
1076 |id=''name''||セルタグにid属性を付加する。|
1077 |class=''name,name,...''||セルタグにclass属性を付加する。|
1078 |width=''number''&|;''number''%||セルタグにwidth属性を付加する。|
1079 |height=''number''&|;''number''%||セルタグにheight属性を付加する。|
1080 |bgcolor=#''hex''|bg=|セルタグにbg属性を付加する。|
1081 |onclick=''fn(arg1,arg2,...)''||onClick属性を出力する。''name''はdefun-wiki-linkで定義したもの。|
1085 |&<;''text''|左のセルと内容が一致するとき,結合する。|
1086 |&<;^''text''|左のセルと内容が一致し,左のセルが上のセルと結合しているとき,結合する。|
1088 |&^;''text''|上のセルと内容が一致するとき,結合する。|
1089 |&^;<''text''|上のセルと内容が一致し,上のセルが左のセルと結合しているとき,結合する。|
1092 行末に「\」を指定すると,次のテーブル記述を1行として継続する。数値指定を付加し「!''NUM''\」と指定するとカラム数が''NUM''に達したところで継続をやめる。
1095 void WikiBlockTable::TableCell::cellBody (WikiMotorObjVec* vtext, WikiBlockTable* table, int idx) {
1099 if (vtext->size () > 0 && (*vtext)[0].get ()->type == WikiMotorObj::wiki_text) {
1100 WikiMotorObjText* w = WikiMotorObjText_type ((*vtext)[0].get ());
1101 uiterator b = w->text.begin ();
1102 uiterator e = w->text.end ();
1104 if (b < e && *b == '<') {
1107 if (b < e && *b == '^') {
1111 } else if (b < e && *b == '^') {
1114 if (b < e && *b == '<') {
1119 (*vtext)[0].reset (new WikiMotorObjText (b, e));
1122 html = vtext->htmlOut (table->wiki);
1124 if (! spanmatch || table->ary.size () <= 1 || table->ary[table->ary.size () - 2][idx].colspan == 0) {
1125 col = &table->ary.back ();
1126 for (i = idx - 1; i >= 0; i --) {
1127 if ((*col)[i].colspan > 0) {
1128 if (html.length () == 0 || (*col)[i].html == html) {
1130 (*col)[i].colspan ++;
1138 if (! spanmatch || idx == 0 || table->ary.back ()[idx - 1].rowspan == 0) {
1139 for (i = table->ary.size () - 2; i >= 0; i --) {
1140 col = &table->ary[i];
1141 if (idx < col->size () && (*col)[idx].rowspan > 0) {
1142 if (html.length () == 0 || (*col)[idx].html == html) {
1144 (*col)[idx].rowspan ++;
1153 void WikiBlockTable::TableCell::outputTD (WikiFormat* wiki, MotorOutput* out, bool fturn) {
1157 out->out_raw (CharConst ("<th"));
1159 out->out_raw (CharConst ("<td"));
1160 attrib.output (out);
1163 wiki->outputName (out, CharConst ("rowspan"), colspan, false);
1165 wiki->outputName (out, CharConst ("colspan"), rowspan, false);
1168 wiki->outputName (out, CharConst ("colspan"), colspan, false);
1170 wiki->outputName (out, CharConst ("rowspan"), rowspan, false);
1172 out->out_raw (CharConst (">"));
1175 void WikiBlockTable::TableCell::outputTDe (MotorOutput* out) {
1177 out->out_raw (CharConst ("</th>\n"));
1179 out->out_raw (CharConst ("</td>\n"));
1182 /* ============================================================ */
1183 bool WikiBlockTable::nextLine (uiterator b, uiterator e) {
1184 if (*b == kWikiTABLE) {
1192 void WikiBlockTable::addLine (uiterator b, uiterator e) {
1193 assert (b[0] == '|');
1195 if (n == 0 && matchSkip (b, e, CharConst ("table:"))) {
1196 addLine_head (b, e);
1198 addLine_body (b, e);
1203 WikiBlock::closeType WikiBlockTable::closeLine (uiterator b, uiterator e) {
1204 static uregex re ("^\\}\\}(($)|(\\|)|((!([1-9][0-9]*))?\\\\$))");
1207 if (usearch (b, e, m, re)) {
1208 if (m[2].matched) { // }}
1211 } else if (m[3].matched) { // }}|...
1213 if (wiki->cur && wiki->cur->type == BlockTable) {
1214 WikiBlockTable* obj = (WikiBlockTable*)wiki->cur;
1216 addLine_body (m[3].second, e);
1221 } else if (m[4].matched) { // }}\ .
1223 if (wiki->cur && wiki->cur->type == BlockTable) {
1224 WikiBlockTable* obj = (WikiBlockTable*)wiki->cur;
1226 addLine_body (m[4].first, e);
1236 void WikiBlockTable::output (MotorOutput* out) {
1238 outputTableTag (out);
1240 out->out_raw (CharConst ("</table>\n"));
1243 void WikiBlockTable::addLine_head (uiterator b, uiterator e) {
1244 WikiMotor motor (b, e, wiki);
1245 WikiMotorObjVec objv;
1246 WikiMotorObjVecVec objvv;
1250 motor.compile (objv);
1251 objv.splitCharA ('|', objvv);
1252 if (objvv.size () > 0 && objvv.back ()->size () == 0)
1254 attrib.shiftAttrib (objvv[0]);
1255 for (i = 1; i < objvv.size (); i ++) {
1256 cell = new TableCell (wiki, true);
1257 cell->attrib.shiftAttrib (objvv[i]);
1258 defaultList.push_back (cell);
1262 void WikiBlockTable::addLine_body (uiterator b, uiterator e) {
1264 bool fmorecell = false;
1266 static uregex re ("(!([1-9][0-9]*))?\\\\$");
1270 cols = &ary.back ();
1272 cols = new CellList_t;
1273 ary.push_back (cols);
1276 if (usearch (b, e, m, re)) { //
1278 if (m[2].matched) { // ...!NUM\ .
1279 int v = strtoul (m[2].first);
1290 if (b < e && e[-1] == '|') { // ...|\ .
1298 WikiMotor motor (b, e, wiki);
1299 WikiMotorObjVec objv;
1300 WikiMotorObjVecVec objvv;
1304 static const ustring brabra (CharConst ("{{"));
1306 motor.compile (objv);
1307 objv.splitCharA ('|', objvv);
1308 if (objvv.size () > 0 && objvv.back ()->size () == 0) {
1314 n = objvv.size () - 1;
1315 for (i = 0; i <= n; i ++) {
1316 cell = newCell (cols->size ());
1317 if (! cell->attrib.shiftAttrib (objvv[i]))
1319 if (i == n && fop && objvv[i]->match (brabra)) {
1320 cols->push_back (cell);
1321 wiki->push_block (&cell->block);
1324 cell->cellBody (objvv[i].get (), this, cols->size ());
1325 cols->push_back (cell);
1329 cell = newCell (cols->size ());
1330 cols->push_back (cell);
1335 WikiBlockTable::TableCell* WikiBlockTable::newCell (int idx) {
1336 TableCell* ans = new TableCell (wiki, false);
1338 if (idx < defaultList.size ())
1339 ans->attrib.copyFrom (defaultList[idx].attrib);
1343 void WikiBlockTable::normalize () {
1349 for (i = 0; i < ary.size (); i ++) {
1351 if (col->size () > maxcol)
1352 maxcol = col->size ();
1354 if (attrib.fpadding) {
1355 for (i = 0; i < ary.size (); i ++) {
1357 if (col->size () < maxcol) {
1358 cell = newCell (col->size ());
1359 cell->colspan = maxcol - col->size ();
1360 col->push_back (cell);
1361 while (col->size () < maxcol) {
1362 cell = newCell (col->size ());
1364 col->push_back (cell);
1369 for (i = 0; i < ary.size (); i ++) {
1371 for (j = col->size () - 1; j >= 0; j --) {
1373 if (cell->colspan > 0) {
1374 cell->colspan += maxcol - col->size ();
1375 while (col->size () < maxcol) {
1376 cell = newCell (col->size ());
1378 col->push_back (cell);
1387 void WikiBlockTable::outputTableTag (MotorOutput* out) {
1390 if (attrib.cellspacing < 0)
1391 attrib.cellspacing = 0;
1392 if (attrib.cellpadding < 0)
1393 attrib.cellpadding = 0;
1394 out->out_raw (CharConst ("<table"));
1395 attrib.output (out);
1396 out->out_raw (CharConst (">\n"));
1399 void WikiBlockTable::outputTBody (MotorOutput* out) {
1405 if (ary.size () > 0) {
1407 for (j = 0; j < n; j ++) {
1408 out->out_raw (CharConst ("<tr>\n"));
1409 for (i = 0; i < ary.size (); i ++) {
1412 outputTBodyCell (wiki, out, cell);
1414 out->out_raw (CharConst ("</tr>\n"));
1418 for (i = 0; i < ary.size (); i ++) {
1420 out->out_raw (CharConst ("<tr>\n"));
1421 for (j = 0; j < col->size (); j ++) {
1423 outputTBodyCell (wiki, out, cell);
1425 out->out_raw (CharConst ("</tr>\n"));
1430 void WikiBlockTable::outputTBodyCell (WikiFormat* wiki, MotorOutput* out, TableCell* cell) {
1431 if (cell->colspan > 0 && cell->rowspan > 0) {
1432 cell->outputTD (wiki, out, attrib.fturn);
1433 if (cell->block.size () > 0) {
1434 wiki->output (cell->block);
1436 if (cell->html.size () > 0) {
1437 out->out_toText (cell->html);
1439 if (! attrib.fnowhite)
1440 out->out_raw (uNbsp);
1443 cell->outputTDe (out);
1447 /* ============================================================ */
1450 |select:NAME:function:default:size=NUM:multiple|
1452 |LABEL|VALUE|selected|
1455 bool WikiBlockSelect::nextLine (uiterator b, uiterator e) {
1456 if (*b == kWikiTABLE) {
1465 void WikiBlockSelect::addLine (uiterator b, uiterator e) {
1466 assert (b[0] == '|');
1468 if (n == 0 && matchSkip (b, e, CharConst ("select:"))) {
1469 addLine_head (b, e);
1471 addLine_body (b, e);
1476 void WikiBlockSelect::addLine_head (uiterator b, uiterator e) {
1477 WikiMotor motor (b, e, wiki);
1478 WikiMotorObjVec objv;
1479 WikiMotorObjVecVec objvv;
1480 WikiMotorObjVec* vcell;
1483 motor.compile (objv);
1484 objv.splitCharA ('|', objvv);
1485 if (objvv.size () > 0 && objvv.back ()->size () == 0)
1487 if (objvv.size () > 0)
1488 attrib.shiftName (objvv[0], name);
1489 if (objvv.size () > 0) {
1490 attrib.shiftAttrib (objvv[0]);
1492 if (attrib.fmultiple && attrib.elsize == 0) {
1497 void WikiBlockSelect::addLine_body (uiterator b, uiterator e) {
1498 WikiMotor motor (b, e, wiki);
1499 WikiMotorObjVec objv;
1500 WikiMotorObjVecVec objvv;
1503 motor.compile (objv);
1504 objv.splitCharA ('|', objvv);
1505 if (objvv.size () > 0 && objvv.back ()->size () == 0)
1507 if (objvv.size () > 0) {
1508 v.label = omitCtrl (objvv[0].get ()->textOut (wiki));
1512 if (objvv.size () > 1) {
1513 v.value = omitCtrl (objvv[1].get ()->textOut (wiki));
1520 if (objvv.size () > 2) {
1521 if (objvv[2].get ()->match (CharConst ("selected"), CharConst ("sel"))) {
1528 void WikiBlockSelect::close () {
1531 assert (wiki->cur->type == BlockParagraph);
1533 MotorOutputString out;
1535 wiki->cur->addHtml (out.ans);
1539 void WikiBlockSelect::output (MotorOutput* out) {
1543 if (attrib.elsize == 1)
1544 attrib.elsize = item.size ();
1545 out->out_raw (CharConst ("<select"));
1546 wiki->outputName (out, CharConst ("name"), name, false);
1547 attrib.output (out);
1548 if (attrib.script.length () > 0)
1549 wiki->outputName (out, CharConst ("onChange"), attrib.script);
1550 out->out_raw (CharConst (">\n"));
1552 if (attrib.fdefault)
1553 u = wiki->getVar (name);
1555 std::cerr << "u:" << u << uLF;
1558 for (i = 0; i < item.size (); i ++) {
1559 SelectItem* v = &item[i];
1560 out->out_raw (CharConst ("<option"));
1562 wiki->outputName (out, CharConst ("value"), v->value, false);
1563 if (v->fselect || (attrib.fdefault && u == v->value))
1564 out->out_raw (CharConst (" selected=\"selected\""));
1566 if (v->fselect || (attrib.fdefault && u == v->label))
1567 out->out_raw (CharConst (" selected=\"selected\""));
1569 out->out_raw (CharConst (">"));
1570 out->out_toHTML (v->label)->out_raw (CharConst ("</option>\n"));
1572 out->out_raw (CharConst ("</select>\n"));
1575 /* ============================================================ */
1583 bool WikiBlockQuote::nextLine (uiterator b, uiterator e) {
1587 WikiBlock::closeType WikiBlockQuote::closeLine (uiterator b, uiterator e) {
1588 if (e - b == 1 && *b == kWikiQUOTE_e) {
1597 void WikiBlockQuote::addLine (uiterator b, uiterator e) {
1601 void WikiBlockQuote::output (MotorOutput* out) {
1602 out->out_raw (CharConst ("<blockquote>\n"));
1604 out->out_raw (CharConst ("</blockquote>\n"));
1607 /* ============================================================ */
1613 {div:id=Name:SideMenu:onclick=fn()
1618 bool WikiBlockDiv::nextLine (uiterator b, uiterator e) {
1622 void WikiBlockDiv::addLine (uiterator b, uiterator e) {
1623 bool rc = matchSkip (b, e, CharConst ("{div:"));
1625 WikiMotor motor (b, e, wiki);
1626 WikiMotorObjVecPtr vec (new WikiMotorObjVec);
1628 motor.compile (*vec);
1629 attrib.shiftAttrib (vec);
1632 WikiBlock::closeType WikiBlockDiv::closeLine (uiterator b, uiterator e) {
1633 if (e - b == 1 && *b == kWikiDIV_e) {
1642 void WikiBlockDiv::output (MotorOutput* out) {
1643 out->out_raw (CharConst ("<div"));
1644 attrib.output (out);
1645 out->out_raw (CharConst (">\n"));
1647 out->out_raw (CharConst ("</div>\n"));
1650 /* ============================================================ */
1656 // {form:POST:id=form1:class=formclass:post.hml
1657 // {form:POST:post.hml:id=form1:class=formclass
1658 {form:POST:post.hml:target=target_window:id=form1:class=formclass
1663 bool WikiBlockForm::nextLine (uiterator b, uiterator e) {
1667 void WikiBlockForm::addLine (uiterator b, uiterator e) {
1668 bool rc = matchSkip (b, e, CharConst ("{form:"));
1671 WikiMotor motor (b, e, wiki);
1672 WikiMotorObjVecPtr vec (new WikiMotorObjVec);
1674 WikiMotorObjVecPtr v2 (new WikiMotorObjVec);
1676 motor.compile (*vec);
1677 vec->splitChar_keyword (':', key, *v2);
1678 if (match (key, CharConst ("get"), CharConst ("GET"))) {
1681 } else if (match (key, CharConst ("post"), CharConst ("POST"))) {
1685 if (vec->size () > 0) {
1686 attrib.shiftLink (vec, url, fscript);
1688 attrib.shiftAttrib (vec);
1691 WikiBlock::closeType WikiBlockForm::closeLine (uiterator b, uiterator e) {
1692 if (e - b == 1 && *b == kWikiDIV_e) {
1695 wiki->curform = NULL;
1702 void WikiBlockForm::output (MotorOutput* out) {
1703 out->out_raw (CharConst ("<form"));
1706 out->out_raw (CharConst (" method=\"get\""));
1710 out->out_raw (CharConst (" method=\"post\""));
1716 wiki->outputName (out, CharConst ("action"), ustring (CharConst ("#")), false);
1717 wiki->outputSubmitScript (out, CharConst ("onSubmit"), url);
1719 wiki->outputName (out, CharConst ("action"), url, false);
1722 out->out_raw (CharConst (" enctype=\"multipart/form-data\""));
1723 attrib.output (out);
1724 out->out_raw (CharConst (">\n"));
1726 out->out_raw (CharConst ("</form>\n"));
1729 /* ============================================================ */
1735 bool WikiBlockHR::nextLine (uiterator b, uiterator e) {
1739 void WikiBlockHR::addLine (uiterator b, uiterator e) {
1743 void WikiBlockHR::output (MotorOutput* out) {
1744 out->out_raw (CharConst (uHR));
1747 /* ============================================================ */
1748 void WikiFormat::pass1 (const ustring& text, WikiLine::linevec* block, bool fsuper) {
1749 Splitter sp (text, re_nl);
1751 pass1_1 (sp, NULL, NULL, block, NULL, NULL, NULL, fsuper);
1754 int WikiFormat::pass1_1 (Splitter& sp, ustring* elseword, ustring* endword, WikiLine::linevec* block, uiterator* elsebegin0, uiterator* elsebegin, uiterator* elseend, bool fsuper) {
1755 uiterator b, e, t, u, v;
1758 while (sp.next ()) {
1761 while (b < e && b[0] == '\t')
1763 if (matchSkip (b, e, CharConst (kComment))) {
1765 } else if (b != e && b[0] == kWikiCmd) {
1766 if (usearch (b, e, m, re_wikicmdsep)) {
1775 if (endword && match (t, u, *endword)) {
1776 return 2; // endword
1777 } else if (elseword && match (t, u, *elseword)) {
1784 return 1; // elseword
1785 } else if (pass1_2 (sp, b, e, t, u, v, block, fsuper)) {
1788 block->push_back (wl = new WikiLine (b, e, fsuper));
1789 wl->fn = wc_call_defun;
1792 block->push_back (new WikiLine (b, e, fsuper));
1795 return 0; // end of line
1798 bool WikiFormat::pass1_2 (Splitter& sp, uiterator& b, uiterator& e, uiterator& t, uiterator& u, uiterator& v, WikiLine::linevec* block, bool fsuper) {
1799 WikiCmdTable::iterator it;
1800 ustring elseword, endword;
1805 if ((it = GWikiCmdTable.find (ustring (t, u))) != GWikiCmdTable.end ()) {
1806 block->push_back (wl = new WikiLine (b, v, e, fsuper));
1807 wl->fn = it->second->fn;
1808 if (it->second->endname) {
1809 endword.assign (it->second->endname, it->second->endnamelen);
1810 if (it->second->elsename) {
1811 elseword.assign (it->second->elsename, it->second->elsenamelen);
1812 // if-then-else block
1813 wl->block = new WikiLine::linevec;
1814 rc = pass1_1 (sp, &elseword, &endword, wl->block, &b, &v, &e, fsuper);
1818 if (endword.length () > 0) {
1819 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1824 wl2 = new WikiLine (b, v, e, fsuper);
1828 wl->block = new WikiLine::linevec;
1829 rc = pass1_1 (sp, &elseword, &endword, wl->block, &b, &v, &e, fsuper);
1832 if (endword.length () > 0) {
1833 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1835 } else if (rc == 2) {
1836 assert (wl->block2 == NULL);
1837 wl->block2 = new WikiLine (sp.begin (), sp.end (), false);
1842 assert (wl->block2 == NULL);
1843 wl->block2 = new WikiLine (sp.begin (), sp.end (), false);
1850 wl->block = new WikiLine::linevec;
1851 rc = pass1_1 (sp, NULL, &endword, wl->block, NULL, NULL, NULL, fsuper);
1853 // no end line error
1854 if (endword.length () > 0) {
1855 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1857 } else if (rc == 2) {
1858 assert (wl->block2 == NULL);
1859 wl->block2 = new WikiLine (sp.begin (), sp.end (), false);
1872 static void dump (WikiLine::linevec* block, int indent = 0) {
1875 for (j = 0; j < indent; j ++) std::cerr << " ";
1876 std::cerr << "(NULL)\n";
1879 for (i = 0; i < block->size (); i ++) {
1880 WikiLine* wl = &(*block)[i];
1881 for (j = 0; j < indent; j ++) std::cerr << " ";
1883 std::cerr << (void*)wl->fn << ":";
1884 std::cerr << ustring (wl->begin, wl->end) << uLF;
1887 dump (wl->block, indent + 1);
1891 for (j = 0; j < indent; j ++) std::cerr << " ";
1892 std::cerr << "else:" << (void*)wl->fn << ":" << ustring (wl->begin, wl->end) << uLF;
1893 // dump (wl->block, indent + 1);
1902 void WikiFormat::compile (const ustring& text, bool fsuper) {
1904 WikiLine::linevec block;
1905 pass1 (text, &block, fsuper);
1911 WikiLineScanner scanner (&block);
1912 compileLines (scanner);
1917 if (bstack.size () > 0)
1924 } catch (ustring& msg) {
1925 logLispFunctionError (msg, uEmpty);
1929 void WikiFormat::output (boost::ptr_vector<WikiBlock>& ary) {
1932 for (i = 0; i < ary.size (); i ++) {
1933 ary[i].output (env->output);
1938 void WikiFormat::errorOutput () {
1939 if (errorMsg.size () > 0) {
1940 env->output->out_raw (CharConst (uP));
1941 env->output->out_toHTML_br (errorMsg);
1942 env->output->out_raw (CharConst (uPe));
1943 errorMsg.resize (0);
1947 bool WikiFormat::checkClose (uiterator b, uiterator e) {
1948 int n = bstack.size ();
1949 WikiBlock::closeType rc;
1953 rc = bstack[n]->closeLine (b, e);
1955 case WikiBlock::CloseTrue:
1957 case WikiBlock::CloseFalse:
1964 void WikiFormat::compileLine (WikiLineScanner& scanner) {
1965 WikiLine* wl = scanner.cur ();
1969 uiterator b = wl->begin;
1970 uiterator e = wl->end;
1975 if (b == e) { // empty line
1980 } else if (matchSkip (b, e, CharConst ("//"))) { // comment
1981 } else if (checkClose (b, e)) {
1982 } else if (cur && cur->nextLine (b, e)) {
1983 } else if (b[0] == kWikiP) { // ^
1986 cur = new WikiBlockParagraph (this);
1987 blockp->push_back (cur);
1988 cur->addLine (b, e);
1989 } else if (b[0] == kWikiH) { // =
1993 cur = obj = new WikiBlockH (this);
1994 blockp->push_back (cur);
1995 cur->addLine (b, e);
1996 push_block (&obj->block);
1997 } else if (b[0] == kWikiPRE // SPC
1998 || b[0] == kWikiPRE2) { // TAB
2001 cur = new WikiBlockPreformat (this);
2002 blockp->push_back (cur);
2003 cur->addLine (b, e);
2004 } else if (b[0] == kWikiUL) { // *
2008 cur = obj = new WikiBlockItem (WikiBlock::BlockItemUL, this);
2009 blockp->push_back (cur);
2010 obj->addLine (b, e);
2011 } else if (b[0] == kWikiOL) { // #
2015 cur = obj = new WikiBlockItem (WikiBlock::BlockItemOL, this);
2016 blockp->push_back (cur);
2017 obj->addLine (b, e);
2018 } else if (b[0] == kWikiNL) { // ]
2022 cur = obj = new WikiBlockItem (WikiBlock::BlockItemNL, this);
2023 blockp->push_back (cur);
2024 obj->addLine (b, e);
2025 } else if (b[0] == kWikiDL) { // ;
2028 cur = new WikiBlockItemDL (this);
2029 blockp->push_back (cur);
2030 cur->addLine (b, e);
2031 } else if (matchHead (b, e, CharConst ("|select:"))) { // |select:
2032 if (cur && cur->type == WikiBlock::BlockParagraph) {
2036 cur = new WikiBlockParagraph (this);
2037 blockp->push_back (cur);
2040 cur = new WikiBlockSelect (this);
2041 cur->addLine (b, e);
2042 } else if (b[0] == kWikiTABLE) { // |
2043 WikiBlockTable* obj;
2046 cur = obj = new WikiBlockTable (this);
2047 blockp->push_back (cur);
2048 cur->addLine (b, e);
2049 } else if (b[0] == kWikiQUOTE && e - b == 1) { // >
2050 WikiBlockQuote* obj;
2053 cur = obj = new WikiBlockQuote (this);
2054 blockp->push_back (cur);
2055 push_block (&obj->block);
2056 } else if (matchHead (b, e, CharConst ("{div:"))) {
2057 WikiBlockComplex* obj;
2060 cur = obj = new WikiBlockDiv (this);
2061 blockp->push_back (cur);
2062 cur->addLine (b, e);
2063 push_block (&obj->block);
2064 } else if (curform == NULL && matchHead (b, e, CharConst ("{form:"))) {
2065 WikiBlockComplex* obj;
2068 cur = obj = curform = new WikiBlockForm (this);
2069 blockp->push_back (cur);
2070 cur->addLine (b, e);
2071 push_block (&obj->block);
2072 } else if (matchHead (b, e, CharConst ("----"))) { // ----
2075 cur = new WikiBlockHR (this);
2076 blockp->push_back (cur);
2077 cur->addLine (b, e);
2080 if (cur && cur->type != WikiBlock::BlockParagraph) {
2085 cur = new WikiBlockParagraph (this);
2086 blockp->push_back (cur);
2088 cur->addLine (b, e);
2093 void WikiFormat::compileLines (WikiLineScanner& scanner, bool (*fn)(WikiLine& spp, WikiLineScanner& scanner, WikiFormat* wiki, void* par), void* par) {
2096 while (wl = scanner.next ()) {
2097 if (fn && fn (*scanner.cur (), scanner, this, par)) {
2100 compileLine (scanner);
2105 int WikiFormat::countWikiH (uiterator& b, uiterator e) {
2108 while (b != e && *b == kWikiH) {
2117 bool WikiFormat::paramID (const ustring& key, WikiMotorObjVec& vval, ustring& var_id, bool& ferr) {
2118 if (match (key, CharConst ("id"))) {
2119 ustring value (vval.textOut (this));
2120 if (value.length () > 0) {
2121 if (checkWikiID (value)) {
2125 errorMsg.append (key).append (uEq).append (value).append (CharConst (": bad id\n"));
2135 bool WikiFormat::paramClass (const ustring& key, WikiMotorObjVec& vval, std::vector<ustring>& classes, bool& ferr) {
2136 if (match (key, CharConst ("class"))) {
2137 paramClassValue (vval, classes, ferr);
2144 void WikiFormat::paramClassValue (WikiMotorObjVec& vval, std::vector<ustring>& classes, bool& ferr) {
2145 WikiMotorObjVecVec args;
2147 vval.splitCharA (',', args);
2148 for (int i = 0; i < args.size (); i ++) {
2149 ustring value (args[i]->textOut (this));
2150 if (value.length () > 0) {
2151 if (checkWikiID (value)) {
2152 classes.push_back (value);
2154 errorMsg.append (value).append (CharConst (": bad class name\n"));
2161 bool WikiFormat::paramName (const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
2162 if (match (key, CharConst ("name"))) {
2163 ustring value (vval.textOut (this));
2164 if (checkWikiID (value)) {
2176 bool WikiFormat::paramWidth (const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
2177 if (match (key, CharConst ("width"), CharConst ("w"))) {
2178 ustring value (vval.textOut (this));
2179 if (checkWidth (value)) {
2181 if (checkNum (value))
2182 var.append (CharConst ("px"));
2193 bool WikiFormat::paramHeight (const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
2194 if (match (key, CharConst ("height"), CharConst ("h"))) {
2195 ustring value (vval.textOut (this));
2196 if (checkWidth (value)) {
2200 errorMsg.append (key).append (uEq).append (value).append (CharConst (": bad value\n"));
2209 bool WikiFormat::paramSize (const char* name, size_t namelen, const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
2210 if (match (key, name, namelen)) {
2211 ustring value (vval.textOut (this));
2212 if (checkNum (value)) {
2223 void WikiFormat::paramUNum (const ustring& value, int& var, const ustring& name) {
2224 if (checkNum (value)) {
2225 var = strtoul (value);
2227 errorMsg.append (name).append (uEq).append (value).append (uErrorBadValue).append (uLF);
2231 void WikiFormat::paramColor (const ustring& value, ustring& var, const ustring& name) {
2232 if (checkColor (value)) {
2235 errorMsg.append (name).append (uEq).append (value).append (uErrorBadValue).append (uLF);
2239 bool WikiFormat::paramTargetCheck (const ustring& key) {
2240 return match (key, CharConst ("target"));
2243 void WikiFormat::paramTargetBody (const ustring& key, const ustring& value, ustring& var, bool& ferr) {
2244 if (value.length () == 0 || checkWikiID (value)) {
2247 if (key.length () > 0)
2248 errorMsg.append (key).append (uEq).append (value).append (CharConst (": bad target name.\n"));
2250 errorMsg.append (value).append (CharConst (": bad target name.\n"));
2255 bool WikiFormat::paramOnClickCheck (const ustring& name) {
2256 return match (name, CharConst ("onclick"));
2259 void WikiFormat::outputName (MotorOutput* out, const char* name, size_t len, const ustring& val, bool cond) {
2260 if (! cond || val.length () > 0)
2262 ->out_raw (name, len)
2263 ->out_raw (CharConst ("=\""))
2264 ->out_toHTML_noCtrl (val)
2268 void WikiFormat::outputName (MotorOutput* out, const char* name, size_t len, long val, bool cond) {
2269 if (! cond || val > 0)
2271 ->out_raw (name, len)
2272 ->out_raw (CharConst ("=\""))
2273 ->out_raw (to_ustring (val))
2277 void WikiFormat::outputFlag (MotorOutput* out, const char* name, size_t len, bool flag) {
2280 ->out_raw (name, len)
2281 ->out_raw (CharConst ("=\""))
2282 ->out_raw (name, len)
2286 void WikiFormat::outputID (MotorOutput* out, const ustring& id) {
2287 if (id.length () > 0)
2288 out->out_raw (CharConst (" id=\""))
2289 ->out_toHTML_noCtrl (id)
2293 void WikiFormat::outputClass (MotorOutput* out, std::vector<ustring>& classes) {
2294 if (classes.size () > 0) {
2295 out->out_raw (CharConst (" class=\""));
2296 for (int i = 0; i < classes.size (); i ++) {
2298 out->out_raw (uSPC);
2299 out->out_toHTML_noCtrl (classes[i]);
2305 void WikiFormat::outputSubmitScript (MotorOutput* out, const char* name, size_t len, const ustring& onclick) {
2306 if (onclick.length () > 0)
2308 ->out_raw (name, len)
2309 ->out_raw (CharConst ("=\""))
2310 ->out_toHTML_noCtrl (onclick)
2311 ->out_raw ("return false;\"");
2312 // ->out_raw ("\"");
2315 void WikiFormat::wikiMotor (uiterator b, uiterator e, WikiMotorObjVec& ans) {
2316 WikiMotor motor (b, e, this);
2318 motor.compile (ans, WikiMotor::TMATCH_NONE);
2321 ustring WikiFormat::wikiMotor (uiterator b, uiterator e) {
2322 WikiMotorObjVec objv;
2324 wikiMotor (b, e, objv);
2325 return objv.htmlOut (this);
2328 MNode* WikiFormat::buildArgs (WikiMotorObjVecVec::const_iterator b, WikiMotorObjVecVec::const_iterator e, bool dumpmode) {
2332 for (; b < e; b ++) {
2333 ans.append (newMNode_str (new ustring ((*b)->dump ())));
2336 for (; b < e; b ++) {
2337 ans.append (newMNode_str (new ustring ((*b)->textOut (this))));
2341 return ans.release ();
2347 ans = a = new MNode;
2348 a->set_car (newMNode_str (new ustring ((*b)->textOut (this))));
2349 for (b ++; b < e; b ++) {
2351 a->set_car (newMNode_str (new ustring ((*b)->textOut (this))));
2358 void WikiFormat::logLispFunctionError (const ustring& msg, const ustring& cmd) {
2359 if (cmd.length () > 0)
2360 errorMsg.append (cmd).append (CharConst (": "));
2361 errorMsg.append (CharConst ("lisp function error.\n"));
2362 if (mlenv->env->mlenv->currentCell ()) {
2363 if (mlenv->env->log)
2364 *mlenv->env->log << mlenv->env->mlenv->currentCell ()->dump_string_short () << ": ";
2365 *mlenv->env->log << msg << uLF;
2369 /* ============================================================ */