diff --git a/tutorial/latex.pike b/tutorial/latex.pike index ecd375e5870195bcd9d0751fb9519edf49f9419d..153296c875b4e603819020e8de65839d196805fd 100644 --- a/tutorial/latex.pike +++ b/tutorial/latex.pike @@ -31,7 +31,7 @@ string packages = object wcache=.Cache("latex_wcache"); -array(float) find_max_width(array(SGML) data) +array(float) find_line_width(array(SGML) data) { array(string) keys=Array.map(data,Sgml.get_text); @@ -65,10 +65,13 @@ array(float) find_max_width(array(SGML) data) Stdio.write_file("___tmp.tex",x); string tmp=Process.popen("latex '\\scrollmode\\input ___tmp.tex'"); - foreach(keys, key) + sscanf(tmp,"%{%*slength=%f%}",array(array(float)) lengths); +// werror("%O\n",lengths); +// werror("%O\n",keys); + for(int e=0;e<sizeof(keys);e++) { - sscanf(tmp,"%*slength=%f%s",float w, tmp); - wcache[key]=w / 65536; // convert to points + wcache[keys[e]]=lengths[e][0] / 65536; // convert to points +// werror("Width of %s is %f\n",key, lengths[e][0]/65536); } break; @@ -78,61 +81,216 @@ array(float) find_max_width(array(SGML) data) return rows(wcache, keys); } +array(SGML) split_lines(SGML data) +{ + array(SGML) lines=({ ({}) }); -// FIXME: improve this!!! -array(float) find_min_width(array(SGML) datas) + for(int e=0;e<sizeof(data);e++) + { + TAG tag=data[e]; + if(objectp(tag)) + { + switch(tag->tag) + { + case "hr": + break; + + case "br": + lines+=({ ({}) }); + break; + + case "center": + case "p": + lines+=({ ({}) }); + if(tag->data) lines+=split_lines(tag->data); + lines+=({ ({}) }); + break; + + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + lines+=({ ({}) }); + foreach(split_lines(tag->data),SGML data) + lines+=({ ({ Sgml.Tag(tag->tag, + tag->params, + tag->pos, + data) }) }); + lines+=({ ({}) }); + break; + + case "ex_keyword": + case "smallcaps": + case "sub": + case "sup": + case "tt": + case "ex_meta": + case "i": + case "b": + case "a": + { + array tmp=split_lines(tag->data); + lines[-1]+= ({ Sgml.Tag(tag->tag, + tag->params, + tag->pos, + tmp[0]) }); + foreach(tmp[1..],SGML data) + lines+=({ ({ Sgml.Tag(tag->tag, + tag->params, + tag->pos, + data) }) }); + break; + } + + case "link": + if(tag->data) + { + array tmp=split_lines(tag->data); + lines[-1]+=tmp[0]; + lines+=tmp[1..]; + } + break; + + default: + lines[-1]+=({tag}); + + } + }else{ + lines[-1]+=({tag}); + } + } + + return lines; +} + +array(float) find_max_width(array(SGML) datas) { array(SGML) pieces=({}); foreach(datas, SGML data) - { - SGML z=({}); - - for(int e=0;e<sizeof(data);e++) - { - TAG tag=data[e]; + { + pieces+=({ split_lines(data) }); + } - if(stringp(tag)) + array(float) widths=find_line_width(pieces * ({})); + int pos=0; + array(float) ret=allocate(sizeof(pieces)); + for(int q=0;q<sizeof(pieces);q++) + { + int num=sizeof(pieces[q]); + ret[q]=max(0.0,@widths[pos..pos+num-1]); + pos+=num; + } +// werror("%O\n%O\n%O\n",widths,pieces,ret); + if(pos != sizeof(widths)) + error("Major internal error!\n"); + return ret; +} + + +// FIXME: improve this!!! + +array(SGML) split_words(SGML data) +{ + array(SGML) words=({ ({}) }); + + for(int e=0;e<sizeof(data);e++) + { + TAG tag=data[e]; + if(objectp(tag)) + { + switch(tag->tag) { - foreach(tag/" ", string text) - z+=({ ({text}) }); + case "hr": + break; + + case "wbr": + words[-1]+=({"-"}); + case "br": + words+=({ ({}) }); + break; - }else{ - switch(tag->tag) + case "center": + case "p": + words+=({ ({}) }); + if(tag->data) words+=split_words(tag->data); + words+=({ ({}) }); + break; + + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + words+=({ ({}) }); + foreach(split_words(tag->data),SGML data) + words+=({ ({ Sgml.Tag(tag->tag, + tag->params, + tag->pos, + data) }) }); + words+=({ ({}) }); + break; + + case "ex_keyword": + case "smallcaps": + case "sub": + case "sup": + case "ex_meta": + case "i": + case "tt": + case "b": + case "a": { -// FIXME -// case "tt": -// case "i": -// case "b": + array tmp=split_words(tag->data); + words[-1]+=({ Sgml.Tag(tag->tag, + tag->params, + tag->pos, + tmp[0]) }); + foreach(tmp[1..],SGML data) + words+=({ ({ Sgml.Tag(tag->tag, + tag->params, + tag->pos, + data) }) }); + break; + } - case "hr": - break; + case "link": + if(tag->data) + { + array tmp=split_words(tag->data); + words[-1]+=tmp[0]; + words+=tmp[1..]; + } + break; - case "img": - case "tt": - case "image": - case "illustration": - z+=({ ({ tag }) }); - break; - default: - if(tag->data) - { - data+=tag->data; - z+=({ ({ Sgml.Tag(tag->tag,tag->params,0,({})) }) }); - } - else - { - z+=({ ({ Sgml.Tag(tag->tag,tag->params) }) }); - } - } + + default: + words[-1]+=({tag}); + } + }else{ + array tmp=replace(tag,"\n"," ")/" "; + words[-1]+=({ tmp[0] }); + foreach(tmp[1..], string word) words+=({ ({word}) }); } - - pieces+=({z}); } - array(float) widths=find_max_width(pieces * ({})); + return words; +} + + +array(float) find_min_width(array(SGML) datas) +{ + array(SGML) pieces=({}); + + foreach(datas, SGML data) + pieces+=({ split_words(data) }); + + array(float) widths=find_line_width(pieces * ({})); int pos=0; array(float) ret=allocate(sizeof(pieces)); for(int q=0;q<sizeof(pieces);q++) @@ -354,6 +512,21 @@ string convert_table(TAG table) } } +#ifdef TABLE_DEBUG + for(int row=0;row<sizeof(table);row++) + { + for(int col=0;col<columns;col++) + werror("%15s ",Sgml.get_text( table[row][col]->tag->data )[0..14]); + werror("\n"); + for(int col=0;col<columns;col++) + werror("%15f ",maxwidths[row][col]); + werror("\n"); + for(int col=0;col<columns;col++) + werror("%15f ",minwidths[row][col]); + werror("\n"); + } +#endif + // werror("%O %O\n",minwidths,maxwidths); array(float) actual_widths=allocate(columns,0.0); @@ -524,15 +697,35 @@ string convert_table(TAG table) for(int col=0;col<columns;col+=row[col]->cols) { + string r=""; int cols=row[col]->cols; - if(cols > 1) ltxrow+="\\multicolumn{"+cols+"}{l}{"; - ltxrow+=({ - "\\begin{minipage}{"+actual_widths[col]+"pt}\n"+ - convert_to_latex(row[col]->tag->data)+ - "\\end{minipage}" - }); - if(cols > 1) ltxrow+="}"; + if(cols > 1) r+="\\multicolumn{"+cols+"}{l}{"; + r+="\\begin{minipage}{"+actual_widths[col]+"pt}\n"; + switch(row[col]->tag->params->align) + { + // FIXME: might need to add \\ to end of each line + case "right": + r+="\\begin{flushright}\n"; + r+=convert_to_latex(row[col]->tag->data); + r+="\\end{flushright}\n"; + break; + + // FIXME: might need to add \\ to end of each line + case "center": + r+="\\begin{center}\n"; + r+=convert_to_latex(row[col]->tag->data); + r+="\\end{center}\n"; + break; + + default: + case "left": + r+=convert_to_latex(row[col]->tag->data); + break; } + r+="\\end{minipage}"; + if(cols > 1) r+="}"; + ltxrow+=({r}); + } ret+=ltxrow*" & "+"\\\\\n"; if(border) ret+="\\hline\n"; } @@ -676,9 +869,11 @@ string convert_to_latex(SGML data, void|int flags) 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 "b": ret+="\\textbf{"+convert_to_latex(tag->data)+"}"; break; case "ex_meta": - case "i": ret+="\\emph{"+convert_to_latex(tag->data)+"}"; break; + + // FIXME: support <emph> and <i> correctly. + case "i": ret+="\\textit{"+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": @@ -841,11 +1036,16 @@ string convert_to_latex(SGML data, void|int flags) case "bloackquote": case "example": { - array(string) tmp= - convert_to_latex(tag->data)/"\\\\"; + // FIXME: this could probably be fixed better with + // a parbox... + string tmp1=convert_to_latex(tag->data); + if(pre) tmp1=replace(tmp1,"\n","\\\\"); + array(string) tmp=tmp1/"\\\\"; + for(int e=0;e<sizeof(tmp);e++) tmp[e]="\\indent "+tmp[e]; - ret+=tmp*"\\\\"; + ret+=tmp* (pre ? "\n" : "\\\\"); + break; }