示例#1
0
static int
pre_RS(DECL_ARGS)
{
	int		 ival;
	size_t		 sz;

	switch (n->type) {
	case MAN_BLOCK:
		term_newln(p);
		return(1);
	case MAN_HEAD:
		return(0);
	default:
		break;
	}

	sz = term_len(p, p->defindent);

	if (NULL != (n = n->parent->head->child))
		if ((ival = a2width(p, n->string)) >= 0)
			sz = (size_t)ival;

	mt->offset += sz;
	p->offset = mt->offset;
	p->rmargin = p->maxrmargin > p->offset ?
	    p->maxrmargin : p->offset;

	if (++mt->lmarginsz < MAXMARGINS)
		mt->lmargincur = mt->lmarginsz;

	mt->lmargin[mt->lmargincur] = mt->lmargin[mt->lmargincur - 1];
	return(1);
}
示例#2
0
static int
man_RS_pre(MAN_ARGS)
{
	struct roffsu	 su;

	if (n->type == ROFFT_HEAD)
		return 0;
	else if (n->type == ROFFT_BODY)
		return 1;

	SCALE_HS_INIT(&su, INDENT);
	if (n->head->child)
		a2width(n->head->child, &su);

	print_otag(h, TAG_DIV, "sul", &su);
	return 1;
}
示例#3
0
/* ARGSUSED */
static int
pre_in(DECL_ARGS)
{
	int		 len, less;
	size_t		 v;
	const char	*cp;

	term_newln(p);

	if (NULL == n->child) {
		p->offset = mt->offset;
		return(0);
	}

	cp = n->child->string;
	less = 0;

	if ('-' == *cp)
		less = -1;
	else if ('+' == *cp)
		less = 1;
	else
		cp--;

	if ((len = a2width(p, ++cp)) < 0)
		return(0);

	v = (size_t)len;

	if (less < 0)
		p->offset -= p->offset > v ? v : p->offset;
	else if (less > 0)
		p->offset += v;
	else 
		p->offset = v;

	/* Don't let this creep beyond the right margin. */

	if (p->offset > p->rmargin)
		p->offset = p->rmargin;

	return(0);
}
示例#4
0
static int
pre_HP(DECL_ARGS)
{
	size_t			 len, one;
	int			 ival;
	const struct man_node	*nn;

	switch (n->type) {
	case MAN_BLOCK:
		print_bvspace(p, n, mt->pardist);
		return(1);
	case MAN_BODY:
		break;
	default:
		return(0);
	}

	if ( ! (MANT_LITERAL & mt->fl)) {
		p->flags |= TERMP_NOBREAK | TERMP_BRIND;
		p->trailspace = 2;
	}

	len = mt->lmargin[mt->lmargincur];
	ival = -1;

	/* Calculate offset. */

	if (NULL != (nn = n->parent->head->child))
		if ((ival = a2width(p, nn->string)) >= 0)
			len = (size_t)ival;

	one = term_len(p, 1);
	if (len < one)
		len = one;

	p->offset = mt->offset;
	p->rmargin = mt->offset + len;

	if (ival >= 0)
		mt->lmargin[mt->lmargincur] = (size_t)ival;

	return(1);
}
示例#5
0
static int
man_RS_pre(MAN_ARGS)
{
	struct htmlpair	 tag;
	struct roffsu	 su;

	if (MAN_HEAD == n->type)
		return(0);
	else if (MAN_BODY == n->type)
		return(1);

	SCALE_HS_INIT(&su, INDENT);
	if (n->head->child)
		a2width(n->head->child, &su);

	bufinit(h);
	bufcat_su(h, "margin-left", &su);
	PAIR_STYLE_INIT(&tag, h);
	print_otag(h, TAG_DIV, 1, &tag);
	return(1);
}
示例#6
0
/* ARGSUSED */
static int
pre_HP(DECL_ARGS)
{
	size_t			 len;
	int			 ival;
	const struct man_node	*nn;

	switch (n->type) {
	case (MAN_BLOCK):
		print_bvspace(p, n);
		return(1);
	case (MAN_BODY):
		p->flags |= TERMP_NOBREAK;
		p->flags |= TERMP_TWOSPACE;
		break;
	default:
		return(0);
	}

	len = mt->lmargin;
	ival = -1;

	/* Calculate offset. */

	if (NULL != (nn = n->parent->head->child))
		if ((ival = a2width(p, nn->string)) >= 0)
			len = (size_t)ival;

	if (0 == len)
		len = term_len(p, 1);

	p->offset = mt->offset;
	p->rmargin = mt->offset + len;

	if (ival >= 0)
		mt->lmargin = (size_t)ival;

	return(1);
}
示例#7
0
static int
man_HP_pre(MAN_ARGS)
{
	struct roffsu	 sum, sui;
	const struct roff_node *np;

	if (n->type == ROFFT_HEAD)
		return 0;
	else if (n->type != ROFFT_BLOCK)
		return 1;

	np = n->head->child;

	if (np == NULL || !a2width(np, &sum))
		SCALE_HS_INIT(&sum, INDENT);

	sui.unit = sum.unit;
	sui.scale = -sum.scale;

	print_bvspace(h, n);
	print_otag(h, TAG_DIV, "csului", "Pp", &sum, &sui);
	return 1;
}
示例#8
0
/* ARGSUSED */
static int
mdoc_bl_pre(MDOC_ARGS)
{
	int		 i;
	struct htmlpair	 tag[3];
	struct roffsu	 su;
	char		 buf[BUFSIZ];

	if (MDOC_BODY == n->type) {
		if (LIST_column == n->norm->Bl.type)
			print_otag(h, TAG_TBODY, 0, NULL);
		return(1);
	}

	if (MDOC_HEAD == n->type) {
		if (LIST_column != n->norm->Bl.type)
			return(0);

		/*
		 * For each column, print out the <COL> tag with our
		 * suggested width.  The last column gets min-width, as
		 * in terminal mode it auto-sizes to the width of the
		 * screen and we want to preserve that behaviour.
		 */

		for (i = 0; i < (int)n->norm->Bl.ncols; i++) {
			a2width(n->norm->Bl.cols[i], &su);
			bufinit(h);
			if (i < (int)n->norm->Bl.ncols - 1)
				bufcat_su(h, "width", &su);
			else
				bufcat_su(h, "min-width", &su);
			PAIR_STYLE_INIT(&tag[0], h);
			print_otag(h, TAG_COL, 1, tag);
		}

		return(0);
	}

	SCALE_VS_INIT(&su, 0);
	bufcat_su(h, "margin-top", &su);
	bufcat_su(h, "margin-bottom", &su);
	PAIR_STYLE_INIT(&tag[0], h);

	assert(lists[n->norm->Bl.type]);
	strlcpy(buf, "list ", BUFSIZ);
	strlcat(buf, lists[n->norm->Bl.type], BUFSIZ);
	PAIR_INIT(&tag[1], ATTR_CLASS, buf);

	/* Set the block's left-hand margin. */

	if (n->norm->Bl.offs) {
		a2offs(n->norm->Bl.offs, &su);
		bufcat_su(h, "margin-left", &su);
	}

	switch (n->norm->Bl.type) {
	case(LIST_bullet):
		/* FALLTHROUGH */
	case(LIST_dash):
		/* FALLTHROUGH */
	case(LIST_hyphen):
		/* FALLTHROUGH */
	case(LIST_item):
		print_otag(h, TAG_UL, 2, tag);
		break;
	case(LIST_enum):
		print_otag(h, TAG_OL, 2, tag);
		break;
	case(LIST_diag):
		/* FALLTHROUGH */
	case(LIST_hang):
		/* FALLTHROUGH */
	case(LIST_inset):
		/* FALLTHROUGH */
	case(LIST_ohang):
		/* FALLTHROUGH */
	case(LIST_tag):
		print_otag(h, TAG_DL, 2, tag);
		break;
	case(LIST_column):
		print_otag(h, TAG_TABLE, 2, tag);
		break;
	default:
		abort();
		/* NOTREACHED */
	}

	return(1);
}
示例#9
0
/* ARGSUSED */
static int
mdoc_it_pre(MDOC_ARGS)
{
	struct roffsu	 su;
	enum mdoc_list	 type;
	struct htmlpair	 tag[2];
	const struct mdoc_node *bl;

	bl = n->parent;
	while (bl && MDOC_Bl != bl->tok)
		bl = bl->parent;

	assert(bl);

	type = bl->norm->Bl.type;

	assert(lists[type]);
	PAIR_CLASS_INIT(&tag[0], lists[type]);

	if (MDOC_HEAD == n->type) {
		switch (type) {
		case(LIST_bullet):
			/* FALLTHROUGH */
		case(LIST_dash):
			/* FALLTHROUGH */
		case(LIST_item):
			/* FALLTHROUGH */
		case(LIST_hyphen):
			/* FALLTHROUGH */
		case(LIST_enum):
			return(0);
		case(LIST_diag):
			/* FALLTHROUGH */
		case(LIST_hang):
			/* FALLTHROUGH */
		case(LIST_inset):
			/* FALLTHROUGH */
		case(LIST_ohang):
			/* FALLTHROUGH */
		case(LIST_tag):
			SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
			bufcat_su(h, "margin-top", &su);
			PAIR_STYLE_INIT(&tag[1], h);
			print_otag(h, TAG_DT, 2, tag);
			if (LIST_diag != type)
				break;
			PAIR_CLASS_INIT(&tag[0], "diag");
			print_otag(h, TAG_B, 1, tag);
			break;
		case(LIST_column):
			break;
		default:
			break;
		}
	} else if (MDOC_BODY == n->type) {
		switch (type) {
		case(LIST_bullet):
			/* FALLTHROUGH */
		case(LIST_hyphen):
			/* FALLTHROUGH */
		case(LIST_dash):
			/* FALLTHROUGH */
		case(LIST_enum):
			/* FALLTHROUGH */
		case(LIST_item):
			SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
			bufcat_su(h, "margin-top", &su);
			PAIR_STYLE_INIT(&tag[1], h);
			print_otag(h, TAG_LI, 2, tag);
			break;
		case(LIST_diag):
			/* FALLTHROUGH */
		case(LIST_hang):
			/* FALLTHROUGH */
		case(LIST_inset):
			/* FALLTHROUGH */
		case(LIST_ohang):
			/* FALLTHROUGH */
		case(LIST_tag):
			if (NULL == bl->norm->Bl.width) {
				print_otag(h, TAG_DD, 1, tag);
				break;
			}
			a2width(bl->norm->Bl.width, &su);
			bufcat_su(h, "margin-left", &su);
			PAIR_STYLE_INIT(&tag[1], h);
			print_otag(h, TAG_DD, 2, tag);
			break;
		case(LIST_column):
			SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
			bufcat_su(h, "margin-top", &su);
			PAIR_STYLE_INIT(&tag[1], h);
			print_otag(h, TAG_TD, 2, tag);
			break;
		default:
			break;
		}
	} else {
		switch (type) {
		case (LIST_column):
			print_otag(h, TAG_TR, 1, tag);
			break;
		default:
			break;
		}
	}

	return(1);
}
示例#10
0
static int
termp_it_pre(DECL_ARGS)
{
	char			buf[24];
	const struct roff_node *bl, *nn;
	size_t			ncols, dcol;
	int			i, offset, width;
	enum mdoc_list		type;

	if (n->type == ROFFT_BLOCK) {
		print_bvspace(p, n->parent->parent, n);
		return 1;
	}

	bl = n->parent->parent->parent;
	type = bl->norm->Bl.type;

	/*
	 * Defaults for specific list types.
	 */

	switch (type) {
	case LIST_bullet:
	case LIST_dash:
	case LIST_hyphen:
	case LIST_enum:
		width = term_len(p, 2);
		break;
	case LIST_hang:
		width = term_len(p, 8);
		break;
	case LIST_column:
	case LIST_tag:
		width = term_len(p, 10);
		break;
	default:
		width = 0;
		break;
	}
	offset = 0;

	/*
	 * First calculate width and offset.  This is pretty easy unless
	 * we're a -column list, in which case all prior columns must
	 * be accounted for.
	 */

	if (bl->norm->Bl.offs != NULL) {
		offset = a2width(p, bl->norm->Bl.offs);
		if (offset < 0 && (size_t)(-offset) > p->offset)
			offset = -p->offset;
		else if (offset > SHRT_MAX)
			offset = 0;
	}

	switch (type) {
	case LIST_column:
		if (n->type == ROFFT_HEAD)
			break;

		/*
		 * Imitate groff's column handling:
		 * - For each earlier column, add its width.
		 * - For less than 5 columns, add four more blanks per
		 *   column.
		 * - For exactly 5 columns, add three more blank per
		 *   column.
		 * - For more than 5 columns, add only one column.
		 */
		ncols = bl->norm->Bl.ncols;
		dcol = ncols < 5 ? term_len(p, 4) :
		    ncols == 5 ? term_len(p, 3) : term_len(p, 1);

		/*
		 * Calculate the offset by applying all prior ROFFT_BODY,
		 * so we stop at the ROFFT_HEAD (nn->prev == NULL).
		 */

		for (i = 0, nn = n->prev;
		    nn->prev && i < (int)ncols;
		    nn = nn->prev, i++)
			offset += dcol + a2width(p,
			    bl->norm->Bl.cols[i]);

		/*
		 * When exceeding the declared number of columns, leave
		 * the remaining widths at 0.  This will later be
		 * adjusted to the default width of 10, or, for the last
		 * column, stretched to the right margin.
		 */
		if (i >= (int)ncols)
			break;

		/*
		 * Use the declared column widths, extended as explained
		 * in the preceding paragraph.
		 */
		width = a2width(p, bl->norm->Bl.cols[i]) + dcol;
		break;
	default:
		if (NULL == bl->norm->Bl.width)
			break;

		/*
		 * Note: buffer the width by 2, which is groff's magic
		 * number for buffering single arguments.  See the above
		 * handling for column for how this changes.
		 */
		width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
		if (width < 0 && (size_t)(-width) > p->offset)
			width = -p->offset;
		else if (width > SHRT_MAX)
			width = 0;
		break;
	}

	/*
	 * Whitespace control.  Inset bodies need an initial space,
	 * while diagonal bodies need two.
	 */

	p->flags |= TERMP_NOSPACE;

	switch (type) {
	case LIST_diag:
		if (n->type == ROFFT_BODY)
			term_word(p, "\\ \\ ");
		break;
	case LIST_inset:
		if (n->type == ROFFT_BODY && n->parent->head->child != NULL)
			term_word(p, "\\ ");
		break;
	default:
		break;
	}

	p->flags |= TERMP_NOSPACE;

	switch (type) {
	case LIST_diag:
		if (n->type == ROFFT_HEAD)
			term_fontpush(p, TERMFONT_BOLD);
		break;
	default:
		break;
	}

	/*
	 * Pad and break control.  This is the tricky part.  These flags
	 * are documented in term_flushln() in term.c.  Note that we're
	 * going to unset all of these flags in termp_it_post() when we
	 * exit.
	 */

	switch (type) {
	case LIST_enum:
	case LIST_bullet:
	case LIST_dash:
	case LIST_hyphen:
		/*
		 * Weird special case.
		 * Some very narrow lists actually hang.
		 */
		if (width <= (int)term_len(p, 2))
			p->flags |= TERMP_HANG;
		if (n->type != ROFFT_HEAD)
			break;
		p->flags |= TERMP_NOBREAK;
		p->trailspace = 1;
		break;
	case LIST_hang:
		if (n->type != ROFFT_HEAD)
			break;

		/*
		 * This is ugly.  If `-hang' is specified and the body
		 * is a `Bl' or `Bd', then we want basically to nullify
		 * the "overstep" effect in term_flushln() and treat
		 * this as a `-ohang' list instead.
		 */
		if (NULL != n->next &&
		    NULL != n->next->child &&
		    (MDOC_Bl == n->next->child->tok ||
		     MDOC_Bd == n->next->child->tok))
			break;

		p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG;
		p->trailspace = 1;
		break;
	case LIST_tag:
		if (n->type != ROFFT_HEAD)
			break;

		p->flags |= TERMP_NOBREAK | TERMP_BRTRSP | TERMP_BRIND;
		p->trailspace = 2;

		if (NULL == n->next || NULL == n->next->child)
			p->flags |= TERMP_DANGLE;
		break;
	case LIST_column:
		if (n->type == ROFFT_HEAD)
			break;

		if (NULL == n->next) {
			p->flags &= ~TERMP_NOBREAK;
			p->trailspace = 0;
		} else {
			p->flags |= TERMP_NOBREAK;
			p->trailspace = 1;
		}

		break;
	case LIST_diag:
		if (n->type != ROFFT_HEAD)
			break;
		p->flags |= TERMP_NOBREAK | TERMP_BRIND;
		p->trailspace = 1;
		break;
	default:
		break;
	}

	/*
	 * Margin control.  Set-head-width lists have their right
	 * margins shortened.  The body for these lists has the offset
	 * necessarily lengthened.  Everybody gets the offset.
	 */

	p->offset += offset;

	switch (type) {
	case LIST_hang:
		/*
		 * Same stipulation as above, regarding `-hang'.  We
		 * don't want to recalculate rmargin and offsets when
		 * using `Bd' or `Bl' within `-hang' overstep lists.
		 */
		if (n->type == ROFFT_HEAD &&
		    NULL != n->next &&
		    NULL != n->next->child &&
		    (MDOC_Bl == n->next->child->tok ||
		     MDOC_Bd == n->next->child->tok))
			break;
		/* FALLTHROUGH */
	case LIST_bullet:
	case LIST_dash:
	case LIST_enum:
	case LIST_hyphen:
	case LIST_tag:
		if (n->type == ROFFT_HEAD)
			p->rmargin = p->offset + width;
		else
			p->offset += width;
		break;
	case LIST_column:
		assert(width);
		p->rmargin = p->offset + width;
		/*
		 * XXX - this behaviour is not documented: the
		 * right-most column is filled to the right margin.
		 */
		if (n->type == ROFFT_HEAD)
			break;
		if (NULL == n->next && p->rmargin < p->maxrmargin)
			p->rmargin = p->maxrmargin;
		break;
	default:
		break;
	}

	/*
	 * The dash, hyphen, bullet and enum lists all have a special
	 * HEAD character (temporarily bold, in some cases).
	 */

	if (n->type == ROFFT_HEAD)
		switch (type) {
		case LIST_bullet:
			term_fontpush(p, TERMFONT_BOLD);
			term_word(p, "\\[bu]");
			term_fontpop(p);
			break;
		case LIST_dash:
		case LIST_hyphen:
			term_fontpush(p, TERMFONT_BOLD);
			term_word(p, "-");
			term_fontpop(p);
			break;
		case LIST_enum:
			(pair->ppair->ppair->count)++;
			(void)snprintf(buf, sizeof(buf), "%d.",
			    pair->ppair->ppair->count);
			term_word(p, buf);
			break;
		default:
			break;
		}

	/*
	 * If we're not going to process our children, indicate so here.
	 */

	switch (type) {
	case LIST_bullet:
	case LIST_item:
	case LIST_dash:
	case LIST_hyphen:
	case LIST_enum:
		if (n->type == ROFFT_HEAD)
			return 0;
		break;
	case LIST_column:
		if (n->type == ROFFT_HEAD)
			return 0;
		break;
	default:
		break;
	}

	return 1;
}
示例#11
0
static int
termp_bd_pre(DECL_ARGS)
{
	size_t			 tabwidth, lm, len, rm, rmax;
	struct roff_node	*nn;
	int			 offset;

	if (n->type == ROFFT_BLOCK) {
		print_bvspace(p, n, n);
		return 1;
	} else if (n->type == ROFFT_HEAD)
		return 0;

	/* Handle the -offset argument. */

	if (n->norm->Bd.offs == NULL ||
	    ! strcmp(n->norm->Bd.offs, "left"))
		/* nothing */;
	else if ( ! strcmp(n->norm->Bd.offs, "indent"))
		p->offset += term_len(p, p->defindent + 1);
	else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
		p->offset += term_len(p, (p->defindent + 1) * 2);
	else {
		offset = a2width(p, n->norm->Bd.offs);
		if (offset < 0 && (size_t)(-offset) > p->offset)
			p->offset = 0;
		else if (offset < SHRT_MAX)
			p->offset += offset;
	}

	/*
	 * If -ragged or -filled are specified, the block does nothing
	 * but change the indentation.  If -unfilled or -literal are
	 * specified, text is printed exactly as entered in the display:
	 * for macro lines, a newline is appended to the line.  Blank
	 * lines are allowed.
	 */

	if (DISP_literal != n->norm->Bd.type &&
	    DISP_unfilled != n->norm->Bd.type &&
	    DISP_centered != n->norm->Bd.type)
		return 1;

	tabwidth = p->tabwidth;
	if (DISP_literal == n->norm->Bd.type)
		p->tabwidth = term_len(p, 8);

	lm = p->offset;
	rm = p->rmargin;
	rmax = p->maxrmargin;
	p->rmargin = p->maxrmargin = TERM_MAXMARGIN;

	for (nn = n->child; nn; nn = nn->next) {
		if (DISP_centered == n->norm->Bd.type) {
			if (nn->type == ROFFT_TEXT) {
				len = term_strlen(p, nn->string);
				p->offset = len >= rm ? 0 :
				    lm + len >= rm ? rm - len :
				    (lm + rm - len) / 2;
			} else
				p->offset = lm;
		}
		print_mdoc_node(p, pair, meta, nn);
		/*
		 * If the printed node flushes its own line, then we
		 * needn't do it here as well.  This is hacky, but the
		 * notion of selective eoln whitespace is pretty dumb
		 * anyway, so don't sweat it.
		 */
		switch (nn->tok) {
		case MDOC_Sm:
		case MDOC_br:
		case MDOC_sp:
		case MDOC_Bl:
		case MDOC_D1:
		case MDOC_Dl:
		case MDOC_Lp:
		case MDOC_Pp:
			continue;
		default:
			break;
		}
		if (p->flags & TERMP_NONEWLINE ||
		    (nn->next && ! (nn->next->flags & MDOC_LINE)))
			continue;
		term_flushln(p);
		p->flags |= TERMP_NOSPACE;
	}

	p->tabwidth = tabwidth;
	p->rmargin = rm;
	p->maxrmargin = rmax;
	return 0;
}
示例#12
0
/* ARGSUSED */
static int
pre_TP(DECL_ARGS)
{
	const struct man_node	*nn;
	size_t			 len;
	int			 savelit, ival;

	switch (n->type) {
	case (MAN_HEAD):
		p->flags |= TERMP_NOBREAK;
		break;
	case (MAN_BODY):
		p->flags |= TERMP_NOSPACE;
		break;
	case (MAN_BLOCK):
		print_bvspace(p, n);
		/* FALLTHROUGH */
	default:
		return(1);
	}

	len = (size_t)mt->lmargin[mt->lmargincur];
	ival = -1;

	/* Calculate offset. */

	if (NULL != (nn = n->parent->head->child))
		if (nn->string && nn->parent->line == nn->line)
			if ((ival = a2width(p, nn->string)) >= 0)
				len = (size_t)ival;

	switch (n->type) {
	case (MAN_HEAD):
		/* Handle zero-length properly. */
		if (0 == len)
			len = term_len(p, 1);

		p->offset = mt->offset;
		p->rmargin = mt->offset + len;

		savelit = MANT_LITERAL & mt->fl;
		mt->fl &= ~MANT_LITERAL;

		/* Don't print same-line elements. */
		for (nn = n->child; nn; nn = nn->next)
			if (nn->line > n->line)
				print_man_node(p, mt, nn, m);

		if (savelit)
			mt->fl |= MANT_LITERAL;
		if (ival >= 0)
			mt->lmargin[mt->lmargincur] = (size_t)ival;

		return(0);
	case (MAN_BODY):
		p->offset = mt->offset + len;
		p->rmargin = p->maxrmargin;
		break;
	default:
		break;
	}

	return(1);
}
示例#13
0
/* ARGSUSED */
static int
pre_IP(DECL_ARGS)
{
	const struct man_node	*nn;
	size_t			 len;
	int			 savelit, ival;

	switch (n->type) {
	case (MAN_BODY):
		p->flags |= TERMP_NOSPACE;
		break;
	case (MAN_HEAD):
		p->flags |= TERMP_NOBREAK;
		break;
	case (MAN_BLOCK):
		print_bvspace(p, n);
		/* FALLTHROUGH */
	default:
		return(1);
	}

	len = mt->lmargin[mt->lmargincur];
	ival = -1;

	/* Calculate the offset from the optional second argument. */
	if (NULL != (nn = n->parent->head->child))
		if (NULL != (nn = nn->next))
			if ((ival = a2width(p, nn->string)) >= 0)
				len = (size_t)ival;

	switch (n->type) {
	case (MAN_HEAD):
		/* Handle zero-width lengths. */
		if (0 == len)
			len = term_len(p, 1);

		p->offset = mt->offset;
		p->rmargin = mt->offset + len;
		if (ival < 0)
			break;

		/* Set the saved left-margin. */
		mt->lmargin[mt->lmargincur] = (size_t)ival;

		savelit = MANT_LITERAL & mt->fl;
		mt->fl &= ~MANT_LITERAL;

		if (n->child)
			print_man_node(p, mt, n->child, m);

		if (savelit)
			mt->fl |= MANT_LITERAL;

		return(0);
	case (MAN_BODY):
		p->offset = mt->offset + len;
		p->rmargin = p->maxrmargin;
		break;
	default:
		break;
	}

	return(1);
}
示例#14
0
static int
mdoc_bd_pre(MDOC_ARGS)
{
	struct htmlpair		 tag[2];
	int			 comp, sv;
	struct mdoc_node	*nn;
	struct roffsu		 su;

	if (MDOC_HEAD == n->type)
		return(0);

	if (MDOC_BLOCK == n->type) {
		comp = n->norm->Bd.comp;
		for (nn = n; nn && ! comp; nn = nn->parent) {
			if (MDOC_BLOCK != nn->type)
				continue;
			if (MDOC_Ss == nn->tok || MDOC_Sh == nn->tok)
				comp = 1;
			if (nn->prev)
				break;
		}
		if ( ! comp)
			print_paragraph(h);
		return(1);
	}

	/* Handle the -offset argument. */

	if (n->norm->Bd.offs == NULL ||
	    ! strcmp(n->norm->Bd.offs, "left"))
		SCALE_HS_INIT(&su, 0);
	else if ( ! strcmp(n->norm->Bd.offs, "indent"))
		SCALE_HS_INIT(&su, INDENT);
	else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
		SCALE_HS_INIT(&su, INDENT * 2);
	else
		a2width(n->norm->Bd.offs, &su);

	bufinit(h);
	bufcat_su(h, "margin-left", &su);
	PAIR_STYLE_INIT(&tag[0], h);

	if (DISP_unfilled != n->norm->Bd.type &&
	    DISP_literal != n->norm->Bd.type) {
		PAIR_CLASS_INIT(&tag[1], "display");
		print_otag(h, TAG_DIV, 2, tag);
		return(1);
	}

	PAIR_CLASS_INIT(&tag[1], "lit display");
	print_otag(h, TAG_PRE, 2, tag);

	/* This can be recursive: save & set our literal state. */

	sv = h->flags & HTML_LITERAL;
	h->flags |= HTML_LITERAL;

	for (nn = n->child; nn; nn = nn->next) {
		print_mdoc_node(meta, nn, h);
		/*
		 * If the printed node flushes its own line, then we
		 * needn't do it here as well.  This is hacky, but the
		 * notion of selective eoln whitespace is pretty dumb
		 * anyway, so don't sweat it.
		 */
		switch (nn->tok) {
		case MDOC_Sm:
			/* FALLTHROUGH */
		case MDOC_br:
			/* FALLTHROUGH */
		case MDOC_sp:
			/* FALLTHROUGH */
		case MDOC_Bl:
			/* FALLTHROUGH */
		case MDOC_D1:
			/* FALLTHROUGH */
		case MDOC_Dl:
			/* FALLTHROUGH */
		case MDOC_Lp:
			/* FALLTHROUGH */
		case MDOC_Pp:
			continue;
		default:
			break;
		}
		if (h->flags & HTML_NONEWLINE ||
		    (nn->next && ! (nn->next->flags & MDOC_LINE)))
			continue;
		else if (nn->next)
			print_text(h, "\n");

		h->flags |= HTML_NOSPACE;
	}

	if (0 == sv)
		h->flags &= ~HTML_LITERAL;

	return(0);
}
示例#15
0
/* ARGSUSED */
static int
termp_it_pre(DECL_ARGS)
{
	const struct mdoc_node *bl, *nn;
	char		        buf[7];
	int		        i;
	size_t		        width, offset, ncols, dcol;
	enum mdoc_list		type;

	if (MDOC_BLOCK == n->type) {
		print_bvspace(p, n->parent->parent, n);
		return(1);
	}

	bl = n->parent->parent->parent;
	type = bl->norm->Bl.type;

	/* 
	 * First calculate width and offset.  This is pretty easy unless
	 * we're a -column list, in which case all prior columns must
	 * be accounted for.
	 */

	width = offset = 0;

	if (bl->norm->Bl.offs)
		offset = a2offs(p, bl->norm->Bl.offs);

	switch (type) {
	case (LIST_column):
		if (MDOC_HEAD == n->type)
			break;

		/*
		 * Imitate groff's column handling:
		 * - For each earlier column, add its width.
		 * - For less than 5 columns, add four more blanks per
		 *   column.
		 * - For exactly 5 columns, add three more blank per
		 *   column.
		 * - For more than 5 columns, add only one column.
		 */
		ncols = bl->norm->Bl.ncols;

		/* LINTED */
		dcol = ncols < 5 ? term_len(p, 4) : 
			ncols == 5 ? term_len(p, 3) : term_len(p, 1);

		/*
		 * Calculate the offset by applying all prior MDOC_BODY,
		 * so we stop at the MDOC_HEAD (NULL == nn->prev).
		 */

		for (i = 0, nn = n->prev; 
				nn->prev && i < (int)ncols; 
				nn = nn->prev, i++)
			offset += dcol + a2width
				(p, bl->norm->Bl.cols[i]);

		/*
		 * When exceeding the declared number of columns, leave
		 * the remaining widths at 0.  This will later be
		 * adjusted to the default width of 10, or, for the last
		 * column, stretched to the right margin.
		 */
		if (i >= (int)ncols)
			break;

		/*
		 * Use the declared column widths, extended as explained
		 * in the preceding paragraph.
		 */
		width = a2width(p, bl->norm->Bl.cols[i]) + dcol;
		break;
	default:
		if (NULL == bl->norm->Bl.width)
			break;

		/* 
		 * Note: buffer the width by 2, which is groff's magic
		 * number for buffering single arguments.  See the above
		 * handling for column for how this changes.
		 */
		assert(bl->norm->Bl.width);
		width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
		break;
	}

	/* 
	 * List-type can override the width in the case of fixed-head
	 * values (bullet, dash/hyphen, enum).  Tags need a non-zero
	 * offset.
	 */

	switch (type) {
	case (LIST_bullet):
		/* FALLTHROUGH */
	case (LIST_dash):
		/* FALLTHROUGH */
	case (LIST_hyphen):
		if (width < term_len(p, 4))
			width = term_len(p, 4);
		break;
	case (LIST_enum):
		if (width < term_len(p, 5))
			width = term_len(p, 5);
		break;
	case (LIST_hang):
		if (0 == width)
			width = term_len(p, 8);
		break;
	case (LIST_column):
		/* FALLTHROUGH */
	case (LIST_tag):
		if (0 == width)
			width = term_len(p, 10);
		break;
	default:
		break;
	}

	/* 
	 * Whitespace control.  Inset bodies need an initial space,
	 * while diagonal bodies need two.
	 */

	p->flags |= TERMP_NOSPACE;

	switch (type) {
	case (LIST_diag):
		if (MDOC_BODY == n->type)
			term_word(p, "\\ \\ ");
		break;
	case (LIST_inset):
		if (MDOC_BODY == n->type) 
			term_word(p, "\\ ");
		break;
	default:
		break;
	}

	p->flags |= TERMP_NOSPACE;

	switch (type) {
	case (LIST_diag):
		if (MDOC_HEAD == n->type)
			term_fontpush(p, TERMFONT_BOLD);
		break;
	default:
		break;
	}

	/*
	 * Pad and break control.  This is the tricky part.  These flags
	 * are documented in term_flushln() in term.c.  Note that we're
	 * going to unset all of these flags in termp_it_post() when we
	 * exit.
	 */

	switch (type) {
	case (LIST_bullet):
		/* FALLTHROUGH */
	case (LIST_dash):
		/* FALLTHROUGH */
	case (LIST_enum):
		/* FALLTHROUGH */
	case (LIST_hyphen):
		if (MDOC_HEAD == n->type)
			p->flags |= TERMP_NOBREAK;
		break;
	case (LIST_hang):
		if (MDOC_HEAD == n->type)
			p->flags |= TERMP_NOBREAK;
		else
			break;

		/*
		 * This is ugly.  If `-hang' is specified and the body
		 * is a `Bl' or `Bd', then we want basically to nullify
		 * the "overstep" effect in term_flushln() and treat
		 * this as a `-ohang' list instead.
		 */
		if (n->next->child && 
				(MDOC_Bl == n->next->child->tok ||
				 MDOC_Bd == n->next->child->tok))
			p->flags &= ~TERMP_NOBREAK;
		else
			p->flags |= TERMP_HANG;
		break;
	case (LIST_tag):
		if (MDOC_HEAD == n->type)
			p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE;

		if (MDOC_HEAD != n->type)
			break;
		if (NULL == n->next || NULL == n->next->child)
			p->flags |= TERMP_DANGLE;
		break;
	case (LIST_column):
		if (MDOC_HEAD == n->type)
			break;

		if (NULL == n->next)
			p->flags &= ~TERMP_NOBREAK;
		else
			p->flags |= TERMP_NOBREAK;

		break;
	case (LIST_diag):
		if (MDOC_HEAD == n->type)
			p->flags |= TERMP_NOBREAK;
		break;
	default:
		break;
	}

	/* 
	 * Margin control.  Set-head-width lists have their right
	 * margins shortened.  The body for these lists has the offset
	 * necessarily lengthened.  Everybody gets the offset.
	 */

	p->offset += offset;

	switch (type) {
	case (LIST_hang):
		/*
		 * Same stipulation as above, regarding `-hang'.  We
		 * don't want to recalculate rmargin and offsets when
		 * using `Bd' or `Bl' within `-hang' overstep lists.
		 */
		if (MDOC_HEAD == n->type && n->next->child &&
				(MDOC_Bl == n->next->child->tok || 
				 MDOC_Bd == n->next->child->tok))
			break;
		/* FALLTHROUGH */
	case (LIST_bullet):
		/* FALLTHROUGH */
	case (LIST_dash):
		/* FALLTHROUGH */
	case (LIST_enum):
		/* FALLTHROUGH */
	case (LIST_hyphen):
		/* FALLTHROUGH */
	case (LIST_tag):
		assert(width);
		if (MDOC_HEAD == n->type)
			p->rmargin = p->offset + width;
		else 
			p->offset += width;
		break;
	case (LIST_column):
		assert(width);
		p->rmargin = p->offset + width;
		/* 
		 * XXX - this behaviour is not documented: the
		 * right-most column is filled to the right margin.
		 */
		if (MDOC_HEAD == n->type)
			break;
		if (NULL == n->next && p->rmargin < p->maxrmargin)
			p->rmargin = p->maxrmargin;
		break;
	default:
		break;
	}

	/* 
	 * The dash, hyphen, bullet and enum lists all have a special
	 * HEAD character (temporarily bold, in some cases).  
	 */

	if (MDOC_HEAD == n->type)
		switch (type) {
		case (LIST_bullet):
			term_fontpush(p, TERMFONT_BOLD);
			term_word(p, "\\[bu]");
			term_fontpop(p);
			break;
		case (LIST_dash):
			/* FALLTHROUGH */
		case (LIST_hyphen):
			term_fontpush(p, TERMFONT_BOLD);
			term_word(p, "\\(hy");
			term_fontpop(p);
			break;
		case (LIST_enum):
			(pair->ppair->ppair->count)++;
			snprintf(buf, sizeof(buf), "%d.", 
					pair->ppair->ppair->count);
			term_word(p, buf);
			break;
		default:
			break;
		}

	/* 
	 * If we're not going to process our children, indicate so here.
	 */

	switch (type) {
	case (LIST_bullet):
		/* FALLTHROUGH */
	case (LIST_item):
		/* FALLTHROUGH */
	case (LIST_dash):
		/* FALLTHROUGH */
	case (LIST_hyphen):
		/* FALLTHROUGH */
	case (LIST_enum):
		if (MDOC_HEAD == n->type)
			return(0);
		break;
	case (LIST_column):
		if (MDOC_HEAD == n->type)
			return(0);
		break;
	default:
		break;
	}

	return(1);
}