diff --git a/.gitattributes b/.gitattributes index c43dc1b497c7ac026f83f85064642ad3c6da9f0b..adde843db5e5d43a4096c8b8c44ed9d0b370bdf7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,7 @@ [attr]binary -text -crlf -diff -ident * text ident *.db binary +*.eps binary *.gif binary *.gz binary *.png binary diff --git a/tutorial/Makefile b/tutorial/Makefile index 3e5c8f05a3603febe5958047bb2c3d3e382d4bfc..466383b1502a008f586ed2dac6b6f9abfd1f5586 100644 --- a/tutorial/Makefile +++ b/tutorial/Makefile @@ -8,7 +8,8 @@ all: low_all: tutorial.html tutorial_onepage.html MADEFILES=Image.wmml Mysql.wmml ProtocolsLysKOM.wmml \ - ProtocolsHTTP.wmml Parser.wmml Calendar.wmml + ProtocolsHTTP.wmml Parser.wmml Calendar.wmml \ + SRCFILES=tutorial.wmml $(MADEFILES) pike=pike @@ -48,6 +49,13 @@ tutorial.html: .DUMMY $(SRCFILES) tutorial_onepage.html: .DUMMY $(SRCFILES) $(pike) ./wmmltohtml2 tutorial.wmml html_onepage tutorial_onepage +tutorial.tex: .DUMMY $(SRCFILES) + $(pike) ./wmmltohtml2 tutorial.wmml latex tutorial + +tutorial.dvi: tutorial.tex + -@rm tutorial.aux + latex tutorial.tex + tut.html: .DUMMY $(SRCFILES) $(pike) ./wmmltohtml2 tutorial.wmml sitebuilder tut @@ -64,7 +72,9 @@ the_image_module.html: Image.wmml the_image_module.wmml $(pike) ./wmmltohtml2 the_image_module.wmml mirar_html the_image_module clean: - -rm -f *.html *.md illustration_cache illustration*.gif $(MADEFILES) + -rm -f *.html *.md illustration_cache illustration*.gif $(MADEFILES) + -rm -f tutorial.dvi tutorial.tex tutorial.aux illustration*.eps + -rm -f tutorial.log rebuild: -rm -f $(MADEFILES) diff --git a/tutorial/Wmml.pmod b/tutorial/Wmml.pmod index ff1f6b313c95940d81a53c8172048d5900ead0ce..207d8e1e192a88e76ffa5c4974cd9caf0f061b4f 100644 --- a/tutorial/Wmml.pmod +++ b/tutorial/Wmml.pmod @@ -26,6 +26,10 @@ class Trace } + +// This function verifies SGML data +// FIXME: check for superflous tags in <table> +// FIXME: put a cap on the <section> depth static private int verify_any(SGML data, Trace in, string input, @@ -135,6 +139,18 @@ static private int verify_any(SGML data, break; + case "image": + if(!x->params->src && + !x->params->gif && + !x->params->xfig && + !x->params->jpeg && + !x->params->eps) + { + werror("Image without source near "+x->location()+"\n"); + werror(in->dump()); + i=0; + } + case "insert_added_appendices": case "ex_indent": case "ex_br": @@ -146,7 +162,7 @@ static private int verify_any(SGML data, case "hr": case "br": case "img": - case "image": + case "table-of-contents": case "index": if(x->data) @@ -175,6 +191,10 @@ int verify(SGML data, string input, string input_name) return verify_any(data,Trace(0,0), input, input_name); } + +// Generate an index +// Might not be required for all output formats +// INDEX_DATA collect_index(SGML data, void|INDEX_DATA index,void|mapping taken) { if(!index) index=([]); @@ -267,6 +287,8 @@ INDEX group_index_by_character(INDEX i) return m; } + +// Rerserver dowrds in Pike string * reserved_pike = ({ "array","break","case","catch","continue","default","do","else","float", @@ -276,6 +298,8 @@ string * reserved_pike = "varargs","void","while" }); + +// Reserved words in C string *reserved_c = ({ "break","case","continue","default","do","else","float","double", @@ -284,6 +308,9 @@ string *reserved_c = "void","while" }); + +// Parce C/C++/Pike/Java and highlight +// object(Tag) parse_pike_code(string x, int pos, mapping(string:string) reserved_type) @@ -409,6 +436,8 @@ object(Tag) parse_pike_code(string x, return Tag("example",([]),pos,ret); } +// All data that will be sent to the +// output generator. class Wmml { SGML metadata; @@ -417,6 +446,8 @@ class Wmml SGML data; }; +// Enumerators are used to give numbers to chapters, +// sections and appendixes class Enumerator { string *base; @@ -897,6 +928,8 @@ void save_image_cache(); int gifnum; mapping gifcache=([]); +mapping jpgcache=([]); +mapping epscache=([]); mapping srccache=([]); string mkgif(mixed o,void|object alpha) @@ -931,13 +964,42 @@ string mkgif(mixed o,void|object alpha) return gifname; } +string mkeps(mixed o,float dpi) +{ + string g=Image.PS.encode(o, (["dpi":dpi]) ); + + int key=hash(g); + + foreach(epscache[key]||({}),string file) + { + if(Stdio.read_file(file)==g) + { + werror("Cache hit in mkeps: "+file+"\n"); + return file; + } + } + + gifnum++; + string epsname="illustration"+gifnum+".eps"; + rm(epsname); + werror("Writing "+epsname+".\n"); + Stdio.write_file(epsname,g); + + if(epscache[key]) + epscache[key]+=({epsname}); + else + epscache[key]=({epsname}); + + return epsname; +} + string mkjpeg(mixed o,void|int quality) { string g=Image.JPEG.encode(o,(["quality":quality||100])); int key=hash(g); - foreach(gifcache[key]||({}),string file) + foreach(jpgcache[key]||({}),string file) { if(Stdio.read_file(file)==g) { @@ -952,25 +1014,28 @@ string mkjpeg(mixed o,void|int quality) werror("Writing "+gifname+".\n"); Stdio.write_file(gifname,g); - if(gifcache[key]) - gifcache[key]+=({gifname}); + if(jpgcache[key]) + jpgcache[key]+=({gifname}); else - gifcache[key]=({gifname}); + jpgcache[key]=({gifname}); return gifname; } - -object render_illustration(string pike_code, mapping params, float dpi) +// +// Execute a small pice of pike code to generate an illustration. +// +object render_illustration(string pike_code, mapping params, float wanted_dpi) { werror("Rendering "); if (params->__from__) werror("["+params->__from__+"] "); string src=params->src; object img=Image.image(); - if(params->dpi) dpi=(float)params->dpi; - if(params->scale) dpi/=(float)params->scale; - float scale=75.0/dpi; + float actual_dpi=75.0; + if(params->dpi) actual_dpi=(float)params->dpi; + if(params->scale) wanted_dpi*=(float)params->scale; + float scale=wanted_dpi/actual_dpi; if(params->src) img=srccache[params->src]|| @@ -1002,7 +1067,7 @@ string illustration_to_gif(TAG data, float dpi) { mapping params=data->params; string pike_code=data->data[0]; - string key=mkkey(params,pike_code,dpi); + string key=mkkey(params,pike_code,dpi,"gif"); string ret=illustration_cache[key]; if(!ret) @@ -1025,6 +1090,35 @@ string illustration_to_gif(TAG data, float dpi) return ret; } + +string illustration_to_eps(TAG data, float dpi) +{ + mapping params=data->params; + string pike_code=data->data[0]; + string key=mkkey(params,pike_code,dpi,"eps"); + + string ret=illustration_cache[key]; + if(!ret) + { + mixed err=catch + { + ret=mkeps(render_illustration(pike_code,params, dpi), dpi); + illustration_cache[key]=ret; + save_image_cache(); + }; + if (err) + { + werror("error while compiling and running\n"+pike_code+"\n"); + if (params->__from__) + werror("from "+params->__from__+":\n"); + werror(master()->describe_backtrace(err)+"\n"); + return "error.eps"; + } + } + return ret; + +} + array execute_contents(Tag tag) { string data=get_text(tag->data); @@ -1111,7 +1205,8 @@ array execute_contents(Tag tag) werror("from "+tag->params->__from__+"\n"); array dat=data/"\n"; - werror("%O\n",err[1]); +// master()->describe_error(err); +// werror("%O\n",err[1]); foreach (reverse(err[1]),array y) if (y[0]=="inline wmml generating code" && y[1]<10000) @@ -1131,6 +1226,7 @@ array execute_contents(Tag tag) } +// FIXME: handle EPS input string image_to_gif(TAG data, float dpi) { mapping params=data->params; @@ -1144,7 +1240,7 @@ string image_to_gif(TAG data, float dpi) if(params->xfig) params->src=params->xfig+".fig"; - string key=mkkey(params,dpi); + string key=mkkey(params,dpi,"gif"); string ret=illustration_cache[key]; if(!ret) @@ -1162,7 +1258,7 @@ string image_to_gif(TAG data, float dpi) werror("Converting "); Process.system("/bin/sh -c 'fig2dev -L ps "+params->src+" ___tmp.ps;echo showpage >>___tmp.ps'"); Process.system("/bin/sh -c 'gs -q -sDEVICE=pbmraw -r225 -g2500x2500 -sOutputFile=___tmp.ppm ___tmp.ps </dev/null >/dev/null'"); - object o=Image.PNM.decode(Stdio.read_file("___tmp.ppm"))->autocrop()->scale(1.0/3)->rotate(-90); + object o=Image.PNM.decode(Stdio.read_file("___tmp.ppm"))->autocrop()->scale(1.0/3); //->rotate(-90); o=Image.image(o->xsize()+40, o->ysize()+40, 255,255,255)->paste(o,20,20); rm("___tmp.ps"); rm("___tmp.ppm"); @@ -1180,6 +1276,54 @@ string image_to_gif(TAG data, float dpi) return ret; } +// FIXME: move all graphics stuff into a separate module +string image_to_eps(TAG data, float dpi) +{ + mapping params=data->params; + + if(params->eps) + return params->eps; + + if(params->jpeg) + params->src=params->jpeg; + + if(params->gif) + params->src=params->gif; + + if(params->xfig) + params->src=params->xfig+".fig"; + + string key=mkkey(params,dpi,"eps"); + + string ret=illustration_cache[key]; + if(!ret) + { + if(!params->src) + { + throw( ({"Image without source near "+data->location()+".\n", + backtrace() }) ); + } + string ext=reverse(params->src); + sscanf(ext,"%s.",ext); + switch(reverse(ext)) + { + case "fig": + werror("Converting "); + ret="illustration"+ (++gifnum) +".eps"; + Process.create_process( ({"fig2dev","-L","ps","-m","0.6666666666",params->src,ret }))->wait(); + break; + + default: + ret=mkeps(render_illustration("return src",params,dpi),dpi); + break; + } + + illustration_cache[key]=ret; + save_image_cache(); + } + return ret; +} + void save_image_cache() { rm("illustration_cache"); @@ -1187,6 +1331,8 @@ void save_image_cache() encode_value(([ "gifnum":gifnum, "gifcache":gifcache, + "jpgcache":gifcache, + "epscache":gifcache, "illustration_cache":illustration_cache, ]))); } @@ -1198,6 +1344,8 @@ void create() mixed x=decode_value(Stdio.read_file("illustration_cache")); gifnum=x->gifnum; gifcache=x->gifcache; + jpgcache=x->jpgcache; + epscache=x->epscache; illustration_cache=x->illustration_cache; } } diff --git a/tutorial/error.eps b/tutorial/error.eps new file mode 100644 index 0000000000000000000000000000000000000000..b3fe94ba72ee3956e65116b44ab6a29460faf17b --- /dev/null +++ b/tutorial/error.eps @@ -0,0 +1,98 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: error.eps +%%Creator: fig2dev Version 3.2 Patchlevel 1 +%%CreationDate: Sat Jul 3 14:40:34 1999 +%%For: hubbe@adenin.hubbe.net (Fredrik Hubinette) +%%Orientation: Portrait +%%BoundingBox: 0 0 99 33 +%%Pages: 0 +%%BeginSetup +%%EndSetup +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +-27.0 68.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def +%%EndProlog + +$F2psBegin +10 setmiterlimit +n -1000 2125 m -1000 -1000 l 3096 -1000 l 3096 2125 l cp clip + 0.06000 0.06000 sc +/Times-Roman ff 780.00 scf sf +450 1125 m +gs 1 -1 sc (Error) col4 sh gr +$F2psEnd +rs diff --git a/tutorial/error.fig b/tutorial/error.fig new file mode 100644 index 0000000000000000000000000000000000000000..ee04e535a52a22938122337a45f94b65d1976904 --- /dev/null +++ b/tutorial/error.fig @@ -0,0 +1,10 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +4 0 4 100 0 0 52 0.0000 4 540 1605 450 1125 Error\001 diff --git a/tutorial/html.pike b/tutorial/html.pike index 9aa633964a2c3a67d233177f3ebf7204586da08d..772c7c637e35bc8ca54af6319540e1cddd3df4c3 100644 --- a/tutorial/html.pike +++ b/tutorial/html.pike @@ -578,10 +578,11 @@ SGML convert(SGML data) break; case "ex_identifier": - case "ex_commend": + case "ex_comment": ret+=convert(data->data); continue; case "ex_string": + // FIXME: this doesn't work ret+=convert(replace(data->data," ","�")); continue; diff --git a/tutorial/latex.pike b/tutorial/latex.pike new file mode 100644 index 0000000000000000000000000000000000000000..a082b8c5ac58727f473f8eeac1e4bb712a805368 --- /dev/null +++ b/tutorial/latex.pike @@ -0,0 +1,526 @@ +#include "types.h" +#if __VERSION__ >= 0.6 +import "."; +#endif /* __VERSION__ >= 0.6 */ +inherit Stdio.File : out; + +object html=.html(); + +string low_latex_quote(string text) +{ + return replace( text, + ({"<",">", + "{","}", + "�","&", + "�","\\", + "[","]", + "#","%", + "$","~", + "^","_", + }), + ({"$<$","$>$", + "\\{","\\}", + "$\\mu$","\\&", + "\\verb+ +","$\\backslash$", + "\\verb+[+","\\verb+]+", + + "\\#","\\%", + "\\$","\\verb+~+", + "\\verb+^+","\\_", + }) ); +} + +string latex_quote(string text) +{ + return low_latex_quote( pre ? text : ((text/"\n") - ({""})) *"" ); +} + + +float weighted_strlen(string tag) +{ + return strlen(tag)+ + `+(0.0,@rows(([ + 'i':-0.3, + 'm': 0.2, + 'w': 0.2, + '@': 0.2, + ' ':-0.5, + '\n':-1.0, + ]), indices(tag))); +} + +float aproximate_length(SGML data) +{ + float len=0.0; + if(!data) return 0.0; + foreach(data, TAG tag) + { + if(stringp(tag)) + { + len+=weighted_strlen(tag); + }else{ + len+=aproximate_length(tag->data); + } + } + return len; +} + +string convert_table(TAG table) +{ + SGML data=table->data; + int rows,columns; + int border=(int)table->params->border; + array(float) column_data=allocate(100,1.0); + + foreach(data, TAG tag) + { + if(stringp(tag)) + { + string tmp=replace(tag,({" ","�","\t","\n"}),({"","","",""})); + if(strlen(tmp)) + { + werror("Warning: Skipping string %s inside table!\n",tag); + } + }else{ + if(tag->tag != "tr") + { + werror("Tag in table is not <tr>, it is %s! (near %s)\n",tag->tag,tag->location()); + continue; + } + + rows++; + int row_cells=0; + foreach(tag->data, TAG cell) + { + if(stringp(cell)) + { + string tmp=replace(cell,({" ","�","\t","\n"}),({"","","",""})); + if(strlen(tmp)) + { + werror("Warning: Skipping string %s inside table!\n",cell); + } + }else{ + switch(cell->tag) + { + default: + werror("Tag inside table row is not <td> or <th>, it is %s! (near %s)\n",cell->tag,cell->location()); + break; + + case "anchor": + // FIXME!!! Anchors should be moved outside of + // the table!! + break; + + case "th": + case "td": + column_data[row_cells]+=aproximate_length(cell->data); + row_cells++; + } + } + } + if(row_cells > columns) + columns=row_cells; + } + } + + column_data=column_data[..columns-1]; + for(int e=0;e<sizeof(column_data);e++) column_data[e]+=20.0*rows; + + float total_data=`+(@column_data); + + string fmt=(border ? "|" : "") + ("l"+(border ? "|" : ""))*columns; + + string ret="\n\n\\begin{longtable}{"+ fmt +"}\n"; + + if(border) ret+="\\hline \\\\\n"; + + foreach(data, TAG tag) + { + int c=0; + if(stringp(tag)) continue; + if(tag->tag != "tr") continue; + array(string) row=({}); + foreach(tag->data, TAG cell) + { + if(stringp(cell)) continue; + if(cell->tag != "td" && cell->tag!="th") continue; + row+=({ + "\\begin{minipage}{"+( column_data[c] / total_data ) +" \\linewidth}\n"+ + convert_to_latex(cell->data)+ + "\\end{minipage}" + }); + c++; + } + ret+=row*" & "+"\\\\\n"; + if(border) ret+="\\hline\n"; + } + + ret+="\\end{longtable}\n"; + + return ret; +} + +string convert_image_to_latex(TAG tag) +{ + mapping params=tag->params; + if(params->xfig) + params->src=params->xfig+".fig"; + + if(params->src && (params->src/".")[-1]=="fig") + { + rm("___tmp.latex"); + werror("Converting fig->latex"); + Process.create_process( ({ "fig2dev", "-L","latex",params->src,"___tmp.latex" }) )->wait(); + string ret=Stdio.read_file("___tmp.latex"); + rm("___tmp.latex"); + return ret; + }else{ + string file=Wmml.image_to_eps(tag,600.0); + return "\\epsfbox{"+file+"}"; + } +} + +int depth; +int appendixes; +int pre; + +constant FLAG_TABLE=1; +constant FLAG_LIST=2; + + +string convert_to_latex(SGML data, void|int flags) +{ + if(!data) return ""; + string ret=""; + foreach(data, TAG tag) + { + if(stringp(tag)) + { + ret+=latex_quote(tag); + } + else if(objectp(tag)) + { + switch(tag->tag) + { + case "smallcaps": + ret+="{\\sc "+convert_to_latex(tag->data)+"}"; + break; + case "tt": ret+="{\\tt "+convert_to_latex(tag->data)+"}"; break; + case "ex_keyword": + case "b": ret+="{\\bf "+convert_to_latex(tag->data)+"}"; break; + case "ex_meta": + case "i": ret+="\\emph{"+convert_to_latex(tag->data)+"}"; break; + case "sub": ret+="$^{"+convert_to_latex(tag->data)+"}$"; break; + case "sup": ret+="$_{"+convert_to_latex(tag->data)+"}$"; break; + case "h1": + ret+="\\begin{huge} "+convert_to_latex(tag->data)+"\\end{huge}"; + break; + case "h2": + ret+="\\begin{Large} "+convert_to_latex(tag->data)+"\\end{Large}"; + break; + case "h3": + ret+=convert_to_latex(tag->data); + break; + case "h4": + ret+="\\begin{small} "+convert_to_latex(tag->data)+"\\end{small}"; + break; + case "h5": + case "h6": + ret+="\\begin{tiny} "+convert_to_latex(tag->data)+"\\end{tiny}"; + break; + + case "wbr": + ret+="\-"; + break; + + case "ex_identifier": + case "ex_comment": + ret+=convert_to_latex(tag->data); + break; + + case "man_title": + // FIXME encaps? + // FIXME indentation + ret+="\n\n"+latex_quote(tag->params->title)+"\\\\\n "+ + convert_to_latex(tag->data)+ + "\n"; + break; + + case "chapter": + depth++; + ret+="\\cleardoublepage \\section{"+ + latex_quote(tag->params->title)+"}\n"+ + convert_to_latex(tag->data); + depth--; + break; + + case "appendix": + if(!appendixes) + { + ret+="\n\\appendix\n"; + appendixes=1; + } + depth++; + ret+="\\cleardoublepage \\section{"+ + latex_quote(tag->params->title)+"}\n"+ + convert_to_latex(tag->data); + depth--; + break; + + case "section": + string tmp=""; + switch(depth) + { + default: + case 2: tmp+="sub"; + case 1: tmp+="sub"; + case 0: + } + depth++; + ret+="\\"+tmp+"section{"+latex_quote(tag->params->title)+"}"+ + convert_to_latex(tag->data); + depth--; + break; + + case "center": + ret+="\\begin{center}\n"+ + convert_to_latex(tag->data)+ + "\n\\end{center}\n"; + break; + + case "firstpage": + case "variable": + case "constant": + case "method": + case "function": + case "class": + case "module": + // FIXME: but how? + ret+=convert_to_latex(tag->data); + break; + + case "pre": + if(pre) + { + ret+=convert_to_latex(tag->data); + }else{ + pre=1; + // FIXME: we will have to remove all tags inside <pre> + ret+="{\\startcode\n\n"+ + convert_to_latex(tag->data)+ + "\n}\n"; + pre=0; + } + break; + + case "encaps": + // FIXME: Manual should not really use <encaps> + ret+=convert_to_latex(tag->data); + break; + + case "bloackquote": + case "example": + { + array(string) tmp= + convert_to_latex(tag->data)/"\\\\"; + for(int e=0;e<sizeof(tmp);e++) + tmp[e]="\\indent "+tmp[e]; + ret+=tmp*"\\\\"; + break; + } + + case "ex_string": + // Make all spaces nonbreakable + ret+=convert_to_latex(tag->data); + break; + + case "dl": + ret+="\\begin{list}{}{} \\item "+ + convert_to_latex(tag->data)+ + "\n\\end{list}\n\n"; + break; + + case "dt": ret+="\n\\item "; break; + case "dd": ret+="\n\\item \\verb+ +"; break; + + case "ex_indent": + ret+="\\verb+ +"; + break; + case "ex_br": + case "br": + int e=strlen(ret)-1; + while(e>=0 && ret[e]==' ') e--; + if(e<0 || ret[e]=='\n') + ret=ret[..e]+"\n"; + else + ret+="\\\\"; + break; + + case "p": + ret+="\n\n"+convert_to_latex(tag->data)+"\n\n"; + break; + + case "hr": + if(tag->params->newline) + ret+="\\pagebreak\n"; + else + ret+="\n\n\\begin{tabular}{p{\\linewidth}} \\\\ \\hline \\end{tabular}\n\n"; + break; + + case "table": + ret+=convert_table(tag); + break; + + case "a": + if(tag->params->href) + { + string href=tag->params->href; + if((lower_case(href)/":")[0] == "mailto") + { + ret+=convert_to_latex(tag->data)+ + latex_quote(" <"+(href/":")[1..]*":"+">"); + }else{ + ret+= + convert_to_latex(tag->data)+ + "* \\marginpar{"+ + replace(latex_quote(href), + ({".","/",":"}), + ({ + ".\\discretionary{}{}{}", + "/\\discretionary{}{}{}", + ":\\discretionary{}{}{}", + }))+ + "}"; + } + }else{ + ret+=convert_to_latex(tag->data); + } + break; + + case "link": + // FIXME +// if(tag->params->to) +// { +// ret+= +// convert_to_latex(tag->data)+ +// "\\marginpar{See "+latex_quote(tag->params->to)+"}"; +// }else{ + ret+=convert_to_latex(tag->data); +// } + break; + + + case "ul": + ret+="\\begin{itemize} "+ + convert_to_latex(tag->data,FLAG_LIST)+ + "\\end{itemize} "; + break; + + case "li": // FIXME?? + if(flags & FLAG_LIST) + ret+="\\item "; + else + ; // FIXME, insert filled circle + break; + + + case "ol": + ret+="\\begin{enumerate} "+ + convert_to_latex(tag->data,FLAG_LIST)+ + "\\end{enumerate} "; + break; + + case "anchor": +// FIXME labels causes tex stack overflow!! +// ret+="\\label{"+latex_quote(tag->params->name)+"}"; + ret+=convert_to_latex(tag->data); + break; + + case "ref": + // FIXME: must find out what type of object we are + // referencing!! + ret+="\\ref{"+tag->params->to+"}"; + break; + + + case "arguments": + case "aargdesc": + case "adesc": + // FIXME FIXME FIXME + break; + + case "aarg": + ret+="{\\tt "+convert_to_latex(tag->data)+"}\\\\"; + break; + + case "data_description": + ret+=convert_to_latex( html->data_description(tag->params, + tag->pos, + tag->data, + tag) ); + break; + +// #endif + + case "exercise": + case "exercises": + // FIXME: + ret+=convert_to_latex(tag->data); + break; + + case "image": + ret+="\\epsfbox{"+Wmml.image_to_eps(tag,300.0)+"}"; + break; + + case "illustration": + ret+="\\epsfbox{"+Wmml.illustration_to_eps(tag,300.0)+"}"; + break; + + default: + werror("Latex: unknown tag <%s> (near %s)\n",tag->tag,tag->location()); + + if(tag->data) + ret+=convert_to_latex(tag->data); + } + + } + else + { + throw(({"Tag or contents has illegal type: "+sprintf("%O\n",tag), + backtrace()})); + } + } + return ret; +} + + +void output(string base, WMML data) +{ + string x=convert_to_latex(data->data); + + x=replace(x, + "\\verb+ +\\verb+ +", + "\\verb+ +" + ); + + x=#" +\\documentclass[twoside,a4paper]{book} +\\usepackage{isolatin1} +\\usepackage{latexsym} % For $\Box$ +\\usepackage{amsmath} +\\usepackage{longtable} +\\usepackage{epsfig} +\\begin{document} +\\author{html2latex}\n +\\setlength{\\unitlength}{1mm}\n + +{\\catcode`\\^^20=\\active\\catcode`\\^^0d=\\active% +\\global\\def\\startcode{\\catcode`\\^^20=\\active\\def^^20{\\hbox{\\ }}% +\\catcode`\\^^0d=\\active\\def^^0d{\\hskip0pt\\par\\noindent}% +\\parskip=1pt\\tt}} +"+ + x+ + "\\end{document}\n"; + rm(base+".tex"); + Stdio.write_file(base+".tex",x); +}