=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/tbl_term.c,v retrieving revision 1.51 retrieving revision 1.52 diff -c -r1.51 -r1.52 *** src/usr.bin/mandoc/tbl_term.c 2018/11/28 13:43:26 1.51 --- src/usr.bin/mandoc/tbl_term.c 2018/11/29 21:40:08 1.52 *************** *** 1,4 **** ! /* $OpenBSD: tbl_term.c,v 1.51 2018/11/28 13:43:26 schwarze Exp $ */ /* * Copyright (c) 2009, 2011 Kristaps Dzonsons * Copyright (c) 2011-2018 Ingo Schwarze --- 1,4 ---- ! /* $OpenBSD: tbl_term.c,v 1.52 2018/11/29 21:40:08 schwarze Exp $ */ /* * Copyright (c) 2009, 2011 Kristaps Dzonsons * Copyright (c) 2011-2018 Ingo Schwarze *************** *** 30,43 **** #define IS_HORIZ(cp) ((cp)->pos == TBL_CELL_HORIZ || \ (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_strlen(const char *, void *); static size_t term_tbl_sulen(const struct roffsu *, void *); --- 30,36 ---- *************** *** 49,55 **** static void tbl_fill_border(struct termp *, int, 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_hrule(struct termp *, const struct tbl_span *, int); static void tbl_literal(struct termp *, const struct tbl_dat *, const struct roffcol *); static void tbl_number(struct termp *, const struct tbl_opts *, --- 42,49 ---- static void tbl_fill_border(struct termp *, int, 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_hrule(struct termp *, const struct tbl_span *, ! const struct tbl_span *, int); static void tbl_literal(struct termp *, const struct tbl_dat *, const struct roffcol *); static void tbl_number(struct termp *, const struct tbl_opts *, *************** *** 222,230 **** if (tp->enc == TERMENC_ASCII && sp->opts->opts & TBL_OPT_DBOX) ! tbl_hrule(tp, sp, HRULE_DBOX | HRULE_ENDS); if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) ! tbl_hrule(tp, sp, HRULE_DOWN | HRULE_ENDS); } /* Set up the columns. */ --- 216,224 ---- if (tp->enc == TERMENC_ASCII && sp->opts->opts & TBL_OPT_DBOX) ! tbl_hrule(tp, NULL, sp, TBL_OPT_DBOX); if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) ! tbl_hrule(tp, NULL, sp, TBL_OPT_BOX); } /* Set up the columns. */ *************** *** 339,345 **** more = 0; if (horiz) ! tbl_hrule(tp, sp, HRULE_DATA | HRULE_DOWN | HRULE_UP); else { cp = sp->layout->first; cpn = sp->next == NULL ? NULL : --- 333,339 ---- more = 0; if (horiz) ! tbl_hrule(tp, sp->prev, sp, 0); else { cp = sp->layout->first; cpn = sp->next == NULL ? NULL : *************** *** 559,570 **** tp->tcol->rmargin = tp->maxrmargin; if (sp->next == NULL) { if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) { ! tbl_hrule(tp, sp, HRULE_UP | HRULE_ENDS); tp->skipvsp = 1; } if (tp->enc == TERMENC_ASCII && sp->opts->opts & TBL_OPT_DBOX) { ! tbl_hrule(tp, sp, HRULE_DBOX | HRULE_ENDS); tp->skipvsp = 2; } assert(tp->tbl.cols); --- 553,564 ---- tp->tcol->rmargin = tp->maxrmargin; if (sp->next == NULL) { if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) { ! tbl_hrule(tp, sp, NULL, TBL_OPT_BOX); tp->skipvsp = 1; } if (tp->enc == TERMENC_ASCII && sp->opts->opts & TBL_OPT_DBOX) { ! tbl_hrule(tp, sp, NULL, TBL_OPT_DBOX); tp->skipvsp = 2; } assert(tp->tbl.cols); *************** *** 574,658 **** } else if (horiz == 0 && sp->opts->opts & TBL_OPT_ALLBOX && (sp->next == NULL || sp->next->pos == TBL_SPAN_DATA || sp->next->next != NULL)) ! tbl_hrule(tp, sp, ! HRULE_DATA | HRULE_DOWN | HRULE_UP | HRULE_ENDS); tp->flags &= ~TERMP_NONOSPACE; } static void ! tbl_hrule(struct termp *tp, const struct tbl_span *sp, int flags) { ! const struct tbl_cell *cp, *cpn, *cpp; ! const struct roffcol *col; ! int cross, dvert, line, linewidth, uvert; ! cp = sp->layout->first; ! cpn = cpp = NULL; ! if (flags & HRULE_DATA) { ! linewidth = sp->pos == TBL_SPAN_DHORIZ ? 2 : 1; ! cpn = sp->next == NULL ? NULL : sp->next->layout->first; ! if (cpn == cp) ! cpn = NULL; ! } else ! linewidth = tp->enc == TERMENC_UTF8 && ! sp->opts->opts & TBL_OPT_DBOX ? 2 : 1; if (tp->viscol == 0) { (*tp->advance)(tp, tp->tcols->offset); tp->viscol = tp->tcols->offset; } ! if (flags & HRULE_ENDS) ! tbl_direct_border(tp, linewidth * (BRIGHT + ! (flags & (HRULE_UP | HRULE_DBOX) ? BUP : 0) + ! (flags & (HRULE_DOWN | HRULE_DBOX) ? BDOWN : 0)), 1); ! else { ! cpp = sp->prev == NULL ? NULL : sp->prev->layout->first; ! if (cpp == cp) ! cpp = NULL; ! } for (;;) { ! col = tp->tbl.cols + cp->col; ! line = cpn == NULL || cpn->pos != TBL_CELL_DOWN ? ! BHORIZ * linewidth : 0; ! tbl_direct_border(tp, line, col->width + col->spacing / 2); ! uvert = dvert = 0; ! if (flags & HRULE_UP && ! (tp->enc == TERMENC_ASCII || sp->pos == TBL_SPAN_DATA || ! (sp->prev != NULL && sp->prev->layout == sp->layout))) ! uvert = cp->vert; ! if (flags & HRULE_DOWN) ! dvert = cp->vert; ! if ((cp = cp->next) == NULL) ! break; if (cpp != NULL) { ! if (uvert < cpp->vert) ! uvert = cpp->vert; cpp = cpp->next; } if (cpn != NULL) { ! if (dvert < cpn->vert) ! dvert = cpn->vert; cpn = cpn->next; } ! if (sp->opts->opts & TBL_OPT_ALLBOX) { ! if (flags & HRULE_UP && uvert == 0) ! uvert = 1; ! if (flags & HRULE_DOWN && dvert == 0) ! dvert = 1; ! } ! cross = BHORIZ * linewidth + BUP * uvert + BDOWN * dvert; if (col->spacing) ! tbl_direct_border(tp, cross, 1); if (col->spacing > 2) ! tbl_direct_border(tp, tp->enc == TERMENC_ASCII && ! (uvert > 1 || dvert > 1) ? cross : line, 1); if (col->spacing > 4) ! tbl_direct_border(tp, line, (col->spacing - 3) / 2); } ! if (flags & HRULE_ENDS) { ! tbl_direct_border(tp, linewidth * (BLEFT + ! (flags & (HRULE_UP | HRULE_DBOX) ? BUP : 0) + ! (flags & (HRULE_DOWN | HRULE_DBOX) ? BDOWN : 0)), 1); (*tp->endline)(tp); tp->viscol = 0; } --- 568,692 ---- } else if (horiz == 0 && sp->opts->opts & TBL_OPT_ALLBOX && (sp->next == NULL || sp->next->pos == TBL_SPAN_DATA || sp->next->next != NULL)) ! tbl_hrule(tp, sp, sp->next, TBL_OPT_ALLBOX); tp->flags &= ~TERMP_NONOSPACE; } static void ! tbl_hrule(struct termp *tp, const struct tbl_span *spp, ! const struct tbl_span *spn, int flags) { ! const struct tbl_cell *cpp; /* Cell above this line. */ ! const struct tbl_cell *cpn; /* 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. */ ! cpp = spp == NULL ? NULL : spp->layout->first; ! cpn = spn == NULL ? NULL : spn->layout->first; ! 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) { (*tp->advance)(tp, tp->tcols->offset); tp->viscol = tp->tcols->offset; } ! if (flags != 0) ! tbl_direct_border(tp, ! (spp == NULL ? 0 : BUP * bw) + ! (spn == NULL ? 0 : BDOWN * bw) + ! (spp == NULL || cpn == NULL || ! cpn->pos != TBL_CELL_DOWN ? BRIGHT * hw : 0), 1); ! for (;;) { ! col = tp->tbl.cols + (cpn == NULL ? cpp->col : cpn->col); ! ! /* Print the horizontal line inside this column. */ ! ! lw = cpp == NULL || cpn == NULL || ! cpn->pos != TBL_CELL_DOWN ? hw : 0; ! tbl_direct_border(tp, BHORIZ * lw, ! col->width + col->spacing / 2); ! ! /* ! * 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 (flags != TBL_OPT_DBOX) { ! uw = cpp->vert; ! if (uw == 0 && opts & TBL_OPT_ALLBOX) ! uw = 1; ! } cpp = cpp->next; } if (cpn != NULL) { ! if (flags != TBL_OPT_DBOX) { ! dw = cpn->vert; ! if (dw == 0 && opts & TBL_OPT_ALLBOX) ! dw = 1; ! } cpn = cpn->next; } ! if (cpp == NULL && cpn == NULL) ! break; ! ! /* Vertical lines do not cross spanned cells. */ ! ! if (cpp != NULL && cpp->pos == TBL_CELL_SPAN) ! 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 ? hw : 0; ! ! /* The line crossing at the end of this column. */ ! if (col->spacing) ! 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) ! tbl_direct_border(tp, ! BHORIZ * rw + BUP * uw + BDOWN * dw, 1); ! ! /* Padding before the start of the next column. */ ! if (col->spacing > 4) ! tbl_direct_border(tp, ! BHORIZ * rw, (col->spacing - 3) / 2); } ! ! /* Print the right end of the line. */ ! ! 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->viscol = 0; }