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'
27 #define kWikiTABLE '|'
28 #define kWikiQUOTE '>'
29 #define kWikiQUOTE_e '<'
31 #define kWikiDIV_e '}'
43 #define uH1e "</h1>\n"
44 #define uH2e "</h2>\n"
45 #define uH3e "</h3>\n"
46 #define uH4e "</h4>\n"
47 #define uH5e "</h5>\n"
48 #define uH6e "</h6>\n"
49 #define uHR "<hr />\n"
50 //#define unbsp " "
52 ustring uWiki (CharConst ("wiki_"));
58 /* ============================================================ */
59 void WikiMlEnv::setVar (const ustring& name, MNode* val) {
62 parent->setVar (na, val);
65 void WikiMlEnv::setAry (const ustring& name, size_t i, MNode* val) {
68 parent->setAry (na, i, val);
71 void WikiMlEnv::setArySize (const ustring& name, size_t n) {
74 parent->setArySize (na, n);
77 void WikiMlEnv::setAry (const ustring& name, MNode* list) {
80 parent->setAry (na, list);
83 MNode* WikiMlEnv::getVar (const ustring& name) {
86 return parent->getVar (na);
89 MNode* WikiMlEnv::getAry (const ustring& name, size_t i) {
92 return parent->getAry (na, i);
95 size_t WikiMlEnv::getArySize (const ustring& name) {
98 return parent->getArySize (na);
101 /* ============================================================ */
102 bool WikiTableSplitter::next () {
109 while (u != e && usearch (u, e, m, *re)) {
112 if (m[5].matched) { // [[...:
114 } else if (m[6].matched) { // ]]
117 } else if (m[7].matched) { // |
127 /* ============================================================ */
128 void WikiBlockComplex::outputBlock (MotorOutput* out) {
129 for (int i = 0; i < block.size (); i ++) {
130 block[i].output (out);
134 /* ============================================================ */
137 マークアップ文字以外の文字で書き出すと,段落になる。
138 ^行頭が他のマークアップ文字になるときは,行頭に^を書く。
143 bool WikiBlockParagraph::nextLine (uiterator b, uiterator e) {
152 void WikiBlockParagraph::addLine (uiterator b, uiterator e) {
160 if (html.size () == 0) {
163 n = html.end () - it;
167 if (n == 3 && it - b == 3) {
175 html.append (wiki->wikiMotor (b, e));
178 void WikiBlockParagraph::addHtml (const ustring& ht) {
182 void WikiBlockParagraph::output (MotorOutput* out) {
183 out->out (CharConst (uP))->out_text (html)->out (CharConst (uPe));
186 /* ============================================================ */
193 行頭に=を書くと,タイトルになる。行末の=は,省略可。
197 bool WikiBlockH::nextLine (uiterator b, uiterator e) {
201 void WikiBlockH::addLine (uiterator b, uiterator e) {
205 static uregex re ("(=+)#([a-zA-Z0-9_-]+)$");
207 cn = wiki->countWikiH (b, e);
208 level = cn + wiki->headbase;
211 level0 = wiki->hlevel;
213 for (; b < e && *b == ' '; b ++) {}
214 if (usearch (b, e, m, re)) {
216 n = m[1].second - m[1].first - cn;
220 for (; b < u && u[-1] == ' '; u --) {}
221 title = wiki->wikiMotor (b, u);
222 anchor = ustring (m[2].first, m[2].second);
225 for (n = cn; n > 0 && b < u && u[-1] == '='; u --, n --) {}
226 for (; b < u && u[-1] == ' '; u --) {}
227 title = wiki->wikiMotor (b, u);
229 wiki->hlevel = level;
232 WikiBlock::closeType WikiBlockH::closeLine (uiterator b, uiterator e) {
233 if (e - b == 1 && *b == kWikiDIV_e) {
235 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
236 switch (wiki->bstack[i]->type) {
239 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
241 switch (wiki->bstack[i]->type) {
253 } else if (b != e && *b == kWikiH) {
254 int l = wiki->countWikiH (b, e) + wiki->headbase;
259 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
260 if (wiki->bstack[i]->type == BlockH) {
261 obj = (WikiBlockH*)wiki->bstack[i];
262 if (obj->level >= l) {
280 void WikiBlockH::close () {
281 wiki->hlevel = level0;
284 void WikiBlockH::output (MotorOutput* out) {
287 assert (0 < level && level <= 6);
288 for (i = level0 + 1; i <= level; i ++) {
289 outputBeginDiv (i, out);
292 case 1: out->out (CharConst (uH1)); break;
293 case 2: out->out (CharConst (uH2)); break;
294 case 3: out->out (CharConst (uH3)); break;
295 case 4: out->out (CharConst (uH4)); break;
296 case 5: out->out (CharConst (uH5)); break;
297 case 6: out->out (CharConst (uH6)); break;
299 if (anchor.size () > 0) {
300 out->out (CharConst ("<a name=\""))->out_HTML_noCtrl (anchor)->out (CharConst ("\">"))->out_text (title)->out (CharConst ("</a>"));
305 case 1: out->out (CharConst (uH1e)); break;
306 case 2: out->out (CharConst (uH2e)); break;
307 case 3: out->out (CharConst (uH3e)); break;
308 case 4: out->out (CharConst (uH4e)); break;
309 case 5: out->out (CharConst (uH5e)); break;
310 case 6: out->out (CharConst (uH6e)); break;
313 for (i = level; i > level0; i --) {
315 out->out (CharConst ("</div><!-- hh"))->out (boost::lexical_cast<ustring> (i))->out (CharConst (" -->\n"));
322 void WikiBlockH::outputBeginDiv (int lv, MotorOutput* out) {
324 case 1: out->out (CharConst ("<div class=\"hh1\">\n")); break;
325 case 2: out->out (CharConst ("<div class=\"hh2\">\n")); break;
326 case 3: out->out (CharConst ("<div class=\"hh3\">\n")); break;
327 case 4: out->out (CharConst ("<div class=\"hh4\">\n")); break;
328 case 5: out->out (CharConst ("<div class=\"hh5\">\n")); break;
329 case 6: out->out (CharConst ("<div class=\"hh6\">\n")); break;
333 void WikiBlockH::outputEndDiv (MotorOutput* out) {
334 out->out (CharConst ("</div>\n"));
337 /* ============================================================ */
339 ===フォーマット済みテキストブロック===
340 行頭に空白文字を書くと,<pre>〜</pre>タグで囲まれます。
343 bool WikiBlockPreformat::nextLine (uiterator b, uiterator e) {
352 void WikiBlockPreformat::addLine (uiterator b, uiterator e) {
355 html.append (wiki->wikiMotor (b + 1, e));
357 html.append (wiki->wikiMotor (b, e));
362 void WikiBlockPreformat::output (MotorOutput* out) {
363 out->out (CharConst ("<pre>"))->out_text (html)->out (CharConst ("</pre>\n"));
366 /* ============================================================ */
367 bool WikiBlockItemText::nextLine (uiterator b, uiterator e) {
371 void WikiBlockItemText::addLine (uiterator b, uiterator e) {
372 html.append (wiki->wikiMotor (b, e));
375 bool WikiBlockItemText::checkAddLine (uiterator b, uiterator e) {
381 html.append (wiki->wikiMotor (b, e));
384 if (block.size () > 0) {
385 obj = &block.back ();
390 wbi = (WikiBlockItem*)obj;
403 void WikiBlockItemText::output (MotorOutput* out) {
407 out->out (CharConst ("<li>"));
408 out->out_text (html);
410 out->out (CharConst ("</li>\n"));
414 /* ============================================================ */
425 bool WikiBlockItem::nextLine (uiterator b, uiterator e) {
434 void WikiBlockItem::setChar (char c) {
439 void WikiBlockItem::addLine (uiterator b, uiterator e) {
442 WikiBlockItemText* wbt;
447 assert (b != e && b[0] == ch);
450 wbt = new WikiBlockItemText (wiki);
451 block.push_back (wbt);
455 if (block.size () > 0 && block.back ().checkAddLine (b, e)) {
459 wbi = new WikiBlockItem (WikiBlock::BlockItemUL, wiki);
462 wbi = new WikiBlockItem (WikiBlock::BlockItemOL, wiki);
465 wbi = new WikiBlockItem (WikiBlock::BlockItemNL, wiki);
471 if (block.size () > 0) {
472 wbt = &block.back ();
474 wbt->block.push_back (wbi);
476 wbt = new WikiBlockItemText (wiki);
477 block.push_back (wbt);
479 wbt->block.push_back (wbi);
480 wbt->indentHack = true;
483 wbt = new WikiBlockItemText (wiki);
484 block.push_back (wbt);
491 void WikiBlockItem::output (MotorOutput* out) {
496 out->out (CharConst ("<ul>\n"));
498 out->out (CharConst ("</ul>\n"));
501 out->out (CharConst ("<ol>\n"));
503 out->out (CharConst ("</ol>\n"));
506 out->out (CharConst ("<ul class=\"nobull\">\n"));
508 out->out (CharConst ("</ul>\n"));
511 std::cerr << "type:" << type << uLF;
516 void WikiBlockItem::outputBlock (MotorOutput* out) {
517 for (int i = 0; i < block.size (); i ++) {
518 block[i].output (out);
522 /* ============================================================ */
528 bool WikiBlockItemDL::nextLine (uiterator b, uiterator e) {
537 void WikiBlockItemDL::addLine (uiterator b, uiterator e) {
538 WikiMotor motor (b + 1, e, wiki);
539 WikiMotorObjVec objs;
542 motor.compile (objs);
543 objs.splitChar (wiki, ':', def, desc);
544 html1.push_back (def);
545 html2.push_back (desc);
548 void WikiBlockItemDL::output (MotorOutput* out) {
551 out->out (CharConst ("<dl>\n"));
552 for (i = 0; i < html1.size (); i ++) {
553 out->out (CharConst ("<dt>"))->out_text (html1[i])->out (CharConst ("</dt>\n"));
554 out->out (CharConst ("<dd>"))->out_text (html2[i])->out (CharConst ("</dd>\n"));
556 out->out (CharConst ("</dl>\n"));
559 /* ============================================================ */
562 |table:w=100%|head:right:||right:|
570 |noborder|nb|border="0"を出力する。|
571 |cellspacing=''integer''|spc=|cellspacing属性を出力する。|
572 |cellpadding=''integer''||cellpadding属性を出力する。|
573 |padding|pad|テーブルの最大のカラム数よりカラムが少ない行に,空のカラムを追加する。|
574 |expanding|expand|テーブルの最大のカラム数よりカラムが少ない行の最後のカラムを引き延ばす。|
575 |center|c|テーブルをセンタリングする。|
577 |right|r|テーブルを右寄せする。|
578 |id=''name''||id属性を出力する。|
579 |class=''name''||class属性を出力する。|
580 |width=''number'', width=''number''%|w=|width属性を出力する。|
581 |bgcolor=#''color''|bg=|bgcolor属性を出力する。|
583 |turn||セルの並びの横方向と縦方向を交換する。|
588 |header|h|ヘッダタグ(<th>)を出力する。|
591 |center|c|横方向で中央あわせする。|
593 |middle|m|縦方向で中央あわせする。|
595 |nowrap|nw|セル内での折り返しを禁止する。|
596 |*||これ以前にtable:行などで指定したセルオプションを破棄する。|
597 |id=''name''||セルタグにid属性を付加する。|
598 |class=''name''||セルタグにclass属性を付加する。|
599 |width=''number''&|;''number''%||セルタグにwidth属性を付加する。|
600 |height=''number''&|;''number''%||セルタグにheight属性を付加する。|
601 |bgcolor=#''hex''|bg=|セルタグにbg属性を付加する。|
605 |&<;''text''|左のセルと内容が一致するとき,結合する。|
606 |&<;^''text''|左のセルと内容が一致し,左のセルが上のセルと結合しているとき,結合する。|
608 |&^;''text''|上のセルと内容が一致するとき,結合する。|
609 |&^;<''text''|上のセルと内容が一致し,上のセルが左のセルと結合しているとき,結合する。|
612 void WikiBlockTable::TableCell::init () {
617 while (! classlist.empty ())
618 classlist.pop_back ();
625 void WikiBlockTable::TableCell::copyFrom (WikiBlockTable::TableCell& b) {
632 for (i = 0; i < b.classlist.size (); i ++)
633 classlist.push_back (b.classlist[i]);
640 void WikiBlockTable::TableCell::cellAttrib (WikiFormat* wiki, WikiMotor* motor, WikiMotorObjVec* in, WikiMotorObjVec& out, bool inHeader) {
641 WikiMotorObjVec::const_iterator b = in->begin ();
642 WikiMotorObjVec::const_iterator e = in->end ();
643 WikiMotorObj* t = NULL;
645 WikiMotorObjVecPtr v1;
646 WikiMotorObjVecPtr v2;
648 v1 = WikiMotorObjVecPtr (new WikiMotorObjVec);
649 for (; b < e; b ++) {
652 while (v1->size () > 0) {
653 WikiMotorObjVec cell;
655 WikiMotorObjVec vval;
656 v2 = WikiMotorObjVecPtr (new WikiMotorObjVec);
657 if (v1->splitChar (':', cell, *v2) || inHeader) {
658 if (cell.splitChar_keyword ('=', key, vval)) {
659 if (wiki->paramID (key, vval, id, ferr)) {
660 } else if (wiki->paramClass (key, vval, classlist, ferr)) {
661 } else if (wiki->paramWidth (key, vval, width, ferr)) {
662 } else if (wiki->paramHeight (key, vval, height, ferr)) {
663 } else if (match (key, CharConst ("bgcolor"), CharConst ("bg"))) {
664 wiki->paramColor (vval.textOut (wiki), bgcolor, key);
669 if (match (key, CharConst ("header"), CharConst ("h"))) {
671 } else if (match (key, CharConst ("left"), CharConst ("l"))) {
673 } else if (match (key, CharConst ("right"), CharConst ("r"))) {
674 halign = HAlignRight;
675 } else if (match (key, CharConst ("center"), CharConst ("c"))) {
676 halign = HAlignCenter;
677 } else if (match (key, CharConst ("top"), CharConst ("t"))) {
679 } else if (match (key, CharConst ("middle"), CharConst ("m"))) {
680 valign = VAlignMiddle;
681 } else if (match (key, CharConst ("bottom"), CharConst ("b"))) {
682 valign = VAlignBottom;
683 } else if (match (key, CharConst ("nowrap"), CharConst ("nw"))) {
685 } else if (match (key, CharConst ("*"))) {
699 for (; b < e; b ++) {
705 int WikiBlockTable::TableCell::cellAttrib (WikiBlockTable* table, WikiMotor* motor, WikiMotorObjVecVec& objvv, bool inHeader) {
707 WikiMotorObj* t = NULL;
713 n = objvv.size () - 1;
714 for (i = 0; i < n; i ++) {
716 WikiMotorObjVec vval;
717 if (objvv[i].get ()->splitChar_keyword ('=', key, vval)) {
718 if (table->wiki->paramID (key, vval, id, ferr)) {
719 } else if (table->wiki->paramClass (key, vval, classlist, ferr)) {
720 } else if (table->wiki->paramWidth (key, vval, width, ferr)) {
721 } else if (table->wiki->paramHeight (key, vval, height, ferr)) {
722 } else if (match (key, CharConst ("bgcolor"), CharConst ("bg"))) {
723 table->wiki->paramColor (vval.textOut (table->wiki), bgcolor, key);
728 if (match (key, CharConst ("header"), CharConst ("h"))) {
730 } else if (match (key, CharConst ("left"), CharConst ("l"))) {
732 } else if (match (key, CharConst ("right"), CharConst ("r"))) {
733 halign = HAlignRight;
734 } else if (match (key, CharConst ("center"), CharConst ("c"))) {
735 halign = HAlignCenter;
736 } else if (match (key, CharConst ("top"), CharConst ("t"))) {
738 } else if (match (key, CharConst ("middle"), CharConst ("m"))) {
739 valign = VAlignMiddle;
740 } else if (match (key, CharConst ("bottom"), CharConst ("b"))) {
741 valign = VAlignBottom;
742 } else if (match (key, CharConst ("nowrap"), CharConst ("nw"))) {
744 } else if (match (key, CharConst ("*"))) {
755 void WikiBlockTable::TableCell::cellBody (WikiMotorObjVec* vtext, WikiBlockTable* table, int idx) {
759 if (vtext->size () > 0 && (*vtext)[0].get ()->type == WikiMotorObj::wiki_text) {
760 WikiMotorObjText* w = WikiMotorObjText_type ((*vtext)[0].get ());
761 uiterator b = w->text.begin ();
762 uiterator e = w->text.end ();
764 if (b < e && *b == '<') {
767 if (b < e && *b == '^') {
771 } else if (b < e && *b == '^') {
774 if (b < e && *b == '<') {
779 (*vtext)[0].reset (new WikiMotorObjText (b, e));
782 html = vtext->htmlOut (table->wiki);
784 if (! spanmatch || table->ary.size () <= 1 || table->ary[table->ary.size () - 2][idx].colspan == 0) {
785 col = &table->ary.back ();
786 for (i = idx - 1; i >= 0; i --) {
787 if ((*col)[i].colspan > 0) {
788 if (html.length () == 0 || (*col)[i].html == html) {
790 (*col)[i].colspan ++;
798 if (! spanmatch || idx == 0 || table->ary.back ()[idx - 1].rowspan == 0) {
799 for (i = table->ary.size () - 2; i >= 0; i --) {
800 col = &table->ary[i];
801 if (idx < col->size () && (*col)[idx].rowspan > 0) {
802 if (html.length () == 0 || (*col)[idx].html == html) {
804 (*col)[idx].rowspan ++;
813 void WikiBlockTable::TableCell::outputTD (WikiFormat* wiki, MotorOutput* out, bool fturn) {
817 out->out (CharConst ("<th"));
819 out->out (CharConst ("<td"));
823 out->out (CharConst (" align=\"left\""));
826 out->out (CharConst (" align=\"center\""));
829 out->out (CharConst (" align=\"right\""));
834 out->out (CharConst (" valign=\"top\""));
837 out->out (CharConst (" valign=\"middle\""));
840 out->out (CharConst (" valign=\"bottom\""));
843 wiki->outputID (out, id);
844 wiki->outputClass (out, classlist);
845 wiki->outputName (out, CharConst ("width"), width);
846 wiki->outputName (out, CharConst ("height"), height);
847 wiki->outputName (out, CharConst ("bgcolor"), bgcolor);
848 wiki->outputFlag (out, CharConst ("nowrap"), fnowrap);
851 wiki->outputName (out, CharConst ("rowspan"), colspan, false);
853 wiki->outputName (out, CharConst ("colspan"), rowspan, false);
856 wiki->outputName (out, CharConst ("colspan"), colspan, false);
858 wiki->outputName (out, CharConst ("rowspan"), rowspan, false);
860 out->out (CharConst (">"));
863 void WikiBlockTable::TableCell::outputTDe (MotorOutput* out) {
865 out->out (CharConst ("</th>\n"));
867 out->out (CharConst ("</td>\n"));
870 /* ============================================================ */
871 bool WikiBlockTable::nextLine (uiterator b, uiterator e) {
872 if (*b == kWikiTABLE) {
880 void WikiBlockTable::addLine (uiterator b, uiterator e) {
881 assert (b[0] == '|');
883 if (n == 0 && matchSkip (b, e, CharConst ("table:"))) {
891 WikiBlock::closeType WikiBlockTable::closeLine (uiterator b, uiterator e) {
892 static uregex re ("^\\}\\}(($)|(\\|)|((!([1-9][0-9]*))?\\\\$))");
895 if (usearch (b, e, m, re)) {
896 if (m[2].matched) { // }}
899 } else if (m[3].matched) { // }}|...
901 if (wiki->cur && wiki->cur->type == BlockTable) {
902 WikiBlockTable* obj = (WikiBlockTable*)wiki->cur;
904 addLine_body (m[3].second, e);
909 } else if (m[4].matched) { // }}\ .
911 if (wiki->cur && wiki->cur->type == BlockTable) {
912 WikiBlockTable* obj = (WikiBlockTable*)wiki->cur;
914 addLine_body (m[4].first, e);
924 void WikiBlockTable::output (MotorOutput* out) {
926 outputTableTag (out);
928 out->out (CharConst ("</table>\n"));
931 void WikiBlockTable::addLine_head (uiterator b, uiterator e) {
932 WikiMotor motor (b, e, wiki);
933 WikiMotorObjVec objv;
934 WikiMotorObjVecVec objvv;
938 motor.compile (objv);
939 objv.splitCharA ('|', objvv);
940 if (objvv.size () > 0 && objvv.back ()->size () == 0)
942 addLine_head_table (&motor, objvv[0].get ());
943 for (i = 1; i < objvv.size (); i ++) {
944 // WikiMotorObjVecVec params;
945 WikiMotorObjVec texts;
946 cell = newCell (defaultList.size ());
947 // objvv[i].get ()->splitCharA (':', params);
948 // cell->cellAttrib (this, &motor, params, true);
949 cell->cellAttrib (wiki, &motor, objvv[i].get (), texts, true);
950 defaultList.push_back (cell);
954 void WikiBlockTable::addLine_head_table (WikiMotor* motor, WikiMotorObjVec* objs) {
956 WikiMotorObjVecVec params;
957 WikiMotorObjVec* param;
960 objs->splitCharA (':', params);
961 for (i = 0; i < params.size (); i ++) {
962 param = params[i].get ();
963 if (param->size () > 0) {
965 WikiMotorObjVec vvalue;
966 if (params[i].get ()->splitChar_keyword ('=', name, vvalue)) {
967 if (match (name, CharConst ("cellspacing"), CharConst ("spc"))) {
968 wiki->paramUNum (vvalue.textOut (wiki), cellspacing, name);
969 } else if (match (name, CharConst ("cellpadding"))) {
970 wiki->paramUNum (vvalue.textOut (wiki), cellpadding, name);
971 } else if (match (name, CharConst ("bgcolor"), CharConst ("bg"))) {
972 wiki->paramColor (vvalue.textOut (wiki), bgcolor, name);
973 } else if (wiki->paramID (name, vvalue, id, ferr)) {
974 } else if (wiki->paramClass (name, vvalue, classlist, ferr)) {
975 } else if (wiki->paramWidth (name, vvalue, width, ferr)) {
977 wiki->errorMsg.append (name).append (uEq).append (vvalue.dump ()).append (CharConst (": error.\n"));
980 if (match (name, CharConst ("noborder"), CharConst ("nb"))) {
982 } else if (match (name, CharConst ("padding"), CharConst ("pad"))) {
984 } else if (match (name, CharConst ("expanding"), CharConst ("expand"))) {
986 } else if (match (name, CharConst ("center"), CharConst ("c"))) {
987 halign = HAlignCenter;
988 } else if (match (name, CharConst ("left"), CharConst ("l"))) {
990 } else if (match (name, CharConst ("right"), CharConst ("r"))) {
991 halign = HAlignRight;
992 } else if (match (name, CharConst ("nowhite"), CharConst ("nw"))) {
994 } else if (match (name, CharConst ("turn"))) {
997 wiki->errorMsg.append (name).append (CharConst (": error.\n"));
1004 void WikiBlockTable::addLine_body (uiterator b, uiterator e) {
1007 bool fmorecell = false;
1009 static uregex re ("(!([1-9][0-9]*))?\\\\$");
1013 cols = &ary.back ();
1015 cols = new CellList_t;
1016 ary.push_back (cols);
1019 if (usearch (b, e, m, re)) { //
1021 if (m[2].matched) { // ...!NUM\ .
1022 int v = strtoul (m[2].first);
1033 if (b < e && e[-1] == '|') { // ...|\ .
1041 WikiMotor motor (b, e, wiki);
1042 WikiMotorObjVec objv;
1043 WikiMotorObjVecVec objvv;
1044 WikiMotorObjVec* vcell;
1049 static const ustring brabra (CharConst ("{{"));
1051 motor.compile (objv);
1052 objv.splitCharA ('|', objvv);
1053 if (objvv.size () > 0 && objvv.back ()->size () == 0) {
1059 n = objvv.size () - 1;
1060 for (i = 0; i <= n; i ++) {
1061 // WikiMotorObjVecVec params;
1062 WikiMotorObjVec texts;
1064 vcell = objvv[i].get ();
1065 cell = newCell (cols->size ());
1066 // vcell->splitCharA (':', params);
1067 // x = cell->cellAttrib (this, &motor, params);
1068 cell->cellAttrib (wiki, &motor, vcell, texts);
1069 // if (i == n && fop && vcell->size () > 0 && x < vcell->size () && *vcell->back ().get () == brabra) {
1070 if (i == n && fop && texts.match (brabra)) {
1071 cols->push_back (cell);
1072 wiki->push_block (&cell->block);
1075 // cell->cellBody (t, u, this, cols->size ());
1076 // WikiMotorObjVec v;
1077 // cell->rebuildCell (x, ¶ms, v);
1078 // motor.join (¶ms, x, uColon, v);
1079 // params.join (x, uColon, v);
1080 cell->cellBody (&texts, this, cols->size ());
1081 cols->push_back (cell);
1085 cell = newCell (cols->size ());
1086 cols->push_back (cell);
1091 WikiBlockTable::TableCell* WikiBlockTable::newCell (int idx) {
1092 TableCell* ans = new TableCell;
1094 if (idx < defaultList.size ())
1095 ans->copyFrom (defaultList[idx]);
1099 void WikiBlockTable::normalize () {
1105 for (i = 0; i < ary.size (); i ++) {
1107 if (col->size () > maxcol)
1108 maxcol = col->size ();
1111 for (i = 0; i < ary.size (); i ++) {
1113 if (col->size () < maxcol) {
1114 cell = newCell (col->size ());
1115 cell->colspan = maxcol - col->size ();
1116 col->push_back (cell);
1117 while (col->size () < maxcol) {
1118 cell = newCell (col->size ());
1120 col->push_back (cell);
1125 for (i = 0; i < ary.size (); i ++) {
1127 for (j = col->size () - 1; j >= 0; j --) {
1129 if (cell->colspan > 0) {
1130 cell->colspan += maxcol - col->size ();
1131 while (col->size () < maxcol) {
1132 cell = newCell (col->size ());
1134 col->push_back (cell);
1143 void WikiBlockTable::outputTableTag (MotorOutput* out) {
1146 if (cellspacing < 0)
1148 if (cellpadding < 0)
1150 out->out (CharConst ("<table"));
1151 wiki->outputName (out, CharConst ("border"), fnoborder ? 1 : 0, false);
1152 wiki->outputName (out, CharConst ("cellspacing"), cellspacing, false);
1153 wiki->outputName (out, CharConst ("cellpadding"), cellpadding, false);
1156 out->out (CharConst (" align=\"left\""));
1159 out->out (CharConst (" align=\"center\""));
1162 out->out (CharConst (" align=\"right\""));
1165 wiki->outputID (out, id);
1166 wiki->outputClass (out, classlist);
1167 wiki->outputName (out, CharConst ("width"), width);
1168 wiki->outputName (out, CharConst ("bgcolor"), bgcolor);
1169 out->out (CharConst (">\n"));
1172 void WikiBlockTable::outputTBody (MotorOutput* out) {
1178 if (ary.size () > 0) {
1180 for (j = 0; j < n; j ++) {
1181 out->out (CharConst ("<tr>\n"));
1182 for (i = 0; i < ary.size (); i ++) {
1185 outputTBodyCell (wiki, out, cell);
1187 out->out (CharConst ("</tr>\n"));
1191 for (i = 0; i < ary.size (); i ++) {
1193 out->out (CharConst ("<tr>\n"));
1194 for (j = 0; j < col->size (); j ++) {
1196 outputTBodyCell (wiki, out, cell);
1198 out->out (CharConst ("</tr>\n"));
1203 void WikiBlockTable::outputTBodyCell (WikiFormat* wiki, MotorOutput* out, TableCell* cell) {
1204 if (cell->colspan > 0 && cell->rowspan > 0) {
1205 cell->outputTD (wiki, out, fturn);
1206 if (cell->block.size () > 0) {
1207 wiki->output (cell->block);
1209 if (cell->html.size () > 0) {
1210 out->out_text (cell->html);
1216 cell->outputTDe (out);
1220 /* ============================================================ */
1223 |select:NAME:function:default:size=NUM:multiple|
1225 |LABEL|VALUE|selected|
1228 bool WikiBlockSelect::nextLine (uiterator b, uiterator e) {
1229 if (*b == kWikiTABLE) {
1238 void WikiBlockSelect::addLine (uiterator b, uiterator e) {
1239 assert (b[0] == '|');
1241 if (n == 0 && matchSkip (b, e, CharConst ("select:"))) {
1242 addLine_head (b, e);
1244 addLine_body (b, e);
1249 void WikiBlockSelect::addLine_head (uiterator b, uiterator e) {
1250 WikiMotor motor (b, e, wiki);
1251 WikiMotorObjVec objv;
1252 WikiMotorObjVecVec objvv;
1253 WikiMotorObjVec* vcell;
1256 motor.compile (objv);
1257 objv.splitCharA ('|', objvv);
1258 if (objvv.size () > 0 && objvv.back ()->size () == 0)
1260 if (objvv.size () > 0) {
1261 vcell = objvv[0].get ();
1262 vcell->splitCharA (':', args);
1263 if (args.size () > 0) {
1264 name = args[0].get ()->textOut (wiki);
1265 args.erase (args.begin ());
1266 while (args.size () > 0) {
1268 WikiMotorObjVec vvalue;
1269 if (args[0].get ()->splitChar_keyword ('=', key, vvalue)) {
1270 if (match (key, CharConst ("size"))) {
1271 ustring v = vvalue.textOut (wiki);
1272 if (match (v, CharConst ("*"))) {
1274 } else if (checkNum (v)) {
1275 elsize = boost::lexical_cast<int> (v);
1276 if (elsize < 0 || elsize > 999) {
1282 args.erase (args.begin ());
1283 } else if (wiki->paramID (key, vvalue, id, ferr)) {
1284 } else if (wiki->paramClass (key, vvalue, classlist, ferr)) {
1289 if (match (key, CharConst ("default"))) {
1291 args.erase (args.begin ());
1292 } else if (match (key, CharConst ("multiple"))) {
1294 args.erase (args.begin ());
1302 if (fmultiple && elsize == 0) {
1307 void WikiBlockSelect::addLine_body (uiterator b, uiterator e) {
1308 WikiMotor motor (b, e, wiki);
1309 WikiMotorObjVec objv;
1310 WikiMotorObjVecVec objvv;
1313 motor.compile (objv);
1314 objv.splitCharA ('|', objvv);
1315 if (objvv.size () > 0 && objvv.back ()->size () == 0)
1317 if (objvv.size () > 0) {
1318 v.label = omitCtrl (objvv[0].get ()->textOut (wiki));
1322 if (objvv.size () > 1) {
1323 v.value = omitCtrl (objvv[1].get ()->textOut (wiki));
1330 if (objvv.size () > 2) {
1331 if (objvv[2].get ()->match (CharConst ("selected"), CharConst ("sel"))) {
1338 void WikiBlockSelect::close () {
1341 assert (wiki->cur->type == BlockParagraph);
1343 MotorOutputString out;
1345 wiki->cur->addHtml (out.ans);
1349 void WikiBlockSelect::output (MotorOutput* out) {
1352 WikiMotorObjVecVec::const_iterator b = args.begin ();
1353 WikiMotorObjVecVec::const_iterator e = args.end ();
1355 out->out (CharConst ("<select"));
1356 wiki->outputName (out, CharConst ("name"), name, false);
1358 wiki->outputName (out, CharConst ("size"), item.size (), false);
1360 wiki->outputName (out, CharConst ("size"), elsize);
1362 wiki->outputFlag (out, CharConst ("multiple"), fmultiple);
1363 wiki->outputID (out, id);
1364 wiki->outputClass (out, classlist);
1366 if (wiki->outputLinkScript (b, e, u))
1367 wiki->outputName (out, CharConst ("onChange"), u);
1369 out->out (CharConst (">\n"));
1372 u = wiki->getVar (name);
1374 std::cerr << "u:" << u << uLF;
1377 for (i = 0; i < item.size (); i ++) {
1378 SelectItem* v = &item[i];
1379 out->out (CharConst ("<option"));
1381 wiki->outputName (out, CharConst ("value"), v->value, false);
1383 std::cerr << "u:" << u << " v:" << v->value << " ::" << (u == v->value) << uLF;
1385 wiki->outputName (out, CharConst ("selected"), (v->fselect || (fdefault && u == v->value)));
1387 wiki->outputName (out, CharConst ("selected"), (v->fselect || (fdefault && u == v->label)));
1389 out->out (CharConst (">"));
1390 out->out_HTML (v->label)->out (CharConst ("</option>\n"));
1392 out->out (CharConst ("</select>\n"));
1395 /* ============================================================ */
1403 bool WikiBlockQuote::nextLine (uiterator b, uiterator e) {
1407 WikiBlock::closeType WikiBlockQuote::closeLine (uiterator b, uiterator e) {
1408 if (e - b == 1 && *b == kWikiQUOTE_e) {
1417 void WikiBlockQuote::addLine (uiterator b, uiterator e) {
1421 void WikiBlockQuote::output (MotorOutput* out) {
1422 out->out (CharConst ("<blockquote>\n"));
1424 out->out (CharConst ("</blockquote>\n"));
1427 /* ============================================================ */
1433 {div:id=Name:SideMenu
1438 bool WikiBlockDiv::nextLine (uiterator b, uiterator e) {
1442 void WikiBlockDiv::addLine (uiterator b, uiterator e) {
1443 WikiMotor motor (b, e, wiki);
1444 WikiMotorObjVec objv;
1445 WikiMotorObjVecVec args;
1449 motor.compile (objv);
1450 objv.splitCharA (':', args);
1451 args.erase (args.begin ()); // "div"
1452 if (args.size () > 0 && args.back ()->size () == 0)
1454 for (i = 0; i < args.size (); i ++) {
1456 WikiMotorObjVec vval;
1457 if (args[i].get ()->splitChar_keyword ('=', key, vval)) {
1458 if (wiki->paramID (key, vval, id, ferr)) {
1459 } else if (wiki->paramClass (key, vval, classlist, ferr)) {
1461 wiki->errorMsg.append (key).append (uEq).append (vval.dump ()).append (CharConst (": error.\n"));
1464 wiki->paramClassValue (*args[i].get (), classlist, ferr);
1469 WikiBlock::closeType WikiBlockDiv::closeLine (uiterator b, uiterator e) {
1470 if (e - b == 1 && *b == kWikiDIV_e) {
1479 void WikiBlockDiv::output (MotorOutput* out) {
1482 out->out (CharConst ("<div"));
1483 wiki->outputID (out, id);
1484 wiki->outputClass (out, classlist);
1485 out->out (CharConst (">\n"));
1487 out->out (CharConst ("</div>\n"));
1490 /* ============================================================ */
1496 // {form:POST:id=form1:class=formclass:post.hgh
1497 // {form:POST:post.hgh:id=form1:class=formclass
1498 {form:POST:id=form1:class=formclass:post.hgh:target_window
1503 bool WikiBlockForm::nextLine (uiterator b, uiterator e) {
1507 void WikiBlockForm::addLine (uiterator b, uiterator e) {
1508 WikiMotor motor (b, e, wiki);
1509 WikiMotorObjVec objv;
1510 WikiMotorObjVecVec args;
1512 WikiMotorObjVecVec::const_iterator ab, ae;
1514 motor.compile (objv);
1515 objv.splitCharA (':', args);
1516 args.erase (args.begin ()); // "form"
1517 if (args.size () > 0 && args.back ()->size () == 0)
1522 if ((*ab)->match (CharConst ("get"), CharConst ("GET"))) {
1525 } else if ((*ab)->match (CharConst ("post"), CharConst ("POST"))) {
1532 WikiMotorObjVec vval;
1533 if ((*ab)->splitChar_keyword ('=', key, vval)) {
1534 if (wiki->paramID (key, vval, id, ferr)) {
1536 } else if (wiki->paramClass (key, vval, classlist, ferr)) {
1545 wiki->wikiURLParam (ab, ae, fscript, url, target);
1548 WikiBlock::closeType WikiBlockForm::closeLine (uiterator b, uiterator e) {
1549 if (e - b == 1 && *b == kWikiDIV_e) {
1552 wiki->curform = NULL;
1559 void WikiBlockForm::output (MotorOutput* out) {
1560 out->out (CharConst ("<form"));
1564 out->out (CharConst (" method=\"get\""));
1567 out->out (CharConst (" method=\"post\""));
1572 // if (wiki->outputLinkScript (b, e, url)) {
1574 wiki->outputName (out, CharConst ("action"), ustring (CharConst ("#")), false);
1575 wiki->outputName (out, CharConst ("onSubmit"), url);
1577 wiki->outputName (out, CharConst ("action"), url, false);
1580 out->out (CharConst (" enctype=\"multipart/form-data\""));
1581 wiki->outputName (out, CharConst ("target"), target);
1582 wiki->outputID (out, id);
1583 wiki->outputClass (out, classlist);
1584 out->out (CharConst (">\n"));
1586 out->out (CharConst ("</form>\n"));
1589 /* ============================================================ */
1595 bool WikiBlockHR::nextLine (uiterator b, uiterator e) {
1599 void WikiBlockHR::addLine (uiterator b, uiterator e) {
1603 void WikiBlockHR::output (MotorOutput* out) {
1604 out->out (CharConst (uHR));
1607 /* ============================================================ */
1608 void WikiFormat::pass1 (const ustring& text, WikiLine::linevec* block, bool fsuper) {
1609 Splitter sp (text, re_nl);
1611 pass1_1 (sp, NULL, NULL, block, NULL, NULL, fsuper);
1614 int WikiFormat::pass1_1 (Splitter& sp, ustring* elseword, ustring* endword, WikiLine::linevec* block, uiterator* elsebegin, uiterator* elseend, bool fsuper) {
1615 uiterator b, e, t, u, v;
1618 while (sp.next ()) {
1621 while (b < e && b[0] == '\t')
1623 if (matchSkip (b, e, CharConst (kComment))) {
1625 } else if (b != e && b[0] == kWikiCmd) {
1626 if (usearch (b, e, m, re_wikicmdsep)) {
1635 if (endword && match (t, u, *endword)) {
1636 return 2; // endword
1637 } else if (elseword && match (t, u, *elseword)) {
1642 return 1; // elseword
1643 } else if (pass1_2 (sp, b, e, t, u, v, block, fsuper)) {
1646 block->push_back (wl = new WikiLine (b, e, fsuper));
1647 wl->fn = wc_call_defun;
1650 block->push_back (new WikiLine (b, e, fsuper));
1653 return 0; // end of line
1656 bool WikiFormat::pass1_2 (Splitter& sp, uiterator& b, uiterator& e, uiterator& t, uiterator& u, uiterator& v, WikiLine::linevec* block, bool fsuper) {
1657 WikiCmdTable::iterator it;
1658 ustring elseword, endword;
1663 if ((it = GWikiCmdTable.find (ustring (t, u))) != GWikiCmdTable.end ()) {
1664 block->push_back (wl = new WikiLine (b, v, e, fsuper));
1665 wl->fn = it->second->fn;
1666 if (it->second->endname) {
1667 endword.assign (it->second->endname, it->second->endnamelen);
1668 if (it->second->elsename) {
1669 elseword.assign (it->second->elsename, it->second->elsenamelen);
1670 // if-then-else block
1671 wl->block = new WikiLine::linevec;
1672 rc = pass1_1 (sp, &elseword, &endword, wl->block, &b, &e, fsuper);
1676 if (endword.length () > 0) {
1677 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1682 wl2 = new WikiLine (b, e, fsuper);
1686 wl->block = new WikiLine::linevec;
1687 rc = pass1_1 (sp, &elseword, &endword, wl->block, &b, &e, fsuper);
1690 if (endword.length () > 0) {
1691 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1703 wl->block = new WikiLine::linevec;
1704 rc = pass1_1 (sp, NULL, &endword, wl->block, NULL, NULL, fsuper);
1706 // no end line error
1707 if (endword.length () > 0) {
1708 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1722 static void dump (WikiLine::linevec* block, int indent = 0) {
1725 for (j = 0; j < indent; j ++) std::cerr << " ";
1726 std::cerr << "(NULL)\n";
1729 for (i = 0; i < block->size (); i ++) {
1730 WikiLine* wl = &(*block)[i];
1731 for (j = 0; j < indent; j ++) std::cerr << " ";
1733 std::cerr << (void*)wl->fn << ":";
1734 std::cerr << ustring (wl->begin, wl->end) << uLF;
1737 dump (wl->block, indent + 1);
1741 for (j = 0; j < indent; j ++) std::cerr << " ";
1742 std::cerr << "else:" << (void*)wl->fn << ":" << ustring (wl->begin, wl->end) << uLF;
1743 // dump (wl->block, indent + 1);
1752 void WikiFormat::compile (const ustring& text, bool fsuper) {
1754 WikiLine::linevec block;
1755 pass1 (text, &block, fsuper);
1761 WikiLineScanner scanner (&block);
1762 compileLines (scanner);
1767 if (bstack.size () > 0)
1774 } catch (ustring& msg) {
1775 logLispFunctionError (msg, uEmpty);
1779 void WikiFormat::output (boost::ptr_vector<WikiBlock>& ary) {
1782 for (i = 0; i < ary.size (); i ++) {
1783 ary[i].output (env->output);
1788 void WikiFormat::errorOutput () {
1789 if (errorMsg.size () > 0) {
1790 env->output->out (CharConst (uP));
1791 env->output->out_HTML_br (errorMsg);
1792 env->output->out (CharConst (uPe));
1793 errorMsg.resize (0);
1797 bool WikiFormat::checkClose (uiterator b, uiterator e) {
1798 int n = bstack.size ();
1799 WikiBlock::closeType rc;
1803 rc = bstack[n]->closeLine (b, e);
1805 case WikiBlock::CloseTrue:
1807 case WikiBlock::CloseFalse:
1814 void WikiFormat::compileLine (WikiLineScanner& scanner) {
1815 WikiLine* wl = scanner.cur ();
1819 uiterator b = wl->begin;
1820 uiterator e = wl->end;
1824 std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
1828 if (b == e) { // empty line
1833 } else if (matchSkip (b, e, CharConst ("//"))) { // comment
1834 } else if (checkClose (b, e)) {
1835 } else if (cur && cur->nextLine (b, e)) {
1836 } else if (b[0] == kWikiP) { // ^
1839 cur = new WikiBlockParagraph (this);
1840 blockp->push_back (cur);
1841 cur->addLine (b, e);
1842 } else if (b[0] == kWikiH) { // =
1846 cur = obj = new WikiBlockH (this);
1847 blockp->push_back (cur);
1848 cur->addLine (b, e);
1849 push_block (&obj->block);
1850 } else if (b[0] == kWikiPRE // SPC
1851 || b[0] == kWikiPRE2) { // TAB
1854 cur = new WikiBlockPreformat (this);
1855 blockp->push_back (cur);
1856 cur->addLine (b, e);
1857 } else if (b[0] == kWikiUL) { // *
1861 cur = obj = new WikiBlockItem (WikiBlock::BlockItemUL, this);
1862 blockp->push_back (cur);
1863 obj->addLine (b, e);
1864 } else if (b[0] == kWikiOL) { // #
1868 cur = obj = new WikiBlockItem (WikiBlock::BlockItemOL, this);
1869 blockp->push_back (cur);
1870 obj->addLine (b, e);
1871 } else if (b[0] == kWikiNL) { // ]
1875 cur = obj = new WikiBlockItem (WikiBlock::BlockItemNL, this);
1876 blockp->push_back (cur);
1877 obj->addLine (b, e);
1878 } else if (b[0] == kWikiDL) { // ;
1881 cur = new WikiBlockItemDL (this);
1882 blockp->push_back (cur);
1883 cur->addLine (b, e);
1884 } else if (matchHead (b, e, CharConst ("|select:"))) { // |select:
1885 if (cur && cur->type == WikiBlock::BlockParagraph) {
1889 cur = new WikiBlockParagraph (this);
1890 blockp->push_back (cur);
1893 cur = new WikiBlockSelect (this);
1894 cur->addLine (b, e);
1895 } else if (b[0] == kWikiTABLE) { // |
1896 WikiBlockTable* obj;
1899 cur = obj = new WikiBlockTable (this);
1900 blockp->push_back (cur);
1901 cur->addLine (b, e);
1902 } else if (b[0] == kWikiQUOTE && e - b == 1) { // >
1903 WikiBlockQuote* obj;
1906 cur = obj = new WikiBlockQuote (this);
1907 blockp->push_back (cur);
1908 push_block (&obj->block);
1909 } else if (matchHead (b, e, CharConst ("{div:"))) {
1910 WikiBlockComplex* obj;
1913 cur = obj = new WikiBlockDiv (this);
1914 blockp->push_back (cur);
1915 cur->addLine (b, e);
1916 push_block (&obj->block);
1917 } else if (curform == NULL && matchHead (b, e, CharConst ("{form:"))) {
1918 WikiBlockComplex* obj;
1921 cur = obj = curform = new WikiBlockForm (this);
1922 blockp->push_back (cur);
1923 cur->addLine (b, e);
1924 push_block (&obj->block);
1925 } else if (matchHead (b, e, CharConst ("----"))) { // ----
1928 cur = new WikiBlockHR (this);
1929 blockp->push_back (cur);
1930 cur->addLine (b, e);
1933 if (cur && cur->type != WikiBlock::BlockParagraph) {
1938 cur = new WikiBlockParagraph (this);
1939 blockp->push_back (cur);
1941 cur->addLine (b, e);
1946 void WikiFormat::compileLines (WikiLineScanner& scanner, bool (*fn)(WikiLine& spp, WikiLineScanner& scanner, WikiFormat* wiki, void* par), void* par) {
1949 while (wl = scanner.next ()) {
1950 if (fn && fn (*scanner.cur (), scanner, this, par)) {
1953 compileLine (scanner);
1958 int WikiFormat::countWikiH (uiterator& b, uiterator e) {
1961 while (b != e && *b == kWikiH) {
1971 ustring WikiFormat::wikiLink (const ustring& url) {
1974 ustring host, port, v;
1985 static uregex re ("\\[\\[(" rWIKIVAR ")\\]\\]|(:)|(/)|(\\?)|(#)");
1989 if (matchSkip (b, e, CharConst ("http://")) || matchSkip (b, e, CharConst ("https://"))) {
1990 Splitter sp (b, e, re);
1993 ans.assign (url.begin (), b); // http://
1994 while (sp.next ()) {
1995 if (sp.begin () < sp.end ())
1996 host.append (sp.begin (), sp.end ());
1997 if (! sp.match (0)) {
1999 } else if (sp.match (1)) { // [[VAR]]
2000 host.append (getVar (ustring (sp.matchBegin (1), sp.matchEnd (1))));
2001 } else if (sp.match (2)) { // :
2004 } else if (sp.match (3)) { // /
2012 if (mode == MPORT) {
2013 while (sp.next ()) {
2014 if (sp.begin () < sp.end ())
2015 port.append (sp.begin (), sp.end ());
2016 if (! sp.match (0)) {
2018 } else if (sp.match (1)) { // [[VAR]]
2019 port.append (getVar (ustring (sp.matchBegin (1), sp.matchEnd (1))));
2020 } else if (sp.match (3)) { // /
2031 if (! checkHostname (host))
2034 if (port.length () > 0) {
2035 if (! checkNum (port))
2037 ans.append (CharConst (":")).append (port);
2039 if (! sp.isEnd ()) {
2040 ans.append (CharConst ("/"));
2050 Splitter sp (b, e, re);
2054 while (sp.next ()) {
2055 if (sp.begin () < sp.end ()) {
2057 v = urldecode_nonul (v);
2061 if (! sp.match (0)) {
2063 } else if (sp.match (1)) { // [[VAR]]
2064 v = getVar (ustring (sp.matchBegin (1), sp.matchEnd (1)));
2065 ans.append (urlencode (v));
2066 } else if (sp.match (3)) { // /
2067 ans.append (CharConst ("/"));
2068 } else if (sp.match (4)) { // ?
2069 ans.append (CharConst ("?"));
2072 } else if (sp.match (5)) { // #
2074 ans.append (CharConst ("#"));
2075 v = ustring (sp.matchEnd (), e);
2076 v = urldecode_nonul (v);
2087 static uregex re ("\\[\\[(" rWIKIVAR ")\\]\\]|(=)|(&)|(#)");
2088 Splitter sp (b, e, re);
2089 ustring name, value;
2096 while (mode == MNAME && sp.next ()) {
2097 if (sp.begin () < sp.end ()) {
2099 v = urldecode_nonul (v);
2102 if (! sp.match (0)) {
2104 } else if (sp.match (1)) { // [[VAR]]
2105 name.append (getVar (ustring (sp.matchBegin (1), sp.matchEnd (1))));
2106 } else if (sp.match (2)) { // =
2109 } else if (sp.match (3)) { // &
2112 } else if (sp.match (4)) { // #
2117 while (mode == MVALUE && sp.next ()) {
2118 if (sp.begin () < sp.end ()) {
2120 v = urldecode_nonul (v);
2123 if (! sp.match (0)) {
2125 } else if (sp.match (1)) { // [[VAR]]
2126 value.append (getVar (ustring (sp.matchBegin (1), sp.matchEnd (1))));
2127 } else if (sp.match (2)) { // =
2129 } else if (sp.match (3)) { // &
2132 } else if (sp.match (4)) { // #
2139 ans.append (CharConst ("&"));
2140 if (name.length () > 0) {
2141 ans.append (urlencode (name)).append (uEq).append (urlencode (value));
2147 if (mode == MFRAG) {
2148 ans.append (CharConst ("#"));
2149 v = ustring (sp.matchEnd (), e);
2150 v = urldecode_nonul (v);
2161 bool WikiFormat::wikiURLParam (WikiMotorObjVecVec::const_iterator& b, WikiMotorObjVecVec::const_iterator e, bool& fscript, ustring& url) {
2164 if (outputLinkScript (b, e, url)) {
2168 if ((*b)->match (CharConst ("http"), CharConst ("https"))) {
2169 ustring proto = (*b)->dump ();
2175 if (! (*b)->splitURL_2 (this, proto, url)) {
2180 if (b < e && (*b)->splitURL_3 (this, url, url))
2182 } else if ((*b)->splitURLPath (this, url)) {
2194 bool WikiFormat::wikiURLParam (WikiMotorObjVecVec::const_iterator& b, WikiMotorObjVecVec::const_iterator e, bool& fscript, ustring& url, ustring& target) {
2195 if (wikiURLParam (b, e, fscript, url)) {
2196 if (! paramTarget (b, e, target))
2205 bool WikiFormat::wikiUrlPort (WikiMotorObjVecVec::const_iterator& b, WikiMotorObjVecVec::const_iterator e, ustring& port) {
2211 bool WikiFormat::outputLinkScript (WikiMotorObjVecVec::const_iterator& b, WikiMotorObjVecVec::const_iterator e, ustring& ans) {
2219 if ((*b)->size () == 1 && (*(*b))[0]->type == WikiMotorObj::wiki_text) {
2220 WikiMotorObjText* t = WikiMotorObjText_type ((*(*b))[0].get ());
2221 ustring* u = &t->text;
2222 if (wf = env->wikienv->wikiLink_getVar (*u)) {
2224 MotorOutputString out2;
2225 MotorOutput* back = env->output;
2227 vargs = buildArgs (b, e);
2228 env->output = &out2;
2230 node = execDefun (env->mlenv, wf, vargs ());
2231 } catch (ustring& msg) {
2232 logLispFunctionError (msg, *u);
2236 // ans = omitCtrl (out2.ans);
2243 bool WikiFormat::paramID (const ustring& key, WikiMotorObjVec& vval, ustring& var_id, bool& ferr) {
2244 if (match (key, CharConst ("id"))) {
2245 ustring value (vval.textOut (this));
2246 if (checkWikiID (value)) {
2250 errorMsg.append (key).append (uEq).append (value).append (CharConst (": bad id\n"));
2259 bool WikiFormat::paramClass (const ustring& key, WikiMotorObjVec& vval, std::vector<ustring>& classes, bool& ferr) {
2260 if (match (key, CharConst ("class"))) {
2261 paramClassValue (vval, classes, ferr);
2268 void WikiFormat::paramClassValue (WikiMotorObjVec& vval, std::vector<ustring>& classes, bool& ferr) {
2269 WikiMotorObjVecVec args;
2271 vval.splitCharA (',', args);
2272 for (int i = 0; i < args.size (); i ++) {
2273 ustring value (args[i]->textOut (this));
2274 if (checkWikiID (value)) {
2275 classes.push_back (value);
2277 errorMsg.append (value).append (CharConst (": bad class name\n"));
2283 bool WikiFormat::paramWidth (const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
2284 if (match (key, CharConst ("width"), CharConst ("w"))) {
2285 ustring value (vval.textOut (this));
2286 if (checkWidth (value)) {
2298 bool WikiFormat::paramHeight (const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
2299 if (match (key, CharConst ("height"), CharConst ("h"))) {
2300 ustring value (vval.textOut (this));
2301 if (checkWidth (value)) {
2305 errorMsg.append (key).append (uEq).append (value).append (CharConst (": bad value\n"));
2314 bool WikiFormat::paramSize (const char* name, size_t namelen, const ustring& key, WikiMotorObjVec& vval, ustring& var, bool& ferr) {
2315 if (match (key, name, namelen)) {
2316 ustring value (vval.textOut (this));
2317 if (checkNum (value)) {
2328 void WikiFormat::paramUNum (const ustring& value, int& var, const ustring& name) {
2329 if (checkNum (value)) {
2330 var = strtoul (value);
2332 errorMsg.append (name).append (uEq).append (value).append (uErrorBadValue).append (uLF);
2336 void WikiFormat::paramColor (const ustring& value, ustring& var, const ustring& name) {
2337 if (checkColor (value)) {
2340 errorMsg.append (name).append (uEq).append (value).append (uErrorBadValue).append (uLF);
2344 bool WikiFormat::paramTarget (WikiMotorObjVecVec::const_iterator& b, WikiMotorObjVecVec::const_iterator e, ustring& target) {
2346 target = (*b)->textOut (this); // no LF
2347 if (! checkWikiID (target)) {
2348 errorMsg.append (target).append (CharConst (": bad target name.\n"));
2353 return true; // no error
2356 void WikiFormat::outputName (MotorOutput* out, const char* name, size_t len, const ustring& val, bool cond) {
2357 if (! cond || val.length () > 0)
2358 out->out (uSPC)->out (name, len)->out (CharConst ("=\""))->out_HTML_noCtrl (val)->out (uQ2);
2361 void WikiFormat::outputName (MotorOutput* out, const char* name, size_t len, long val, bool cond) {
2362 if (! cond || val > 0)
2363 out->out (uSPC)->out (name, len)->out (CharConst ("=\""))->out (boost::lexical_cast<ustring> (val))->out (uQ2);
2366 void WikiFormat::outputFlag (MotorOutput* out, const char* name, size_t len, bool flag) {
2368 out->out (uSPC)->out (name, len)->out (CharConst ("=\""))->out (name, len)->out (uQ2);
2371 void WikiFormat::outputID (MotorOutput* out, const ustring& id) {
2372 if (id.length () > 0)
2373 out->out (CharConst (" id=\""))->out_HTML_noCtrl (id)->out (uQ2);
2376 void WikiFormat::outputClass (MotorOutput* out, std::vector<ustring>& classes) {
2377 if (classes.size () > 0) {
2378 out->out (CharConst (" class=\""));
2379 for (int i = 0; i < classes.size (); i ++) {
2382 out->out_HTML_noCtrl (classes[i]);
2388 void WikiFormat::wikiMotor (uiterator b, uiterator e, WikiMotorObjVec& ans) {
2389 WikiMotor motor (b, e, this);
2390 motor.compile (ans, WikiMotor::TMATCH_NONE);
2393 ustring WikiFormat::wikiMotor (uiterator b, uiterator e) {
2394 WikiMotorObjVec objv;
2396 wikiMotor (b, e, objv);
2397 return objv.htmlOut (this);
2400 MNode* WikiFormat::buildArgs (WikiMotorObjVecVec::const_iterator& b, WikiMotorObjVecVec::const_iterator e) {
2405 ans = a = new MNode;
2406 a->set_car (newMNode_str (new ustring ((*b)->textOut (this))));
2407 for (b ++; b < e; b ++) {
2409 a->set_car (newMNode_str (new ustring ((*b)->textOut (this))));
2415 void WikiFormat::logLispFunctionError (const ustring& msg, const ustring& cmd) {
2416 if (cmd.length () > 0)
2417 errorMsg.append (cmd).append (CharConst (": "));
2418 errorMsg.append (CharConst ("lisp function error.\n"));
2419 if (mlenv->env->mlenv->currentCell ()) {
2420 if (mlenv->env->log)
2421 *mlenv->env->log << mlenv->env->mlenv->currentCell ()->dump_string_short () << ": ";
2422 *mlenv->env->log << msg << uLF;
2426 /* ============================================================ */