Exemplo n.º 1
0
/*
 * Calculate the abstract widths and decimal positions of columns in a
 * table.  This routine allocates the columns structures then runs over
 * all rows and cells in the table.  The function pointers in "tbl" are
 * used for the actual width calculations.
 */
void
tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
{
	const struct tbl_dat	*dp;
	const struct tbl_head	*hp;
	struct roffcol		*col;

	/*
	 * Allocate the master column specifiers.  These will hold the
	 * widths and decimal positions for all cells in the column.  It
	 * must be freed and nullified by the caller.
	 */

	assert(NULL == tbl->cols);
	tbl->cols = calloc(sp->tbl->cols, sizeof(struct roffcol));

	hp = sp->head;

	for ( ; sp; sp = sp->next) {
		if (TBL_SPAN_DATA != sp->pos)
			continue;
		/*
		 * Account for the data cells in the layout, matching it
		 * to data cells in the data section.
		 */
		for (dp = sp->first; dp; dp = dp->next) {
			if (NULL == dp->layout)
				continue;
			col = &tbl->cols[dp->layout->head->ident];
			tblcalc_data(tbl, col, sp->tbl, dp);
		}
	}

	/* 
	 * Calculate width of the spanners.  These get one space for a
	 * vertical line, two for a double-vertical line. 
	 */

	for ( ; hp; hp = hp->next) {
		col = &tbl->cols[hp->ident];
		switch (hp->pos) {
		case (TBL_HEAD_VERT):
			col->width = (*tbl->len)(1, tbl->arg);
			break;
		case (TBL_HEAD_DVERT):
			col->width = (*tbl->len)(2, tbl->arg);
			break;
		default:
			break;
		}
	}
}
Exemplo n.º 2
0
/*
 * Calculate the abstract widths and decimal positions of columns in a
 * table.  This routine allocates the columns structures then runs over
 * all rows and cells in the table.  The function pointers in "tbl" are
 * used for the actual width calculations.
 */
void
tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
{
	const struct tbl_dat	*dp;
	const struct tbl_head	*hp;
	struct roffcol		*col;
	int			 spans;

	/*
	 * Allocate the master column specifiers.  These will hold the
	 * widths and decimal positions for all cells in the column.  It
	 * must be freed and nullified by the caller.
	 */

	assert(NULL == tbl->cols);
	tbl->cols = mandoc_calloc
		((size_t)sp->opts->cols, sizeof(struct roffcol));

	hp = sp->head;

	for ( ; sp; sp = sp->next) {
		if (TBL_SPAN_DATA != sp->pos)
			continue;
		spans = 1;
		/*
		 * Account for the data cells in the layout, matching it
		 * to data cells in the data section.
		 */
		for (dp = sp->first; dp; dp = dp->next) {
			/* Do not used spanned cells in the calculation. */
			if (0 < --spans)
				continue;
			spans = dp->spans;
			if (1 < spans)
				continue;
			assert(dp->layout);
			col = &tbl->cols[dp->layout->head->ident];
			tblcalc_data(tbl, col, sp->opts, dp);
		}
	}
}
Exemplo n.º 3
0
/*
 * Calculate the abstract widths and decimal positions of columns in a
 * table.  This routine allocates the columns structures then runs over
 * all rows and cells in the table.  The function pointers in "tbl" are
 * used for the actual width calculations.
 */
void
tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
	size_t totalwidth)
{
	const struct tbl_opts	*opts;
	const struct tbl_dat	*dp;
	struct roffcol		*col;
	size_t			 ewidth, xwidth;
	int			 spans;
	int			 icol, maxcol, necol, nxcol, quirkcol;

	/*
	 * Allocate the master column specifiers.  These will hold the
	 * widths and decimal positions for all cells in the column.  It
	 * must be freed and nullified by the caller.
	 */

	assert(NULL == tbl->cols);
	tbl->cols = mandoc_calloc((size_t)sp->opts->cols,
	    sizeof(struct roffcol));
	opts = sp->opts;

	for (maxcol = -1; sp; sp = sp->next) {
		if (TBL_SPAN_DATA != sp->pos)
			continue;
		spans = 1;
		/*
		 * Account for the data cells in the layout, matching it
		 * to data cells in the data section.
		 */
		for (dp = sp->first; dp; dp = dp->next) {
			/* Do not used spanned cells in the calculation. */
			if (0 < --spans)
				continue;
			spans = dp->spans;
			if (1 < spans)
				continue;
			icol = dp->layout->col;
			if (maxcol < icol)
				maxcol = icol;
			col = tbl->cols + icol;
			col->flags |= dp->layout->flags;
			if (dp->layout->flags & TBL_CELL_WIGN)
				continue;
			tblcalc_data(tbl, col, opts, dp);
		}
	}

	/*
	 * Count columns to equalize and columns to maximize.
	 * Find maximum width of the columns to equalize.
	 * Find total width of the columns *not* to maximize.
	 */

	necol = nxcol = 0;
	ewidth = xwidth = 0;
	for (icol = 0; icol <= maxcol; icol++) {
		col = tbl->cols + icol;
		if (col->flags & TBL_CELL_EQUAL) {
			necol++;
			if (ewidth < col->width)
				ewidth = col->width;
		}
		if (col->flags & TBL_CELL_WMAX)
			nxcol++;
		else
			xwidth += col->width;
	}

	/*
	 * Equalize columns, if requested for any of them.
	 * Update total width of the columns not to maximize.
	 */

	if (necol) {
		for (icol = 0; icol <= maxcol; icol++) {
			col = tbl->cols + icol;
			if ( ! (col->flags & TBL_CELL_EQUAL))
				continue;
			if (col->width == ewidth)
				continue;
			if (nxcol && totalwidth)
				xwidth += ewidth - col->width;
			col->width = ewidth;
		}
	}

	/*
	 * If there are any columns to maximize, find the total
	 * available width, deducting 3n margins between columns.
	 * Distribute the available width evenly.
	 */

	if (nxcol && totalwidth) {
		xwidth = totalwidth - xwidth - 3*maxcol -
		    (opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX) ?
		     2 : !!opts->lvert + !!opts->rvert);

		/*
		 * Emulate a bug in GNU tbl width calculation that
		 * manifests itself for large numbers of x-columns.
		 * Emulating it for 5 x-columns gives identical
		 * behaviour for up to 6 x-columns.
		 */

		if (nxcol == 5) {
			quirkcol = xwidth % nxcol + 2;
			if (quirkcol != 3 && quirkcol != 4)
				quirkcol = -1;
		} else
			quirkcol = -1;

		necol = 0;
		ewidth = 0;
		for (icol = 0; icol <= maxcol; icol++) {
			col = tbl->cols + icol;
			if ( ! (col->flags & TBL_CELL_WMAX))
				continue;
			col->width = (double)xwidth * ++necol / nxcol
			    - ewidth + 0.4995;
			if (necol == quirkcol)
				col->width--;
			ewidth += col->width;
		}
	}
}