[BACK]Return to tbl_term.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mandoc

Annotation of src/usr.bin/mandoc/tbl_term.c, Revision 1.5

1.5     ! schwarze    1: /*     $Id: tbl_term.c,v 1.1 2011/01/02 12:21:07 kristaps Exp $ */
1.1       schwarze    2: /*
1.5     ! schwarze    3:  * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@kth.se>
1.1       schwarze    4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: #include <assert.h>
                     18: #include <stdio.h>
                     19: #include <stdlib.h>
                     20: #include <string.h>
                     21:
1.5     ! schwarze   22: #include "mandoc.h"
1.2       schwarze   23: #include "out.h"
                     24: #include "term.h"
1.1       schwarze   25:
                     26: /* FIXME: `n' modifier doesn't always do the right thing. */
                     27: /* FIXME: `n' modifier doesn't use the cell-spacing buffer. */
                     28:
1.5     ! schwarze   29: static inline void      tbl_char(struct termp *, char, int);
        !            30: static void             tbl_hframe(struct termp *,
        !            31:                                const struct tbl_span *);
        !            32: static void             tbl_data_number(struct termp *,
        !            33:                                const struct tbl *,
        !            34:                                const struct tbl_dat *,
        !            35:                                const struct termp_tbl *);
        !            36: static void             tbl_data_literal(struct termp *,
        !            37:                                const struct tbl_dat *,
        !            38:                                const struct termp_tbl *);
        !            39: static void             tbl_data(struct termp *, const struct tbl *,
        !            40:                                const struct tbl_dat *,
        !            41:                                const struct termp_tbl *);
        !            42: static void             tbl_spanner(struct termp *,
        !            43:                                const struct tbl_head *);
        !            44: static void             tbl_hrule(struct termp *,
        !            45:                                const struct tbl_span *);
        !            46: static void             tbl_vframe(struct termp *,
        !            47:                                const struct tbl *);
        !            48: static void             tbl_calc(struct termp *,
        !            49:                                const struct tbl_span *);
        !            50: static void             tbl_calc_data(struct termp *,
        !            51:                                const struct tbl *,
        !            52:                                const struct tbl_dat *,
        !            53:                                struct termp_tbl *);
        !            54: static void             tbl_calc_data_literal(struct termp *,
        !            55:                                const struct tbl_dat *,
        !            56:                                struct termp_tbl *);
        !            57: static void             tbl_calc_data_number(struct termp *,
        !            58:                                const struct tbl *,
        !            59:                                const struct tbl_dat *,
        !            60:                                struct termp_tbl *);
        !            61:
        !            62: void
        !            63: term_tbl(struct termp *tp, const struct tbl_span *sp)
        !            64: {
        !            65:        const struct tbl_head *hp;
        !            66:        const struct tbl_dat *dp;
        !            67:
        !            68:        /* Inhibit printing of spaces: we do padding ourselves. */
        !            69:
        !            70:        tp->flags |= TERMP_NONOSPACE;
        !            71:        tp->flags |= TERMP_NOSPACE;
1.1       schwarze   72:
                     73:        /*
1.5     ! schwarze   74:         * The first time we're invoked for a given table block, create
        !            75:         * the termp_tbl structure.  This contains the column
        !            76:         * configuration for the entire table, e.g., table-wide column
        !            77:         * width, decimal point, etc.
1.1       schwarze   78:         */
                     79:
1.5     ! schwarze   80:        if (TBL_SPAN_FIRST & sp->flags) {
        !            81:                assert(NULL == tp->tbl);
        !            82:                tp->tbl = calloc
        !            83:                        (sp->tbl->cols, sizeof(struct termp_tbl));
        !            84:                if (NULL == tp->tbl) {
        !            85:                        perror(NULL);
        !            86:                        exit(EXIT_FAILURE);
        !            87:                }
        !            88:                tbl_calc(tp, sp);
        !            89:
        !            90:                /* Flush out any preceding data. */
        !            91:                term_flushln(tp);
        !            92:        }
1.2       schwarze   93:
1.5     ! schwarze   94:        /* Horizontal frame at the start of boxed tables. */
1.1       schwarze   95:
1.5     ! schwarze   96:        if (TBL_SPAN_FIRST & sp->flags)
        !            97:                tbl_hframe(tp, sp);
        !            98:
        !            99:        /* Vertical frame at the start of each row. */
        !           100:
        !           101:        tbl_vframe(tp, sp->tbl);
1.1       schwarze  102:
                    103:        /*
1.5     ! schwarze  104:         * Now print the actual data itself depending on the span type.
        !           105:         * Spanner spans get a horizontal rule; data spanners have their
        !           106:         * data printed by matching data to header.
1.1       schwarze  107:         */
                    108:
1.5     ! schwarze  109:        switch (sp->pos) {
        !           110:        case (TBL_SPAN_HORIZ):
        !           111:                /* FALLTHROUGH */
        !           112:        case (TBL_SPAN_DHORIZ):
        !           113:                tbl_hrule(tp, sp);
        !           114:                break;
        !           115:        case (TBL_SPAN_DATA):
        !           116:                /* Iterate over template headers. */
        !           117:                dp = sp->first;
        !           118:                for (hp = sp->head; hp; hp = hp->next) {
        !           119:                        switch (hp->pos) {
1.1       schwarze  120:                        case (TBL_HEAD_VERT):
                    121:                                /* FALLTHROUGH */
                    122:                        case (TBL_HEAD_DVERT):
1.5     ! schwarze  123:                                tbl_spanner(tp, hp);
        !           124:                                continue;
1.1       schwarze  125:                        case (TBL_HEAD_DATA):
                    126:                                break;
                    127:                        }
1.5     ! schwarze  128:                        tbl_data(tp, sp->tbl, dp,
        !           129:                                &tp->tbl[hp->ident]);
        !           130:
        !           131:                        /* Go to the next data cell. */
        !           132:                        if (dp)
        !           133:                                dp = dp->next;
1.1       schwarze  134:                }
1.5     ! schwarze  135:                break;
1.1       schwarze  136:        }
                    137:
1.5     ! schwarze  138:        tbl_vframe(tp, sp->tbl);
        !           139:        term_flushln(tp);
1.1       schwarze  140:
1.5     ! schwarze  141:        /*
        !           142:         * If we're the last row, clean up after ourselves: clear the
        !           143:         * existing table configuration and set it to NULL.
        !           144:         */
1.1       schwarze  145:
1.5     ! schwarze  146:        if (TBL_SPAN_LAST & sp->flags) {
        !           147:                tbl_hframe(tp, sp);
        !           148:                assert(tp->tbl);
        !           149:                free(tp->tbl);
        !           150:                tp->tbl = NULL;
1.1       schwarze  151:        }
                    152:
1.5     ! schwarze  153:        tp->flags &= ~TERMP_NONOSPACE;
1.1       schwarze  154:
                    155: }
                    156:
                    157: static void
1.5     ! schwarze  158: tbl_hrule(struct termp *tp, const struct tbl_span *sp)
1.1       schwarze  159: {
1.5     ! schwarze  160:        const struct tbl_head *hp;
        !           161:        char             c;
        !           162:        int              width;
1.1       schwarze  163:
                    164:        /*
                    165:         * An hrule extends across the entire table and is demarked by a
                    166:         * standalone `_' or whatnot in lieu of a table row.  Spanning
                    167:         * headers are marked by a `+', as are table boundaries.
                    168:         */
                    169:
                    170:        c = '-';
1.5     ! schwarze  171:        if (TBL_SPAN_DHORIZ == sp->pos)
1.1       schwarze  172:                c = '=';
                    173:
                    174:        /* FIXME: don't use `+' between data and a spanner! */
                    175:
1.5     ! schwarze  176:        for (hp = sp->head; hp; hp = hp->next) {
        !           177:                width = tp->tbl[hp->ident].width;
        !           178:                switch (hp->pos) {
1.1       schwarze  179:                case (TBL_HEAD_DATA):
1.5     ! schwarze  180:                        tbl_char(tp, c, width);
1.1       schwarze  181:                        break;
                    182:                case (TBL_HEAD_DVERT):
1.5     ! schwarze  183:                        tbl_char(tp, '+', width);
1.1       schwarze  184:                        /* FALLTHROUGH */
                    185:                case (TBL_HEAD_VERT):
1.5     ! schwarze  186:                        tbl_char(tp, '+', width);
1.1       schwarze  187:                        break;
                    188:                default:
                    189:                        abort();
                    190:                        /* NOTREACHED */
                    191:                }
                    192:        }
                    193: }
                    194:
                    195: static void
1.5     ! schwarze  196: tbl_hframe(struct termp *tp, const struct tbl_span *sp)
1.1       schwarze  197: {
1.5     ! schwarze  198:        const struct tbl_head *hp;
        !           199:        int              width;
1.1       schwarze  200:
1.5     ! schwarze  201:        if ( ! (TBL_OPT_BOX & sp->tbl->opts ||
        !           202:                        TBL_OPT_DBOX & sp->tbl->opts))
1.1       schwarze  203:                return;
                    204:
                    205:        /*
                    206:         * Print out the horizontal part of a frame or double frame.  A
                    207:         * double frame has an unbroken `-' outer line the width of the
                    208:         * table, bordered by `+'.  The frame (or inner frame, in the
                    209:         * case of the double frame) is a `-' bordered by `+' and broken
                    210:         * by `+' whenever a span is encountered.
                    211:         */
                    212:
1.5     ! schwarze  213:        if (TBL_OPT_DBOX & sp->tbl->opts) {
        !           214:                term_word(tp, "+");
        !           215:                for (hp = sp->head; hp; hp = hp->next) {
        !           216:                        width = tp->tbl[hp->ident].width;
        !           217:                        tbl_char(tp, '-', width);
        !           218:                }
        !           219:                term_word(tp, "+");
        !           220:                term_flushln(tp);
1.1       schwarze  221:        }
                    222:
1.5     ! schwarze  223:        term_word(tp, "+");
        !           224:        for (hp = sp->head; hp; hp = hp->next) {
        !           225:                width = tp->tbl[hp->ident].width;
        !           226:                switch (hp->pos) {
1.1       schwarze  227:                case (TBL_HEAD_DATA):
1.5     ! schwarze  228:                        tbl_char(tp, '-', width);
1.1       schwarze  229:                        break;
                    230:                default:
1.5     ! schwarze  231:                        tbl_char(tp, '+', width);
1.1       schwarze  232:                        break;
                    233:                }
                    234:        }
1.5     ! schwarze  235:        term_word(tp, "+");
        !           236:        term_flushln(tp);
1.1       schwarze  237: }
                    238:
                    239: static void
1.5     ! schwarze  240: tbl_data(struct termp *tp, const struct tbl *tbl,
        !           241:                const struct tbl_dat *dp,
        !           242:                const struct termp_tbl *tbp)
1.1       schwarze  243: {
1.5     ! schwarze  244:        enum tbl_cellt   pos;
1.1       schwarze  245:
1.5     ! schwarze  246:        if (NULL == dp) {
        !           247:                tbl_char(tp, ASCII_NBRSP, tbp->width);
1.1       schwarze  248:                return;
1.5     ! schwarze  249:        }
1.1       schwarze  250:
1.5     ! schwarze  251:        switch (dp->pos) {
        !           252:        case (TBL_DATA_NONE):
        !           253:                tbl_char(tp, ASCII_NBRSP, tbp->width);
        !           254:                return;
        !           255:        case (TBL_DATA_HORIZ):
        !           256:                /* FALLTHROUGH */
        !           257:        case (TBL_DATA_NHORIZ):
        !           258:                tbl_char(tp, '-', tbp->width);
        !           259:                return;
        !           260:        case (TBL_DATA_NDHORIZ):
1.1       schwarze  261:                /* FALLTHROUGH */
1.5     ! schwarze  262:        case (TBL_DATA_DHORIZ):
        !           263:                tbl_char(tp, '=', tbp->width);
        !           264:                return;
1.1       schwarze  265:        default:
                    266:                break;
                    267:        }
1.5     ! schwarze  268:
        !           269:        pos = dp->layout ? dp->layout->pos : TBL_CELL_LEFT;
1.1       schwarze  270:
1.5     ! schwarze  271:        switch (pos) {
1.1       schwarze  272:        case (TBL_CELL_HORIZ):
1.5     ! schwarze  273:                tbl_char(tp, '-', tbp->width);
        !           274:                break;
1.1       schwarze  275:        case (TBL_CELL_DHORIZ):
1.5     ! schwarze  276:                tbl_char(tp, '=', tbp->width);
1.1       schwarze  277:                break;
                    278:        case (TBL_CELL_LONG):
                    279:                /* FALLTHROUGH */
                    280:        case (TBL_CELL_CENTRE):
                    281:                /* FALLTHROUGH */
                    282:        case (TBL_CELL_LEFT):
                    283:                /* FALLTHROUGH */
                    284:        case (TBL_CELL_RIGHT):
1.5     ! schwarze  285:                tbl_data_literal(tp, dp, tbp);
1.1       schwarze  286:                break;
                    287:        case (TBL_CELL_NUMBER):
1.5     ! schwarze  288:                tbl_data_number(tp, tbl, dp, tbp);
1.4       schwarze  289:                break;
1.1       schwarze  290:        default:
                    291:                abort();
                    292:                /* NOTREACHED */
                    293:        }
                    294: }
                    295: static void
1.5     ! schwarze  296: tbl_spanner(struct termp *tp, const struct tbl_head *hp)
1.1       schwarze  297: {
                    298:
1.5     ! schwarze  299:        switch (hp->pos) {
        !           300:        case (TBL_HEAD_VERT):
        !           301:                term_word(tp, "|");
        !           302:                break;
        !           303:        case (TBL_HEAD_DVERT):
        !           304:                term_word(tp, "||");
        !           305:                break;
        !           306:        default:
        !           307:                break;
        !           308:        }
1.1       schwarze  309: }
                    310:
                    311: static void
1.5     ! schwarze  312: tbl_vframe(struct termp *tp, const struct tbl *tbl)
1.1       schwarze  313: {
1.5     ! schwarze  314:        /* Always just a single vertical line. */
1.1       schwarze  315:
1.5     ! schwarze  316:        if (TBL_OPT_BOX & tbl->opts || TBL_OPT_DBOX & tbl->opts)
        !           317:                term_word(tp, "|");
        !           318: }
1.1       schwarze  319:
1.5     ! schwarze  320: static inline void
        !           321: tbl_char(struct termp *tp, char c, int len)
        !           322: {
        !           323:        int             i, sz;
        !           324:        char            cp[2];
1.1       schwarze  325:
1.5     ! schwarze  326:        cp[0] = c;
        !           327:        cp[1] = '\0';
1.1       schwarze  328:
1.5     ! schwarze  329:        sz = term_strlen(tp, cp);
1.1       schwarze  330:
1.5     ! schwarze  331:        for (i = 0; i < len; i += sz)
        !           332:                term_word(tp, cp);
1.1       schwarze  333: }
                    334:
                    335: static void
1.5     ! schwarze  336: tbl_data_literal(struct termp *tp,
        !           337:                const struct tbl_dat *dp,
        !           338:                const struct termp_tbl *tblp)
1.1       schwarze  339: {
1.5     ! schwarze  340:        int              padl, padr, ssz;
        !           341:        enum tbl_cellt   pos;
1.1       schwarze  342:
                    343:        padl = padr = 0;
                    344:
1.5     ! schwarze  345:        pos = dp->layout ? dp->layout->pos : TBL_CELL_LEFT;
        !           346:        ssz = term_len(tp, 1);
        !           347:
        !           348:        switch (pos) {
1.1       schwarze  349:        case (TBL_CELL_LONG):
1.5     ! schwarze  350:                padl = ssz;
        !           351:                padr = tblp->width - term_strlen(tp, dp->string) - ssz;
1.1       schwarze  352:                break;
                    353:        case (TBL_CELL_CENTRE):
1.5     ! schwarze  354:                padl = tblp->width - term_strlen(tp, dp->string);
1.1       schwarze  355:                if (padl % 2)
                    356:                        padr++;
                    357:                padl /= 2;
                    358:                padr += padl;
                    359:                break;
                    360:        case (TBL_CELL_RIGHT):
1.5     ! schwarze  361:                padl = tblp->width - term_strlen(tp, dp->string);
1.1       schwarze  362:                break;
                    363:        default:
1.5     ! schwarze  364:                padr = tblp->width - term_strlen(tp, dp->string);
1.1       schwarze  365:                break;
                    366:        }
                    367:
1.5     ! schwarze  368:        tbl_char(tp, ASCII_NBRSP, padl);
        !           369:        term_word(tp, dp->string);
        !           370:        tbl_char(tp, ASCII_NBRSP, padr);
1.1       schwarze  371: }
                    372:
1.5     ! schwarze  373: static void
        !           374: tbl_data_number(struct termp *tp, const struct tbl *tbl,
        !           375:                const struct tbl_dat *dp,
        !           376:                const struct termp_tbl *tblp)
        !           377: {
        !           378:        char            *decp, buf[2];
        !           379:        int              d, padl, sz, psz, ssz, i;
        !           380:
        !           381:        /*
        !           382:         * See calc_data_number().  Left-pad by taking the offset of our
        !           383:         * and the maximum decimal; right-pad by the remaining amount.
        !           384:         */
        !           385:
        !           386:        sz = term_strlen(tp, dp->string);
        !           387:        psz = term_strlen(tp, ".");
        !           388:
        !           389:        if (NULL != (decp = strchr(dp->string, tbl->decimal))) {
        !           390:                buf[1] = '\0';
        !           391:                for (ssz = i = 0; decp != &dp->string[i]; i++) {
        !           392:                        buf[0] = dp->string[i];
        !           393:                        ssz += term_strlen(tp, buf);
        !           394:                }
        !           395:                d = ssz + psz;
        !           396:        } else
        !           397:                d = sz + psz;
        !           398:
        !           399:        assert(d <= tblp->decimal);
        !           400:        assert(sz - d <= tblp->width - tblp->decimal);
        !           401:
        !           402:        padl = tblp->decimal - d + term_len(tp, 1);
        !           403:        assert(tblp->width - sz - padl);
        !           404:
        !           405:        tbl_char(tp, ASCII_NBRSP, padl);
        !           406:        term_word(tp, dp->string);
        !           407:        tbl_char(tp, ASCII_NBRSP, tblp->width - sz - padl);
        !           408: }
1.1       schwarze  409:
                    410: static void
1.5     ! schwarze  411: tbl_calc(struct termp *tp, const struct tbl_span *sp)
1.1       schwarze  412: {
1.5     ! schwarze  413:        const struct tbl_dat *dp;
        !           414:        const struct tbl_head *hp;
        !           415:        struct termp_tbl *p;
1.1       schwarze  416:
1.5     ! schwarze  417:        /* Calculate width as the max of column cells' widths. */
        !           418:
        !           419:        hp = sp->head;
        !           420:
        !           421:        for ( ; sp; sp = sp->next) {
        !           422:                if (TBL_SPAN_DATA != sp->pos)
        !           423:                        continue;
        !           424:
        !           425:                for (dp = sp->first; dp; dp = dp->next) {
        !           426:                        if (NULL == dp->layout)
        !           427:                                continue;
        !           428:                        p = &tp->tbl[dp->layout->head->ident];
        !           429:                        tbl_calc_data(tp, sp->tbl, dp, p);
        !           430:                }
1.1       schwarze  431:        }
                    432:
1.5     ! schwarze  433:        /* Calculate width as the simple spanner value. */
        !           434:
        !           435:        for ( ; hp; hp = hp->next)
        !           436:                switch (hp->pos) {
        !           437:                case (TBL_HEAD_VERT):
        !           438:                        tp->tbl[hp->ident].width = term_len(tp, 1);
        !           439:                        break;
        !           440:                case (TBL_HEAD_DVERT):
        !           441:                        tp->tbl[hp->ident].width = term_len(tp, 2);
        !           442:                        break;
        !           443:                default:
        !           444:                        break;
        !           445:                }
        !           446: }
        !           447:
        !           448: static void
        !           449: tbl_calc_data(struct termp *tp, const struct tbl *tbl,
        !           450:                const struct tbl_dat *dp, struct termp_tbl *tblp)
        !           451: {
        !           452:        int              sz;
        !           453:
        !           454:        /* Branch down into data sub-types. */
1.1       schwarze  455:
1.5     ! schwarze  456:        switch (dp->layout->pos) {
1.1       schwarze  457:        case (TBL_CELL_HORIZ):
                    458:                /* FALLTHROUGH */
                    459:        case (TBL_CELL_DHORIZ):
1.5     ! schwarze  460:                sz = term_len(tp, 1);
        !           461:                if (tblp->width < sz)
        !           462:                        tblp->width = sz;
1.1       schwarze  463:                break;
                    464:        case (TBL_CELL_LONG):
                    465:                /* FALLTHROUGH */
                    466:        case (TBL_CELL_CENTRE):
                    467:                /* FALLTHROUGH */
                    468:        case (TBL_CELL_LEFT):
                    469:                /* FALLTHROUGH */
                    470:        case (TBL_CELL_RIGHT):
1.5     ! schwarze  471:                tbl_calc_data_literal(tp, dp, tblp);
1.1       schwarze  472:                break;
                    473:        case (TBL_CELL_NUMBER):
1.5     ! schwarze  474:                tbl_calc_data_number(tp, tbl, dp, tblp);
1.1       schwarze  475:                break;
                    476:        default:
                    477:                abort();
                    478:                /* NOTREACHED */
                    479:        }
                    480: }
                    481:
1.5     ! schwarze  482: static void
        !           483: tbl_calc_data_number(struct termp *tp, const struct tbl *tbl,
        !           484:                const struct tbl_dat *dp, struct termp_tbl *tblp)
        !           485: {
        !           486:        int              sz, d, psz, i, ssz;
        !           487:        char            *cp, buf[2];
        !           488:
        !           489:        /*
        !           490:         * First calculate number width and decimal place (last + 1 for
        !           491:         * no-decimal numbers).  If the stored decimal is subsequent
        !           492:         * ours, make our size longer by that difference
        !           493:         * (right-"shifting"); similarly, if ours is subsequent the
        !           494:         * stored, then extend the stored size by the difference.
        !           495:         * Finally, re-assign the stored values.
        !           496:         */
        !           497:
        !           498:        /* TODO: use spacing modifier. */
        !           499:
        !           500:        assert(dp->string);
        !           501:        sz = term_strlen(tp, dp->string);
        !           502:        psz = term_strlen(tp, ".");
        !           503:
        !           504:        if (NULL != (cp = strchr(dp->string, tbl->decimal))) {
        !           505:                buf[1] = '\0';
        !           506:                for (ssz = i = 0; cp != &dp->string[i]; i++) {
        !           507:                        buf[0] = dp->string[i];
        !           508:                        ssz += term_strlen(tp, buf);
        !           509:                }
        !           510:                d = ssz + psz;
        !           511:        } else
        !           512:                d = sz + psz;
        !           513:
        !           514:        sz += term_len(tp, 2);
        !           515:
        !           516:        if (tblp->decimal > d) {
        !           517:                sz += tblp->decimal - d;
        !           518:                d = tblp->decimal;
        !           519:        } else
        !           520:                tblp->width += d - tblp->decimal;
        !           521:
        !           522:        if (sz > tblp->width)
        !           523:                tblp->width = sz;
        !           524:        if (d > tblp->decimal)
        !           525:                tblp->decimal = d;
        !           526: }
1.1       schwarze  527:
                    528: static void
1.5     ! schwarze  529: tbl_calc_data_literal(struct termp *tp,
        !           530:                const struct tbl_dat *dp,
        !           531:                struct termp_tbl *tblp)
1.1       schwarze  532: {
1.5     ! schwarze  533:        int              sz, bufsz, spsz;
1.1       schwarze  534:
1.5     ! schwarze  535:        /*
        !           536:         * Calculate our width and use the spacing, with a minimum
        !           537:         * spacing dictated by position (centre, e.g,. gets a space on
        !           538:         * either side, while right/left get a single adjacent space).
        !           539:         */
        !           540:
        !           541:        assert(dp->string);
        !           542:        sz = term_strlen(tp, dp->string);
        !           543:
        !           544:        switch (dp->layout->pos) {
        !           545:        case (TBL_CELL_LONG):
        !           546:                /* FALLTHROUGH */
        !           547:        case (TBL_CELL_CENTRE):
        !           548:                bufsz = term_len(tp, 2);
1.1       schwarze  549:                break;
                    550:        default:
1.5     ! schwarze  551:                bufsz = term_len(tp, 1);
1.1       schwarze  552:                break;
                    553:        }
                    554:
1.5     ! schwarze  555:        spsz = 0;
        !           556:        if (dp->layout->spacing)
        !           557:                spsz = term_len(tp, dp->layout->spacing);
1.1       schwarze  558:
1.5     ! schwarze  559:        if (spsz)
        !           560:                bufsz = bufsz > spsz ?  bufsz : spsz;
1.1       schwarze  561:
1.5     ! schwarze  562:        sz += bufsz;
        !           563:        if (tblp->width < sz)
        !           564:                tblp->width = sz;
1.1       schwarze  565: }