[BACK]Return to out.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/out.c, Revision 1.49

1.49    ! schwarze    1: /*     $Id: out.c,v 1.48 2014/04/20 16:46:05 schwarze Exp $ */
1.1       kristaps    2: /*
1.36      schwarze    3:  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.37      schwarze    4:  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
1.1       kristaps    5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
1.12      kristaps   18: #ifdef HAVE_CONFIG_H
                     19: #include "config.h"
                     20: #endif
                     21:
1.1       kristaps   22: #include <sys/types.h>
                     23:
1.6       kristaps   24: #include <assert.h>
1.1       kristaps   25: #include <ctype.h>
1.3       kristaps   26: #include <stdio.h>
1.1       kristaps   27: #include <stdlib.h>
1.6       kristaps   28: #include <string.h>
1.7       kristaps   29: #include <time.h>
1.1       kristaps   30:
1.47      schwarze   31: #include "mandoc_aux.h"
1.30      kristaps   32: #include "mandoc.h"
1.1       kristaps   33: #include "out.h"
                     34:
1.30      kristaps   35: static void    tblcalc_data(struct rofftbl *, struct roffcol *,
1.45      schwarze   36:                        const struct tbl_opts *, const struct tbl_dat *);
1.30      kristaps   37: static void    tblcalc_literal(struct rofftbl *, struct roffcol *,
                     38:                        const struct tbl_dat *);
                     39: static void    tblcalc_number(struct rofftbl *, struct roffcol *,
1.45      schwarze   40:                        const struct tbl_opts *, const struct tbl_dat *);
1.30      kristaps   41:
1.48      schwarze   42:
                     43: /*
1.3       kristaps   44:  * Convert a `scaling unit' to a consistent form, or fail.  Scaling
1.5       kristaps   45:  * units are documented in groff.7, mdoc.7, man.7.
1.3       kristaps   46:  */
1.1       kristaps   47: int
1.5       kristaps   48: a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
1.1       kristaps   49: {
1.4       kristaps   50:        char             buf[BUFSIZ], hasd;
1.1       kristaps   51:        int              i;
1.3       kristaps   52:        enum roffscale   unit;
1.1       kristaps   53:
1.5       kristaps   54:        if ('\0' == *src)
                     55:                return(0);
                     56:
1.4       kristaps   57:        i = hasd = 0;
                     58:
                     59:        switch (*src) {
1.48      schwarze   60:        case '+':
1.4       kristaps   61:                src++;
                     62:                break;
1.48      schwarze   63:        case '-':
1.4       kristaps   64:                buf[i++] = *src++;
                     65:                break;
                     66:        default:
                     67:                break;
                     68:        }
                     69:
1.5       kristaps   70:        if ('\0' == *src)
                     71:                return(0);
                     72:
1.4       kristaps   73:        while (i < BUFSIZ) {
1.42      kristaps   74:                if ( ! isdigit((unsigned char)*src)) {
1.4       kristaps   75:                        if ('.' != *src)
                     76:                                break;
                     77:                        else if (hasd)
                     78:                                break;
                     79:                        else
                     80:                                hasd = 1;
                     81:                }
                     82:                buf[i++] = *src++;
                     83:        }
1.1       kristaps   84:
1.3       kristaps   85:        if (BUFSIZ == i || (*src && *(src + 1)))
1.1       kristaps   86:                return(0);
                     87:
1.4       kristaps   88:        buf[i] = '\0';
1.1       kristaps   89:
1.3       kristaps   90:        switch (*src) {
1.48      schwarze   91:        case 'c':
1.3       kristaps   92:                unit = SCALE_CM;
                     93:                break;
1.48      schwarze   94:        case 'i':
1.3       kristaps   95:                unit = SCALE_IN;
                     96:                break;
1.48      schwarze   97:        case 'P':
1.3       kristaps   98:                unit = SCALE_PC;
                     99:                break;
1.48      schwarze  100:        case 'p':
1.3       kristaps  101:                unit = SCALE_PT;
                    102:                break;
1.48      schwarze  103:        case 'f':
1.3       kristaps  104:                unit = SCALE_FS;
                    105:                break;
1.48      schwarze  106:        case 'v':
1.3       kristaps  107:                unit = SCALE_VS;
                    108:                break;
1.48      schwarze  109:        case 'm':
1.3       kristaps  110:                unit = SCALE_EM;
                    111:                break;
1.48      schwarze  112:        case '\0':
1.5       kristaps  113:                if (SCALE_MAX == def)
                    114:                        return(0);
                    115:                unit = SCALE_BU;
                    116:                break;
1.48      schwarze  117:        case 'u':
1.3       kristaps  118:                unit = SCALE_BU;
                    119:                break;
1.48      schwarze  120:        case 'M':
1.3       kristaps  121:                unit = SCALE_MM;
                    122:                break;
1.48      schwarze  123:        case 'n':
1.3       kristaps  124:                unit = SCALE_EN;
                    125:                break;
                    126:        default:
1.1       kristaps  127:                return(0);
1.3       kristaps  128:        }
1.1       kristaps  129:
1.23      kristaps  130:        /* FIXME: do this in the caller. */
1.49    ! schwarze  131:        if ((dst->scale = atof(buf)) < 0.0)
        !           132:                dst->scale = 0.0;
1.3       kristaps  133:        dst->unit = unit;
                    134:        return(1);
1.8       kristaps  135: }
1.30      kristaps  136:
                    137: /*
                    138:  * Calculate the abstract widths and decimal positions of columns in a
                    139:  * table.  This routine allocates the columns structures then runs over
                    140:  * all rows and cells in the table.  The function pointers in "tbl" are
                    141:  * used for the actual width calculations.
                    142:  */
                    143: void
                    144: tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
                    145: {
                    146:        const struct tbl_dat    *dp;
                    147:        struct roffcol          *col;
1.43      schwarze  148:        int                      spans;
1.30      kristaps  149:
                    150:        /*
                    151:         * Allocate the master column specifiers.  These will hold the
                    152:         * widths and decimal positions for all cells in the column.  It
                    153:         * must be freed and nullified by the caller.
                    154:         */
                    155:
                    156:        assert(NULL == tbl->cols);
1.48      schwarze  157:        tbl->cols = mandoc_calloc((size_t)sp->opts->cols,
                    158:            sizeof(struct roffcol));
1.30      kristaps  159:
                    160:        for ( ; sp; sp = sp->next) {
                    161:                if (TBL_SPAN_DATA != sp->pos)
                    162:                        continue;
1.43      schwarze  163:                spans = 1;
1.30      kristaps  164:                /*
                    165:                 * Account for the data cells in the layout, matching it
                    166:                 * to data cells in the data section.
                    167:                 */
                    168:                for (dp = sp->first; dp; dp = dp->next) {
1.43      schwarze  169:                        /* Do not used spanned cells in the calculation. */
                    170:                        if (0 < --spans)
                    171:                                continue;
                    172:                        spans = dp->spans;
                    173:                        if (1 < spans)
                    174:                                continue;
1.33      kristaps  175:                        assert(dp->layout);
1.30      kristaps  176:                        col = &tbl->cols[dp->layout->head->ident];
1.45      schwarze  177:                        tblcalc_data(tbl, col, sp->opts, dp);
1.30      kristaps  178:                }
                    179:        }
                    180: }
                    181:
                    182: static void
                    183: tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
1.45      schwarze  184:                const struct tbl_opts *opts, const struct tbl_dat *dp)
1.30      kristaps  185: {
                    186:        size_t           sz;
                    187:
                    188:        /* Branch down into data sub-types. */
                    189:
                    190:        switch (dp->layout->pos) {
1.48      schwarze  191:        case TBL_CELL_HORIZ:
1.30      kristaps  192:                /* FALLTHROUGH */
1.48      schwarze  193:        case TBL_CELL_DHORIZ:
1.30      kristaps  194:                sz = (*tbl->len)(1, tbl->arg);
                    195:                if (col->width < sz)
                    196:                        col->width = sz;
                    197:                break;
1.48      schwarze  198:        case TBL_CELL_LONG:
1.30      kristaps  199:                /* FALLTHROUGH */
1.48      schwarze  200:        case TBL_CELL_CENTRE:
1.30      kristaps  201:                /* FALLTHROUGH */
1.48      schwarze  202:        case TBL_CELL_LEFT:
1.30      kristaps  203:                /* FALLTHROUGH */
1.48      schwarze  204:        case TBL_CELL_RIGHT:
1.30      kristaps  205:                tblcalc_literal(tbl, col, dp);
                    206:                break;
1.48      schwarze  207:        case TBL_CELL_NUMBER:
1.45      schwarze  208:                tblcalc_number(tbl, col, opts, dp);
1.35      kristaps  209:                break;
1.48      schwarze  210:        case TBL_CELL_DOWN:
1.30      kristaps  211:                break;
                    212:        default:
                    213:                abort();
                    214:                /* NOTREACHED */
                    215:        }
                    216: }
                    217:
                    218: static void
                    219: tblcalc_literal(struct rofftbl *tbl, struct roffcol *col,
                    220:                const struct tbl_dat *dp)
                    221: {
1.43      schwarze  222:        size_t           sz;
1.34      kristaps  223:        const char      *str;
1.30      kristaps  224:
1.34      kristaps  225:        str = dp->string ? dp->string : "";
                    226:        sz = (*tbl->slen)(str, tbl->arg);
                    227:
1.30      kristaps  228:        if (col->width < sz)
                    229:                col->width = sz;
                    230: }
                    231:
                    232: static void
                    233: tblcalc_number(struct rofftbl *tbl, struct roffcol *col,
1.45      schwarze  234:                const struct tbl_opts *opts, const struct tbl_dat *dp)
1.30      kristaps  235: {
1.48      schwarze  236:        int              i;
1.34      kristaps  237:        size_t           sz, psz, ssz, d;
                    238:        const char      *str;
1.30      kristaps  239:        char            *cp;
                    240:        char             buf[2];
                    241:
                    242:        /*
                    243:         * First calculate number width and decimal place (last + 1 for
1.43      schwarze  244:         * non-decimal numbers).  If the stored decimal is subsequent to
1.30      kristaps  245:         * ours, make our size longer by that difference
                    246:         * (right-"shifting"); similarly, if ours is subsequent the
                    247:         * stored, then extend the stored size by the difference.
                    248:         * Finally, re-assign the stored values.
                    249:         */
                    250:
1.34      kristaps  251:        str = dp->string ? dp->string : "";
                    252:        sz = (*tbl->slen)(str, tbl->arg);
1.30      kristaps  253:
1.34      kristaps  254:        /* FIXME: TBL_DATA_HORIZ et al.? */
1.30      kristaps  255:
1.45      schwarze  256:        buf[0] = opts->decimal;
1.30      kristaps  257:        buf[1] = '\0';
                    258:
                    259:        psz = (*tbl->slen)(buf, tbl->arg);
                    260:
1.45      schwarze  261:        if (NULL != (cp = strrchr(str, opts->decimal))) {
1.30      kristaps  262:                buf[1] = '\0';
                    263:                for (ssz = 0, i = 0; cp != &str[i]; i++) {
                    264:                        buf[0] = str[i];
                    265:                        ssz += (*tbl->slen)(buf, tbl->arg);
                    266:                }
                    267:                d = ssz + psz;
                    268:        } else
                    269:                d = sz + psz;
                    270:
                    271:        /* Adjust the settings for this column. */
                    272:
                    273:        if (col->decimal > d) {
                    274:                sz += col->decimal - d;
                    275:                d = col->decimal;
                    276:        } else
                    277:                col->width += d - col->decimal;
                    278:
                    279:        if (sz > col->width)
                    280:                col->width = sz;
                    281:        if (d > col->decimal)
                    282:                col->decimal = d;
                    283: }

CVSweb