void process(Biobuf *b, char *name) { int c, r, v, i; char *p; cno = 0; prevlineH = res; filename = name; for(;;){ c = getc(b); switch(c){ case Beof: /* go to ground state */ attr = 0; emit('\n'); return; case '\n': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': v = c-'0'; c = getc(b); if(c<'0' || '9'<c) sysfatal("illegal character motion at %s:#%d", filename, cno); v = v*10 + (c-'0'); hp += v; /* fall through to character case */ case 'c': indent(); r = getc(b); emithtmlchar(r); break; case 'D': /* draw line; ignore */ do c = getc(b); while(c!='\n' && c!= Beof); break; case 'f': v = setnum(b, "font", 0, Nfont); switchfont(v); break; case 'h': v = setnum(b, "hpos", -20000, 20000); /* generate spaces if motion is large and within a line */ if(!atnewline && v>2*72) for(i=0; i<v; i+=72) emitstr(" "); hp += v; break; case 'n': setnum(b, "n1", -10000, 10000); //Bprint(&bout, " N1=%d", v); getc(b); /* space separates */ setnum(b, "n2", -10000, 10000); atnewline = 1; if(!didP && hp < (Wid-1)*res) /* if line is less than 19" long, probably need a line break */ emitstr("<br>"); emit('\n'); break; case 'p': page = setnum(b, "ps", -10000, 10000); break; case 's': ps = setnum(b, "ps", 1, 1000); break; case 'v': vp += setnum(b, "vpos", -10000, 10000); /* BUG: ignore motion */ break; case 'x': xcmd(b); break; case 'w': emit(' '); break; case 'C': indent(); p = getstr(b); emitstr(troffchar(p)); break; case 'H': hp = setnum(b, "hpos", 0, 20000); //Bprint(&bout, " H=%d ", hp); break; case 'V': vp = setnum(b, "vpos", 0, 10000); break; default: fprint(2, "dhtml: unknown directive %c(0x%.2ux) at %s:#%d\n", c, c, filename, cno); return; } } }
/* This assumes there is a font active when it starts * * Note: \overline causes it to construct the path for the chars to measure * how much space they take up. This eats printer memory - our printer * has a limit of about 30 characters. */ static char *outputobj(std::ostream &out, char *textptr, char *fontname, double fontsize, int pathonly) { int idx, length, cnt; char *newtextptr; char *endptr; char newfontname[1024]; if (*textptr == '\\') { ++textptr; endptr = textptr; while (isalpha(*endptr)) ++endptr; length = endptr - textptr; /* First, handle special control sequences - they * are picked up by the "if" and "else if" parts. * Anything that isn't handled in this part is handled in the * "else" which assumes anything in the table should be * translated into the Symbol font. Stuff not in the table is * sent "as-is". */ if (length == 5 && strncmp(textptr,"prime",length) == 0) { /* Make the prime large (like TeX) by rescaling * the font & shifting the coords. */ endfont(out,pathonly); out << "0 " << -.46*PRIMESCALE * fontsize << " RM2\n"; startfont(out,SYMBOLFONT,PRIMESCALE*fontsize); out << "\\242"; endfont(out,pathonly); out << "0 " << .46*PRIMESCALE * fontsize << " RM2\n"; startfont(out,fontname,fontsize); return endptr; } else if (length == 5 && strncmp(textptr,"minus",length) == 0) { switchfont(out,fontname,SYMBOLFONT,fontsize,pathonly); out << '-'; switchfont(out,SYMBOLFONT,fontname,fontsize,pathonly); return endptr; } else if (length == 3 && strncmp(textptr,"dag",length) == 0) { switchfont(out,fontname,"Times-Roman",fontsize,pathonly); out << "\\262"; switchfont(out,"Times-Roman",fontname,fontsize,pathonly); return endptr; } else if (length == 4 && strncmp(textptr,"font",length) == 0) { if (*endptr != '{') { std::cerr << ERRSTR << "Expect '{fontname}' after \\font, but found "; std::cerr << '\'' << endptr << "'\n"; exit(1); } ++endptr; cnt = 0; while (*endptr != '}' && *endptr != '\0') { newfontname[cnt] = *endptr; ++endptr; ++cnt; } newfontname[cnt] = '\0'; if (*endptr != '}') { std::cerr << ERRSTR << "Missing '}' in \\font{fontname}\n"; exit(1); } switchfont(out,fontname,newfontname,fontsize,pathonly); endptr = outputobj(out,endptr+1,newfontname,fontsize,pathonly); switchfont(out,newfontname,fontname,fontsize,pathonly); return endptr; } else if (length == 8 && strncmp(textptr,"overline",length) == 0) { /* Do the overline by first constructing path for the text * we are going to overline, then get bounding box and use * to position the line. Then re-create the text (yes, * all text is generated twice - once for sizing, once * for output). * * WARNING: If already have pathonly==true, just don't output * anything - this is done because if we put the overbar in * the path, using "PBX" will pick up info about earlier * parts of the path & will screw things up. The upshot of this * is that if you overline an object which contains an overline, * the contained overline is not included when the position of * the overline is calculated - this is a bug which probably * won't hurt much... */ if (!pathonly) { get_overline_coords(out, endptr, fontname, fontsize , pathonly); out << "NP M2 " ; out << OVERLINE_THICKNESS * fontsize << " SLW\n"; out << "L2 ST\n"; out << "M2\n"; // Now move back & draw the text under the overline startfont(out,fontname,fontsize); return outputobj(out,endptr,fontname,fontsize,pathonly); } return endptr; } else if (length == 9 && strncmp(textptr,"widetilde",length) == 0) { /* The above comments for overline apply here too. */ if (!pathonly) { get_overline_coords(out, endptr, fontname, fontsize , pathonly); out << TILDE_HEIGHT * fontsize << " tilde fill\n"; out << "M2\n"; // Now move back & draw the text under the overline startfont(out,fontname,fontsize); return outputobj(out,endptr,fontname,fontsize,pathonly); } return endptr; } else if (length == 14 && strncmp(textptr,"overrightarrow",length) == 0) { /* The above comments for overline apply here too. */ if (!pathonly) { get_overline_coords(out, endptr, fontname, fontsize , pathonly); // Draw the arrow head out << "2 copy 2 copy 4 -1 roll " << -ARROW_LENGTH*fontsize << " add\n"; out << "4 1 roll " << ARROW_ANGLE << " arrow fill\n"; // Draw the stem of the arrow out << "2 1 roll " << -ARROW_LENGTH*fontsize << " add 2 1 roll\n"; out << "NP M2 " ; out << OVERLINE_THICKNESS * fontsize << " SLW\n"; out << "L2 ST\n"; out << "M2\n"; // Now move back & draw the text under the overline startfont(out,fontname,fontsize); return outputobj(out,endptr,fontname,fontsize,pathonly); } return endptr; } else if (length == 8 && strncmp(textptr,"tildebar",length) == 0) { /* The above comments for overline apply here too. */ if (!pathonly) { get_overline_coords(out, endptr, fontname, fontsize , pathonly); out << "4 copy\n"; // Copy coords for the tilde // Make the overline out << "NP M2 " ; out << OVERLINE_THICKNESS * fontsize << " SLW\n"; out << "L2 ST\n"; // Make the tilde out << OVERLINE_SHIFT * fontsize << " add\n"; out << "3 -1 roll " << OVERLINE_SHIFT * fontsize << " add 3 1 roll\n"; out << TILDE_HEIGHT * fontsize << " tilde fill\n"; out << "M2\n"; // Now move back & draw the text under the overline startfont(out,fontname,fontsize); return outputobj(out,endptr,fontname,fontsize,pathonly); } return endptr; } else { for (idx = sizeof(text2PS_syms) /sizeof(struct text2PS_symbol_translation) - 1 ; idx >= 0 ; --idx) { if (strncmp(textptr,text2PS_syms[idx].insym,length) == 0 && (strlen(text2PS_syms[idx].insym) == length)) break; } if (idx >= 0) // have a match - map to something in Symbol font { endfont(out,pathonly); startfont(out,SYMBOLFONT,fontsize); out << text2PS_syms[idx].outsym; endfont(out,pathonly); startfont(out,fontname,fontsize); return endptr; } else // no match (not in table) - send "as is" { outputchar(out,*textptr); return textptr + 1; } } } else if (*textptr == '{') { ++textptr; while (*textptr != '}' && *textptr != '\0') textptr = outputobj(out,textptr,fontname,fontsize,pathonly); return textptr + 1; } else if (*textptr == '_') { endfont(out,pathonly); out << "CPT\n"; newtextptr = outputsubscript(out,textptr+1,fontname,fontsize,pathonly); if (*newtextptr == '^') { out << "CPT pop\n"; // save x value out << "3 1 roll\n"; // push the x value to the bottom out << "M2\n"; out << "CPT exch pop exch\n"; // save the y value & put before x newtextptr = outputsuperscript(out,newtextptr+1,fontname,fontsize,pathonly); // move to start of normal text - compare x's & fetch y, then move out << "CPT pop max exch M2\n"; // now stack is empty } else // use old y & new x value out << "exch pop CPT pop exch M2\n"; // now stack is empty startfont(out,fontname,fontsize); return newtextptr; } else if (*textptr == '^') { endfont(out,pathonly); out << "CPT\n"; newtextptr = outputsuperscript(out,textptr+1,fontname,fontsize,pathonly); if (*newtextptr == '_') { out << "CPT pop\n"; // save x value out << "3 1 roll\n"; // push the x value to the bottom out << "M2\n"; out << "CPT exch pop exch\n"; // save the y value & put before x newtextptr = outputsubscript(out,newtextptr+1,fontname,fontsize,pathonly); // move to start of normal text - compare x's & fetch y, then move out << "CPT pop max exch M2\n"; // now stack is empty } else // use old y & new x value out << "exch pop CPT pop exch M2\n"; // now stack is empty startfont(out,fontname,fontsize); return newtextptr; } else { outputchar(out,*textptr); return textptr + 1; } }