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

Diff for /mandoc/out.c between version 1.29 and 1.30

version 1.29, 2010/08/29 11:28:09 version 1.30, 2011/01/05 15:37:23
Line 27 
Line 27 
 #include <string.h>  #include <string.h>
 #include <time.h>  #include <time.h>
   
   #include "mandoc.h"
 #include "out.h"  #include "out.h"
   
   static  void    tblcalc_data(struct rofftbl *, struct roffcol *,
                           const struct tbl *, const struct tbl_dat *);
   static  void    tblcalc_literal(struct rofftbl *, struct roffcol *,
                           const struct tbl_dat *);
   static  void    tblcalc_number(struct rofftbl *, struct roffcol *,
                           const struct tbl *, const struct tbl_dat *);
   
 /*  /*
  * Convert a `scaling unit' to a consistent form, or fail.  Scaling   * Convert a `scaling unit' to a consistent form, or fail.  Scaling
  * units are documented in groff.7, mdoc.7, man.7.   * units are documented in groff.7, mdoc.7, man.7.
Line 358  a2roffdeco(enum roffdeco *d, const char **word, size_t
Line 366  a2roffdeco(enum roffdeco *d, const char **word, size_t
   
         return(i);          return(i);
 }  }
   
   /*
    * Calculate the abstract widths and decimal positions of columns in a
    * table.  This routine allocates the columns structures then runs over
    * all rows and cells in the table.  The function pointers in "tbl" are
    * used for the actual width calculations.
    */
   void
   tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
   {
           const struct tbl_dat    *dp;
           const struct tbl_head   *hp;
           struct roffcol          *col;
   
           /*
            * Allocate the master column specifiers.  These will hold the
            * widths and decimal positions for all cells in the column.  It
            * must be freed and nullified by the caller.
            */
   
           assert(NULL == tbl->cols);
           tbl->cols = calloc(sp->tbl->cols, sizeof(struct roffcol));
   
           hp = sp->head;
   
           for ( ; sp; sp = sp->next) {
                   if (TBL_SPAN_DATA != sp->pos)
                           continue;
                   /*
                    * Account for the data cells in the layout, matching it
                    * to data cells in the data section.
                    */
                   for (dp = sp->first; dp; dp = dp->next) {
                           if (NULL == dp->layout)
                                   continue;
                           col = &tbl->cols[dp->layout->head->ident];
                           tblcalc_data(tbl, col, sp->tbl, dp);
                   }
           }
   
           /*
            * Calculate width of the spanners.  These get one space for a
            * vertical line, two for a double-vertical line.
            */
   
           for ( ; hp; hp = hp->next) {
                   col = &tbl->cols[hp->ident];
                   switch (hp->pos) {
                   case (TBL_HEAD_VERT):
                           col->width = (*tbl->len)(1, tbl->arg);
                           break;
                   case (TBL_HEAD_DVERT):
                           col->width = (*tbl->len)(2, tbl->arg);
                           break;
                   default:
                           break;
                   }
           }
   }
   
   static void
   tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
                   const struct tbl *tp, const struct tbl_dat *dp)
   {
           size_t           sz;
   
           /* Branch down into data sub-types. */
   
           switch (dp->layout->pos) {
           case (TBL_CELL_HORIZ):
                   /* FALLTHROUGH */
           case (TBL_CELL_DHORIZ):
                   sz = (*tbl->len)(1, tbl->arg);
                   if (col->width < sz)
                           col->width = sz;
                   break;
           case (TBL_CELL_LONG):
                   /* FALLTHROUGH */
           case (TBL_CELL_CENTRE):
                   /* FALLTHROUGH */
           case (TBL_CELL_LEFT):
                   /* FALLTHROUGH */
           case (TBL_CELL_RIGHT):
                   tblcalc_literal(tbl, col, dp);
                   break;
           case (TBL_CELL_NUMBER):
                   tblcalc_number(tbl, col, tp, dp);
                   break;
           default:
                   abort();
                   /* NOTREACHED */
           }
   }
   
   static void
   tblcalc_literal(struct rofftbl *tbl, struct roffcol *col,
                   const struct tbl_dat *dp)
   {
           size_t           sz, bufsz, spsz;
   
           /*
            * Calculate our width and use the spacing, with a minimum
            * spacing dictated by position (centre, e.g,. gets a space on
            * either side, while right/left get a single adjacent space).
            */
   
           sz = bufsz = spsz = 0;
           if (dp->string)
                   sz = (*tbl->slen)(dp->string, tbl->arg);
   
           assert(dp->layout);
           switch (dp->layout->pos) {
           case (TBL_CELL_LONG):
                   /* FALLTHROUGH */
           case (TBL_CELL_CENTRE):
                   bufsz = (*tbl->len)(2, tbl->arg);
                   break;
           default:
                   bufsz = (*tbl->len)(1, tbl->arg);
                   break;
           }
   
           if (dp->layout->spacing) {
                   spsz = (*tbl->len)(dp->layout->spacing, tbl->arg);
                   bufsz = bufsz > spsz ? bufsz : spsz;
           }
   
           sz += bufsz;
           if (col->width < sz)
                   col->width = sz;
   }
   
   static void
   tblcalc_number(struct rofftbl *tbl, struct roffcol *col,
                   const struct tbl *tp, const struct tbl_dat *dp)
   {
           int              i;
           size_t           sz, psz, ssz, d;
           char            *cp;
           const char      *str;
           char             buf[2];
   
           /* TODO: use spacing modifier. */
   
           /*
            * First calculate number width and decimal place (last + 1 for
            * no-decimal numbers).  If the stored decimal is subsequent
            * ours, make our size longer by that difference
            * (right-"shifting"); similarly, if ours is subsequent the
            * stored, then extend the stored size by the difference.
            * Finally, re-assign the stored values.
            */
   
           str = "";
           if (dp->string)
                   str = dp->string;
   
           sz = (*tbl->slen)(str, tbl->arg);
   
           buf[0] = tp->decimal;
           buf[1] = '\0';
   
           psz = (*tbl->slen)(buf, tbl->arg);
   
           if (NULL != (cp = strchr(str, tp->decimal))) {
                   buf[1] = '\0';
                   for (ssz = 0, i = 0; cp != &str[i]; i++) {
                           buf[0] = str[i];
                           ssz += (*tbl->slen)(buf, tbl->arg);
                   }
                   d = ssz + psz;
           } else
                   d = sz + psz;
   
           /* Padding. */
   
           sz += (*tbl->len)(2, tbl->arg);
           d += (*tbl->len)(1, tbl->arg);
   
           /* Adjust the settings for this column. */
   
           if (col->decimal > d) {
                   sz += col->decimal - d;
                   d = col->decimal;
           } else
                   col->width += d - col->decimal;
   
           if (sz > col->width)
                   col->width = sz;
           if (d > col->decimal)
                   col->decimal = d;
   }
   
   

Legend:
Removed from v.1.29  
changed lines
  Added in v.1.30

CVSweb