1 #include "e.h" 2 #include "y.tab.h" 3 #include <ctype.h> 4 5 #define CSSIZE 1000 6 char cs[CSSIZE+20]; /* text string converted into this */ 7 char *csp; /* next spot in cs[] */ 8 char *psp; /* next character in input token */ 9 10 int lf, rf; /* temporary spots for left and right fonts */ 11 int lastft; /* last \f added */ 12 int nextft; /* next \f to be added */ 13 14 int pclass; /* class of previous character */ 15 int nclass; /* class of next character */ 16 17 int class[LAST][LAST] ={ /* guesswork, tuned to times roman postscript */ 18 19 /*OT OL IL DG LP RP SL PL IF IJ VB */ 20 /*OT*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 0 }, /* OTHER */ 21 /*OL*/ { 1, 0, 1, 1, 1, 1, 1, 2, 2, 2, 0 }, /* OLET */ 22 /*IL*/ { 1, 1, 0, 1, 1, 1, 1, 3, 2, 1, 0 }, /* ILET */ 23 /*DG*/ { 1, 1, 1, 0, 1, 1, 1, 2, 2, 2, 0 }, /* DIG */ 24 /*LP*/ { 1, 1, 1, 1, 1, 2, 1, 2, 3, 3, 0 }, /* LPAR */ 25 /*RP*/ { 2, 2, 2, 1, 1, 1, 1, 2, 3, 3, 0 }, /* RPAR */ 26 /*SL*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0 }, /* SLASH */ 27 /*PL*/ { 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 0 }, /* PLUS */ 28 /*IF*/ { 3, 3, 1, 2, 2, 3, 2, 3, 0, 1, 1 }, /* ILETF */ 29 /*IJ*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0 }, /* ILETJ */ 30 /*VB*/ { 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 1 }, /* VBAR */ 31 32 }; 33 34 extern void shim(int, int); 35 extern void roman(int); 36 extern void sadd(char *); 37 extern void cadd(int); 38 extern int trans(int, char *); 39 40 void text(int t, char *p1) /* convert text string p1 of type t */ 41 { 42 int c; 43 char *p; 44 tbl *tp; 45 46 yyval = salloc(); 47 ebase[yyval] = 0; 48 eht[yyval] = EM(1.0, ps); /* ht in ems of orig size */ 49 lfont[yyval] = rfont[yyval] = ROM; 50 lclass[yyval] = rclass[yyval] = OTHER; 51 if (t == QTEXT) { 52 for (p = p1; *p; p++) /* scan for embedded \f's */ 53 if (*p == '\\' && *(p+1) == 'f') 54 break; 55 if (*p) /* if found \f, leave it alone and hope */ 56 p = p1; 57 else { 58 sprintf(cs, "\\f%s%s\\fP", ftp->name, p1); 59 p = cs; 60 } 61 } else if (t == SPACE) 62 p = "\\ "; 63 else if (t == THIN) 64 p = "\\|"; 65 else if (t == TAB) 66 p = "\\t"; 67 else if ((tp = lookup(restbl, p1)) != NULL) { 68 p = tp->cval; 69 } else { 70 lf = rf = 0; 71 lastft = 0; 72 nclass = NONE; /* get started with no class == no pad */ 73 csp = cs; 74 for (psp = p1; (c = *psp++) != '\0'; ) { 75 nextft = ft; 76 pclass = nclass; 77 rf = trans(c, p1); 78 if (lf == 0) { 79 lf = rf; /* left stuff is first found */ 80 lclass[yyval] = nclass; 81 } 82 if (csp-cs > CSSIZE) 83 ERROR "converted token %.25s... too long", p1 FATAL ; 84 } 85 sadd("\\fP"); 86 *csp = '\0'; 87 p = cs; 88 lfont[yyval] = lf; 89 rfont[yyval] = rf; 90 rclass[yyval] = nclass; 91 } 92 dprintf(".\t%dtext: S%d <- %s; b=%g,h=%g,lf=%c,rf=%c,ps=%d\n", 93 t, yyval, p, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval], ps); 94 printf(".ds %d \"%s\n", yyval, p); 95 } 96 97 trans(int c, char *p1) 98 { 99 int f; 100 101 if (isalpha(c) && ft == ITAL && c != 'f' && c != 'j') { /* italic letter */ 102 shim(pclass, nclass = ILET); 103 cadd(c); 104 return ITAL; 105 } 106 if (isalpha(c) && ft != ITAL) { /* other letter */ 107 shim(pclass, nclass = OLET); 108 cadd(c); 109 return ROM; 110 } 111 if (isdigit(c)) { 112 shim(pclass, nclass = DIG); 113 roman(c); 114 return ROM; /* this is the right side font of this object */ 115 } 116 f = ROM; 117 nclass = OTHER; 118 switch (c) { 119 case ':': case ';': case '!': case '%': case '?': 120 shim(pclass, nclass); 121 roman(c); 122 return f; 123 case '(': case '[': 124 shim(pclass, nclass = LPAR); 125 roman(c); 126 return f; 127 case ')': case ']': 128 shim(pclass, nclass = RPAR); 129 roman(c); 130 return f; 131 case ',': 132 shim(pclass, nclass = OTHER); 133 roman(c); 134 return f; 135 case '.': 136 if (rf == ROM) 137 roman(c); 138 else 139 cadd(c); 140 return f; 141 case '|': /* postscript needs help with default width! */ 142 shim(pclass, nclass = VBAR); 143 sadd("\\v'.17m'\\z|\\v'-.17m'\\|"); /* and height */ 144 return f; 145 case '=': 146 shim(pclass, nclass = PLUS); 147 sadd("\\(eq"); 148 return f; 149 case '+': 150 shim(pclass, nclass = PLUS); 151 sadd("\\(pl"); 152 return f; 153 case '>': 154 case '<': /* >, >=, >>, <, <-, <=, << */ 155 shim(pclass, nclass = PLUS); 156 if (*psp == '=') { 157 sadd(c == '<' ? "\\(<=" : "\\(>="); 158 psp++; 159 } else if (c == '<' && *psp == '-') { /* <- only */ 160 sadd("\\(<-"); 161 psp++; 162 } else if (*psp == c) { /* << or >> */ 163 cadd(c); 164 cadd(c); 165 psp++; 166 } else { 167 cadd(c); 168 } 169 return f; 170 case '-': 171 shim(pclass, nclass = PLUS); /* probably too big for ->'s */ 172 if (*psp == '>') { 173 sadd("\\(->"); 174 psp++; 175 } else { 176 sadd("\\(mi"); 177 } 178 return f; 179 case '/': 180 shim(pclass, nclass = SLASH); 181 cadd('/'); 182 return f; 183 case '~': 184 case ' ': 185 sadd("\\|\\|"); 186 return f; 187 case '^': 188 sadd("\\|"); 189 return f; 190 case '\\': /* troff - pass only \(xx without comment */ 191 shim(pclass, nclass); 192 cadd('\\'); 193 cadd(c = *psp++); 194 if (c == '(' && *psp && *(psp+1)) { 195 cadd(*psp++); 196 cadd(*psp++); 197 } else 198 fprintf(stderr, "eqn warning: unquoted troff command \\%c, line %d, file %s\n", 199 c, curfile->lineno, curfile->fname); 200 return f; 201 case '\'': 202 shim(pclass, nclass); 203 sadd("\\(fm"); 204 return f; 205 206 case 'f': 207 if (ft == ITAL) { 208 shim(pclass, nclass = ILETF); 209 cadd('f'); 210 f = ITAL; 211 } else 212 cadd('f'); 213 return f; 214 case 'j': 215 if (ft == ITAL) { 216 shim(pclass, nclass = ILETJ); 217 cadd('j'); 218 f = ITAL; 219 } else 220 cadd('j'); 221 return f; 222 default: 223 shim(pclass, nclass); 224 cadd(c); 225 return ft==ITAL ? ITAL : ROM; 226 } 227 } 228 229 char *pad(int n) /* return the padding as a string */ 230 { 231 static char buf[20]; 232 233 buf[0] = 0; 234 if (n < 0) { 235 sprintf(buf, "\\h'-%du*\\w'\\^'u'", -n); 236 return buf; 237 } 238 for ( ; n > 1; n -= 2) 239 strcat(buf, "\\|"); 240 if (n > 0) 241 strcat(buf, "\\^"); 242 return buf; 243 } 244 245 void shim(int lc, int rc) /* add padding space suitable to left and right classes */ 246 { 247 sadd(pad(class[lc][rc])); 248 } 249 250 void roman(int c) /* add char c in "roman" font */ 251 { 252 nextft = ROM; 253 cadd(c); 254 } 255 256 void sadd(char *s) /* add string s to cs */ 257 { 258 while (*s) 259 cadd(*s++); 260 } 261 262 void cadd(int c) /* add char c to end of cs */ 263 { 264 char *p; 265 266 if (lastft != nextft) { 267 if (lastft != 0) { 268 *csp++ = '\\'; 269 *csp++ = 'f'; 270 *csp++ = 'P'; 271 } 272 *csp++ = '\\'; 273 *csp++ = 'f'; 274 if (ftp == ftstack) { /* bottom level */ 275 if (ftp->ft == ITAL) /* usual case */ 276 *csp++ = nextft; 277 else /* gfont set, use it */ 278 for (p = ftp->name; *csp = *p++; ) 279 csp++; 280 } else { /* inside some kind of font ... */ 281 for (p = ftp->name; *csp = *p++; ) 282 csp++; 283 } 284 lastft = nextft; 285 } 286 *csp++ = c; 287 } 288