html2ms: remove underline, it just make text unreadable. support more tags.

front
cinap_lenrek 2011-09-20 12:38:08 +02:00
parent 671c7ba858
commit 050b58cb03
1 changed files with 153 additions and 89 deletions

View File

@ -23,17 +23,16 @@ struct Tag {
void (*close)(Text *, Tag *); void (*close)(Text *, Tag *);
union { union {
void *aux; void *aux;
int restore;
}; };
}; };
struct Text { struct Text {
char* font; char* fontstyle;
char* fontsize;
int pre; int pre;
int pos; int pos;
int space; int space;
int output; int output;
int underline;
}; };
void eatwhite(void); void eatwhite(void);
@ -44,29 +43,44 @@ int parseattr(Attr *);
Biobuf in, out; Biobuf in, out;
void void
emit(Text *text, char *fmt, ...) emitrune(Text *text, Rune r)
{ {
va_list a; if(r == '\r' || r =='\n')
if(text->pos > 0){
text->pos = 0; text->pos = 0;
Bputc(&out, '\n'); else
} text->pos++;
va_start(a, fmt); Bputrune(&out, r);
Bvprint(&out, fmt, a);
va_end(a);
} }
void void
restoreoutput(Text *text, Tag *tag) emit(Text *text, char *fmt, ...)
{ {
text->output = tag->restore; Rune buf[64];
va_list a;
int i;
if(fmt[0] == '.' && text->pos){
emitrune(text, '\n');
text->space = 0;
}
va_start(a, fmt);
runevsnprint(buf, nelem(buf), fmt, a);
va_end(a);
for(i=0; buf[i]; i++)
emitrune(text, buf[i]);
}
void
restoreoutput(Text *text, Tag *)
{
text->output = 1;
} }
void void
ongarbage(Text *text, Tag *tag) ongarbage(Text *text, Tag *tag)
{ {
tag->restore = text->output; if(text->output == 0)
return;
tag->close = restoreoutput; tag->close = restoreoutput;
text->output = 0; text->output = 0;
} }
@ -78,16 +92,17 @@ onp(Text *text, Tag *)
} }
void void
restorepre(Text *text, Tag *tag) restorepre(Text *text, Tag *)
{ {
text->pre = tag->restore; text->pre = 0;
emit(text, ".DE\n"); emit(text, ".DE\n");
} }
void void
onpre(Text *text, Tag *tag) onpre(Text *text, Tag *tag)
{ {
tag->restore = text->pre; if(text->pre)
return;
tag->close = restorepre; tag->close = restorepre;
text->pre = 1; text->pre = 1;
emit(text, ".DS L\n"); emit(text, ".DS L\n");
@ -107,7 +122,7 @@ onli(Text *text, Tag *tag)
void void
onh(Text *text, Tag *tag) onh(Text *text, Tag *tag)
{ {
emit(text, ".SH %c\n", tag->tag[1]); emit(text, ".SH\n");
tag->close = onp; tag->close = onp;
} }
@ -121,69 +136,126 @@ onbr(Text *text, Tag *tag)
} }
void void
restorefont(Text *text, Tag *tag) fontstyle(Text *text, char *style)
{ {
text->font = tag->aux; if(strcmp(text->fontstyle, style) == 0)
text->pos += Bprint(&out, "\\f%s", text->font);
}
void
onfont(Text *text, Tag *tag)
{
if(text->font == 0)
text->font = "R";
tag->aux = text->font;
tag->close = restorefont;
if(cistrcmp(tag->tag, "i") == 0)
text->font = "I";
else if(cistrcmp(tag->tag, "b") == 0)
text->font = "B";
text->pos += Bprint(&out, "\\f%s", text->font);
}
void
restoreunderline(Text *text, Tag *tag)
{
text->underline = tag->restore;
emit(text, "");
}
void
ona(Text *text, Tag *tag)
{
int i;
for(i=0; i<tag->nattr; i++)
if(cistrcmp(tag->attr[i].attr, "href") == 0)
break;
if(i == tag->nattr)
return; return;
tag->restore = text->underline; text->fontstyle = style;
tag->close = restoreunderline; emit(text, "\\f%s", style);
text->underline = 1; }
void
fontsize(Text *text, char *size)
{
if(strcmp(text->fontsize, size) == 0)
return;
text->fontsize = size;
emit(text, ".%s\n", size);
}
void
restorefontstyle(Text *text, Tag *tag)
{
fontstyle(text, tag->aux);
}
void
restorefontsize(Text *text, Tag *tag)
{
fontsize(text, tag->aux);
}
void
oni(Text *text, Tag *tag)
{
tag->aux = text->fontstyle;
tag->close = restorefontstyle;
fontstyle(text, "I");
}
void
onb(Text *text, Tag *tag)
{
tag->aux = text->fontstyle;
tag->close = restorefontstyle;
fontstyle(text, "B");
}
void
ontt(Text *text, Tag *tag)
{
tag->aux = text->fontsize;
tag->close = restorefontsize;
fontsize(text, "CW");
}
void
onsmall(Text *text, Tag *tag)
{
tag->aux = text->fontsize;
tag->close = restorefontsize;
fontsize(text, "SM");
}
void
onbig(Text *text, Tag *tag)
{
tag->aux = text->fontsize;
tag->close = restorefontsize;
fontsize(text, "LG");
}
void
endquote(Text *text, Tag *tag)
{
if(cistrcmp(tag->tag, "q") == 0)
emitrune(text, '"');
emit(text, ".QE\n");
}
void
onquote(Text *text, Tag *tag)
{
tag->close = endquote;
if(cistrcmp(tag->tag, "q") == 0)
emit(text, ".QS\n\"");
else
emit(text, ".QP\n");
} }
struct { struct {
char *tag; char *tag;
void (*open)(Text *, Tag *); void (*open)(Text *, Tag *);
} ontag[] = { } ontag[] = {
"a", ona, "b", onb,
"big", onbig,
"blockquote", onquote,
"br", onbr, "br", onbr,
"hr", onbr, "cite", oni,
"b", onfont, "code", ontt,
"i", onfont, "dfn", oni,
"p", onp, "em", oni,
"h1", onh, "h1", onh,
"h2", onh, "h2", onh,
"h3", onh, "h3", onh,
"h4", onh, "h4", onh,
"h5", onh, "h5", onh,
"h6", onh, "h6", onh,
"li", onli,
"pre", onpre,
"head", ongarbage, "head", ongarbage,
"style", ongarbage, "hr", onbr,
"i", oni,
"kbd", ontt,
"li", onli,
"p", onp,
"pre", onpre,
"q", onquote,
"samp", ontt,
"script", ongarbage, "script", ongarbage,
"small", onsmall,
"strong", onb,
"style", ongarbage,
"tt", ontt,
"var", oni,
}; };
void void
@ -444,34 +516,25 @@ parsetext(Text *text, Tag *tag)
case '\r': case '\r':
case ' ': case ' ':
case '\t': case '\t':
text->space = 1; if(text->pre == 0){
if(text->pre == 0) text->space = 1;
continue; break;
}
default: default:
if(r == '\n' || r == '\r')
text->pos = 0;
if(text->space){ if(text->space){
text->space = 0; text->space = 0;
if(text->underline){ if(text->pos >= 70)
emit(text, ".UL "); emitrune(text, '\n');
text->pos = 1; else if(text->pos > 0)
} else if(text->pos >= 70){ emitrune(text, ' ');
text->pos = 0;
Bputc(&out, '\n');
} else if(text->pos > 0){
text->pos++;
Bputc(&out, ' ');
}
} }
if(text->pos == 0 && r == '.') if((text->pos == 0 && r == '.') || r == '\\')
text->pos += Bprint(&out, "\\&"); emit(text, "\\&");
else if(r == '\\') if(r == '\\' || r == 0xA0)
text->pos += Bprint(&out, "\\&\\"); emitrune(text, '\\');
else if(r == 0xA0){ if(r == 0xA0)
r = ' '; r = ' ';
text->pos += Bprint(&out, "\\"); emitrune(text, r);
}
text->pos += Bprint(&out, "%C", r);
} }
} }
} }
@ -491,7 +554,8 @@ main(void)
memset(&text, 0, sizeof(text)); memset(&text, 0, sizeof(text));
text.font = "R"; text.fontstyle = "R";
text.fontsize = "NL";
text.output = 1; text.output = 1;
parsetext(&text, nil); parsetext(&text, nil);