Home | History | Annotate | Line # | Download | only in dist
roff_term.c revision 1.1.1.2
      1 /*	Id: roff_term.c,v 1.19 2019/01/04 03:24:33 schwarze Exp  */
      2 /*
      3  * Copyright (c) 2010,2014,2015,2017-2019 Ingo Schwarze <schwarze (at) openbsd.org>
      4  *
      5  * Permission to use, copy, modify, and distribute this software for any
      6  * purpose with or without fee is hereby granted, provided that the above
      7  * copyright notice and this permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  */
     17 #include <sys/types.h>
     18 
     19 #include <assert.h>
     20 #include <stdio.h>
     21 #include <string.h>
     22 
     23 #include "mandoc.h"
     24 #include "roff.h"
     25 #include "out.h"
     26 #include "term.h"
     27 
     28 #define	ROFF_TERM_ARGS struct termp *p, const struct roff_node *n
     29 
     30 typedef	void	(*roff_term_pre_fp)(ROFF_TERM_ARGS);
     31 
     32 static	void	  roff_term_pre_br(ROFF_TERM_ARGS);
     33 static	void	  roff_term_pre_ce(ROFF_TERM_ARGS);
     34 static	void	  roff_term_pre_ft(ROFF_TERM_ARGS);
     35 static	void	  roff_term_pre_ll(ROFF_TERM_ARGS);
     36 static	void	  roff_term_pre_mc(ROFF_TERM_ARGS);
     37 static	void	  roff_term_pre_po(ROFF_TERM_ARGS);
     38 static	void	  roff_term_pre_sp(ROFF_TERM_ARGS);
     39 static	void	  roff_term_pre_ta(ROFF_TERM_ARGS);
     40 static	void	  roff_term_pre_ti(ROFF_TERM_ARGS);
     41 
     42 static	const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = {
     43 	roff_term_pre_br,  /* br */
     44 	roff_term_pre_ce,  /* ce */
     45 	roff_term_pre_br,  /* fi */
     46 	roff_term_pre_ft,  /* ft */
     47 	roff_term_pre_ll,  /* ll */
     48 	roff_term_pre_mc,  /* mc */
     49 	roff_term_pre_br,  /* nf */
     50 	roff_term_pre_po,  /* po */
     51 	roff_term_pre_ce,  /* rj */
     52 	roff_term_pre_sp,  /* sp */
     53 	roff_term_pre_ta,  /* ta */
     54 	roff_term_pre_ti,  /* ti */
     55 };
     56 
     57 
     58 void
     59 roff_term_pre(struct termp *p, const struct roff_node *n)
     60 {
     61 	assert(n->tok < ROFF_MAX);
     62 	(*roff_term_pre_acts[n->tok])(p, n);
     63 }
     64 
     65 static void
     66 roff_term_pre_br(ROFF_TERM_ARGS)
     67 {
     68 	term_newln(p);
     69 	if (p->flags & TERMP_BRIND) {
     70 		p->tcol->offset = p->tcol->rmargin;
     71 		p->tcol->rmargin = p->maxrmargin;
     72 		p->trailspace = 0;
     73 		p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
     74 		p->flags |= TERMP_NOSPACE;
     75 	}
     76 }
     77 
     78 static void
     79 roff_term_pre_ce(ROFF_TERM_ARGS)
     80 {
     81 	const struct roff_node	*nc1, *nc2;
     82 
     83 	roff_term_pre_br(p, n);
     84 	p->flags |= n->tok == ROFF_ce ? TERMP_CENTER : TERMP_RIGHT;
     85 	nc1 = n->child->next;
     86 	while (nc1 != NULL) {
     87 		nc2 = nc1;
     88 		do {
     89 			nc2 = nc2->next;
     90 		} while (nc2 != NULL && (nc2->type != ROFFT_TEXT ||
     91 		    (nc2->flags & NODE_LINE) == 0));
     92 		while (nc1 != nc2) {
     93 			if (nc1->type == ROFFT_TEXT)
     94 				term_word(p, nc1->string);
     95 			else
     96 				roff_term_pre(p, nc1);
     97 			nc1 = nc1->next;
     98 		}
     99 		p->flags |= TERMP_NOSPACE;
    100 		term_flushln(p);
    101 	}
    102 	p->flags &= ~(TERMP_CENTER | TERMP_RIGHT);
    103 }
    104 
    105 static void
    106 roff_term_pre_ft(ROFF_TERM_ARGS)
    107 {
    108 	const char	*cp;
    109 
    110 	cp = n->child->string;
    111 	switch (mandoc_font(cp, (int)strlen(cp))) {
    112 	case ESCAPE_FONTBOLD:
    113 		term_fontrepl(p, TERMFONT_BOLD);
    114 		break;
    115 	case ESCAPE_FONTITALIC:
    116 		term_fontrepl(p, TERMFONT_UNDER);
    117 		break;
    118 	case ESCAPE_FONTBI:
    119 		term_fontrepl(p, TERMFONT_BI);
    120 		break;
    121 	case ESCAPE_FONTPREV:
    122 		term_fontlast(p);
    123 		break;
    124 	case ESCAPE_FONTROMAN:
    125 	case ESCAPE_FONTCW:
    126 		term_fontrepl(p, TERMFONT_NONE);
    127 		break;
    128 	default:
    129 		break;
    130 	}
    131 }
    132 
    133 static void
    134 roff_term_pre_ll(ROFF_TERM_ARGS)
    135 {
    136 	term_setwidth(p, n->child != NULL ? n->child->string : NULL);
    137 }
    138 
    139 static void
    140 roff_term_pre_mc(ROFF_TERM_ARGS)
    141 {
    142 	if (p->col) {
    143 		p->flags |= TERMP_NOBREAK;
    144 		term_flushln(p);
    145 		p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE);
    146 	}
    147 	if (n->child != NULL) {
    148 		p->mc = n->child->string;
    149 		p->flags |= TERMP_NEWMC;
    150 	} else
    151 		p->flags |= TERMP_ENDMC;
    152 }
    153 
    154 static void
    155 roff_term_pre_po(ROFF_TERM_ARGS)
    156 {
    157 	struct roffsu	 su;
    158 	static int	 po, polast;
    159 	int		 ponew;
    160 
    161 	if (n->child != NULL &&
    162 	    a2roffsu(n->child->string, &su, SCALE_EM) != NULL) {
    163 		ponew = term_hen(p, &su);
    164 		if (*n->child->string == '+' ||
    165 		    *n->child->string == '-')
    166 			ponew += po;
    167 	} else
    168 		ponew = polast;
    169 	polast = po;
    170 	po = ponew;
    171 
    172 	ponew = po - polast + (int)p->tcol->offset;
    173 	p->tcol->offset = ponew > 0 ? ponew : 0;
    174 }
    175 
    176 static void
    177 roff_term_pre_sp(ROFF_TERM_ARGS)
    178 {
    179 	struct roffsu	 su;
    180 	int		 len;
    181 
    182 	if (n->child != NULL) {
    183 		if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL)
    184 			su.scale = 1.0;
    185 		len = term_vspan(p, &su);
    186 	} else
    187 		len = 1;
    188 
    189 	if (len < 0)
    190 		p->skipvsp -= len;
    191 	else
    192 		while (len--)
    193 			term_vspace(p);
    194 
    195 	roff_term_pre_br(p, n);
    196 }
    197 
    198 static void
    199 roff_term_pre_ta(ROFF_TERM_ARGS)
    200 {
    201 	term_tab_set(p, NULL);
    202 	for (n = n->child; n != NULL; n = n->next)
    203 		term_tab_set(p, n->string);
    204 }
    205 
    206 static void
    207 roff_term_pre_ti(ROFF_TERM_ARGS)
    208 {
    209 	struct roffsu	 su;
    210 	const char	*cp;
    211 	int		 len, sign;
    212 
    213 	roff_term_pre_br(p, n);
    214 
    215 	if (n->child == NULL)
    216 		return;
    217 	cp = n->child->string;
    218 	if (*cp == '+') {
    219 		sign = 1;
    220 		cp++;
    221 	} else if (*cp == '-') {
    222 		sign = -1;
    223 		cp++;
    224 	} else
    225 		sign = 0;
    226 
    227 	if (a2roffsu(cp, &su, SCALE_EM) == NULL)
    228 		return;
    229 	len = term_hen(p, &su);
    230 
    231 	if (sign == 0) {
    232 		p->ti = len - p->tcol->offset;
    233 		p->tcol->offset = len;
    234 	} else if (sign == 1) {
    235 		p->ti = len;
    236 		p->tcol->offset += len;
    237 	} else if ((size_t)len < p->tcol->offset) {
    238 		p->ti = -len;
    239 		p->tcol->offset -= len;
    240 	} else {
    241 		p->ti = -p->tcol->offset;
    242 		p->tcol->offset = 0;
    243 	}
    244 }
    245