1*e501e731Sschwarze /* $OpenBSD: roff_term.c,v 1.16 2018/12/14 01:17:46 schwarze Exp $ */ 296a5de47Sschwarze /* 39b153f25Sschwarze * Copyright (c) 2010,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org> 496a5de47Sschwarze * 596a5de47Sschwarze * Permission to use, copy, modify, and distribute this software for any 696a5de47Sschwarze * purpose with or without fee is hereby granted, provided that the above 796a5de47Sschwarze * copyright notice and this permission notice appear in all copies. 896a5de47Sschwarze * 996a5de47Sschwarze * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1096a5de47Sschwarze * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1196a5de47Sschwarze * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1296a5de47Sschwarze * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1396a5de47Sschwarze * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1496a5de47Sschwarze * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1596a5de47Sschwarze * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1696a5de47Sschwarze */ 1796a5de47Sschwarze #include <sys/types.h> 1896a5de47Sschwarze 1996a5de47Sschwarze #include <assert.h> 20*e501e731Sschwarze #include <stdio.h> 2196a5de47Sschwarze 22f3476b07Sschwarze #include "mandoc.h" 2396a5de47Sschwarze #include "roff.h" 2496a5de47Sschwarze #include "out.h" 2596a5de47Sschwarze #include "term.h" 2696a5de47Sschwarze 2796a5de47Sschwarze #define ROFF_TERM_ARGS struct termp *p, const struct roff_node *n 2896a5de47Sschwarze 2996a5de47Sschwarze typedef void (*roff_term_pre_fp)(ROFF_TERM_ARGS); 3096a5de47Sschwarze 3196a5de47Sschwarze static void roff_term_pre_br(ROFF_TERM_ARGS); 32e13b4195Sschwarze static void roff_term_pre_ce(ROFF_TERM_ARGS); 33c4d3fa85Sschwarze static void roff_term_pre_ft(ROFF_TERM_ARGS); 34644b390bSschwarze static void roff_term_pre_ll(ROFF_TERM_ARGS); 3524f1eaadSschwarze static void roff_term_pre_mc(ROFF_TERM_ARGS); 36af1e8f15Sschwarze static void roff_term_pre_po(ROFF_TERM_ARGS); 376561cb23Sschwarze static void roff_term_pre_sp(ROFF_TERM_ARGS); 38f7242c43Sschwarze static void roff_term_pre_ta(ROFF_TERM_ARGS); 3911d70615Sschwarze static void roff_term_pre_ti(ROFF_TERM_ARGS); 4096a5de47Sschwarze 4196a5de47Sschwarze static const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = { 4296a5de47Sschwarze roff_term_pre_br, /* br */ 43e13b4195Sschwarze roff_term_pre_ce, /* ce */ 44c4d3fa85Sschwarze roff_term_pre_ft, /* ft */ 4524f1eaadSschwarze roff_term_pre_ll, /* ll */ 4624f1eaadSschwarze roff_term_pre_mc, /* mc */ 47af1e8f15Sschwarze roff_term_pre_po, /* po */ 486de096f4Sschwarze roff_term_pre_ce, /* rj */ 49f7242c43Sschwarze roff_term_pre_sp, /* sp */ 50f7242c43Sschwarze roff_term_pre_ta, /* ta */ 5111d70615Sschwarze roff_term_pre_ti, /* ti */ 5296a5de47Sschwarze }; 5396a5de47Sschwarze 5496a5de47Sschwarze 5596a5de47Sschwarze void 5696a5de47Sschwarze roff_term_pre(struct termp *p, const struct roff_node *n) 5796a5de47Sschwarze { 5896a5de47Sschwarze assert(n->tok < ROFF_MAX); 5996a5de47Sschwarze (*roff_term_pre_acts[n->tok])(p, n); 6096a5de47Sschwarze } 6196a5de47Sschwarze 6296a5de47Sschwarze static void 6396a5de47Sschwarze roff_term_pre_br(ROFF_TERM_ARGS) 6496a5de47Sschwarze { 6596a5de47Sschwarze term_newln(p); 6696a5de47Sschwarze if (p->flags & TERMP_BRIND) { 67e93ea447Sschwarze p->tcol->offset = p->tcol->rmargin; 68e93ea447Sschwarze p->tcol->rmargin = p->maxrmargin; 6996a5de47Sschwarze p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); 7096a5de47Sschwarze } 7196a5de47Sschwarze } 72c4d3fa85Sschwarze 73c4d3fa85Sschwarze static void 74e13b4195Sschwarze roff_term_pre_ce(ROFF_TERM_ARGS) 75e13b4195Sschwarze { 766de096f4Sschwarze const struct roff_node *nc1, *nc2; 77e13b4195Sschwarze size_t len, lm; 78e13b4195Sschwarze 79e13b4195Sschwarze roff_term_pre_br(p, n); 80e93ea447Sschwarze lm = p->tcol->offset; 816de096f4Sschwarze nc1 = n->child->next; 826de096f4Sschwarze while (nc1 != NULL) { 836de096f4Sschwarze nc2 = nc1; 84e13b4195Sschwarze len = 0; 85e13b4195Sschwarze do { 866de096f4Sschwarze if (nc2->type == ROFFT_TEXT) { 87e13b4195Sschwarze if (len) 88e13b4195Sschwarze len++; 896de096f4Sschwarze len += term_strlen(p, nc2->string); 90e13b4195Sschwarze } 916de096f4Sschwarze nc2 = nc2->next; 926de096f4Sschwarze } while (nc2 != NULL && (nc2->type != ROFFT_TEXT || 936de096f4Sschwarze (nc2->flags & NODE_LINE) == 0)); 94e93ea447Sschwarze p->tcol->offset = len >= p->tcol->rmargin ? 0 : 95e93ea447Sschwarze lm + len >= p->tcol->rmargin ? p->tcol->rmargin - len : 966de096f4Sschwarze n->tok == ROFF_rj ? p->tcol->rmargin - len : 97e93ea447Sschwarze (lm + p->tcol->rmargin - len) / 2; 986de096f4Sschwarze while (nc1 != nc2) { 996de096f4Sschwarze if (nc1->type == ROFFT_TEXT) 1006de096f4Sschwarze term_word(p, nc1->string); 101e13b4195Sschwarze else 1026de096f4Sschwarze roff_term_pre(p, nc1); 1036de096f4Sschwarze nc1 = nc1->next; 104e13b4195Sschwarze } 105e13b4195Sschwarze p->flags |= TERMP_NOSPACE; 106e13b4195Sschwarze term_flushln(p); 107e13b4195Sschwarze } 108e93ea447Sschwarze p->tcol->offset = lm; 109e13b4195Sschwarze } 110e13b4195Sschwarze 111e13b4195Sschwarze static void 112c4d3fa85Sschwarze roff_term_pre_ft(ROFF_TERM_ARGS) 113c4d3fa85Sschwarze { 1149b153f25Sschwarze const char *cp; 1159b153f25Sschwarze 1169b153f25Sschwarze if (*(cp = n->child->string) == 'C') 1179b153f25Sschwarze cp++; 1189b153f25Sschwarze 1199b153f25Sschwarze switch (*cp) { 120c4d3fa85Sschwarze case '4': 121c4d3fa85Sschwarze case '3': 122c4d3fa85Sschwarze case 'B': 123c4d3fa85Sschwarze term_fontrepl(p, TERMFONT_BOLD); 124c4d3fa85Sschwarze break; 125c4d3fa85Sschwarze case '2': 126c4d3fa85Sschwarze case 'I': 127c4d3fa85Sschwarze term_fontrepl(p, TERMFONT_UNDER); 128c4d3fa85Sschwarze break; 129c4d3fa85Sschwarze case 'P': 130c4d3fa85Sschwarze term_fontlast(p); 131c4d3fa85Sschwarze break; 132c4d3fa85Sschwarze case '1': 133c4d3fa85Sschwarze case 'C': 134c4d3fa85Sschwarze case 'R': 135c4d3fa85Sschwarze term_fontrepl(p, TERMFONT_NONE); 136c4d3fa85Sschwarze break; 137c4d3fa85Sschwarze default: 138c4d3fa85Sschwarze break; 139c4d3fa85Sschwarze } 140c4d3fa85Sschwarze } 141644b390bSschwarze 142644b390bSschwarze static void 143644b390bSschwarze roff_term_pre_ll(ROFF_TERM_ARGS) 144644b390bSschwarze { 145644b390bSschwarze term_setwidth(p, n->child != NULL ? n->child->string : NULL); 146644b390bSschwarze } 1476561cb23Sschwarze 1486561cb23Sschwarze static void 14924f1eaadSschwarze roff_term_pre_mc(ROFF_TERM_ARGS) 15024f1eaadSschwarze { 15124f1eaadSschwarze if (p->col) { 15224f1eaadSschwarze p->flags |= TERMP_NOBREAK; 15324f1eaadSschwarze term_flushln(p); 15424f1eaadSschwarze p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE); 15524f1eaadSschwarze } 15624f1eaadSschwarze if (n->child != NULL) { 15724f1eaadSschwarze p->mc = n->child->string; 15824f1eaadSschwarze p->flags |= TERMP_NEWMC; 15924f1eaadSschwarze } else 16024f1eaadSschwarze p->flags |= TERMP_ENDMC; 16124f1eaadSschwarze } 16224f1eaadSschwarze 16324f1eaadSschwarze static void 164af1e8f15Sschwarze roff_term_pre_po(ROFF_TERM_ARGS) 165af1e8f15Sschwarze { 166af1e8f15Sschwarze struct roffsu su; 167af1e8f15Sschwarze static int po, polast; 168af1e8f15Sschwarze int ponew; 169af1e8f15Sschwarze 170af1e8f15Sschwarze if (n->child != NULL && 171af1e8f15Sschwarze a2roffsu(n->child->string, &su, SCALE_EM) != NULL) { 172af1e8f15Sschwarze ponew = term_hen(p, &su); 173af1e8f15Sschwarze if (*n->child->string == '+' || 174af1e8f15Sschwarze *n->child->string == '-') 175af1e8f15Sschwarze ponew += po; 176af1e8f15Sschwarze } else 177af1e8f15Sschwarze ponew = polast; 178af1e8f15Sschwarze polast = po; 179af1e8f15Sschwarze po = ponew; 180af1e8f15Sschwarze 181af1e8f15Sschwarze ponew = po - polast + (int)p->tcol->offset; 182af1e8f15Sschwarze p->tcol->offset = ponew > 0 ? ponew : 0; 183af1e8f15Sschwarze } 184af1e8f15Sschwarze 185af1e8f15Sschwarze static void 1866561cb23Sschwarze roff_term_pre_sp(ROFF_TERM_ARGS) 1876561cb23Sschwarze { 1886561cb23Sschwarze struct roffsu su; 1896561cb23Sschwarze int len; 1906561cb23Sschwarze 1916561cb23Sschwarze if (n->child != NULL) { 192ecd22486Sschwarze if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL) 1936561cb23Sschwarze su.scale = 1.0; 1946561cb23Sschwarze len = term_vspan(p, &su); 1956561cb23Sschwarze } else 1966561cb23Sschwarze len = 1; 1976561cb23Sschwarze 1986561cb23Sschwarze if (len < 0) 1996561cb23Sschwarze p->skipvsp -= len; 2006561cb23Sschwarze else 2016561cb23Sschwarze while (len--) 2026561cb23Sschwarze term_vspace(p); 2036561cb23Sschwarze 2046561cb23Sschwarze roff_term_pre_br(p, n); 2056561cb23Sschwarze } 206f7242c43Sschwarze 207f7242c43Sschwarze static void 208f7242c43Sschwarze roff_term_pre_ta(ROFF_TERM_ARGS) 209f7242c43Sschwarze { 210f7242c43Sschwarze term_tab_set(p, NULL); 211f7242c43Sschwarze for (n = n->child; n != NULL; n = n->next) 212f7242c43Sschwarze term_tab_set(p, n->string); 213f7242c43Sschwarze } 21411d70615Sschwarze 21511d70615Sschwarze static void 21611d70615Sschwarze roff_term_pre_ti(ROFF_TERM_ARGS) 21711d70615Sschwarze { 21811d70615Sschwarze struct roffsu su; 21911d70615Sschwarze const char *cp; 22011d70615Sschwarze int len, sign; 22111d70615Sschwarze 22211d70615Sschwarze roff_term_pre_br(p, n); 22311d70615Sschwarze 22411d70615Sschwarze if (n->child == NULL) 22511d70615Sschwarze return; 22611d70615Sschwarze cp = n->child->string; 22711d70615Sschwarze if (*cp == '+') { 22811d70615Sschwarze sign = 1; 22911d70615Sschwarze cp++; 23011d70615Sschwarze } else if (*cp == '-') { 23111d70615Sschwarze sign = -1; 23211d70615Sschwarze cp++; 23311d70615Sschwarze } else 23411d70615Sschwarze sign = 0; 23511d70615Sschwarze 236ecd22486Sschwarze if (a2roffsu(cp, &su, SCALE_EM) == NULL) 23711d70615Sschwarze return; 238f4692b45Sschwarze len = term_hen(p, &su); 23911d70615Sschwarze 24011d70615Sschwarze if (sign == 0) { 241e93ea447Sschwarze p->ti = len - p->tcol->offset; 242e93ea447Sschwarze p->tcol->offset = len; 24311d70615Sschwarze } else if (sign == 1) { 24411d70615Sschwarze p->ti = len; 245e93ea447Sschwarze p->tcol->offset += len; 246e93ea447Sschwarze } else if ((size_t)len < p->tcol->offset) { 24711d70615Sschwarze p->ti = -len; 248e93ea447Sschwarze p->tcol->offset -= len; 24911d70615Sschwarze } else { 250e93ea447Sschwarze p->ti = -p->tcol->offset; 251e93ea447Sschwarze p->tcol->offset = 0; 25211d70615Sschwarze } 25311d70615Sschwarze } 254