1*7295610fSBaptiste Daroussin /* $Id: roff_term.c,v 1.19 2019/01/04 03:24:33 schwarze Exp $ */ 261d06d6bSBaptiste Daroussin /* 3*7295610fSBaptiste Daroussin * Copyright (c) 2010,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org> 461d06d6bSBaptiste Daroussin * 561d06d6bSBaptiste Daroussin * Permission to use, copy, modify, and distribute this software for any 661d06d6bSBaptiste Daroussin * purpose with or without fee is hereby granted, provided that the above 761d06d6bSBaptiste Daroussin * copyright notice and this permission notice appear in all copies. 861d06d6bSBaptiste Daroussin * 961d06d6bSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1061d06d6bSBaptiste Daroussin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1161d06d6bSBaptiste Daroussin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1261d06d6bSBaptiste Daroussin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1361d06d6bSBaptiste Daroussin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1461d06d6bSBaptiste Daroussin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1561d06d6bSBaptiste Daroussin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1661d06d6bSBaptiste Daroussin */ 1761d06d6bSBaptiste Daroussin #include <sys/types.h> 1861d06d6bSBaptiste Daroussin 1961d06d6bSBaptiste Daroussin #include <assert.h> 20*7295610fSBaptiste Daroussin #include <stdio.h> 21*7295610fSBaptiste Daroussin #include <string.h> 2261d06d6bSBaptiste Daroussin 2361d06d6bSBaptiste Daroussin #include "mandoc.h" 2461d06d6bSBaptiste Daroussin #include "roff.h" 2561d06d6bSBaptiste Daroussin #include "out.h" 2661d06d6bSBaptiste Daroussin #include "term.h" 2761d06d6bSBaptiste Daroussin 2861d06d6bSBaptiste Daroussin #define ROFF_TERM_ARGS struct termp *p, const struct roff_node *n 2961d06d6bSBaptiste Daroussin 3061d06d6bSBaptiste Daroussin typedef void (*roff_term_pre_fp)(ROFF_TERM_ARGS); 3161d06d6bSBaptiste Daroussin 3261d06d6bSBaptiste Daroussin static void roff_term_pre_br(ROFF_TERM_ARGS); 3361d06d6bSBaptiste Daroussin static void roff_term_pre_ce(ROFF_TERM_ARGS); 3461d06d6bSBaptiste Daroussin static void roff_term_pre_ft(ROFF_TERM_ARGS); 3561d06d6bSBaptiste Daroussin static void roff_term_pre_ll(ROFF_TERM_ARGS); 3661d06d6bSBaptiste Daroussin static void roff_term_pre_mc(ROFF_TERM_ARGS); 3761d06d6bSBaptiste Daroussin static void roff_term_pre_po(ROFF_TERM_ARGS); 3861d06d6bSBaptiste Daroussin static void roff_term_pre_sp(ROFF_TERM_ARGS); 3961d06d6bSBaptiste Daroussin static void roff_term_pre_ta(ROFF_TERM_ARGS); 4061d06d6bSBaptiste Daroussin static void roff_term_pre_ti(ROFF_TERM_ARGS); 4161d06d6bSBaptiste Daroussin 4261d06d6bSBaptiste Daroussin static const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = { 4361d06d6bSBaptiste Daroussin roff_term_pre_br, /* br */ 4461d06d6bSBaptiste Daroussin roff_term_pre_ce, /* ce */ 45*7295610fSBaptiste Daroussin roff_term_pre_br, /* fi */ 4661d06d6bSBaptiste Daroussin roff_term_pre_ft, /* ft */ 4761d06d6bSBaptiste Daroussin roff_term_pre_ll, /* ll */ 4861d06d6bSBaptiste Daroussin roff_term_pre_mc, /* mc */ 49*7295610fSBaptiste Daroussin roff_term_pre_br, /* nf */ 5061d06d6bSBaptiste Daroussin roff_term_pre_po, /* po */ 5161d06d6bSBaptiste Daroussin roff_term_pre_ce, /* rj */ 5261d06d6bSBaptiste Daroussin roff_term_pre_sp, /* sp */ 5361d06d6bSBaptiste Daroussin roff_term_pre_ta, /* ta */ 5461d06d6bSBaptiste Daroussin roff_term_pre_ti, /* ti */ 5561d06d6bSBaptiste Daroussin }; 5661d06d6bSBaptiste Daroussin 5761d06d6bSBaptiste Daroussin 5861d06d6bSBaptiste Daroussin void 5961d06d6bSBaptiste Daroussin roff_term_pre(struct termp *p, const struct roff_node *n) 6061d06d6bSBaptiste Daroussin { 6161d06d6bSBaptiste Daroussin assert(n->tok < ROFF_MAX); 6261d06d6bSBaptiste Daroussin (*roff_term_pre_acts[n->tok])(p, n); 6361d06d6bSBaptiste Daroussin } 6461d06d6bSBaptiste Daroussin 6561d06d6bSBaptiste Daroussin static void 6661d06d6bSBaptiste Daroussin roff_term_pre_br(ROFF_TERM_ARGS) 6761d06d6bSBaptiste Daroussin { 6861d06d6bSBaptiste Daroussin term_newln(p); 6961d06d6bSBaptiste Daroussin if (p->flags & TERMP_BRIND) { 7061d06d6bSBaptiste Daroussin p->tcol->offset = p->tcol->rmargin; 7161d06d6bSBaptiste Daroussin p->tcol->rmargin = p->maxrmargin; 72*7295610fSBaptiste Daroussin p->trailspace = 0; 7361d06d6bSBaptiste Daroussin p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); 74*7295610fSBaptiste Daroussin p->flags |= TERMP_NOSPACE; 7561d06d6bSBaptiste Daroussin } 7661d06d6bSBaptiste Daroussin } 7761d06d6bSBaptiste Daroussin 7861d06d6bSBaptiste Daroussin static void 7961d06d6bSBaptiste Daroussin roff_term_pre_ce(ROFF_TERM_ARGS) 8061d06d6bSBaptiste Daroussin { 8161d06d6bSBaptiste Daroussin const struct roff_node *nc1, *nc2; 8261d06d6bSBaptiste Daroussin 8361d06d6bSBaptiste Daroussin roff_term_pre_br(p, n); 84*7295610fSBaptiste Daroussin p->flags |= n->tok == ROFF_ce ? TERMP_CENTER : TERMP_RIGHT; 8561d06d6bSBaptiste Daroussin nc1 = n->child->next; 8661d06d6bSBaptiste Daroussin while (nc1 != NULL) { 8761d06d6bSBaptiste Daroussin nc2 = nc1; 8861d06d6bSBaptiste Daroussin do { 8961d06d6bSBaptiste Daroussin nc2 = nc2->next; 9061d06d6bSBaptiste Daroussin } while (nc2 != NULL && (nc2->type != ROFFT_TEXT || 9161d06d6bSBaptiste Daroussin (nc2->flags & NODE_LINE) == 0)); 9261d06d6bSBaptiste Daroussin while (nc1 != nc2) { 9361d06d6bSBaptiste Daroussin if (nc1->type == ROFFT_TEXT) 9461d06d6bSBaptiste Daroussin term_word(p, nc1->string); 9561d06d6bSBaptiste Daroussin else 9661d06d6bSBaptiste Daroussin roff_term_pre(p, nc1); 9761d06d6bSBaptiste Daroussin nc1 = nc1->next; 9861d06d6bSBaptiste Daroussin } 9961d06d6bSBaptiste Daroussin p->flags |= TERMP_NOSPACE; 10061d06d6bSBaptiste Daroussin term_flushln(p); 10161d06d6bSBaptiste Daroussin } 102*7295610fSBaptiste Daroussin p->flags &= ~(TERMP_CENTER | TERMP_RIGHT); 10361d06d6bSBaptiste Daroussin } 10461d06d6bSBaptiste Daroussin 10561d06d6bSBaptiste Daroussin static void 10661d06d6bSBaptiste Daroussin roff_term_pre_ft(ROFF_TERM_ARGS) 10761d06d6bSBaptiste Daroussin { 108*7295610fSBaptiste Daroussin const char *cp; 109*7295610fSBaptiste Daroussin 110*7295610fSBaptiste Daroussin cp = n->child->string; 111*7295610fSBaptiste Daroussin switch (mandoc_font(cp, (int)strlen(cp))) { 112*7295610fSBaptiste Daroussin case ESCAPE_FONTBOLD: 11361d06d6bSBaptiste Daroussin term_fontrepl(p, TERMFONT_BOLD); 11461d06d6bSBaptiste Daroussin break; 115*7295610fSBaptiste Daroussin case ESCAPE_FONTITALIC: 11661d06d6bSBaptiste Daroussin term_fontrepl(p, TERMFONT_UNDER); 11761d06d6bSBaptiste Daroussin break; 118*7295610fSBaptiste Daroussin case ESCAPE_FONTBI: 119*7295610fSBaptiste Daroussin term_fontrepl(p, TERMFONT_BI); 120*7295610fSBaptiste Daroussin break; 121*7295610fSBaptiste Daroussin case ESCAPE_FONTPREV: 12261d06d6bSBaptiste Daroussin term_fontlast(p); 12361d06d6bSBaptiste Daroussin break; 124*7295610fSBaptiste Daroussin case ESCAPE_FONTROMAN: 125*7295610fSBaptiste Daroussin case ESCAPE_FONTCW: 12661d06d6bSBaptiste Daroussin term_fontrepl(p, TERMFONT_NONE); 12761d06d6bSBaptiste Daroussin break; 12861d06d6bSBaptiste Daroussin default: 12961d06d6bSBaptiste Daroussin break; 13061d06d6bSBaptiste Daroussin } 13161d06d6bSBaptiste Daroussin } 13261d06d6bSBaptiste Daroussin 13361d06d6bSBaptiste Daroussin static void 13461d06d6bSBaptiste Daroussin roff_term_pre_ll(ROFF_TERM_ARGS) 13561d06d6bSBaptiste Daroussin { 13661d06d6bSBaptiste Daroussin term_setwidth(p, n->child != NULL ? n->child->string : NULL); 13761d06d6bSBaptiste Daroussin } 13861d06d6bSBaptiste Daroussin 13961d06d6bSBaptiste Daroussin static void 14061d06d6bSBaptiste Daroussin roff_term_pre_mc(ROFF_TERM_ARGS) 14161d06d6bSBaptiste Daroussin { 14261d06d6bSBaptiste Daroussin if (p->col) { 14361d06d6bSBaptiste Daroussin p->flags |= TERMP_NOBREAK; 14461d06d6bSBaptiste Daroussin term_flushln(p); 14561d06d6bSBaptiste Daroussin p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE); 14661d06d6bSBaptiste Daroussin } 14761d06d6bSBaptiste Daroussin if (n->child != NULL) { 14861d06d6bSBaptiste Daroussin p->mc = n->child->string; 14961d06d6bSBaptiste Daroussin p->flags |= TERMP_NEWMC; 15061d06d6bSBaptiste Daroussin } else 15161d06d6bSBaptiste Daroussin p->flags |= TERMP_ENDMC; 15261d06d6bSBaptiste Daroussin } 15361d06d6bSBaptiste Daroussin 15461d06d6bSBaptiste Daroussin static void 15561d06d6bSBaptiste Daroussin roff_term_pre_po(ROFF_TERM_ARGS) 15661d06d6bSBaptiste Daroussin { 15761d06d6bSBaptiste Daroussin struct roffsu su; 15861d06d6bSBaptiste Daroussin static int po, polast; 15961d06d6bSBaptiste Daroussin int ponew; 16061d06d6bSBaptiste Daroussin 16161d06d6bSBaptiste Daroussin if (n->child != NULL && 16261d06d6bSBaptiste Daroussin a2roffsu(n->child->string, &su, SCALE_EM) != NULL) { 16361d06d6bSBaptiste Daroussin ponew = term_hen(p, &su); 16461d06d6bSBaptiste Daroussin if (*n->child->string == '+' || 16561d06d6bSBaptiste Daroussin *n->child->string == '-') 16661d06d6bSBaptiste Daroussin ponew += po; 16761d06d6bSBaptiste Daroussin } else 16861d06d6bSBaptiste Daroussin ponew = polast; 16961d06d6bSBaptiste Daroussin polast = po; 17061d06d6bSBaptiste Daroussin po = ponew; 17161d06d6bSBaptiste Daroussin 17261d06d6bSBaptiste Daroussin ponew = po - polast + (int)p->tcol->offset; 17361d06d6bSBaptiste Daroussin p->tcol->offset = ponew > 0 ? ponew : 0; 17461d06d6bSBaptiste Daroussin } 17561d06d6bSBaptiste Daroussin 17661d06d6bSBaptiste Daroussin static void 17761d06d6bSBaptiste Daroussin roff_term_pre_sp(ROFF_TERM_ARGS) 17861d06d6bSBaptiste Daroussin { 17961d06d6bSBaptiste Daroussin struct roffsu su; 18061d06d6bSBaptiste Daroussin int len; 18161d06d6bSBaptiste Daroussin 18261d06d6bSBaptiste Daroussin if (n->child != NULL) { 18361d06d6bSBaptiste Daroussin if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL) 18461d06d6bSBaptiste Daroussin su.scale = 1.0; 18561d06d6bSBaptiste Daroussin len = term_vspan(p, &su); 18661d06d6bSBaptiste Daroussin } else 18761d06d6bSBaptiste Daroussin len = 1; 18861d06d6bSBaptiste Daroussin 18961d06d6bSBaptiste Daroussin if (len < 0) 19061d06d6bSBaptiste Daroussin p->skipvsp -= len; 19161d06d6bSBaptiste Daroussin else 19261d06d6bSBaptiste Daroussin while (len--) 19361d06d6bSBaptiste Daroussin term_vspace(p); 19461d06d6bSBaptiste Daroussin 19561d06d6bSBaptiste Daroussin roff_term_pre_br(p, n); 19661d06d6bSBaptiste Daroussin } 19761d06d6bSBaptiste Daroussin 19861d06d6bSBaptiste Daroussin static void 19961d06d6bSBaptiste Daroussin roff_term_pre_ta(ROFF_TERM_ARGS) 20061d06d6bSBaptiste Daroussin { 20161d06d6bSBaptiste Daroussin term_tab_set(p, NULL); 20261d06d6bSBaptiste Daroussin for (n = n->child; n != NULL; n = n->next) 20361d06d6bSBaptiste Daroussin term_tab_set(p, n->string); 20461d06d6bSBaptiste Daroussin } 20561d06d6bSBaptiste Daroussin 20661d06d6bSBaptiste Daroussin static void 20761d06d6bSBaptiste Daroussin roff_term_pre_ti(ROFF_TERM_ARGS) 20861d06d6bSBaptiste Daroussin { 20961d06d6bSBaptiste Daroussin struct roffsu su; 21061d06d6bSBaptiste Daroussin const char *cp; 21161d06d6bSBaptiste Daroussin int len, sign; 21261d06d6bSBaptiste Daroussin 21361d06d6bSBaptiste Daroussin roff_term_pre_br(p, n); 21461d06d6bSBaptiste Daroussin 21561d06d6bSBaptiste Daroussin if (n->child == NULL) 21661d06d6bSBaptiste Daroussin return; 21761d06d6bSBaptiste Daroussin cp = n->child->string; 21861d06d6bSBaptiste Daroussin if (*cp == '+') { 21961d06d6bSBaptiste Daroussin sign = 1; 22061d06d6bSBaptiste Daroussin cp++; 22161d06d6bSBaptiste Daroussin } else if (*cp == '-') { 22261d06d6bSBaptiste Daroussin sign = -1; 22361d06d6bSBaptiste Daroussin cp++; 22461d06d6bSBaptiste Daroussin } else 22561d06d6bSBaptiste Daroussin sign = 0; 22661d06d6bSBaptiste Daroussin 22761d06d6bSBaptiste Daroussin if (a2roffsu(cp, &su, SCALE_EM) == NULL) 22861d06d6bSBaptiste Daroussin return; 22961d06d6bSBaptiste Daroussin len = term_hen(p, &su); 23061d06d6bSBaptiste Daroussin 23161d06d6bSBaptiste Daroussin if (sign == 0) { 23261d06d6bSBaptiste Daroussin p->ti = len - p->tcol->offset; 23361d06d6bSBaptiste Daroussin p->tcol->offset = len; 23461d06d6bSBaptiste Daroussin } else if (sign == 1) { 23561d06d6bSBaptiste Daroussin p->ti = len; 23661d06d6bSBaptiste Daroussin p->tcol->offset += len; 23761d06d6bSBaptiste Daroussin } else if ((size_t)len < p->tcol->offset) { 23861d06d6bSBaptiste Daroussin p->ti = -len; 23961d06d6bSBaptiste Daroussin p->tcol->offset -= len; 24061d06d6bSBaptiste Daroussin } else { 24161d06d6bSBaptiste Daroussin p->ti = -p->tcol->offset; 24261d06d6bSBaptiste Daroussin p->tcol->offset = 0; 24361d06d6bSBaptiste Daroussin } 24461d06d6bSBaptiste Daroussin } 245