]> git.cameronkatri.com Git - mandoc.git/blobdiff - tbl_term.c
Place mandoc.css into the public domain.
[mandoc.git] / tbl_term.c
index c154a0e9b967cb5668b99753c439b67c405881cb..a552c5e84dd7896737994cd6331de49e1f7d56e6 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: tbl_term.c,v 1.57 2017/07/31 16:14:10 schwarze Exp $ */
+/*     $Id: tbl_term.c,v 1.61 2018/11/25 19:24:20 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011,2012,2014,2015,2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011-2018 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 
 #include <assert.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -76,7 +77,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
        const struct tbl_dat    *dp;
        static size_t            offset;
        size_t                   coloff, tsz;
-       int                      ic, horiz, spans, vert, more;
+       int                      ic, horiz, hspans, vert, more;
        char                     fc;
 
        /* Inhibit printing of spaces: we do padding ourselves. */
@@ -156,9 +157,9 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
                /* Set up the data columns. */
 
                dp = sp->first;
-               spans = 0;
+               hspans = 0;
                for (ic = 0; ic < sp->opts->cols; ic++) {
-                       if (spans == 0) {
+                       if (hspans == 0) {
                                tp->tcol++;
                                tp->tcol->offset = coloff;
                        }
@@ -166,13 +167,13 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
                        tp->tcol->rmargin = coloff;
                        if (ic + 1 < sp->opts->cols)
                                coloff += tp->tbl.cols[ic].spacing;
-                       if (spans) {
-                               spans--;
+                       if (hspans) {
+                               hspans--;
                                continue;
                        }
                        if (dp == NULL)
                                continue;
-                       spans = dp->spans;
+                       hspans = dp->hspans;
                        if (ic || sp->layout->first->pos != TBL_CELL_SPAN)
                                dp = dp->next;
                }
@@ -192,14 +193,14 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
                tp->tcol = tp->tcols;
                cp = cpn = sp->layout->first;
                dp = sp->first;
-               spans = 0;
+               hspans = 0;
                for (ic = 0; ic < sp->opts->cols; ic++) {
                        if (cpn != NULL) {
                                cp = cpn;
                                cpn = cpn->next;
                        }
-                       if (spans) {
-                               spans--;
+                       if (hspans) {
+                               hspans--;
                                continue;
                        }
                        tp->tcol++;
@@ -207,7 +208,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
                        tbl_data(tp, sp->opts, cp, dp, tp->tbl.cols + ic);
                        if (dp == NULL)
                                continue;
-                       spans = dp->spans;
+                       hspans = dp->hspans;
                        if (cp->pos != TBL_CELL_SPAN)
                                dp = dp->next;
                }
@@ -248,7 +249,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
                        cpp = sp->prev == NULL ? NULL :
                            sp->prev->layout->first;
                        dp = sp->first;
-                       spans = 0;
+                       hspans = 0;
                        for (ic = 0; ic < sp->opts->cols; ic++) {
 
                                /*
@@ -303,12 +304,12 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
                                 * and advance to next data cell.
                                 */
 
-                               if (spans) {
-                                       spans--;
+                               if (hspans) {
+                                       hspans--;
                                        continue;
                                }
                                if (dp != NULL) {
-                                       spans = dp->spans;
+                                       hspans = dp->hspans;
                                        if (ic || sp->layout->first->pos
                                            != TBL_CELL_SPAN)
                                                dp = dp->next;
@@ -460,13 +461,11 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp, int kind)
        const struct tbl_cell *cp, *cpn, *cpp;
        const struct roffcol *col;
        int      vert;
-       char     line, cross;
+       char     cross, line, stdcross, stdline;
 
-       line = (kind < 2 && TBL_SPAN_DHORIZ == sp->pos) ? '=' : '-';
-       cross = (kind < 3) ? '+' : '-';
+       stdline = (kind < 2 && TBL_SPAN_DHORIZ == sp->pos) ? '=' : '-';
+       stdcross = (kind < 3) ? '+' : '-';
 
-       if (kind)
-               term_word(tp, "+");
        cp = sp->layout->first;
        cpp = kind || sp->prev == NULL ? NULL : sp->prev->layout->first;
        if (cpp == cp)
@@ -474,8 +473,18 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp, int kind)
        cpn = kind > 1 || sp->next == NULL ? NULL : sp->next->layout->first;
        if (cpn == cp)
                cpn = NULL;
+       if (kind)
+               term_word(tp,
+                   cpn == NULL || cpn->pos != TBL_CELL_DOWN ? "+" : "|");
        for (;;) {
                col = tp->tbl.cols + cp->col;
+               if (cpn == NULL || cpn->pos != TBL_CELL_DOWN) {
+                       line = stdline;
+                       cross = stdcross;
+               } else {
+                       line = ' ';
+                       cross = (kind < 3) ? '|' : ' ';
+               }
                tbl_char(tp, line, col->width + col->spacing / 2);
                vert = cp->vert;
                if ((cp = cp->next) == NULL)
@@ -490,6 +499,11 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp, int kind)
                                vert = cpn->vert;
                        cpn = cpn->next;
                }
+               if (cpn == NULL || cpn->pos != TBL_CELL_DOWN) {
+                       line = stdline;
+                       cross = stdcross;
+               } else
+                       line = ' ';
                if (sp->opts->opts & TBL_OPT_ALLBOX && !vert)
                        vert = 1;
                if (col->spacing)
@@ -500,7 +514,8 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp, int kind)
                        tbl_char(tp, line, (col->spacing - 3) / 2);
        }
        if (kind) {
-               term_word(tp, "+");
+               term_word(tp,
+                   cpn == NULL || cpn->pos != TBL_CELL_DOWN ? "+" : "|");
                term_flushln(tp);
        }
 }
@@ -577,14 +592,14 @@ tbl_literal(struct termp *tp, const struct tbl_dat *dp,
                const struct roffcol *col)
 {
        size_t           len, padl, padr, width;
-       int              ic, spans;
+       int              ic, hspans;
 
        assert(dp->string);
        len = term_strlen(tp, dp->string);
        width = col->width;
        ic = dp->layout->col;
-       spans = dp->spans;
-       while (spans--)
+       hspans = dp->hspans;
+       while (hspans--)
                width += tp->tbl.cols[++ic].width + 3;
 
        padr = width > len ? width - len : 0;
@@ -619,44 +634,66 @@ tbl_number(struct termp *tp, const struct tbl_opts *opts,
                const struct tbl_dat *dp,
                const struct roffcol *col)
 {
-       char            *cp;
+       const char      *cp, *lastdigit, *lastpoint;
+       size_t           intsz, padl, totsz;
        char             buf[2];
-       size_t           sz, psz, ssz, d, padl;
-       int              i;
 
        /*
-        * See calc_data_number().  Left-pad by taking the offset of our
-        * and the maximum decimal; right-pad by the remaining amount.
+        * Almost the same code as in tblcalc_number():
+        * First find the position of the decimal point.
         */
 
        assert(dp->string);
+       lastdigit = lastpoint = NULL;
+       for (cp = dp->string; cp[0] != '\0'; cp++) {
+               if (cp[0] == '\\' && cp[1] == '&') {
+                       lastdigit = lastpoint = cp;
+                       break;
+               } else if (cp[0] == opts->decimal &&
+                   (isdigit((unsigned char)cp[1]) ||
+                    (cp > dp->string && isdigit((unsigned char)cp[-1]))))
+                       lastpoint = cp;
+               else if (isdigit((unsigned char)cp[0]))
+                       lastdigit = cp;
+       }
 
-       sz = term_strlen(tp, dp->string);
+       /* Then measure both widths. */
 
-       buf[0] = opts->decimal;
-       buf[1] = '\0';
+       padl = 0;
+       totsz = term_strlen(tp, dp->string);
+       if (lastdigit != NULL) {
+               if (lastpoint == NULL)
+                       lastpoint = lastdigit + 1;
+               intsz = 0;
+               buf[1] = '\0';
+               for (cp = dp->string; cp < lastpoint; cp++) {
+                       buf[0] = cp[0];
+                       intsz += term_strlen(tp, buf);
+               }
 
-       psz = term_strlen(tp, buf);
+               /*
+                * Pad left to match the decimal position,
+                * but avoid exceeding the total column width.
+                */
 
-       if ((cp = strrchr(dp->string, opts->decimal)) != NULL) {
-               for (ssz = 0, i = 0; cp != &dp->string[i]; i++) {
-                       buf[0] = dp->string[i];
-                       ssz += term_strlen(tp, buf);
+               if (col->decimal > intsz && col->width > totsz) {
+                       padl = col->decimal - intsz;
+                       if (padl + totsz > col->width)
+                               padl = col->width - totsz;
                }
-               d = ssz + psz;
-       } else
-               d = sz + psz;
-
-       if (col->decimal > d && col->width > sz) {
-               padl = col->decimal - d;
-               if (padl + sz > col->width)
-                       padl = col->width - sz;
-               tbl_char(tp, ASCII_NBRSP, padl);
-       } else
-               padl = 0;
+
+       /* If it is not a number, simply center the string. */
+
+       } else if (col->width > totsz)
+               padl = (col->width - totsz) / 2;
+
+       tbl_char(tp, ASCII_NBRSP, padl);
        tbl_word(tp, dp);
-       if (col->width > sz + padl)
-               tbl_char(tp, ASCII_NBRSP, col->width - sz - padl);
+
+       /* Pad right to fill the column.  */
+
+       if (col->width > padl + totsz)
+               tbl_char(tp, ASCII_NBRSP, col->width - padl - totsz);
 }
 
 static void