1 #include "wikiformat.h"
9 #include "motorconst.h"
11 #include "motoroutput.h"
12 #include "util_const.h"
13 #include "util_check.h"
14 #include "util_string.h"
17 #include <boost/ptr_container/ptr_vector.hpp>
20 WIKIMOTORPRE: セットすると,フォーマット済みテキストブロックの中でインライン要素の解釈を行う。
21 UTF8JP: セットすると,条件によりパラグラフ内の改行を空白に置き換えない。
22 WIKITABLECOMPATFLAG: セットすると,旧形式の表の継続記号もゆるす。
29 #define kWikiPRE2 '\t'
35 #define kWikiTABLE '|'
36 #define kWikiQUOTE '>'
37 #define kWikiQUOTE_e '<'
39 #define uWikiDIV "{div:"
40 #define uWikiFORM "{form:"
41 #define uWikiELEMENT "{element:"
42 #define kWikiDIV_e '}'
54 #define uH1e "</h1>\n"
55 #define uH2e "</h2>\n"
56 #define uH3e "</h3>\n"
57 #define uH4e "</h4>\n"
58 #define uH5e "</h5>\n"
59 #define uH6e "</h6>\n"
60 #define uHR "<hr />\n"
61 //#define unbsp " "
63 ustring uWiki (CharConst ("wiki_"));
64 ustring uAWiki (CharConst ("@wiki_"));
71 /* ============================================================ */
72 void WikiMlEnv::setVar (const ustring& name, MNode* val) {
73 MlEnv::setVar (wikiVarName (name), val);
76 void WikiMlEnv::setAry (const ustring& name, size_t i, MNode* val) {
77 MlEnv::setAry (wikiVarName (name), i, val);
80 void WikiMlEnv::setArySize (const ustring& name, size_t n) {
81 MlEnv::setArySize (wikiVarName (name), n);
84 void WikiMlEnv::setAry (const ustring& name, MNode* list) {
85 MlEnv::setAry (wikiVarName (name), list);
88 MNode* WikiMlEnv::getVar (const ustring& name) {
89 return MlEnv::getVar (wikiVarName (name));
92 MNode* WikiMlEnv::getAry (const ustring& name, size_t i) {
93 return MlEnv::getAry (wikiVarName (name), i);
96 size_t WikiMlEnv::getArySize (const ustring& name) {
97 return MlEnv::getArySize (wikiVarName (name));
100 void WikiMlEnv::setLocalVar (const ustring& name, MNode* val) {
101 MlEnv::setLocalVar (wikiVarName (name), val);
104 void WikiMlEnv::defineLocalVar (const ustring& name) {
105 MlEnv::defineLocalVar (wikiVarName (name));
108 ustring WikiMlEnv::wikiVarName (const ustring& name) {
114 /* ============================================================ */
115 void WikiMotorOutputString::flush (bool fsuper) {
116 wikiOutput (ans, fsuper, wiki);
120 /* ============================================================ */
121 void WikiBlockComplex::outputBlock (MotorOutput* out) {
122 for (int i = 0; i < block.size (); i ++) {
123 block[i].output (out);
127 /* ============================================================ */
130 マークアップ文字以外の文字で書き出すと,段落になる。
131 ^行頭が他のマークアップ文字になるときは,行頭に^を書く。
136 bool WikiBlockParagraph::nextLine (uiterator b, uiterator e) {
145 void WikiBlockParagraph::addLine (uiterator b, uiterator e) {
146 if (b[0] == kWikiP) {
154 WikiMotorObjVec::iterator ob;
155 WikiMotorObjVec::iterator oe;
156 wiki->wikiMotorInline (b, e, o);
157 if (objv.size () > 0 && o.size () > 0) {
160 WikiMotorObjText* t1;
161 WikiMotorObjText* t2;
165 if (v->type == WikiMotorObj::wiki_text) {
166 t1 = WikiMotorObjText_type (v);
168 if (v->type == WikiMotorObj::wiki_text) {
169 t2 = WikiMotorObjText_type (v);
170 if (t1->text.length () > 0 && t2->text.length () > 0) {
171 lastChar (t1->text, i1);
172 n = t1->text.end () - i1;
173 i2 = t2->text.begin ();
174 nextChar (i2, t2->text.end ());
175 if (n == 3 && i2 - t2->text.begin () == 3) {
177 objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
180 objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
183 objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
186 objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
189 objv.push_back (WikiMotorObjPtr (new WikiMotorObjText (uSPC)));
194 for (; ob < oe; ob ++) {
195 objv.push_back (*ob);
200 void WikiBlockParagraph::addHtml (const ustring& ht) {
201 objv.push_back (WikiMotorObjPtr (new WikiMotorObjHtml (ht)));
204 void WikiBlockParagraph::output (MotorOutput* out) {
206 out->out_toText (objv.htmlOut (wiki));
208 out->out_raw (CharConst (uP));
209 out->out_toText (objv.htmlOut (wiki));
210 out->out_raw (CharConst (uPe));
214 /* ============================================================ */
221 行頭に=を書くと,タイトルになる。行末の=は,省略可。
225 bool WikiBlockH::nextLine (uiterator b, uiterator e) {
229 void WikiBlockH::addLine (uiterator b, uiterator e) {
233 static uregex re ("(=+)#([a-zA-Z0-9_-]+)$");
235 cn = wiki->countWikiH (b, e);
236 level = cn + wiki->headbase;
239 level0 = wiki->hlevel;
241 for (; b < e && *b == ' '; b ++) {}
242 if (usearch (b, e, m, re)) {
244 n = m[1].second - m[1].first - cn;
248 for (; b < u && u[-1] == ' '; u --) {}
249 title = wiki->wikiMotor (b, u);
250 anchor = ustring (m[2].first, m[2].second);
253 for (n = cn; n > 0 && b < u && u[-1] == '='; u --, n --) {}
254 for (; b < u && u[-1] == ' '; u --) {}
255 title = wiki->wikiMotor (b, u);
257 wiki->hlevel = level;
260 WikiBlock::closeType WikiBlockH::closeLine (uiterator b, uiterator e) {
261 if (e - b == 1 && *b == kWikiDIV_e) {
262 // closing point of the div
264 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
265 switch (wiki->bstack[i]->type) {
269 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
271 switch (wiki->bstack[i]->type) {
286 } else if (b != e && *b == kWikiH) {
287 int l = wiki->countWikiH (b, e) + wiki->headbase;
292 for (i = wiki->bstack.size () - 1; i >= 0; i --) {
293 if (wiki->bstack[i]->type == BlockH) {
294 obj = (WikiBlockH*)wiki->bstack[i];
295 if (obj->level >= l) {
313 void WikiBlockH::close () {
314 wiki->hlevel = level0;
317 void WikiBlockH::output (MotorOutput* out) {
320 assert (0 < level && level <= 6);
324 outputBeginDiv (level, out);
326 case 1: out->out_raw (CharConst (uH1)); break;
327 case 2: out->out_raw (CharConst (uH2)); break;
328 case 3: out->out_raw (CharConst (uH3)); break;
329 case 4: out->out_raw (CharConst (uH4)); break;
330 case 5: out->out_raw (CharConst (uH5)); break;
331 case 6: out->out_raw (CharConst (uH6)); break;
333 if (anchor.size () > 0) {
334 out->out_raw (CharConst ("<a name=\""))->out_toHTML_noCtrl (anchor)->out_raw (CharConst ("\">"))->out_toText (title)->out_raw (CharConst ("</a>"));
336 out->out_noCtrl (title);
339 case 1: out->out_raw (CharConst (uH1e)); break;
340 case 2: out->out_raw (CharConst (uH2e)); break;
341 case 3: out->out_raw (CharConst (uH3e)); break;
342 case 4: out->out_raw (CharConst (uH4e)); break;
343 case 5: out->out_raw (CharConst (uH5e)); break;
344 case 6: out->out_raw (CharConst (uH6e)); break;
347 outputEndDiv (level, out);
350 void WikiBlockH::outputBeginDiv (int lv, MotorOutput* out) {
352 case 1: out->out_raw (CharConst ("<div class=\"hh1\">\n")); break;
353 case 2: out->out_raw (CharConst ("<div class=\"hh2\">\n")); break;
354 case 3: out->out_raw (CharConst ("<div class=\"hh3\">\n")); break;
355 case 4: out->out_raw (CharConst ("<div class=\"hh4\">\n")); break;
356 case 5: out->out_raw (CharConst ("<div class=\"hh5\">\n")); break;
357 case 6: out->out_raw (CharConst ("<div class=\"hh6\">\n")); break;
361 void WikiBlockH::outputEndDiv (int lv, MotorOutput* out) {
363 out->out_raw (CharConst ("</div><!-- hh"))->out_raw (to_ustring (lv))->out_raw (CharConst (" -->\n"));
365 out->out_raw (CharConst ("</div>\n"));
369 bool WikiBlockH::checkEmpty () {
370 return title.empty ();
373 /* ============================================================ */
375 ===フォーマット済みテキストブロック===
376 行頭に空白文字を書くと,<pre>〜</pre>タグで囲まれます。
380 bool WikiBlockPreformatRaw::nextLine (uiterator b, uiterator e) {
389 void WikiBlockPreformatRaw::addLine (uiterator b, uiterator e) {
394 if (wiki->motorPre) {
395 text.append (wiki->wikiMotor (b, e));
398 o.out_toHTML (ustring (b, e));
404 void WikiBlockPreformatRaw::output (MotorOutput* out) {
405 out->out_raw (CharConst ("<pre>"))->out_toText (text)->out_raw (CharConst ("</pre>\n"));
408 /* ============================================================ */
409 bool WikiBlockItemText::nextLine (uiterator b, uiterator e) {
413 void WikiBlockItemText::addLine (uiterator b, uiterator e) {
414 WikiMotor motor (b, e, wiki);
415 WikiMotorObjVecPtr v1 (new WikiMotorObjVec);
418 if (! attrib.shiftAttrib (v1))
420 html.append (v1->htmlOut (wiki));
423 bool WikiBlockItemText::checkAddLine (uiterator b, uiterator e) {
431 if (block.size () > 0) {
432 obj = &block.back ();
437 wbi = (WikiBlockItem*)obj;
450 void WikiBlockItemText::output (MotorOutput* out) {
454 out->out_raw (CharConst ("<li"));
456 out->out_raw (CharConst (">"));
457 out->out_toText (html);
459 out->out_raw (CharConst ("</li>\n"));
463 /* ============================================================ */
472 *''[OPTION1:OPTION2:...:]''TEXT
473 行頭に「*」を書くと,<UL>タグによるリスト,「#」を書くと<NL>タグによる番号付きリスト,「+」を書くとnobullクラス指定の<UL>タグによるリスト。
476 |table:w=100%|t:w=20%|c:w=10%|t:|
478 |'''id='''''ID''||id属性。|
479 |'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
480 //|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
481 |'''onclick='''''Link''||onclick属性。Javascriptリンク。|
482 |'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
483 |'''onblur='''''Link''||onblur属性。Javascriptリンク。|
484 |'''onchange='''''Link''||onchange属性。Javascriptリンク。|
485 |'''start='''''Number''||start属性。OLのみ。|
488 bool WikiBlockItem::nextLine (uiterator b, uiterator e) {
497 void WikiBlockItem::setChar (char c) {
502 void WikiBlockItem::addLine (uiterator b, uiterator e) {
505 WikiBlockItemText* wbt;
510 assert (b != e && b[0] == ch);
513 wbt = new WikiBlockItemText (wiki, this);
514 block.push_back (wbt);
518 if (block.size () > 0 && block.back ().checkAddLine (b, e)) {
522 wbi = new WikiBlockItem (WikiBlock::BlockItemUL, wiki);
525 wbi = new WikiBlockItem (WikiBlock::BlockItemOL, wiki);
528 wbi = new WikiBlockItem (WikiBlock::BlockItemNL, wiki);
534 if (block.size () > 0) {
535 wbt = &block.back ();
537 wbt->block.push_back (wbi);
539 wbt = new WikiBlockItemText (wiki, this);
540 block.push_back (wbt);
542 wbt->block.push_back (wbi);
543 wbt->indentHack = true;
546 wbt = new WikiBlockItemText (wiki, this);
547 block.push_back (wbt);
554 void WikiBlockItem::output (MotorOutput* out) {
559 out->out_raw (CharConst ("<ul"));
561 out->out_raw (CharConst (">\n"));
563 out->out_raw (CharConst ("</ul>\n"));
566 out->out_raw (CharConst ("<ol"));
568 out->out_raw (CharConst (">\n"));
570 out->out_raw (CharConst ("</ol>\n"));
573 out->out_raw (CharConst ("<ul"));
574 attrib.classlist.push_back (ustring (CharConst ("nobull")));
576 attrib.classlist.pop_back ();
577 out->out_raw (CharConst (">\n"));
579 out->out_raw (CharConst ("</ul>\n"));
582 std::cerr << "type:" << type << uLF;
587 void WikiBlockItem::outputBlock (MotorOutput* out) {
588 for (int i = 0; i < block.size (); i ++) {
589 block[i].output (out);
593 /* ============================================================ */
599 bool WikiBlockItemDL::nextLine (uiterator b, uiterator e) {
608 void WikiBlockItemDL::addLine (uiterator b, uiterator e) {
609 WikiMotorObjVec objs;
610 WikiMotorObjVec* def;
611 WikiMotorObjVec* desc;
613 wiki->wikiMotorInline (b + 1, e, objs);
614 def = new WikiMotorObjVec;
615 desc = new WikiMotorObjVec;
616 objv1.push_back (def);
617 objv2.push_back (desc);
618 objs.splitChar (':', *def, *desc);
621 void WikiBlockItemDL::output (MotorOutput* out) {
624 out->out_raw (CharConst ("<dl>\n"));
625 for (i = 0; i < objv1.size (); i ++) {
626 out->out_raw (CharConst ("<dt>"))->out_toText (objv1[i].htmlOut (wiki))->out_raw (CharConst ("</dt>\n"));
627 out->out_raw (CharConst ("<dd>"))->out_toText (objv2[i].htmlOut (wiki))->out_raw (CharConst ("</dd>\n"));
629 out->out_raw (CharConst ("</dl>\n"));
632 /* ============================================================ */
635 |table:w=100%:数量リスト|head:right:||right:|
641 表定義の最初の行の最初のカラムに「table:」を書くと,この行はテーブルオプション指定行になる。属性指定の後にテキストを書くと,表のキャプションになる。
642 2番目以降のカラムは,デフォルトのカラムオプション指定になる。
644 |table:w=100%:テーブルオプション|t:w=20%|c:w=10%|t:|
646 |'''id='''''ID''||id属性。|
647 |'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
648 //|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
649 |'''onclick='''''Link''||onclick属性。Javascriptリンク。|
650 |'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
651 |'''onblur='''''Link''||onblur属性。Javascriptリンク。|
652 |'''onchange='''''Link''||onchange属性。Javascriptリンク。|
653 |'''width='''''Size''|'''w='''|width属性。単位はpx, pt, in, mm, cm, em, ex。または%。|
654 //|'''height='''''Size''|'''h='''|height属性。単位はpx, pt, in, mm, cm, em, ex。または%。|
655 |'''bgcolor='''''Color''|'''bg='''|bgcolor属性。|
656 |'''cellspacing='''''Integer''|'''spc='''|cellspacing属性。*コンパイル時設定による。|
657 |'''cellpadding='''''Integer''||cellpadding属性。*コンパイル時設定による。|
658 |'''left'''|'''l'''|align="left"属性。|
659 |'''right'''|'''r'''|align="right"属性。|
660 |'''center'''|'''c'''|align="center"属性。|
661 |'''noborder'''|''nb''|border="0"属性。|
662 |'''padding'''|'''pad'''|行のカラム定義が最大カラム数に満たない時,空のカラムを追加する。|
663 |'''expanding'''|'''expand'''|行のカラム定義が最大カラム数に満たない時,最終カラムを伸ばす。|
664 |'''nowhite'''|'''nw'''|空セルにnbspを出力する。|
665 |'''turn'''||表の行と列を入れ替える。|
668 |row:bgcolor=#ff0|&[;&[;Name]]|&[;&[;Value]]|
669 表の行の最初のカラムに「row:」を書くと,このカラムは行オプション指定になる。行オプション指定のカラムは,表には出力されず,この後のカラムが表のカラムとなる。
670 行オプションで指定できる属性はセルオプションと同じものである。
673 |header:名前|class=big:東武|
676 |table:w=100%:行オプション,セルオプション|t:w=20%|c:w=10%|t:|
678 |'''id='''''ID''||id属性。|
679 |'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
680 //|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
681 |'''onclick='''''Link''||onclick属性。Javascriptリンク。|
682 |'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
683 |'''onblur='''''Link''||onblur属性。Javascriptリンク。|
684 |'''onchange='''''Link''||onchange属性。Javascriptリンク。|
685 |'''width='''''Size''|'''w='''|width属性。単位はpx, pt, in, mm, cm, em, ex。または%。|
686 |'''height='''''Size''|'''h='''|height属性。単位はpx, pt, in, mm, cm, em, ex。または%。|
687 |'''bgcolor='''''Color''|'''bg='''|bgcolor属性。|
688 |'''header'''|'''h'''|thタグを出力する。|
689 |'''left'''|'''l'''|align="left"属性。|
690 |'''right'''|'''r'''|align="right"属性。|
691 |'''center'''|'''c'''|align="center"属性。|
692 |'''top'''|'''t'''|valign="top"属性。|
693 |'''middle'''|'''m'''|valign="middle"属性。|
694 |'''bottom'''|'''b'''|valign="bottom"属性。|
695 |'''nowrap'''|'''nw'''|nowrap属性。|
696 |'''*'''||オプションのクリア。|
700 |&<;''text''|左のセルと内容が一致するとき,結合する。|
701 |&<;^''text''|左のセルと内容が一致し,左のセルが上のセルと結合しているとき,結合する。|
703 |&^;''text''|上のセルと内容が一致するとき,結合する。|
704 |&^;<''text''|上のセルと内容が一致し,上のセルが左のセルと結合しているとき,結合する。|
707 行末に「&」を指定すると,次のテーブル記述を1行として継続する。数値指定を付加し「!''NUM''&」と指定するとカラム数が''NUM''に達したところで継続をやめる。
710 void WikiBlockTable::TableCell::cellBody (WikiMotorObjVec* vtext, WikiBlockTable* table, int idx) {
714 if (vtext->size () > 0 && (*vtext)[0].get ()->type == WikiMotorObj::wiki_text) {
715 WikiMotorObjText* w = WikiMotorObjText_type ((*vtext)[0].get ());
716 uiterator b = w->text.begin ();
717 uiterator e = w->text.end ();
719 if (b < e && *b == '<') {
722 if (b < e && *b == '^') {
726 } else if (b < e && *b == '^') {
729 if (b < e && *b == '<') {
734 (*vtext)[0].reset (new WikiMotorObjText (b, e));
737 html = vtext->htmlOut (table->wiki);
739 if (! spanmatch || table->ary.size () <= 1 || table->ary[table->ary.size () - 2][idx].colspan == 0) {
740 col = &table->ary.back ();
741 for (i = idx - 1; i >= 0; i --) {
742 if ((*col)[i].colspan > 0) {
743 if (html.length () == 0 || (*col)[i].html == html) {
745 (*col)[i].colspan ++;
753 if (! spanmatch || idx == 0 || table->ary.back ()[idx - 1].rowspan == 0) {
754 for (i = table->ary.size () - 2; i >= 0; i --) {
755 col = &table->ary[i];
756 if (idx < col->size () && (*col)[idx].rowspan > 0) {
757 if (html.length () == 0 || (*col)[idx].html == html) {
759 (*col)[idx].rowspan ++;
768 void WikiBlockTable::TableCell::outputTD (WikiFormat* wiki, MotorOutput* out, bool fturn) {
771 if (cellattrib.fheader)
772 out->out_raw (CharConst ("<th"));
774 out->out_raw (CharConst ("<td"));
775 cellattrib.output (out);
778 wiki->outputName (out, CharConst ("rowspan"), colspan, false);
780 wiki->outputName (out, CharConst ("colspan"), rowspan, false);
783 wiki->outputName (out, CharConst ("colspan"), colspan, false);
785 wiki->outputName (out, CharConst ("rowspan"), rowspan, false);
787 out->out_raw (CharConst (">"));
790 void WikiBlockTable::TableCell::outputTDe (MotorOutput* out) {
791 if (cellattrib.fheader)
792 out->out_raw (CharConst ("</th>\n"));
794 out->out_raw (CharConst ("</td>\n"));
797 /* ============================================================ */
798 bool WikiBlockTable::nextLine (uiterator b, uiterator e) {
799 if (*b == kWikiTABLE) {
807 void WikiBlockTable::addLine (uiterator b, uiterator e) {
808 assert (b[0] == '|');
810 if (n == 0 && matchSkip (b, e, CharConst ("table:"))) {
818 WikiBlock::closeType WikiBlockTable::closeLine (uiterator b, uiterator e) {
819 #ifdef WIKITABLECOMPATFLAG
820 static uregex re ("^\\}\\}(($)|(\\|)|((!([1-9][0-9]*))?(\\\\|&)$))");
822 static uregex re ("^\\}\\}(($)|(\\|)|((!([1-9][0-9]*))?(&)$))");
826 if (usearch (b, e, m, re)) {
827 if (m[2].matched) { // }}
830 } else if (m[3].matched) { // }}|...
832 if (wiki->cur && wiki->cur->type == BlockTable) {
833 WikiBlockTable* obj = (WikiBlockTable*)wiki->cur;
835 addLine_body (m[3].second, e);
840 } else if (m[4].matched) { // }}\ .
842 if (wiki->cur && wiki->cur->type == BlockTable) {
843 WikiBlockTable* obj = (WikiBlockTable*)wiki->cur;
845 addLine_body (m[4].first, e);
855 void WikiBlockTable::output (MotorOutput* out) {
857 outputTableTag (out);
859 out->out_raw (CharConst ("</table>\n"));
862 void WikiBlockTable::addLine_head (uiterator b, uiterator e) {
863 WikiMotor motor (b, e, wiki);
864 WikiMotorObjVec objv;
865 WikiMotorObjVecVec objvv;
869 motor.compile (objv);
870 objv.splitCharA ('|', objvv);
871 if (objvv.size () > 0 && objvv.back ()->size () == 0)
873 if (objvv.size () > 0)
874 attrib.shiftAttrib (objvv[0]);
876 cell = new TableCell (wiki, WikiAttrib1::M_NORMAL);
877 if (objvv.size () > 0)
878 cell->cellBody (objvv[0].get (), this, 0);
879 captionHtml = cell->html;
882 for (i = 1; i < objvv.size (); i ++) {
883 cell = new TableCell (wiki, WikiAttrib1::M_ATTRIB);
884 cell->cellattrib.shiftAttrib (objvv[i]);
885 defaultList.push_back (cell);
889 void WikiBlockTable::addLine_body (uiterator b, uiterator e) {
891 bool fmorecell = false;
893 #ifdef WIKITABLECOMPATFLAG
894 static uregex re ("(!([1-9][0-9]*))?(\\\\|&)$");
896 static uregex re ("(!([1-9][0-9]*))?(&)$");
903 cols = new CellList_t (wiki);
904 ary.push_back (cols);
907 if (usearch (b, e, m, re)) { //
909 if (m[2].matched) { // ...!NUM\ .
910 int v = strtoul (m[2].first);
921 if (b < e && e[-1] == '|') { // ...|\ .
929 WikiMotor motor (b, e, wiki);
930 WikiMotorObjVec objv;
931 WikiMotorObjVecVec objvv;
935 static const ustring brabra (CharConst ("{{"));
937 motor.compile (objv);
938 objv.splitCharA ('|', objvv);
939 if (objvv.size () > 0 && objvv.back ()->size () == 0) {
945 n = objvv.size () - 1;
947 if (i <= n && cols->size () == 0
948 && objvv[i]->matchHead (CharConst ("row:"))) {
949 cols->rowattrib.skipAttrib (objvv[i]);
950 cols->rowattrib.shiftAttrib (objvv[i]);
953 for (; i <= n; i ++) {
955 cell = newCell (cols->rowattrib);
957 cell = newCell (cols->size ());
958 if (! cell->cellattrib.shiftAttrib (objvv[i])) {
962 if (i == n && fop && objvv[i]->match (brabra)) {
963 cols->push_back (cell);
964 wiki->push_block (&cell->block);
967 cell->cellBody (objvv[i].get (), this, cols->size ());
968 cols->push_back (cell);
973 cell = newCell (cols->rowattrib);
975 cell = newCell (cols->size ());
976 cols->push_back (cell);
981 WikiBlockTable::TableCell* WikiBlockTable::newCell (int idx) {
982 TableCell* ans = new TableCell (wiki, WikiAttrib1::M_NORMAL);
984 if (idx < defaultList.size ())
985 ans->cellattrib.copyFrom (defaultList[idx].cellattrib);
989 WikiBlockTable::TableCell* WikiBlockTable::newCell (WikiAttribTable& rowattrib) {
990 TableCell* ans = new TableCell (wiki, WikiAttrib1::M_NORMAL);
992 ans->cellattrib.copyFrom (rowattrib);
996 void WikiBlockTable::normalize () {
1002 for (i = 0; i < ary.size (); i ++) {
1004 if (col->size () > maxcol)
1005 maxcol = col->size ();
1007 if (attrib.fpadding) {
1008 for (i = 0; i < ary.size (); i ++) {
1010 if (col->size () < maxcol) {
1012 cell = newCell (col->rowattrib);
1014 cell = newCell (col->size ());
1015 cell->colspan = maxcol - col->size ();
1016 col->push_back (cell);
1017 while (col->size () < maxcol) {
1019 cell = newCell (col->rowattrib);
1021 cell = newCell (col->size ());
1023 col->push_back (cell);
1028 for (i = 0; i < ary.size (); i ++) {
1030 for (j = col->size () - 1; j >= 0; j --) {
1032 if (cell->colspan > 0) {
1033 cell->colspan += maxcol - col->size ();
1034 while (col->size () < maxcol) {
1036 cell = newCell (col->rowattrib);
1038 cell = newCell (col->size ());
1040 col->push_back (cell);
1049 void WikiBlockTable::outputTableTag (MotorOutput* out) {
1052 #ifdef WIKITABLEATTRIB
1053 if (attrib.cellspacing < 0)
1054 attrib.cellspacing = 0;
1055 if (attrib.cellpadding < 0)
1056 attrib.cellpadding = 0;
1058 out->out_raw (CharConst ("<table"));
1059 attrib.output (out);
1060 out->out_raw (CharConst (">\n"));
1061 if (captionHtml.length () > 0) {
1062 out->out_raw (CharConst ("<caption>"))->out_toText (captionHtml)->out_raw (CharConst ("</caption>\n"));
1066 void WikiBlockTable::outputTBody (MotorOutput* out) {
1072 if (ary.size () > 0) {
1074 for (j = 0; j < n; j ++) {
1075 out->out_raw (CharConst ("<tr"));
1076 if (defaultList.size () > j) {
1077 defaultList[j].cellattrib.output (out);
1079 out->out_raw (CharConst (">\n"));
1080 for (i = 0; i < ary.size (); i ++) {
1083 outputTBodyCell (wiki, out, cell);
1085 out->out_raw (CharConst ("</tr>\n"));
1089 for (i = 0; i < ary.size (); i ++) {
1091 out->out_raw (CharConst ("<tr"));
1092 col->rowattrib.output (out);
1093 out->out_raw (CharConst (">\n"));
1094 for (j = 0; j < col->size (); j ++) {
1096 outputTBodyCell (wiki, out, cell);
1098 out->out_raw (CharConst ("</tr>\n"));
1103 void WikiBlockTable::outputTBodyCell (WikiFormat* wiki, MotorOutput* out, TableCell* cell) {
1104 if (cell->colspan > 0 && cell->rowspan > 0) {
1105 cell->outputTD (wiki, out, attrib.fturn);
1106 if (cell->block.size () > 0) {
1107 if (cell->block.size () == 1 && cell->block[0].type == BlockParagraph) {
1108 WikiBlockParagraph* b = WikiBlockParagraph_type (&cell->block[0]);
1110 b->singleTag = true;
1113 wiki->output (cell->block);
1115 if (cell->html.size () > 0) {
1116 out->out_toText (cell->html);
1118 if (! attrib.fnowhite)
1119 out->out_raw (uNbsp);
1122 cell->outputTDe (out);
1126 /* ============================================================ */
1129 |select:NAME:function:default:size=NUM:multiple|
1131 |LABEL|VALUE|selected|
1134 |table:w=100%|t:w=20%|c:w=10%|t:|
1135 |h:オプション|h:省略形|h:説明|
1136 |'''id='''''ID''||id属性。|
1137 |'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
1138 //|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
1139 |'''onclick='''''Link''||onclick属性。Javascriptリンク。|
1140 |'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
1141 |'''onblur='''''Link''||onblur属性。Javascriptリンク。|
1142 |'''onchange='''''Link''||onchange属性。Javascriptリンク。|
1143 |'''size='''''Integer''||size属性。|
1144 |'''multiple'''||multiple属性。|
1147 bool WikiBlockSelect::nextLine (uiterator b, uiterator e) {
1148 if (*b == kWikiTABLE) {
1157 void WikiBlockSelect::addLine (uiterator b, uiterator e) {
1158 assert (b[0] == '|');
1160 if (n == 0 && matchSkip (b, e, CharConst ("select:"))) {
1161 addLine_head (b, e);
1163 addLine_body (b, e);
1168 void WikiBlockSelect::addLine_head (uiterator b, uiterator e) {
1169 WikiMotor motor (b, e, wiki);
1170 WikiMotorObjVec objv;
1171 WikiMotorObjVecVec objvv;
1172 WikiMotorObjVec* vcell;
1175 motor.compile (objv);
1176 objv.splitCharA ('|', objvv);
1177 if (objvv.size () > 0 && objvv.back ()->size () == 0)
1179 if (objvv.size () > 0)
1180 attrib.shiftName (objvv[0], name);
1181 if (objvv.size () > 0) {
1182 attrib.shiftAttrib (objvv[0]);
1184 if (attrib.fmultiple && attrib.elsize == 0) {
1189 void WikiBlockSelect::addLine_body (uiterator b, uiterator e) {
1190 WikiMotor motor (b, e, wiki);
1191 WikiMotorObjVec objv;
1192 WikiMotorObjVecVec objvv;
1195 motor.compile (objv);
1196 objv.splitCharA ('|', objvv);
1197 if (objvv.size () > 0 && objvv.back ()->size () == 0)
1199 if (objvv.size () > 0) {
1200 v.label = omitCtrl (objvv[0].get ()->textOut (wiki));
1204 if (objvv.size () > 1) {
1205 v.value = omitCtrl (objvv[1].get ()->textOut (wiki));
1212 if (objvv.size () > 2) {
1213 if (objvv[2].get ()->match (CharConst ("selected"), CharConst ("sel"))) {
1220 void WikiBlockSelect::close () {
1223 assert (wiki->cur->type == BlockParagraph);
1225 MotorOutputString out;
1227 wiki->cur->addHtml (out.ans);
1231 void WikiBlockSelect::output (MotorOutput* out) {
1235 if (attrib.elsize == 1)
1236 attrib.elsize = item.size ();
1237 out->out_raw (CharConst ("<select"));
1238 wiki->outputName (out, CharConst ("name"), name, false);
1239 attrib.output (out);
1240 if (attrib.script.length () > 0)
1241 wiki->outputName (out, CharConst ("onChange"), attrib.script);
1242 out->out_raw (CharConst (">\n"));
1244 if (attrib.fdefault)
1245 u = wiki->getVar (name);
1247 std::cerr << "u:" << u << uLF;
1250 for (i = 0; i < item.size (); i ++) {
1251 SelectItem* v = &item[i];
1252 out->out_raw (CharConst ("<option"));
1254 wiki->outputName (out, CharConst ("value"), v->value, false);
1255 if (v->fselect || (attrib.fdefault && u == v->value))
1256 out->out_raw (CharConst (" selected=\"selected\""));
1258 if (v->fselect || (attrib.fdefault && u == v->label))
1259 out->out_raw (CharConst (" selected=\"selected\""));
1261 out->out_raw (CharConst (">"));
1262 out->out_toHTML (v->label)->out_raw (CharConst ("</option>\n"));
1264 out->out_raw (CharConst ("</select>\n"));
1267 /* ============================================================ */
1275 bool WikiBlockQuote::nextLine (uiterator b, uiterator e) {
1279 WikiBlock::closeType WikiBlockQuote::closeLine (uiterator b, uiterator e) {
1280 if (e - b == 1 && *b == kWikiQUOTE_e) {
1289 void WikiBlockQuote::addLine (uiterator b, uiterator e) {
1293 void WikiBlockQuote::output (MotorOutput* out) {
1294 out->out_raw (CharConst ("<blockquote>\n"));
1296 out->out_raw (CharConst ("</blockquote>\n"));
1299 /* ============================================================ */
1305 {div:id=''ID'':''ClassName'':onclick=''LinkFunction''
1310 |table:w=100%|t:w=20%|c:w=10%|t:|
1311 |h:オプション|h:省略形|h:説明|
1312 |'''id='''''ID''||id属性。|
1313 |'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
1314 //|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
1315 |'''onclick='''''Link''||onclick属性。Javascriptリンク。|
1316 |'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
1317 |'''onblur='''''Link''||onblur属性。Javascriptリンク。|
1318 |'''onchange='''''Link''||onchange属性。Javascriptリンク。|
1319 |'''ClassList'''||class=は省略できる。|
1322 bool WikiBlockDiv::nextLine (uiterator b, uiterator e) {
1326 void WikiBlockDiv::addLine (uiterator b, uiterator e) {
1327 // bool rc = matchSkip (b, e, CharConst ("{div:"));
1328 bool rc = matchSkip (b, e, CharConst (uWikiDIV));
1330 WikiMotor motor (b, e, wiki);
1331 WikiMotorObjVecPtr vec (new WikiMotorObjVec);
1333 motor.compile (*vec);
1334 attrib.shiftAttrib (vec);
1337 WikiBlock::closeType WikiBlockDiv::closeLine (uiterator b, uiterator e) {
1338 if (e - b == 1 && *b == kWikiDIV_e) {
1347 void WikiBlockDiv::output (MotorOutput* out) {
1350 if (block.size () == 1 && block[0].type == BlockParagraph) {
1351 WikiBlockParagraph* b = WikiBlockParagraph_type (&block[0]);
1353 b->singleTag = true;
1357 out->out_raw (CharConst ("<div"));
1358 attrib.output (out);
1360 out->out_raw (CharConst (">"));
1362 out->out_raw (CharConst (">\n"));
1364 out->out_raw (CharConst ("</div>\n"));
1367 /* ============================================================ */
1373 // {form:POST:id=form1:class=formclass:post.hml
1374 // {form:POST:post.hml:id=form1:class=formclass
1375 {form:POST:''URL'':target=''TargetWindow'':id=''ID'':class=''ClassName''
1380 |table:w=100%|t:w=20%|c:w=10%|t:|
1381 |h:オプション|h:省略形|h:説明|
1382 |'''id='''''ID''||id属性。|
1383 |'''class='''''ClassList''||class属性。複数のクラスを指定する場合はコンマ区切りで連ねる。|
1384 //|'''data-'''''name'''''='''''ID''||Bootstrap用属性。|
1385 |'''onclick='''''Link''||onclick属性。Javascriptリンク。|
1386 |'''onfocus='''''Link''||onfocus属性。Javascriptリンク。|
1387 |'''onblur='''''Link''||onblur属性。Javascriptリンク。|
1388 |'''onchange='''''Link''||onchange属性。Javascriptリンク。|
1389 |'''target='''''Window''||target属性。|
1392 bool WikiBlockForm::nextLine (uiterator b, uiterator e) {
1396 void WikiBlockForm::addLine (uiterator b, uiterator e) {
1397 // bool rc = matchSkip (b, e, CharConst ("{form:"));
1398 bool rc = matchSkip (b, e, CharConst (uWikiFORM));
1400 WikiMotor motor (b, e, wiki);
1401 WikiMotorObjVecPtr vec (new WikiMotorObjVec);
1403 WikiMotorObjVecPtr v2 (new WikiMotorObjVec);
1405 motor.compile (*vec);
1406 vec->splitChar_keyword (':', key, *v2);
1407 if (match (key, CharConst ("get"), CharConst ("GET"))) {
1410 } else if (match (key, CharConst ("post"), CharConst ("POST"))) {
1414 if (vec->size () > 0) {
1415 attrib.shiftLink (vec, url, fscript);
1417 attrib.shiftAttrib (vec);
1420 WikiBlock::closeType WikiBlockForm::closeLine (uiterator b, uiterator e) {
1421 if (e - b == 1 && *b == kWikiDIV_e) {
1424 wiki->curform = NULL;
1431 void WikiBlockForm::output (MotorOutput* out) {
1432 out->out_raw (CharConst ("<form"));
1435 out->out_raw (CharConst (" method=\"get\""));
1439 out->out_raw (CharConst (" method=\"post\""));
1445 wiki->outputName (out, CharConst ("action"), ustring (CharConst ("#")), false);
1446 wiki->outputSubmitScript (out, CharConst ("onsubmit"), url, true);
1448 wiki->outputName (out, CharConst ("action"), url, false);
1451 out->out_raw (CharConst (" enctype=\"multipart/form-data\""));
1452 attrib.output (out);
1453 out->out_raw (CharConst (">\n"));
1455 out->out_raw (CharConst ("</form>\n"));
1458 /* ============================================================ */
1468 bool WikiBlockElement::nextLine (uiterator b, uiterator e) {
1472 void WikiBlockElement::addLine (uiterator b, uiterator e) {
1473 bool rc = matchSkip (b, e, CharConst (uWikiELEMENT));
1475 WikiMotor motor (b, e, wiki);
1476 WikiMotorObjVecPtr vec (new WikiMotorObjVec);
1477 WikiMotorObjVecPtr v2 (new WikiMotorObjVec);
1479 motor.compile (*vec);
1480 vec->splitChar_keyword (':', name, *v2);
1481 if (name.size () == 0) {
1482 wiki->errorMsg.append (CharConst ("missing name in the element block."));
1484 if (v2->size () > 0) {
1485 wiki->errorMsg.append (v2->dump ()).append (CharConst (": bad attribute.\n"));
1487 if (name.size () > 0) {
1488 wiki->elementMap.put (name, this);
1492 WikiBlock::closeType WikiBlockElement::closeLine (uiterator b, uiterator e) {
1493 if (e - b == 1 && *b == kWikiDIV_e) {
1502 void WikiBlockElement::output (MotorOutput* out) {
1503 //*** outputBlock (out);
1506 /* ============================================================ */
1512 bool WikiBlockHR::nextLine (uiterator b, uiterator e) {
1516 void WikiBlockHR::addLine (uiterator b, uiterator e) {
1520 void WikiBlockHR::output (MotorOutput* out) {
1521 out->out_raw (CharConst (uHR));
1524 /* ============================================================ */
1525 bool WikiBlockRaw::nextLine (uiterator b, uiterator e) {
1529 void WikiBlockRaw::addLine (uiterator b, uiterator e) {
1533 void WikiBlockRaw::output (MotorOutput* out) {
1534 out->out_toText (text);
1537 /* ============================================================ */
1538 void WikiFormat::pass1 (const ustring& text, WikiLine::linevec* block, bool fsuper) {
1539 SplitterNL sp (text);
1541 pass1_1 (sp, NULL, NULL, block, NULL, NULL, NULL, fsuper);
1544 static bool findCmdSep (uiterator& b, uiterator e, uiterator& u) {
1547 for (; p < e; ++ p) {
1553 } else if (c == ' ' || c == '\t') {
1558 } while (u < e && ((c = *u) == ' ' || c == '\t'));
1567 int WikiFormat::pass1_1 (Splitter& sp, ustring* elseword, ustring* endword, WikiLine::linevec* block, uiterator* elsebegin0, uiterator* elsebegin, uiterator* elseend, bool fsuper) {
1568 uiterator b, e, t, u, v;
1570 // static uregex re_wikicmdsep ("(:)|([ \t]+$)");
1572 while (sp.next ()) {
1575 while (b < e && b[0] == '\t') // TABを無視
1577 if (matchSkip (b, e, CharConst (kComment))) {
1579 } else if (b != e && b[0] == kWikiCmd) {
1580 // if (usearch (b, e, m, re_wikicmdsep)) {
1586 if (findCmdSep (u, e, v)) {
1592 if (endword && match (t, u, *endword)) {
1593 return 2; // endword
1594 } else if (elseword && match (t, u, *elseword)) {
1601 return 1; // elseword
1602 } else if (pass1_2 (sp, b, e, t, u, v, block, fsuper)) {
1605 block->push_back (wl = new WikiLine (b, e, fsuper));
1606 wl->fn = wc_call_defun;
1609 block->push_back (new WikiLine (b, e, fsuper));
1612 return 0; // end of line
1615 bool WikiFormat::pass1_2 (Splitter& sp, uiterator& b, uiterator& e, uiterator& t, uiterator& u, uiterator& v, WikiLine::linevec* block, bool fsuper) {
1616 WikiCmdTable::iterator it;
1617 ustring elseword, endword;
1622 if ((it = GWikiCmdTable.find (ustring (t, u))) != GWikiCmdTable.end ()) {
1623 block->push_back (wl = new WikiLine (b, v, e, fsuper));
1624 wl->fn = it->second->fn;
1625 if (it->second->endname) {
1626 endword.assign (it->second->endname, it->second->endnamelen);
1627 if (it->second->elsename) {
1628 elseword.assign (it->second->elsename, it->second->elsenamelen);
1629 // if-then-else block
1630 wl->block = new WikiLine::linevec;
1631 rc = pass1_1 (sp, &elseword, &endword, wl->block, &b, &v, &e, fsuper);
1635 if (endword.length () > 0) {
1636 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1641 wl2 = new WikiLine (b, v, e, fsuper);
1645 wl->block = new WikiLine::linevec;
1646 rc = pass1_1 (sp, &elseword, &endword, wl->block, &b, &v, &e, fsuper);
1649 if (endword.length () > 0) {
1650 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1652 } else if (rc == 2) {
1653 assert (wl->block2 == NULL);
1654 wl->block2 = new WikiLine (sp.begin (), sp.end (), false);
1659 assert (wl->block2 == NULL);
1660 wl->block2 = new WikiLine (sp.begin (), sp.end (), false);
1667 wl->block = new WikiLine::linevec;
1668 rc = pass1_1 (sp, NULL, &endword, wl->block, NULL, NULL, NULL, fsuper);
1670 // no end line error
1671 if (endword.length () > 0) {
1672 errorMsg.append (CharConst ("no matcing \"")).append (endword).append (CharConst ("\".\n"));
1674 } else if (rc == 2) {
1675 assert (wl->block2 == NULL);
1676 wl->block2 = new WikiLine (sp.begin (), sp.end (), false);
1689 static void dump (WikiLine::linevec* block, int indent = 0) {
1692 for (j = 0; j < indent; j ++) std::cerr << " ";
1693 std::cerr << "(NULL)\n";
1696 for (i = 0; i < block->size (); i ++) {
1697 WikiLine* wl = &(*block)[i];
1698 for (j = 0; j < indent; j ++) std::cerr << " ";
1700 std::cerr << (void*)wl->fn << ":";
1701 std::cerr << ustring (wl->begin, wl->end) << uLF;
1704 dump (wl->block, indent + 1);
1708 for (j = 0; j < indent; j ++) std::cerr << " ";
1709 std::cerr << "else:" << (void*)wl->fn << ":" << ustring (wl->begin, wl->end) << uLF;
1710 // dump (wl->block, indent + 1);
1719 void WikiFormat::compile (const ustring& text, bool fsuper) {
1721 WikiLine::linevec block;
1722 pass1 (text, &block, fsuper);
1728 WikiLineScanner scanner (&block);
1729 compileLines (scanner);
1734 if (bstack.size () > 0)
1741 } catch (ustring& msg) {
1742 logLispFunctionError (msg, uEmpty);
1746 void WikiFormat::outputElement (const ustring& elementName) {
1747 WikiBlockElement* b;
1749 b = elementMap.get (elementName);
1755 void WikiFormat::output (boost::ptr_vector<WikiBlock>& ary) {
1758 for (i = 0; i < ary.size (); i ++) {
1759 ary[i].output (env->output);
1764 void WikiFormat::errorOutput () {
1765 if (errorMsg.size () > 0) {
1766 env->output->out_raw (CharConst (uP));
1767 env->output->out_toHTML_br (errorMsg);
1768 env->output->out_raw (CharConst (uPe));
1769 errorMsg.resize (0);
1773 bool WikiFormat::checkClose (uiterator b, uiterator e) {
1774 int n = bstack.size ();
1775 WikiBlock::closeType rc;
1779 rc = bstack[n]->closeLine (b, e);
1781 case WikiBlock::CloseTrue:
1783 case WikiBlock::CloseFalse:
1791 void WikiFormat::compileLine (WikiLineScanner& scanner) {
1792 WikiLine* wl = scanner.cur ();
1796 uiterator b = wl->begin;
1797 uiterator e = wl->end;
1802 if (b == e) { // empty line
1807 } else if (matchSkip (b, e, CharConst ("//"))) { // comment
1808 } else if (checkClose (b, e)) {
1809 } else if (cur && cur->nextLine (b, e)) {
1810 } else if (b[0] == kWikiP) { // ^
1813 cur = new WikiBlockParagraph (this);
1814 blockp->push_back (cur);
1815 cur->addLine (b, e);
1816 } else if (b[0] == kWikiH) { // =
1820 cur = obj = new WikiBlockH (this);
1821 blockp->push_back (cur);
1822 cur->addLine (b, e);
1823 if (obj->checkEmpty ()) {
1827 push_block (&obj->block);
1829 } else if (b[0] == kWikiPRE // SPC
1830 || b[0] == kWikiPRE2) { // TAB
1833 cur = new WikiBlockPreformatRaw (this);
1834 blockp->push_back (cur);
1835 cur->addLine (b, e);
1836 } else if (b[0] == kWikiUL) { // *
1840 cur = obj = new WikiBlockItem (WikiBlock::BlockItemUL, this);
1841 blockp->push_back (cur);
1842 obj->addLine (b, e);
1843 } else if (b[0] == kWikiOL) { // #
1847 cur = obj = new WikiBlockItem (WikiBlock::BlockItemOL, this);
1848 blockp->push_back (cur);
1849 obj->addLine (b, e);
1850 } else if (b[0] == kWikiNL) { // +
1854 cur = obj = new WikiBlockItem (WikiBlock::BlockItemNL, this);
1855 blockp->push_back (cur);
1856 obj->addLine (b, e);
1857 } else if (b[0] == kWikiDL) { // ;
1860 cur = new WikiBlockItemDL (this);
1861 blockp->push_back (cur);
1862 cur->addLine (b, e);
1863 } else if (matchHead (b, e, CharConst ("|select:"))) { // |select:
1864 if (cur && cur->type == WikiBlock::BlockParagraph) {
1868 cur = new WikiBlockParagraph (this);
1869 blockp->push_back (cur);
1871 push_block (blockp);
1872 cur = new WikiBlockSelect (this);
1873 cur->addLine (b, e);
1874 } else if (b[0] == kWikiTABLE) { // |
1875 WikiBlockTable* obj;
1878 cur = obj = new WikiBlockTable (this);
1879 blockp->push_back (cur);
1880 cur->addLine (b, e);
1881 } else if (b[0] == kWikiQUOTE && e - b == 1) { // >
1882 WikiBlockQuote* obj;
1885 cur = obj = new WikiBlockQuote (this);
1886 blockp->push_back (cur);
1887 push_block (&obj->block);
1888 // } else if (matchHead (b, e, CharConst ("{div:"))) {
1889 } else if (matchHead (b, e, CharConst (uWikiDIV))) {
1890 WikiBlockComplex* obj;
1893 cur = obj = new WikiBlockDiv (this);
1894 blockp->push_back (cur);
1895 cur->addLine (b, e);
1896 push_block (&obj->block);
1897 } else if (curform == NULL && matchHead (b, e, CharConst (uWikiFORM))) {
1898 WikiBlockComplex* obj;
1901 cur = obj = curform = new WikiBlockForm (this);
1902 blockp->push_back (cur);
1903 cur->addLine (b, e);
1904 push_block (&obj->block);
1905 } else if (curform == NULL && matchHead (b, e, CharConst (uWikiELEMENT))) {
1906 WikiBlockComplex* obj;
1909 cur = obj = new WikiBlockElement (this);
1910 blockp->push_back (cur);
1911 cur->addLine (b, e);
1912 push_block (&obj->block);
1913 } else if (matchHead (b, e, CharConst ("----"))) { // ----
1916 cur = new WikiBlockHR (this);
1917 blockp->push_back (cur);
1918 cur->addLine (b, e);
1921 if (cur && cur->type != WikiBlock::BlockParagraph) {
1926 cur = new WikiBlockParagraph (this);
1927 blockp->push_back (cur);
1929 cur->addLine (b, e);
1934 void WikiFormat::compileLines (WikiLineScanner& scanner, bool (*fn)(WikiLine& spp, WikiLineScanner& scanner, WikiFormat* wiki, void* par), void* par) {
1937 while ((wl = scanner.next ())) {
1938 if (fn && fn (*scanner.cur (), scanner, this, par)) {
1941 compileLine (scanner);
1946 void WikiFormat::pushBlockRaw (uiterator b, uiterator e) {
1949 obj = new WikiBlockRaw (this);
1950 blockp->push_back (obj);
1951 obj->addLine (b, e);
1954 int WikiFormat::countWikiH (uiterator& b, uiterator e) {
1957 while (b != e && *b == kWikiH) {
1966 void WikiFormat::outputName (MotorOutput* out, const char* name, size_t len, const ustring& val, bool cond) {
1967 if (! cond || val.length () > 0)
1969 ->out_raw (name, len)
1970 ->out_raw (CharConst ("=\""))
1971 ->out_toHTML_noCtrl (val)
1975 void WikiFormat::outputName (MotorOutput* out, const char* name, size_t len, long val, bool cond) {
1976 if (! cond || val > 0)
1978 ->out_raw (name, len)
1979 ->out_raw (CharConst ("=\""))
1980 ->out_raw (to_ustring (val))
1984 void WikiFormat::outputFlag (MotorOutput* out, const char* name, size_t len, bool flag) {
1987 ->out_raw (name, len)
1988 ->out_raw (CharConst ("=\""))
1989 ->out_raw (name, len)
1993 void WikiFormat::outputID (MotorOutput* out, const ustring& id) {
1994 if (id.length () > 0)
1995 out->out_raw (CharConst (" id=\""))
1996 ->out_toHTML_noCtrl (id)
2000 void WikiFormat::outputClass (MotorOutput* out, std::vector<ustring>& classes) {
2001 if (classes.size () > 0) {
2002 out->out_raw (CharConst (" class=\""));
2003 for (int i = 0; i < classes.size (); i ++) {
2005 out->out_raw (uSPC);
2006 out->out_toHTML_noCtrl (classes[i]);
2012 void WikiFormat::outputSubmitScript (MotorOutput* out, const char* name, size_t len, const ustring& onclick, bool scriptcut) {
2013 if (onclick.length () > 0) {
2015 ->out_raw (name, len)
2016 ->out_raw (CharConst ("=\""))
2017 ->out_toHTML_noCtrl (onclick);
2019 out->out_raw (CharConst ("return false;\""));
2021 out->out_raw (CharConst ("\""));
2025 void WikiFormat::outputNum (MotorOutput* out, const char* name, size_t len, int val) {
2027 ->out_raw (name, len)
2028 ->out_raw (CharConst ("="))
2029 ->out_raw (to_ustring (val));
2032 MNode* WikiFormat::arrayToTexp (const ustring& name) {
2036 n = mlenv->getArySize (name);
2037 for (i = 1; i <= n; i ++) {
2038 e.append (mlenv->getAry (name, i));
2043 MNode* WikiFormat::evalVar (const ustring& name) {
2047 if (checkAry (name, sym)) {
2048 return arrayToTexp (sym);
2050 return mlenv->getVar (name);
2054 void WikiFormat::wikiMotor (uiterator b, uiterator e, WikiMotorObjVec& ans) {
2055 WikiMotor motor (b, e, this);
2056 AutoInclCount autoIncl (env->mlenv);
2058 if (! autoIncl.inc_test ())
2059 throw (uErrorInclNest);
2060 motor.compile (ans, WikiMotor::TMATCH_NONE);
2063 ustring WikiFormat::wikiMotor (uiterator b, uiterator e) {
2064 WikiMotorObjVec objv;
2066 wikiMotor (b, e, objv);
2067 return objv.htmlOut (this);
2070 void WikiFormat::wikiMotorInline (uiterator b, uiterator e, WikiMotorObjVec& ans) {
2071 WikiMotorObjVec objv;
2072 WikiMotor motor (b, e, this);
2074 motor.compile (objv, WikiMotor::TMATCH_NONE);
2075 objv.eval (ans, this);
2078 //MNode* WikiFormat::buildArgs (WikiMotorObjVecVec::const_iterator b, WikiMotorObjVecVec::const_iterator e, bool dumpmode) {
2079 MNode* WikiFormat::buildArgs (WikiMotorObjVecVec::const_iterator b, WikiMotorObjVecVec::const_iterator e) {
2083 // for (; b < e; b ++) {
2084 // ans.append (newMNode_str (new ustring ((*b)->dump ())));
2087 for (; b < e; b ++) {
2088 // ans.append (newMNode_str (new ustring ((*b)->textOut (this))));
2089 ans.append ((*b)->toMNode (this));
2093 return ans.release ();
2096 void WikiFormat::logLispFunctionError (const ustring& msg, const ustring& cmd) {
2097 if (cmd.length () > 0)
2098 errorMsg.append (cmd).append (CharConst (": "));
2099 errorMsg.append (CharConst ("lisp function error.\n"));
2100 if (mlenv->env->mlenv->currentCell ()) {
2101 if (mlenv->env->log)
2102 *mlenv->env->log << mlenv->env->mlenv->currentCell ()->dump_string_short () << ": ";
2103 *mlenv->env->log << msg << uLF;
2110 /* ============================================================ */