version 1.63, 2018/11/28 13:43:54 |
version 1.65, 2018/11/29 23:08:13 |
|
|
#define IS_HORIZ(cp) ((cp)->pos == TBL_CELL_HORIZ || \ |
#define IS_HORIZ(cp) ((cp)->pos == TBL_CELL_HORIZ || \ |
(cp)->pos == TBL_CELL_DHORIZ) |
(cp)->pos == TBL_CELL_DHORIZ) |
|
|
/* Flags for tbl_hrule(). */ |
|
#define HRULE_DBOX (1 << 0) /* Top and bottom, ASCII mode only. */ |
|
#define HRULE_DATA (1 << 1) /* In the middle of the table. */ |
|
#define HRULE_DOWN (1 << 2) /* Allow downward branches. */ |
|
#define HRULE_UP (1 << 3) /* Allow upward branches. */ |
|
#define HRULE_ENDS (1 << 4) /* Also generate left and right ends. */ |
|
|
|
|
|
static size_t term_tbl_len(size_t, void *); |
static size_t term_tbl_len(size_t, void *); |
static size_t term_tbl_strlen(const char *, void *); |
static size_t term_tbl_strlen(const char *, void *); |
static size_t term_tbl_sulen(const struct roffsu *, void *); |
static size_t term_tbl_sulen(const struct roffsu *, void *); |
Line 51 static void tbl_direct_border(struct termp *, int, siz |
|
Line 44 static void tbl_direct_border(struct termp *, int, siz |
|
static void tbl_fill_border(struct termp *, int, size_t); |
static void tbl_fill_border(struct termp *, int, size_t); |
static void tbl_fill_char(struct termp *, char, size_t); |
static void tbl_fill_char(struct termp *, char, size_t); |
static void tbl_fill_string(struct termp *, const char *, size_t); |
static void tbl_fill_string(struct termp *, const char *, size_t); |
static void tbl_hrule(struct termp *, const struct tbl_span *, int); |
static void tbl_hrule(struct termp *, const struct tbl_span *, |
|
const struct tbl_span *, int); |
static void tbl_literal(struct termp *, const struct tbl_dat *, |
static void tbl_literal(struct termp *, const struct tbl_dat *, |
const struct roffcol *); |
const struct roffcol *); |
static void tbl_number(struct termp *, const struct tbl_opts *, |
static void tbl_number(struct termp *, const struct tbl_opts *, |
Line 224 term_tbl(struct termp *tp, const struct tbl_span *sp) |
|
Line 218 term_tbl(struct termp *tp, const struct tbl_span *sp) |
|
|
|
if (tp->enc == TERMENC_ASCII && |
if (tp->enc == TERMENC_ASCII && |
sp->opts->opts & TBL_OPT_DBOX) |
sp->opts->opts & TBL_OPT_DBOX) |
tbl_hrule(tp, sp, HRULE_DBOX | HRULE_ENDS); |
tbl_hrule(tp, NULL, sp, TBL_OPT_DBOX); |
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) |
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) |
tbl_hrule(tp, sp, HRULE_DOWN | HRULE_ENDS); |
tbl_hrule(tp, NULL, sp, TBL_OPT_BOX); |
} |
} |
|
|
/* Set up the columns. */ |
/* Set up the columns. */ |
Line 341 term_tbl(struct termp *tp, const struct tbl_span *sp) |
|
Line 335 term_tbl(struct termp *tp, const struct tbl_span *sp) |
|
|
|
more = 0; |
more = 0; |
if (horiz) |
if (horiz) |
tbl_hrule(tp, sp, HRULE_DATA | HRULE_DOWN | HRULE_UP); |
tbl_hrule(tp, sp->prev, sp, 0); |
else { |
else { |
cp = sp->layout->first; |
cp = sp->layout->first; |
cpn = sp->next == NULL ? NULL : |
cpn = sp->next == NULL ? NULL : |
Line 561 term_tbl(struct termp *tp, const struct tbl_span *sp) |
|
Line 555 term_tbl(struct termp *tp, const struct tbl_span *sp) |
|
tp->tcol->rmargin = tp->maxrmargin; |
tp->tcol->rmargin = tp->maxrmargin; |
if (sp->next == NULL) { |
if (sp->next == NULL) { |
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) { |
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) { |
tbl_hrule(tp, sp, HRULE_UP | HRULE_ENDS); |
tbl_hrule(tp, sp, NULL, TBL_OPT_BOX); |
tp->skipvsp = 1; |
tp->skipvsp = 1; |
} |
} |
if (tp->enc == TERMENC_ASCII && |
if (tp->enc == TERMENC_ASCII && |
sp->opts->opts & TBL_OPT_DBOX) { |
sp->opts->opts & TBL_OPT_DBOX) { |
tbl_hrule(tp, sp, HRULE_DBOX | HRULE_ENDS); |
tbl_hrule(tp, sp, NULL, TBL_OPT_DBOX); |
tp->skipvsp = 2; |
tp->skipvsp = 2; |
} |
} |
assert(tp->tbl.cols); |
assert(tp->tbl.cols); |
Line 576 term_tbl(struct termp *tp, const struct tbl_span *sp) |
|
Line 570 term_tbl(struct termp *tp, const struct tbl_span *sp) |
|
} else if (horiz == 0 && sp->opts->opts & TBL_OPT_ALLBOX && |
} else if (horiz == 0 && sp->opts->opts & TBL_OPT_ALLBOX && |
(sp->next == NULL || sp->next->pos == TBL_SPAN_DATA || |
(sp->next == NULL || sp->next->pos == TBL_SPAN_DATA || |
sp->next->next != NULL)) |
sp->next->next != NULL)) |
tbl_hrule(tp, sp, |
tbl_hrule(tp, sp, sp->next, TBL_OPT_ALLBOX); |
HRULE_DATA | HRULE_DOWN | HRULE_UP | HRULE_ENDS); |
|
|
|
tp->flags &= ~TERMP_NONOSPACE; |
tp->flags &= ~TERMP_NONOSPACE; |
} |
} |
|
|
static void |
static void |
tbl_hrule(struct termp *tp, const struct tbl_span *sp, int flags) |
tbl_hrule(struct termp *tp, const struct tbl_span *spp, |
|
const struct tbl_span *spn, int flags) |
{ |
{ |
const struct tbl_cell *cp, *cpn, *cpp; |
const struct tbl_cell *cpp; /* Layout cell above this line. */ |
const struct roffcol *col; |
const struct tbl_cell *cpn; /* Layout cell below this line. */ |
int cross, dvert, line, linewidth, uvert; |
const struct tbl_dat *dpn; /* Data cell below this line. */ |
|
const struct roffcol *col; /* Contains width and spacing. */ |
|
int opts; /* For the table as a whole. */ |
|
int bw; /* Box line width. */ |
|
int hw; /* Horizontal line width. */ |
|
int lw, rw; /* Left and right line widths. */ |
|
int uw, dw; /* Vertical line widths. */ |
|
|
cp = sp->layout->first; |
cpp = spp == NULL ? NULL : spp->layout->first; |
cpn = cpp = NULL; |
cpn = spn == NULL ? NULL : spn->layout->first; |
if (flags & HRULE_DATA) { |
dpn = NULL; |
linewidth = sp->pos == TBL_SPAN_DHORIZ ? 2 : 1; |
if (spn != NULL) { |
cpn = sp->next == NULL ? NULL : sp->next->layout->first; |
if (spn->pos == TBL_SPAN_DATA) |
if (cpn == cp) |
dpn = spn->first; |
cpn = NULL; |
else if (spn->next != NULL) |
} else |
dpn = spn->next->first; |
linewidth = tp->enc == TERMENC_UTF8 && |
} |
sp->opts->opts & TBL_OPT_DBOX ? 2 : 1; |
opts = spn == NULL ? spp->opts->opts : spn->opts->opts; |
|
bw = opts & TBL_OPT_DBOX ? (tp->enc == TERMENC_UTF8 ? 2 : 1) : |
|
opts & (TBL_OPT_BOX | TBL_OPT_ALLBOX) ? 1 : 0; |
|
hw = flags == TBL_OPT_DBOX || flags == TBL_OPT_BOX ? bw : |
|
spn->pos == TBL_SPAN_DHORIZ ? 2 : 1; |
|
|
|
/* Print the left end of the line. */ |
|
|
if (tp->viscol == 0) { |
if (tp->viscol == 0) { |
(*tp->advance)(tp, tp->tcols->offset); |
(*tp->advance)(tp, tp->tcols->offset); |
tp->viscol = tp->tcols->offset; |
tp->viscol = tp->tcols->offset; |
} |
} |
if (flags & HRULE_ENDS) |
if (flags != 0) |
tbl_direct_border(tp, linewidth * (BRIGHT + |
tbl_direct_border(tp, |
(flags & (HRULE_UP | HRULE_DBOX) ? BUP : 0) + |
(spp == NULL ? 0 : BUP * bw) + |
(flags & (HRULE_DOWN | HRULE_DBOX) ? BDOWN : 0)), 1); |
(spn == NULL ? 0 : BDOWN * bw) + |
else { |
(spp == NULL || cpn == NULL || |
cpp = sp->prev == NULL ? NULL : sp->prev->layout->first; |
cpn->pos != TBL_CELL_DOWN ? BRIGHT * hw : 0), 1); |
if (cpp == cp) |
|
cpp = NULL; |
|
} |
|
for (;;) { |
for (;;) { |
col = tp->tbl.cols + cp->col; |
col = tp->tbl.cols + (cpn == NULL ? cpp->col : cpn->col); |
line = cpn == NULL || cpn->pos != TBL_CELL_DOWN ? |
|
BHORIZ * linewidth : 0; |
/* Print the horizontal line inside this column. */ |
tbl_direct_border(tp, line, col->width + col->spacing / 2); |
|
uvert = dvert = 0; |
lw = cpp == NULL || cpn == NULL || |
if (flags & HRULE_UP && |
(cpn->pos != TBL_CELL_DOWN && |
(tp->enc == TERMENC_ASCII || sp->pos == TBL_SPAN_DATA || |
(dpn == NULL || strcmp(dpn->string, "\\^") != 0)) |
(sp->prev != NULL && sp->prev->layout == sp->layout))) |
? hw : 0; |
uvert = cp->vert; |
tbl_direct_border(tp, BHORIZ * lw, |
if (flags & HRULE_DOWN) |
col->width + col->spacing / 2); |
dvert = cp->vert; |
|
if ((cp = cp->next) == NULL) |
/* |
break; |
* Figure out whether a vertical line is crossing |
|
* at the end of this column, |
|
* and advance to the next column. |
|
*/ |
|
|
|
uw = dw = 0; |
if (cpp != NULL) { |
if (cpp != NULL) { |
if (uvert < cpp->vert) |
if (flags != TBL_OPT_DBOX) { |
uvert = cpp->vert; |
uw = cpp->vert; |
|
if (uw == 0 && opts & TBL_OPT_ALLBOX) |
|
uw = 1; |
|
} |
cpp = cpp->next; |
cpp = cpp->next; |
} |
} |
if (cpn != NULL) { |
if (cpn != NULL) { |
if (dvert < cpn->vert) |
if (flags != TBL_OPT_DBOX) { |
dvert = cpn->vert; |
dw = cpn->vert; |
|
if (dw == 0 && opts & TBL_OPT_ALLBOX) |
|
dw = 1; |
|
} |
cpn = cpn->next; |
cpn = cpn->next; |
|
while (dpn != NULL && dpn->layout != cpn) |
|
dpn = dpn->next; |
} |
} |
if (sp->opts->opts & TBL_OPT_ALLBOX) { |
if (cpp == NULL && cpn == NULL) |
if (flags & HRULE_UP && uvert == 0) |
break; |
uvert = 1; |
|
if (flags & HRULE_DOWN && dvert == 0) |
/* Vertical lines do not cross spanned cells. */ |
dvert = 1; |
|
} |
if (cpp != NULL && cpp->pos == TBL_CELL_SPAN) |
cross = BHORIZ * linewidth + BUP * uvert + BDOWN * dvert; |
uw = 0; |
|
if (cpn != NULL && cpn->pos == TBL_CELL_SPAN) |
|
dw = 0; |
|
|
|
/* The horizontal line inside the next column. */ |
|
|
|
rw = cpp == NULL || cpn == NULL || |
|
(cpn->pos != TBL_CELL_DOWN && |
|
(dpn == NULL || strcmp(dpn->string, "\\^") != 0)) |
|
? hw : 0; |
|
|
|
/* The line crossing at the end of this column. */ |
|
|
if (col->spacing) |
if (col->spacing) |
tbl_direct_border(tp, cross, 1); |
tbl_direct_border(tp, BLEFT * lw + |
|
BRIGHT * rw + BUP * uw + BDOWN * dw, 1); |
|
|
|
/* |
|
* In ASCII output, a crossing may print two characters. |
|
*/ |
|
|
|
if (tp->enc != TERMENC_ASCII || (uw < 2 && dw < 2)) |
|
uw = dw = 0; |
if (col->spacing > 2) |
if (col->spacing > 2) |
tbl_direct_border(tp, tp->enc == TERMENC_ASCII && |
tbl_direct_border(tp, |
(uvert > 1 || dvert > 1) ? cross : line, 1); |
BHORIZ * rw + BUP * uw + BDOWN * dw, 1); |
|
|
|
/* Padding before the start of the next column. */ |
|
|
if (col->spacing > 4) |
if (col->spacing > 4) |
tbl_direct_border(tp, line, (col->spacing - 3) / 2); |
tbl_direct_border(tp, |
|
BHORIZ * rw, (col->spacing - 3) / 2); |
} |
} |
if (flags & HRULE_ENDS) { |
|
tbl_direct_border(tp, linewidth * (BLEFT + |
/* Print the right end of the line. */ |
(flags & (HRULE_UP | HRULE_DBOX) ? BUP : 0) + |
|
(flags & (HRULE_DOWN | HRULE_DBOX) ? BDOWN : 0)), 1); |
if (flags != 0) { |
|
tbl_direct_border(tp, |
|
(spp == NULL ? 0 : BUP * bw) + |
|
(spn == NULL ? 0 : BDOWN * bw) + |
|
(spp == NULL || spn == NULL || |
|
spn->layout->last->pos != TBL_CELL_DOWN ? |
|
BLEFT * hw : 0), 1); |
(*tp->endline)(tp); |
(*tp->endline)(tp); |
tp->viscol = 0; |
tp->viscol = 0; |
} |
} |