8 struct box
*box_alloc(int szreg
, int pre
, int style
)
10 struct box
*box
= malloc(sizeof(*box
));
11 memset(box
, 0, sizeof(*box
));
21 void box_free(struct box
*box
)
31 static void box_put(struct box
*box
, char *s
)
33 sbuf_append(&box
->raw
, s
);
35 printf(".as %s \"%s\n", sregname(box
->reg
), s
);
38 void box_putf(struct box
*box
, char *s
, ...)
43 vsnprintf(buf
, sizeof(buf
), s
, ap
);
48 char *box_buf(struct box
*box
)
50 return sbuf_buf(&box
->raw
);
53 /* change box's point size; return the number register storing it */
54 int box_size(struct box
*box
, char *val
)
56 int szreg
= box
->szreg
;
61 box
->szreg
= nregmk();
63 if (val
[0] == '-' || val
[0] == '+')
64 printf(".nr %s %s%s\n", nregname(box
->szreg
), nreg(szreg
), val
);
66 printf(".nr %s %s\n", nregname(box
->szreg
), val
);
70 void box_move(struct box
*box
, int dy
, int dx
)
73 box_putf(box
, "\\v'%du*%sp/100u'", dy
, nreg(box
->szreg
));
75 box_putf(box
, "\\h'%du*%sp/100u'", dx
, nreg(box
->szreg
));
78 /* T_ORD, T_BIGOP, T_BINOP, T_RELOP, T_LEFT, T_RIGHT, T_PUNC, T_INNER */
79 static int spacing
[][8] = {
80 {0, 1, 2, 3, 0, 0, 0, 1},
81 {1, 1, 0, 3, 0, 0, 0, 1},
82 {2, 2, 0, 0, 2, 0, 0, 2},
83 {3, 3, 0, 0, 3, 0, 0, 3},
84 {0, 0, 0, 0, 0, 0, 0, 0},
85 {0, 1, 2, 3, 0, 0, 0, 1},
86 {1, 1, 0, 1, 1, 1, 1, 1},
87 {1, 1, 2, 3, 1, 0, 1, 1},
90 /* return the amount of automatic spacing before adding the given token */
91 static int eqn_gaps(struct box
*box
, int cur
)
94 int a1
= T_ATOM(box
->tcur
); /* previous atom */
95 int a2
= T_ATOM(cur
); /* current atom */
96 if (!TS_SZ(box
->style
) && a1
&& a2
)
97 s
= spacing
[T_ATOMIDX(a1
)][T_ATOMIDX(a2
)];
105 /* call just before inserting a non-italic character */
106 static void box_italiccorrection(struct box
*box
)
108 if (box
->atoms
&& (box
->tcur
& T_ITALIC
))
110 box
->tcur
&= ~T_ITALIC
;
113 static int box_fixatom(int cur
, int pre
)
115 if (cur
== T_BINOP
&& (!pre
|| pre
== T_RELOP
|| pre
== T_BIGOP
||
116 pre
== T_LEFT
|| pre
== T_PUNC
))
118 if (cur
== T_RELOP
&& (!pre
|| pre
== T_LEFT
))
123 /* call before inserting a token with box_put() and box_putf() */
124 static void box_beforeput(struct box
*box
, int type
, int breakable
)
126 int autogaps
; /* automatically inserted space before this token */
128 autogaps
= eqn_gaps(box
, T_ATOM(type
));
129 if (!(type
& T_ITALIC
))
130 box_italiccorrection(box
);
131 if (autogaps
&& type
!= T_GAP
&& box
->tcur
!= T_GAP
) {
132 box_italiccorrection(box
);
133 if (breakable
) { /* enlarge a space to match autogaps */
134 box_putf(box
, "\\s[\\En(.s*%du*%sp/100u/\\w' 'u]\\j'%d' \\s0",
135 autogaps
, nreg(box
->szreg
),
136 def_brcost(T_ATOM(box
->tcur
)));
138 box_putf(box
, "\\h'%du*%sp/100u'",
139 autogaps
, nreg(box
->szreg
));
144 printf(".nr %s 0\\w'%s'\n", box
->tomark
, box_toreg(box
));
149 /* call after inserting a token with box_put() and box_putf() */
150 static void box_afterput(struct box
*box
, int type
)
153 box
->tcur
= T_FONT(type
) | box_fixatom(T_TOK(type
), T_TOK(box
->tcur
));
155 box
->tbeg
= box
->tcur
;
158 /* insert s with the given type */
159 void box_puttext(struct box
*box
, int type
, char *s
, ...)
164 vsnprintf(buf
, sizeof(buf
), s
, ap
);
166 box_beforeput(box
, type
, 0);
167 if (!(box
->tcur
& T_ITALIC
) && (type
& T_ITALIC
))
170 box_afterput(box
, type
);
173 /* append sub to box */
174 void box_merge(struct box
*box
, struct box
*sub
, int breakable
)
178 box_beforeput(box
, sub
->tbeg
, breakable
);
180 box_put(box
, box_toreg(sub
));
182 box
->tbeg
= sub
->tbeg
;
183 /* fix atom type only if merging a single atom */
184 if (sub
->atoms
== 1) {
185 box_afterput(box
, sub
->tcur
);
187 box
->tcur
= sub
->tcur
;
188 box
->atoms
+= sub
->atoms
;
192 /* put the maximum of number registers a and b into register dst */
193 static void roff_max(int dst
, int a
, int b
)
195 printf(".ie %s>=%s .nr %s 0+%s\n",
196 nreg(a
), nreg(b
), nregname(dst
), nreg(a
));
197 printf(".el .nr %s 0+%s\n", nregname(dst
), nreg(b
));
200 /* return the width, height and depth of a string */
201 static void tok_dim(char *s
, int wd
, int ht
, int dp
)
203 printf(".nr %s 0\\w'%s'\n", nregname(wd
), s
);
205 printf(".nr %s 0-\\n[bbury]\n", nregname(ht
));
207 printf(".nr %s 0\\n[bblly]\n", nregname(dp
));
210 static int box_suprise(struct box
*box
)
212 if (TS_0(box
->style
))
214 return box
->style
== TS_D
? e_sup1
: e_sup2
;
217 void box_sub(struct box
*box
, struct box
*sub
, struct box
*sup
)
219 int box_wd
= nregmk();
220 int box_wdnoic
= nregmk();
221 int box_dp
= nregmk();
222 int box_ht
= nregmk();
223 int sub_wd
= nregmk();
224 int sup_wd
= nregmk();
225 int all_wd
= nregmk();
226 int sup_dp
= nregmk();
227 int sub_ht
= nregmk();
228 int sup_rise
= nregmk();
229 int sub_fall
= nregmk();
230 int tmp_18e
= nregmk();
231 int sub_cor
= nregmk();
233 box_italiccorrection(sub
);
235 box_italiccorrection(sup
);
237 tok_dim(box_toreg(box
), box_wdnoic
, 0, 0);
238 box_italiccorrection(box
);
239 printf(".ps %s\n", nreg(box
->szreg
));
240 tok_dim(box_toreg(box
), box_wd
, box_ht
, box_dp
);
241 box_putf(box
, "\\h'5m/100u'");
243 tok_dim(box_toreg(sup
), sup_wd
, 0, sup_dp
);
245 printf(".nr %s 0%su-(%dm/100u)\n",
246 nregname(sup_rise
), nreg(box_ht
), e_supdrop
);
248 printf(".if %s<(%dm/100u) .nr %s (%dm/100u)\n",
249 nreg(sup_rise
), box_suprise(box
),
250 nregname(sup_rise
), box_suprise(box
));
251 printf(".if %s<(%s+(%dm/100u/4)) .nr %s 0%s+(%dm/100u/4)\n",
252 nreg(sup_rise
), nreg(sup_dp
), e_xheight
,
253 nregname(sup_rise
), nreg(sup_dp
), e_xheight
);
256 tok_dim(box_toreg(sub
), sub_wd
, sub_ht
, 0);
258 printf(".nr %s 0%su+(%dm/100u)\n",
259 nregname(sub_fall
), nreg(box_dp
), e_subdrop
);
263 printf(".if %s<(%dm/100u) .nr %s (%dm/100u)\n",
264 nreg(sub_fall
), e_sub1
,
265 nregname(sub_fall
), e_sub1
);
266 printf(".if %s<(%s-(%dm/100u*4/5)) .nr %s 0%s-(%dm/100u*4/5)\n",
267 nreg(sub_fall
), nreg(sub_ht
), e_xheight
,
268 nregname(sub_fall
), nreg(sub_ht
), e_xheight
);
272 printf(".if %s<(%dm/100u) .nr %s (%dm/100u)\n",
273 nreg(sub_fall
), e_sub2
,
274 nregname(sub_fall
), e_sub2
);
276 printf(".if (%s-%s)-(%s-%s)<(%dm/100u*4) \\{\\\n",
277 nreg(sup_rise
), nreg(sup_dp
),
278 nreg(sub_ht
), nreg(sub_fall
), e_rulethickness
);
279 printf(".nr %s (%dm/100u*4)+%s-(%s-%s)\n",
280 nregname(sub_fall
), e_rulethickness
,
281 nreg(sub_ht
), nreg(sup_rise
), nreg(sup_dp
));
282 printf(".nr %s (%dm/100u*4/5)-(%s-%s)\n",
283 nregname(tmp_18e
), e_xheight
,
284 nreg(sup_rise
), nreg(sup_dp
));
285 printf(".if %s>0 .nr %s +%s\n",
286 nreg(tmp_18e
), nregname(sup_rise
), nreg(tmp_18e
));
287 printf(".if %s>0 .nr %s -%s \\}\n",
288 nreg(tmp_18e
), nregname(sub_fall
), nreg(tmp_18e
));
290 /* writing the superscript */
292 box_putf(box
, "\\v'-%su'%s\\v'%su'",
293 nreg(sup_rise
), box_toreg(sup
), nreg(sup_rise
));
295 box_putf(box
, "\\h'-%su'", nreg(sup_wd
));
297 /* writing the subscript */
299 /* subscript correction */
300 printf(".nr %s (%s-%s)\n", nregname(sub_cor
),
301 nreg(box_wd
), nreg(box_wdnoic
));
302 printf(".if %s>0 .nr %s (%s+%s)*(%s-%s)/%s\n",
303 nreg(box_ht
), nregname(sub_cor
),
304 nreg(box_ht
), nreg(sub_fall
),
305 nreg(box_wd
), nreg(box_wdnoic
), nreg(box_ht
));
306 printf(".nr %s -%s\n", nregname(sub_wd
), nreg(sub_cor
));
307 box_putf(box
, "\\h'-%su'", nreg(sub_cor
));
308 box_putf(box
, "\\v'%su'%s\\v'-%su'",
309 nreg(sub_fall
), box_toreg(sub
), nreg(sub_fall
));
311 box_putf(box
, "\\h'-%su'", nreg(sub_wd
));
312 roff_max(all_wd
, sub_wd
, sup_wd
);
313 box_putf(box
, "\\h'+%su'", nreg(all_wd
));
316 box_putf(box
, "\\h'%dm/100u'", e_scriptspace
);
332 void box_from(struct box
*box
, struct box
*lim
, struct box
*llim
, struct box
*ulim
)
334 int lim_wd
= nregmk(); /* box's width */
335 int lim_ht
= nregmk(); /* box's height */
336 int lim_dp
= nregmk(); /* box's depth */
337 int llim_wd
= nregmk(); /* llim's width */
338 int ulim_wd
= nregmk(); /* ulim's width */
339 int ulim_dp
= nregmk(); /* ulim's depth */
340 int llim_ht
= nregmk(); /* llim's height */
341 int ulim_rise
= nregmk(); /* the position of ulim */
342 int llim_fall
= nregmk(); /* the position of llim */
343 int all_wd
= nregmk(); /* the width of all */
344 box_italiccorrection(lim
);
345 box_beforeput(box
, T_BIGOP
, 0);
346 tok_dim(box_toreg(lim
), lim_wd
, lim_ht
, lim_dp
);
347 printf(".ps %s\n", nreg(box
->szreg
));
349 tok_dim(box_toreg(ulim
), ulim_wd
, 0, ulim_dp
);
351 tok_dim(box_toreg(llim
), llim_wd
, llim_ht
, 0);
353 roff_max(all_wd
, llim_wd
, ulim_wd
);
355 printf(".nr %s %s\n", nregname(all_wd
),
356 ulim
? nreg(ulim_wd
) : nreg(llim_wd
));
357 printf(".if %s>%s .nr %s 0%s\n",
358 nreg(lim_wd
), nreg(all_wd
),
359 nregname(all_wd
), nreg(lim_wd
));
360 box_putf(box
, "\\h'%su-%su/2u'", nreg(all_wd
), nreg(lim_wd
));
361 box_merge(box
, lim
, 0);
362 box_putf(box
, "\\h'-%su/2u'", nreg(lim_wd
));
365 printf(".nr %s (%dm/100u)-%s\n",
366 nregname(ulim_rise
), e_bigopspacing3
, nreg(ulim_dp
));
367 printf(".if %s<(%dm/100u) .nr %s (%dm/100u)\n",
368 nreg(ulim_rise
), e_bigopspacing1
,
369 nregname(ulim_rise
), e_bigopspacing1
);
370 printf(".nr %s +%s+%s\n",
371 nregname(ulim_rise
), nreg(lim_ht
), nreg(ulim_dp
));
372 box_putf(box
, "\\h'-%su/2u'\\v'-%su'%s\\v'%su'\\h'-%su/2u'",
373 nreg(ulim_wd
), nreg(ulim_rise
), box_toreg(ulim
),
374 nreg(ulim_rise
), nreg(ulim_wd
));
378 printf(".nr %s (%dm/100u)-%s\n",
379 nregname(llim_fall
), e_bigopspacing4
, nreg(llim_ht
));
380 printf(".if %s<(%dm/100u) .nr %s (%dm/100u)\n",
381 nreg(llim_fall
), e_bigopspacing2
,
382 nregname(llim_fall
), e_bigopspacing2
);
383 printf(".nr %s +%s+%s\n",
384 nregname(llim_fall
), nreg(lim_dp
), nreg(llim_ht
));
385 box_putf(box
, "\\h'-%su/2u'\\v'%su'%s\\v'-%su'\\h'-%su/2u'",
386 nreg(llim_wd
), nreg(llim_fall
), box_toreg(llim
),
387 nreg(llim_fall
), nreg(llim_wd
));
389 box_putf(box
, "\\h'%su/2u'", nreg(all_wd
));
390 box_afterput(box
, T_BIGOP
);
403 /* return the width of s; len is the height plus depth */
404 static void tok_len(char *s
, int wd
, int len
, int ht
, int dp
)
406 printf(".nr %s 0\\w'%s'\n", nregname(wd
), s
);
408 printf(".nr %s 0\\n[bblly]-\\n[bbury]-2\n", nregname(len
));
410 printf(".nr %s 0\\n[bblly]-1\n", nregname(dp
));
412 printf(".nr %s 0-\\n[bbury]-1\n", nregname(ht
));
415 /* len[0]: width, len[1]: vertical length, len[2]: height, len[3]: depth */
416 static void blen_mk(char *s
, int len
[4])
419 for (i
= 0; i
< 4; i
++)
421 tok_len(s
, len
[0], len
[1], len
[2], len
[3]);
424 /* free the registers allocated with blen_mk() */
425 static void blen_rm(int len
[4])
428 for (i
= 0; i
< 4; i
++)
432 /* build a fraction; the correct font should be set up beforehand */
433 void box_over(struct box
*box
, struct box
*num
, struct box
*den
)
435 int num_wd
= nregmk();
436 int num_dp
= nregmk();
437 int den_wd
= nregmk();
438 int den_ht
= nregmk();
439 int all_wd
= nregmk();
440 int num_rise
= nregmk();
441 int den_fall
= nregmk();
442 int bar_wd
= nregmk();
443 int bar_dp
= nregmk();
444 int bar_ht
= nregmk();
445 int bar_fall
= nregmk();
446 int tmp_15d
= nregmk();
447 int bargap
= (TS_DX(box
->style
) ? 7 : 3) * e_rulethickness
/ 2;
448 box_beforeput(box
, T_INNER
, 0);
449 box_italiccorrection(num
);
450 box_italiccorrection(den
);
451 tok_dim(box_toreg(num
), num_wd
, 0, num_dp
);
452 tok_dim(box_toreg(den
), den_wd
, den_ht
, 0);
453 roff_max(all_wd
, num_wd
, den_wd
);
454 printf(".ps %s\n", nreg(box
->szreg
));
455 tok_len("\\(ru", bar_wd
, 0, bar_ht
, bar_dp
);
457 printf(".nr %s 0%dm/100u\n",
458 nregname(num_rise
), TS_DX(box
->style
) ? e_num1
: e_num2
);
459 printf(".nr %s 0%dm/100u\n",
460 nregname(den_fall
), TS_DX(box
->style
) ? e_denom1
: e_denom2
);
462 printf(".nr %s (%s-%s)-((%dm/100u)+(%dm/100u/2))\n",
463 nregname(tmp_15d
), nreg(num_rise
), nreg(num_dp
),
464 e_axisheight
, e_rulethickness
);
465 printf(".if %s<(%dm/100u) .nr %s +(%dm/100u)-%s\n",
466 nreg(tmp_15d
), bargap
, nregname(num_rise
),
467 bargap
, nreg(tmp_15d
));
468 printf(".nr %s ((%dm/100u)-(%dm/100u/2))-(%s-%s)\n",
469 nregname(tmp_15d
), e_axisheight
, e_rulethickness
,
470 nreg(den_ht
), nreg(den_fall
));
471 printf(".if %s<(%dm/100u) .nr %s +(%dm/100u)-%s\n",
472 nreg(tmp_15d
), bargap
, nregname(den_fall
),
473 bargap
, nreg(tmp_15d
));
474 /* calculating the vertical position of the bar */
475 printf(".nr %s 0-%s+%s/2-(%dm/100u)\n",
476 nregname(bar_fall
), nreg(bar_dp
),
477 nreg(bar_ht
), e_axisheight
);
478 /* making the bar longer */
479 printf(".nr %s +2*(%dm/100u)\n",
480 nregname(all_wd
), e_overhang
);
481 /* null delimiter space */
482 box_putf(box
, "\\h'%sp*%du/100u'",nreg(box
->szreg
), e_nulldelim
);
483 /* drawing the bar */
484 box_putf(box
, "\\v'%su'\\f[\\n(.f]\\s[%s]\\l'%su'\\v'-%su'\\h'-%su/2u'",
485 nreg(bar_fall
), nreg(box
->szreg
), nreg(all_wd
),
486 nreg(bar_fall
), nreg(all_wd
));
487 /* output the numerator */
488 box_putf(box
, "\\h'-%su/2u'", nreg(num_wd
));
489 box_putf(box
, "\\v'-%su'%s\\v'%su'",
490 nreg(num_rise
), box_toreg(num
), nreg(num_rise
));
491 box_putf(box
, "\\h'-%su/2u'", nreg(num_wd
));
492 /* output the denominator */
493 box_putf(box
, "\\h'-%su/2u'", nreg(den_wd
));
494 box_putf(box
, "\\v'%su'%s\\v'-%su'",
495 nreg(den_fall
), box_toreg(den
), nreg(den_fall
));
496 box_putf(box
, "\\h'(-%su+%su)/2u'", nreg(den_wd
), nreg(all_wd
));
497 box_putf(box
, "\\h'%sp*%du/100u'",nreg(box
->szreg
), e_nulldelim
);
498 box_afterput(box
, T_INNER
);
514 /* choose the smallest bracket among br[], large enough for \n(ht+\n(dp */
515 static void box_bracketsel(int dst
, int ht
, int dp
, char **br
, int any
, int both
)
518 for (i
= 0; br
[i
]; i
++) {
519 printf(".if '%s'' ", sreg(dst
));
520 printf(".if \\w'%s' ", br
[i
]); /* is this bracket available? */
521 if (both
) { /* check both the height and the depth */
522 printf(".if (%s-(%dm/100)*2)<=(-\\n[bbury]+\\n[bblly]+(%dm/100*2)) ",
523 nreg(ht
), e_rulethickness
, e_axisheight
);
524 printf(".if (%s*2)<=(-\\n[bbury]+\\n[bblly]-(%dm/100*2)) ",
525 nreg(dp
), e_axisheight
);
527 printf(".if (%s+%s)<=(-\\n[bbury]+\\n[bblly]) ", nreg(ht
), nreg(dp
));
529 printf(".ds %s \"%s\n", sregname(dst
), br
[i
]);
531 if (any
) /* choose the largest bracket, if any is 1 */
533 printf(".if '%s'' .if \\w'%s' .ds %s \"%s\n",
534 sreg(dst
), br
[i
], sregname(dst
), br
[i
]);
537 /* build a bracket using the provided pieces */
538 static void box_bracketmk(int dst
, int len
,
539 char *top
, char *mid
, char *bot
, char *cen
)
545 int mid_cnt
= nregmk(); /* number of mid glyphs to insert */
546 int mid_cur
= nregmk(); /* the number of mid glyphs inserted */
547 int cen_pos
= nregmk();
548 int buildmacro
= sregmk();
549 blen_mk(top
, toplen
);
550 blen_mk(mid
, midlen
);
551 blen_mk(bot
, botlen
);
553 blen_mk(cen
, cenlen
);
554 /* the number of mid tokens necessary to cover sub */
556 printf(".nr %s %s*2-%s-%s*11/10/%s\n",
557 nregname(mid_cnt
), nreg(len
),
558 nreg(toplen
[1]), nreg(botlen
[1]), nreg(midlen
[1]));
559 printf(".if %s<0 .nr %s 0\n", nreg(mid_cnt
), nregname(mid_cnt
));
560 } else { /* for brackets with a center like { */
561 printf(".nr %s %s-(%s+%s+%s/2)*11/10/%s\n",
562 nregname(cen_pos
), nreg(len
), nreg(cenlen
[1]),
563 nreg(toplen
[1]), nreg(botlen
[1]), nreg(midlen
[1]));
564 printf(".if %s<0 .nr %s 0\n", nreg(cen_pos
), nregname(cen_pos
));
565 printf(".nr %s 0%s*2\n", nregname(mid_cnt
), nreg(cen_pos
));
567 /* the macro to create the bracket; escaping backslashes */
568 printf(".de %s\n", sregname(buildmacro
));
569 if (cen
) /* inserting cen */
570 printf(".if \\%s=\\%s .as %s \"\\v'-\\%su'%s\\h'-\\%su'\\v'-\\%su'\n",
571 nreg(mid_cur
), nreg(cen_pos
), sregname(dst
),
572 nreg(cenlen
[3]), cen
, nreg(cenlen
[0]), nreg(cenlen
[2]));
573 printf(".if \\%s<\\%s .as %s \"\\v'-\\%su'%s\\h'-\\%su'\\v'-\\%su'\n",
574 nreg(mid_cur
), nreg(mid_cnt
),
575 sregname(dst
), nreg(midlen
[3]),
576 mid
, nreg(midlen
[0]), nreg(midlen
[2]));
577 printf(".if \\\\n+%s<\\%s .%s\n",
578 escarg(nregname(mid_cur
)), nreg(mid_cnt
), sregname(buildmacro
));
580 /* constructing the bracket */
581 printf(".ds %s \"\\v'-%su'%s\\h'-%su'\\v'-%su'\n",
582 sregname(dst
), nreg(botlen
[3]),
583 bot
, nreg(botlen
[0]), nreg(botlen
[2]));
584 printf(".nr %s 0 1\n", nregname(mid_cur
));
585 printf(".%s\n", sregname(buildmacro
));
586 printf(".as %s \"\\v'-%su'%s\\h'-%su'\\v'-%su'\n",
587 sregname(dst
), nreg(toplen
[3]), top
,
588 nreg(toplen
[0]), nreg(toplen
[2]));
589 /* moving back vertically */
590 printf(".as %s \"\\v'%su*%su+%su+%su+%su'\n",
591 sregname(dst
), nreg(mid_cnt
), nreg(midlen
[1]), nreg(botlen
[1]),
592 nreg(toplen
[1]), cen
? nreg(cenlen
[1]) : "0");
594 printf(".as %s \"\\h'%su'\n",
595 sregname(dst
), cen
? nreg(cenlen
[0]) : nreg(midlen
[0]));
607 static void box_bracket(struct box
*box
, char *brac
, int ht
, int dp
)
609 char *sizes
[NSIZES
] = {NULL
};
610 char *top
= NULL
, *mid
= NULL
, *bot
= NULL
, *cen
= NULL
;
615 roff_max(len
, ht
, dp
);
616 def_sizes(brac
, sizes
);
617 printf(".ds %s \"\n", sregname(dst
));
618 def_pieces(brac
, &top
, &mid
, &bot
, &cen
);
619 box_bracketsel(dst
, ht
, dp
, sizes
, !mid
, 1);
621 printf(".if '%s'' \\{\\\n", sreg(dst
));
622 box_bracketmk(dst
, len
, top
, mid
, bot
, cen
);
625 /* calculating the total vertical length of the bracket */
626 blen_mk(sreg(dst
), parlen
);
627 /* calculating the amount the bracket should be moved downwards */
628 printf(".nr %s 0-%s+%s/2-(%sp*%du/100u)\n", nregname(fall
),
629 nreg(parlen
[3]), nreg(parlen
[2]), nreg(box
->szreg
), e_axisheight
);
630 /* printing the output */
631 box_putf(box
, "\\f[\\n(.f]\\s[\\n(.s]\\v'%su'%s\\v'-%su'",
632 nreg(fall
), sreg(dst
), nreg(fall
));
640 static char *bracsign(char *brac
, int left
)
642 if (brac
[0] == 'c' && !strncmp("ceiling", brac
, strlen(brac
)))
643 return left
? "\\(lc" : "\\(rc";
644 if (brac
[0] == 'f' && !strncmp("floor", brac
, strlen(brac
)))
645 return left
? "\\(lf" : "\\(rf";
646 if (brac
[0] == '<' && brac
[1] == '\0')
648 if (brac
[0] == '>' && brac
[1] == '\0')
653 /* build large brackets; the correct font should be set up beforehand */
654 void box_wrap(struct box
*box
, struct box
*sub
, char *left
, char *right
)
657 blen_mk(box_toreg(sub
), sublen
);
658 printf(".ps %s\n", nreg(box
->szreg
));
660 box_beforeput(box
, T_LEFT
, 0);
661 box_bracket(box
, bracsign(left
, 1), sublen
[2], sublen
[3]);
662 box_afterput(box
, T_LEFT
);
664 box_merge(box
, sub
, 0);
666 box_beforeput(box
, T_RIGHT
, 0);
667 box_bracket(box
, bracsign(right
, 0), sublen
[2], sublen
[3]);
668 box_afterput(box
, T_RIGHT
);
673 /* construct a radical with height at least len and width wd in dst register */
674 static void sqrt_rad(int dst
, int len
, int wd
)
676 char *sizes
[NSIZES
] = {NULL
};
679 int sr_sz
= nregmk();
680 int wd_diff
= nregmk(); /* if wd is shorter than \(rn */
681 int sr_rx
= nregmk(); /* the right-most horizontal position of \(sr */
682 int rn_dx
= nregmk(); /* horizontal displacement necessary for \(rn */
685 char *top
= NULL
, *mid
= NULL
, *bot
= NULL
, *cen
;
686 printf(".nr %s 0%s/2*11/10\n", nregname(len2
), nreg(len
));
687 printf(".ds %s \"\n", sregname(rad
));
688 /* selecting a radical of the appropriate size */
689 def_pieces("\\(sr", &top
, &mid
, &bot
, &cen
);
690 def_sizes("\\(sr", sizes
);
691 box_bracketsel(rad
, len2
, len2
, sizes
, 0, 0);
692 /* constructing the bracket if needed */
694 printf(".if \\w'%s' ", mid
);
695 printf(".if '%s'' \\{\\\n", sreg(rad
));
696 box_bracketmk(rad
, len2
, top
, mid
, bot
, NULL
);
699 /* enlarging \(sr if no suitable glyph was found */
700 printf(".if '%s'' \\{\\\n", sreg(rad
));
701 blen_mk("\\(sr", srlen
);
702 printf(".ie %s<(%s+%s) .nr %s 0\\n(.s\n",
703 nreg(len
), nreg(srlen
[2]), nreg(srlen
[3]), nregname(sr_sz
));
704 printf(".el .nr %s 0%s*\\n(.s/(%s+%s-(%dm/100u))+1\n",
705 nregname(sr_sz
), nreg(len
),
706 nreg(srlen
[2]), nreg(srlen
[3]), e_rulethickness
);
707 printf(".ps %s\n", nreg(sr_sz
));
708 printf(".ds %s \"\\(sr\n", sregname(rad
));
711 /* adding the handle */
712 blen_mk(sreg(rad
), srlen
);
713 printf(".nr %s \\n[bburx]\n", nregname(sr_rx
));
714 blen_mk("\\(rn", rnlen
);
715 printf(".nr %s 0%s-\\n[bbllx]-(%dm/100u)\n",
716 nregname(rn_dx
), nreg(sr_rx
), e_rulethickness
);
717 printf(".nr %s 0\n", nregname(wd_diff
));
718 printf(".if %s<%s .nr %s 0%s-%s\n",
719 nreg(wd
), nreg(rnlen
[0]),
720 nregname(wd_diff
), nreg(rnlen
[0]), nreg(wd
));
721 /* output the radical; align the top of the radical to the baseline */
722 printf(".ds %s \"\\s[\\n(.s]\\f[\\n(.f]"
723 "\\v'%su'\\h'%su'\\l'%su+%su\\(rn'\\h'-%su'\\v'-%su'"
724 "\\h'-%su-%su'\\v'%su'%s\\v'-%su'\\h'%su+%su'\n",
726 nreg(rnlen
[2]), nreg(rn_dx
), nreg(wd
), nreg(wd_diff
),
727 nreg(rn_dx
), nreg(rnlen
[2]), nreg(wd
), nreg(wd_diff
),
728 nreg(srlen
[2]), sreg(rad
), nreg(srlen
[2]), nreg(wd
), nreg(wd_diff
));
738 void box_sqrt(struct box
*box
, struct box
*sub
)
743 int rad_rise
= nregmk();
744 int min_ht
= nregmk();
745 box_italiccorrection(sub
);
746 box_beforeput(box
, T_ORD
, 0);
747 blen_mk(box_toreg(sub
), sublen
);
748 printf(".ps %s\n", nreg(box
->szreg
));
750 printf(".nr %s 0%s+%s+(2*%dm/100u)+(%dm/100u/4)\n",
751 nregname(min_ht
), nreg(sublen
[2]), nreg(sublen
[3]),
753 TS_DX(box
->style
) ? e_xheight
: e_rulethickness
);
754 sqrt_rad(rad
, min_ht
, sublen
[0]);
755 blen_mk(sreg(rad
), radlen
);
756 printf(".nr %s 0(%dm/100u)+(%dm/100u/4)\n",
757 nregname(rad_rise
), e_rulethickness
,
758 TS_DX(box
->style
) ? e_xheight
: e_rulethickness
);
759 printf(".if %s>(%s+%s+%s) .nr %s (%s+%s-%s-%s)/2\n",
760 nreg(radlen
[3]), nreg(sublen
[2]), nreg(sublen
[3]),
761 nreg(rad_rise
), nregname(rad_rise
),
762 nreg(rad_rise
), nreg(radlen
[3]), nreg(sublen
[2]),
764 printf(".nr %s +%s\n", nregname(rad_rise
), nreg(sublen
[2]));
765 /* output the radical */
766 box_putf(box
, "\\v'-%su'%s\\v'%su'\\h'-%su'%s",
767 nreg(rad_rise
), sreg(rad
), nreg(rad_rise
),
768 nreg(sublen
[0]), box_toreg(sub
));
769 box_afterput(box
, T_ORD
);
778 void box_bar(struct box
*box
)
780 int box_wd
= nregmk();
781 int box_ht
= nregmk();
782 int bar_wd
= nregmk();
783 int bar_dp
= nregmk();
784 int bar_rise
= nregmk();
785 box_italiccorrection(box
);
786 printf(".ps %s\n", nreg(box
->szreg
));
787 tok_len("\\(ru", bar_wd
, 0, 0, bar_dp
);
788 tok_dim(box_toreg(box
), box_wd
, box_ht
, 0);
789 printf(".if %su<(%dm/100u) .nr %s 0%dm/100u\n",
790 nreg(box_ht
), e_xheight
, nregname(box_ht
), e_xheight
);
791 printf(".nr %s 0%su+%su+(3*%dm/100u)\n",
792 nregname(bar_rise
), nreg(box_ht
),
793 nreg(bar_dp
), e_rulethickness
);
794 box_putf(box
, "\\v'-%su'\\s%s\\f[\\n(.f]\\l'-%su\\(ru'\\v'%su'",
795 nreg(bar_rise
), escarg(nreg(box
->szreg
)),
796 nreg(box_wd
), nreg(bar_rise
));
804 void box_accent(struct box
*box
, char *c
)
806 int box_wd
= nregmk();
807 int box_ht
= nregmk();
808 int ac_rise
= nregmk();
809 int ac_wd
= nregmk();
810 int ac_dp
= nregmk();
811 box_italiccorrection(box
);
812 printf(".ps %s\n", nreg(box
->szreg
));
813 tok_len(c
, ac_wd
, 0, 0, ac_dp
);
814 tok_dim(box_toreg(box
), box_wd
, box_ht
, 0);
815 printf(".if %su<(%dm/100u) .nr %s 0%dm/100u\n",
816 nreg(box_ht
), e_xheight
, nregname(box_ht
), e_xheight
);
817 printf(".nr %s 0%su+%su+(%sp*10u/100u)\n",
818 nregname(ac_rise
), nreg(box_ht
),
819 nreg(ac_dp
), nreg(box
->szreg
));
820 box_putf(box
, "\\v'-%su'\\h'-%su-%su/2u'\\s%s\\f[\\n(.f]%s\\h'%su-%su/2u'\\v'%su'",
821 nreg(ac_rise
), nreg(box_wd
), nreg(ac_wd
),
822 escarg(nreg(box
->szreg
)), c
, nreg(box_wd
),
823 nreg(ac_wd
), nreg(ac_rise
));
831 void box_under(struct box
*box
)
833 int box_wd
= nregmk();
834 int box_dp
= nregmk();
835 int bar_wd
= nregmk();
836 int bar_ht
= nregmk();
837 int bar_fall
= nregmk();
838 box_italiccorrection(box
);
839 printf(".ps %s\n", nreg(box
->szreg
));
840 tok_len("\\(ul", bar_wd
, 0, bar_ht
, 0);
841 tok_dim(box_toreg(box
), box_wd
, 0, box_dp
);
842 printf(".if %s<0 .nr %s 0\n", nreg(box_dp
), nregname(box_dp
));
843 printf(".nr %s 0%su+%su+(3*%dm/100u)\n",
844 nregname(bar_fall
), nreg(box_dp
),
845 nreg(bar_ht
), e_rulethickness
);
846 box_putf(box
, "\\v'%su'\\s%s\\f[\\n(.f]\\l'-%su\\(ul'\\v'-%su'",
847 nreg(bar_fall
), escarg(nreg(box
->szreg
)),
848 nreg(box_wd
), nreg(bar_fall
));
856 char *box_toreg(struct box
*box
)
860 printf(".ds %s \"%s\n", sregname(box
->reg
), box_buf(box
));
862 return sreg(box
->reg
);
865 int box_empty(struct box
*box
)
867 return !strlen(box_buf(box
));
870 void box_vcenter(struct box
*box
, struct box
*sub
)
876 box_beforeput(box
, sub
->tbeg
, 0);
877 tok_dim(box_toreg(sub
), wd
, ht
, dp
);
878 printf(".nr %s 0-%s+%s/2-(%sp*%du/100u)\n", nregname(fall
),
879 nreg(dp
), nreg(ht
), nreg(box
->szreg
), e_axisheight
);
880 box_putf(box
, "\\v'%su'%s\\v'-%su'",
881 nreg(fall
), box_toreg(sub
), nreg(fall
));
883 box_afterput(box
, sub
->tcur
);
890 /* include line-space requests */
891 void box_vertspace(struct box
*box
)
893 int box_wd
= nregmk();
894 int htroom
= nregmk();
895 int dproom
= nregmk();
896 box_italiccorrection(box
);
897 /* amount of room available before and after this line */
898 printf(".nr %s 0+\\n(.vu-%sp+(%sp*%du/100u)\n",
899 nregname(htroom
), nreg(box
->szreg
),
900 nreg(box
->szreg
), e_bodyheight
);
901 printf(".nr %s 0+\\n(.vu-%sp+(%sp*%du/100u)\n",
902 nregname(dproom
), nreg(box
->szreg
),
903 nreg(box
->szreg
), e_bodydepth
);
904 /* appending \x requests */
905 tok_dim(box_toreg(box
), box_wd
, 0, 0);
906 printf(".if -\\n[bbury]>%s .as %s \"\\x'\\n[bbury]u+%su'\n",
907 nreg(htroom
), sregname(box
->reg
), nreg(htroom
));
908 printf(".if \\n[bblly]>%s .as %s \"\\x'\\n[bblly]u-%su'\n",
909 nreg(dproom
), sregname(box
->reg
), nreg(dproom
));
915 /* put the current width to the given number register */
916 void box_markpos(struct box
*box
, char *reg
)
921 /* initialize the length of a pile or column of a matrix */
922 static void box_colinit(struct box
**pile
, int n
,
923 int plen
[][4], int wd
, int ht
)
926 for (i
= 0; i
< n
; i
++)
928 box_italiccorrection(pile
[i
]);
929 for (i
= 0; i
< n
; i
++)
930 blen_mk(pile
[i
] ? box_toreg(pile
[i
]) : "", plen
[i
]);
931 printf(".nr %s 0%s\n", nregname(wd
), nreg(plen
[0][0]));
932 printf(".nr %s 0%s\n", nregname(ht
), nreg(plen
[0][2]));
933 /* finding the maximum width */
934 for (i
= 1; i
< n
; i
++) {
935 printf(".if %s>%s .nr %s 0+%s\n",
936 nreg(plen
[i
][0]), nreg(wd
),
937 nregname(wd
), nreg(plen
[i
][0]));
939 /* finding the maximum height (vertical length) */
940 for (i
= 1; i
< n
; i
++) {
941 printf(".if %s+%s>%s .nr %s 0+%s+%s\n",
942 nreg(plen
[i
- 1][3]), nreg(plen
[i
][2]), nreg(ht
),
943 nregname(ht
), nreg(plen
[i
- 1][3]), nreg(plen
[i
][2]));
945 /* maximum height and the depth of the last row */
946 printf(".if %s>%s .nr %s 0+%s\n",
947 nreg(plen
[n
- 1][3]), nreg(ht
),
948 nregname(ht
), nreg(plen
[n
- 1][3]));
951 /* append the give pile to box */
952 static void box_colput(struct box
**pile
, int n
, struct box
*box
,
953 int adj
, int plen
[][4], int wd
, int ht
)
956 box_putf(box
, "\\v'-%du*%su/2u'", n
- 1, nreg(ht
));
957 /* adding the entries */
958 for (i
= 0; i
< n
; i
++) {
960 box_putf(box
, "\\h'%su-%su/2u'",
961 nreg(wd
), nreg(plen
[i
][0]));
963 box_putf(box
, "\\h'%su-%su'",
964 nreg(wd
), nreg(plen
[i
][0]));
965 box_putf(box
, "\\v'%su'%s", i
? nreg(ht
) : "0",
966 pile
[i
] ? box_toreg(pile
[i
]) : "");
968 box_putf(box
, "\\h'-%su'", nreg(plen
[i
][0]));
970 box_putf(box
, "\\h'-%su+(%su-%su/2u)'",
971 nreg(wd
), nreg(wd
), nreg(plen
[i
][0]));
973 box_putf(box
, "\\h'-%su'", nreg(wd
));
975 box_putf(box
, "\\v'-%du*%su/2u'\\h'%su'", n
- 1, nreg(ht
), nreg(wd
));
978 /* free the registers allocated for this pile */
979 static void box_coldone(struct box
**pile
, int n
, int plen
[][4])
982 for (i
= 0; i
< n
; i
++)
986 /* calculate the number of entries in the given pile */
987 static int box_colnrows(struct box
*cols
[])
990 while (n
< NPILES
&& cols
[n
])
995 void box_pile(struct box
*box
, struct box
**pile
, int adj
, int rowspace
)
998 int max_wd
= nregmk();
999 int max_ht
= nregmk();
1000 int n
= box_colnrows(pile
);
1001 box_beforeput(box
, T_INNER
, 0);
1002 box_colinit(pile
, n
, plen
, max_wd
, max_ht
);
1003 /* inserting spaces between entries */
1004 printf(".if %s<(%sp*%du/100u) .nr %s (%sp*%du/100u)\n",
1005 nreg(max_ht
), nreg(box
->szreg
), e_baselinesep
,
1006 nregname(max_ht
), nreg(box
->szreg
), e_baselinesep
);
1008 printf(".nr %s +(%sp*%du/100u)\n",
1009 nregname(max_ht
), nreg(box
->szreg
), rowspace
);
1010 /* adding the entries */
1011 box_colput(pile
, n
, box
, adj
, plen
, max_wd
, max_ht
);
1012 box_coldone(pile
, n
, plen
);
1013 box_afterput(box
, T_INNER
);
1019 void box_matrix(struct box
*box
, int ncols
, struct box
*cols
[][NPILES
],
1020 int *adj
, int colspace
, int rowspace
)
1022 int plen
[NPILES
][NPILES
][4];
1025 int max_ht
= nregmk();
1026 int max_wd
= nregmk();
1029 box_beforeput(box
, T_INNER
, 0);
1030 for (i
= 0; i
< ncols
; i
++)
1031 if (box_colnrows(cols
[i
]) > nrows
)
1032 nrows
= box_colnrows(cols
[i
]);
1033 for (i
= 0; i
< ncols
; i
++)
1035 for (i
= 0; i
< ncols
; i
++)
1037 /* initializing the columns */
1038 for (i
= 0; i
< ncols
; i
++)
1039 box_colinit(cols
[i
], nrows
, plen
[i
], wd
[i
], ht
[i
]);
1040 /* finding the maximum width and height */
1041 printf(".nr %s 0%s\n", nregname(max_wd
), nreg(wd
[0]));
1042 printf(".nr %s 0%s\n", nregname(max_ht
), nreg(ht
[0]));
1043 for (i
= 1; i
< ncols
; i
++) {
1044 printf(".if %s>%s .nr %s 0+%s\n",
1045 nreg(wd
[i
]), nreg(max_wd
),
1046 nregname(max_wd
), nreg(wd
[i
]));
1048 for (i
= 1; i
< ncols
; i
++) {
1049 printf(".if %s>%s .nr %s 0+%s\n",
1050 nreg(ht
[i
]), nreg(max_ht
),
1051 nregname(max_ht
), nreg(ht
[i
]));
1053 /* inserting spaces between rows */
1054 printf(".if %s<(%sp*%du/100u) .nr %s (%sp*%du/100u)\n",
1055 nreg(max_ht
), nreg(box
->szreg
), e_baselinesep
,
1056 nregname(max_ht
), nreg(box
->szreg
), e_baselinesep
);
1058 printf(".nr %s +(%sp*%du/100u)\n",
1059 nregname(max_ht
), nreg(box
->szreg
), rowspace
);
1060 /* printing the columns */
1061 for (i
= 0; i
< ncols
; i
++) {
1062 if (i
) /* space between columns */
1063 box_putf(box
, "\\h'%sp*%du/100u'",
1064 nreg(box
->szreg
), e_columnsep
+ colspace
);
1065 box_colput(cols
[i
], nrows
, box
, adj
[i
],
1066 plen
[i
], max_wd
, max_ht
);
1068 box_afterput(box
, T_INNER
);
1070 for (i
= 0; i
< ncols
; i
++)
1071 box_coldone(cols
[i
], nrows
, plen
[i
]);
1072 for (i
= 0; i
< ncols
; i
++)
1074 for (i
= 0; i
< ncols
; i
++)