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

Diff for /mandoc/tbl_term.c between version 1.61 and 1.62

version 1.61, 2018/11/25 19:24:20 version 1.62, 2018/11/28 04:47:51
Line 32 
Line 32 
 #define IS_HORIZ(cp)    ((cp)->pos == TBL_CELL_HORIZ || \  #define IS_HORIZ(cp)    ((cp)->pos == TBL_CELL_HORIZ || \
                          (cp)->pos == TBL_CELL_DHORIZ)                           (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_len(size_t, void *);
 static  size_t  term_tbl_strlen(const char *, void *);  static  size_t  term_tbl_strlen(const char *, void *);
 static  size_t  term_tbl_sulen(const struct roffsu *, void *);  static  size_t  term_tbl_sulen(const struct roffsu *, void *);
 static  void    tbl_char(struct termp *, char, size_t);  
 static  void    tbl_data(struct termp *, const struct tbl_opts *,  static  void    tbl_data(struct termp *, const struct tbl_opts *,
                         const struct tbl_cell *,                          const struct tbl_cell *,
                         const struct tbl_dat *,                          const struct tbl_dat *,
                         const struct roffcol *);                          const struct roffcol *);
   static  void    tbl_direct_border(struct termp *, int, size_t);
   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 *,  static  void    tbl_literal(struct termp *, const struct tbl_dat *,
                         const struct roffcol *);                          const struct roffcol *);
 static  void    tbl_number(struct termp *, const struct tbl_opts *,  static  void    tbl_number(struct termp *, const struct tbl_opts *,
                         const struct tbl_dat *,                          const struct tbl_dat *,
                         const struct roffcol *);                          const struct roffcol *);
 static  void    tbl_hrule(struct termp *, const struct tbl_span *, int);  
 static  void    tbl_word(struct termp *, const struct tbl_dat *);  static  void    tbl_word(struct termp *, const struct tbl_dat *);
   
   
   /*
    * The following border-character tables are indexed
    * by ternary (3-based) numbers, as opposed to binary or decimal.
    * Each ternary digit describes the line width in one direction:
    * 0 means no line, 1 single or light line, 2 double or heavy line.
    */
   
   /* Positional values of the four directions. */
   #define BRIGHT  1
   #define BDOWN   3
   #define BLEFT   (3 * 3)
   #define BUP     (3 * 3 * 3)
   #define BHORIZ  (BLEFT + BRIGHT)
   
   /* Code points to use for each combination of widths. */
   static  const int borders_utf8[81] = {
           0x0020, 0x2576, 0x257a,  /* 000 right */
           0x2577, 0x250c, 0x250d,  /* 001 down */
           0x257b, 0x250e, 0x250f,  /* 002 */
           0x2574, 0x2500, 0x257c,  /* 010 left */
           0x2510, 0x252c, 0x252e,  /* 011 left down */
           0x2512, 0x2530, 0x2532,  /* 012 */
           0x2578, 0x257e, 0x2501,  /* 020 left */
           0x2511, 0x252d, 0x252f,  /* 021 left down */
           0x2513, 0x2531, 0x2533,  /* 022 */
           0x2575, 0x2514, 0x2515,  /* 100 up */
           0x2502, 0x251c, 0x251d,  /* 101 up down */
           0x257d, 0x251f, 0x2522,  /* 102 */
           0x2518, 0x2534, 0x2536,  /* 110 up left */
           0x2524, 0x253c, 0x253e,  /* 111 all */
           0x2527, 0x2541, 0x2546,  /* 112 */
           0x2519, 0x2535, 0x2537,  /* 120 up left */
           0x2525, 0x253d, 0x253f,  /* 121 all */
           0x252a, 0x2545, 0x2548,  /* 122 */
           0x2579, 0x2516, 0x2517,  /* 200 up */
           0x257f, 0x251e, 0x2521,  /* 201 up down */
           0x2503, 0x2520, 0x2523,  /* 202 */
           0x251a, 0x2538, 0x253a,  /* 210 up left */
           0x2526, 0x2540, 0x2544,  /* 211 all */
           0x2528, 0x2542, 0x254a,  /* 212 */
           0x251b, 0x2539, 0x253b,  /* 220 up left */
           0x2529, 0x2543, 0x2547,  /* 221 all */
           0x252b, 0x2549, 0x254b,  /* 222 */
   };
   
   /* ASCII approximations for these code points, compatible with groff. */
   static  const int borders_ascii[81] = {
           ' ', '-', '=',  /* 000 right */
           '|', '+', '+',  /* 001 down */
           '|', '+', '+',  /* 002 */
           '-', '-', '=',  /* 010 left */
           '+', '+', '+',  /* 011 left down */
           '+', '+', '+',  /* 012 */
           '=', '=', '=',  /* 020 left */
           '+', '+', '+',  /* 021 left down */
           '+', '+', '+',  /* 022 */
           '|', '+', '+',  /* 100 up */
           '|', '+', '+',  /* 101 up down */
           '|', '+', '+',  /* 102 */
           '+', '+', '+',  /* 110 up left */
           '+', '+', '+',  /* 111 all */
           '+', '+', '+',  /* 112 */
           '+', '+', '+',  /* 120 up left */
           '+', '+', '+',  /* 121 all */
           '+', '+', '+',  /* 122 */
           '|', '+', '+',  /* 200 up */
           '|', '+', '+',  /* 201 up down */
           '|', '+', '+',  /* 202 */
           '+', '+', '+',  /* 210 up left */
           '+', '+', '+',  /* 211 all */
           '+', '+', '+',  /* 212 */
           '+', '+', '+',  /* 220 up left */
           '+', '+', '+',  /* 221 all */
           '+', '+', '+',  /* 222 */
   };
   
   /* Either of the above according to the selected output encoding. */
   static  const int *borders_locale;
   
   
 static size_t  static size_t
 term_tbl_sulen(const struct roffsu *su, void *arg)  term_tbl_sulen(const struct roffsu *su, void *arg)
 {  {
Line 70  term_tbl_len(size_t sz, void *arg)
Line 161  term_tbl_len(size_t sz, void *arg)
         return term_len((const struct termp *)arg, sz);          return term_len((const struct termp *)arg, sz);
 }  }
   
   
 void  void
 term_tbl(struct termp *tp, const struct tbl_span *sp)  term_tbl(struct termp *tp, const struct tbl_span *sp)
 {  {
         const struct tbl_cell   *cp, *cpn, *cpp;          const struct tbl_cell   *cp, *cpn, *cpp, *cps;
         const struct tbl_dat    *dp;          const struct tbl_dat    *dp;
         static size_t            offset;          static size_t            offset;
         size_t                   coloff, tsz;          size_t                   coloff, tsz;
         int                      ic, horiz, hspans, vert, more;          int                      hspans, ic, more;
         char                     fc;          int                      dvert, fc, horiz, line, uvert;
   
         /* Inhibit printing of spaces: we do padding ourselves. */          /* Inhibit printing of spaces: we do padding ourselves. */
   
Line 90  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 182  term_tbl(struct termp *tp, const struct tbl_span *sp)
          */           */
   
         if (tp->tbl.cols == NULL) {          if (tp->tbl.cols == NULL) {
                   borders_locale = tp->enc == TERMENC_UTF8 ?
                       borders_utf8 : borders_ascii;
   
                 tp->tbl.len = term_tbl_len;                  tp->tbl.len = term_tbl_len;
                 tp->tbl.slen = term_tbl_strlen;                  tp->tbl.slen = term_tbl_strlen;
                 tp->tbl.sulen = term_tbl_sulen;                  tp->tbl.sulen = term_tbl_sulen;
Line 127  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 222  term_tbl(struct termp *tp, const struct tbl_span *sp)
   
                 /* Horizontal frame at the start of boxed tables. */                  /* Horizontal frame at the start of boxed tables. */
   
                 if (sp->opts->opts & TBL_OPT_DBOX)                  if (tp->enc == TERMENC_ASCII &&
                         tbl_hrule(tp, sp, 3);                      sp->opts->opts & TBL_OPT_DBOX)
                           tbl_hrule(tp, sp, HRULE_DBOX | HRULE_ENDS);
                 if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX))                  if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX))
                         tbl_hrule(tp, sp, 2);                          tbl_hrule(tp, sp, HRULE_DOWN | HRULE_ENDS);
         }          }
   
         /* Set up the columns. */          /* Set up the columns. */
Line 219  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 315  term_tbl(struct termp *tp, const struct tbl_span *sp)
                 /* Print the vertical frame at the start of each row. */                  /* Print the vertical frame at the start of each row. */
   
                 tp->tcol = tp->tcols;                  tp->tcol = tp->tcols;
                 fc = '\0';                  uvert = dvert = sp->opts->opts & TBL_OPT_DBOX ? 2 :
                 if (sp->layout->vert ||                      sp->opts->opts & TBL_OPT_BOX ? 1 : 0;
                     (sp->next != NULL && sp->next->layout->vert &&                  if (sp->pos == TBL_SPAN_DATA && uvert < sp->layout->vert)
                      sp->next->pos == TBL_SPAN_DATA) ||                          uvert = dvert = sp->layout->vert;
                     (sp->prev != NULL && sp->prev->layout->vert &&                  if (sp->next != NULL && sp->next->pos == TBL_SPAN_DATA &&
                      (horiz || (IS_HORIZ(sp->layout->first) &&                      dvert < sp->next->layout->vert)
                        !IS_HORIZ(sp->prev->layout->first)))) ||                          dvert = sp->next->layout->vert;
                     sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX))                  if (sp->prev != NULL && uvert < sp->prev->layout->vert &&
                         fc = horiz || IS_HORIZ(sp->layout->first) ? '+' : '|';                      (horiz || (IS_HORIZ(sp->layout->first) &&
                 else if (horiz && sp->opts->lvert)                        !IS_HORIZ(sp->prev->layout->first))))
                         fc = '-';                          uvert = sp->prev->layout->vert;
                 if (fc != '\0') {                  line = sp->pos == TBL_SPAN_DHORIZ ||
                       sp->layout->first->pos == TBL_CELL_DHORIZ ? 2 :
                       sp->pos == TBL_SPAN_HORIZ ||
                       sp->layout->first->pos == TBL_CELL_HORIZ ? 1 : 0;
                   fc = BUP * uvert + BDOWN * dvert + BRIGHT * line;
                   if (uvert > 0 || dvert > 0 || (horiz && sp->opts->lvert)) {
                         (*tp->advance)(tp, tp->tcols->offset);                          (*tp->advance)(tp, tp->tcols->offset);
                         (*tp->letter)(tp, fc);                          tp->viscol = tp->tcol->offset;
                         tp->viscol = tp->tcol->offset + 1;                          tbl_direct_border(tp, fc, 1);
                 }                  }
   
                 /* Print the data cells. */                  /* Print the data cells. */
   
                 more = 0;                  more = 0;
                 if (horiz) {                  if (horiz)
                         tbl_hrule(tp, sp, 0);                          tbl_hrule(tp, sp, HRULE_DATA | HRULE_DOWN | HRULE_UP);
                         term_flushln(tp);                  else {
                 } else {  
                         cp = sp->layout->first;                          cp = sp->layout->first;
                         cpn = sp->next == NULL ? NULL :                          cpn = sp->next == NULL ? NULL :
                             sp->next->layout->first;                              sp->next->layout->first;
Line 258  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 358  term_tbl(struct termp *tp, const struct tbl_span *sp)
                                  * and advance to next layout cell.                                   * and advance to next layout cell.
                                  */                                   */
   
                                   uvert = dvert = fc = 0;
                                 if (cp != NULL) {                                  if (cp != NULL) {
                                         vert = cp->vert;                                          cps = cp;
                                           while (cps->next != NULL &&
                                               cps->next->pos == TBL_CELL_SPAN)
                                                   cps = cps->next;
                                           if (sp->pos == TBL_SPAN_DATA)
                                                   uvert = dvert = cps->vert;
                                         switch (cp->pos) {                                          switch (cp->pos) {
                                         case TBL_CELL_HORIZ:                                          case TBL_CELL_HORIZ:
                                                 fc = '-';                                                  fc = BHORIZ;
                                                 break;                                                  break;
                                         case TBL_CELL_DHORIZ:                                          case TBL_CELL_DHORIZ:
                                                 fc = '=';                                                  fc = BHORIZ * 2;
                                                 break;                                                  break;
                                         default:                                          default:
                                                 fc = ' ';  
                                                 break;                                                  break;
                                         }                                          }
                                 } else {  
                                         vert = 0;  
                                         fc = ' ';  
                                 }                                  }
                                 if (cpp != NULL) {                                  if (cpp != NULL) {
                                         if (vert == 0 &&                                          if (uvert < cpp->vert &&
                                             cp != NULL &&                                              cp != NULL &&
                                             ((IS_HORIZ(cp) &&                                              ((IS_HORIZ(cp) &&
                                               !IS_HORIZ(cpp)) ||                                                !IS_HORIZ(cpp)) ||
Line 284  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 386  term_tbl(struct termp *tp, const struct tbl_span *sp)
                                               cpp->next != NULL &&                                                cpp->next != NULL &&
                                               IS_HORIZ(cp->next) &&                                                IS_HORIZ(cp->next) &&
                                               !IS_HORIZ(cpp->next))))                                                !IS_HORIZ(cpp->next))))
                                                 vert = cpp->vert;                                                  uvert = cpp->vert;
                                         cpp = cpp->next;                                          cpp = cpp->next;
                                 }                                  }
                                 if (vert == 0 &&                                  if (sp->opts->opts & TBL_OPT_ALLBOX) {
                                     sp->opts->opts & TBL_OPT_ALLBOX)                                          if (uvert == 0)
                                         vert = 1;                                                  uvert = 1;
                                           if (dvert == 0)
                                                   dvert = 1;
                                   }
                                 if (cpn != NULL) {                                  if (cpn != NULL) {
                                         if (vert == 0)                                          if (dvert == 0 ||
                                                 vert = cpn->vert;                                              (dvert < cpn->vert &&
                                                tp->enc == TERMENC_UTF8))
                                                   dvert = cpn->vert;
                                         cpn = cpn->next;                                          cpn = cpn->next;
                                 }                                  }
                                 if (cp != NULL)  
                                         cp = cp->next;  
   
                                 /*                                  /*
                                  * Skip later cells in a span,                                   * Skip later cells in a span,
Line 306  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 411  term_tbl(struct termp *tp, const struct tbl_span *sp)
   
                                 if (hspans) {                                  if (hspans) {
                                         hspans--;                                          hspans--;
                                           cp = cp->next;
                                         continue;                                          continue;
                                 }                                  }
                                 if (dp != NULL) {                                  if (dp != NULL) {
Line 331  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 437  term_tbl(struct termp *tp, const struct tbl_span *sp)
                                  * but not after the last column.                                   * but not after the last column.
                                  */                                   */
   
                                 if (fc == ' ' && ((vert == 0 &&                                  if (fc == 0 && ((uvert == 0 && dvert == 0 &&
                                      (cp == NULL || !IS_HORIZ(cp))) ||                                       (cp->next == NULL ||
                                     tp->tcol + 1 == tp->tcols + tp->lasttcol))                                        !IS_HORIZ(cp->next))) ||
                                       tp->tcol + 1 == tp->tcols + tp->lasttcol)) {
                                           cp = cp->next;
                                         continue;                                          continue;
                                   }
   
                                 if (tp->viscol < tp->tcol->rmargin) {                                  if (tp->viscol < tp->tcol->rmargin) {
                                         (*tp->advance)(tp, tp->tcol->rmargin                                          (*tp->advance)(tp, tp->tcol->rmargin
Line 342  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 451  term_tbl(struct termp *tp, const struct tbl_span *sp)
                                         tp->viscol = tp->tcol->rmargin;                                          tp->viscol = tp->tcol->rmargin;
                                 }                                  }
                                 while (tp->viscol < tp->tcol->rmargin +                                  while (tp->viscol < tp->tcol->rmargin +
                                     tp->tbl.cols[ic].spacing / 2) {                                      tp->tbl.cols[ic].spacing / 2)
                                         (*tp->letter)(tp, fc);                                          tbl_direct_border(tp, fc, 1);
                                         tp->viscol++;  
                                 }  
   
                                 if (tp->tcol + 1 == tp->tcols + tp->lasttcol)                                  if (tp->tcol + 1 == tp->tcols + tp->lasttcol)
                                         continue;                                          continue;
   
                                 if (fc == ' ' && cp != NULL) {                                  if (cp != NULL) {
                                         switch (cp->pos) {                                          switch (cp->pos) {
                                         case TBL_CELL_HORIZ:                                          case TBL_CELL_HORIZ:
                                                 fc = '-';                                                  fc = BLEFT;
                                                 break;                                                  break;
                                         case TBL_CELL_DHORIZ:                                          case TBL_CELL_DHORIZ:
                                                 fc = '=';                                                  fc = BLEFT * 2;
                                                 break;                                                  break;
                                         default:                                          default:
                                                   fc = 0;
                                                 break;                                                  break;
                                         }                                          }
                                           cp = cp->next;
                                 }                                  }
                                 if (tp->tbl.cols[ic].spacing) {                                  if (cp != NULL) {
                                         (*tp->letter)(tp, fc == ' ' ? '|' :                                          switch (cp->pos) {
                                             vert ? '+' : fc);                                          case TBL_CELL_HORIZ:
                                         tp->viscol++;                                                  fc += BRIGHT;
                                                   break;
                                           case TBL_CELL_DHORIZ:
                                                   fc += BRIGHT * 2;
                                                   break;
                                           default:
                                                   break;
                                           }
                                 }                                  }
                                   if (tp->tbl.cols[ic].spacing)
                                           tbl_direct_border(tp, fc +
                                               BUP * uvert + BDOWN * dvert, 1);
   
                                 if (fc != ' ') {                                  if (tp->enc == TERMENC_UTF8)
                                           uvert = dvert = 0;
   
                                   if (fc != 0) {
                                         if (cp != NULL &&                                          if (cp != NULL &&
                                             cp->pos == TBL_CELL_HORIZ)                                              cp->pos == TBL_CELL_HORIZ)
                                                 fc = '-';                                                  fc = BHORIZ;
                                         else if (cp != NULL &&                                          else if (cp != NULL &&
                                             cp->pos == TBL_CELL_DHORIZ)                                              cp->pos == TBL_CELL_DHORIZ)
                                                 fc = '=';                                                  fc = BHORIZ * 2;
                                         else                                          else
                                                 fc = ' ';                                                  fc = 0;
                                 }                                  }
                                 if (tp->tbl.cols[ic].spacing > 2 &&                                  if (tp->tbl.cols[ic].spacing > 2 &&
                                     (vert > 1 || fc != ' ')) {                                      (uvert > 1 || dvert > 1 || fc != 0))
                                         (*tp->letter)(tp, fc == ' ' ? '|' :                                          tbl_direct_border(tp, fc +
                                             vert > 1 ? '+' : fc);                                              BUP * (uvert > 1) +
                                         tp->viscol++;                                              BDOWN * (dvert > 1), 1);
                                 }  
                         }                          }
                 }                  }
   
                 /* Print the vertical frame at the end of each row. */                  /* Print the vertical frame at the end of each row. */
   
                 fc = '\0';                  uvert = dvert = sp->opts->opts & TBL_OPT_DBOX ? 2 :
                 if ((sp->layout->last->vert &&                      sp->opts->opts & TBL_OPT_BOX ? 1 : 0;
                      sp->layout->last->col + 1 == sp->opts->cols) ||                  if (sp->pos == TBL_SPAN_DATA &&
                     (sp->next != NULL &&                      uvert < sp->layout->last->vert &&
                      sp->next->layout->last->vert &&                      sp->layout->last->col + 1 == sp->opts->cols)
                      sp->next->layout->last->col + 1 == sp->opts->cols) ||                          uvert = dvert = sp->layout->last->vert;
                     (sp->prev != NULL &&                  if (sp->next != NULL &&
                      sp->prev->layout->last->vert &&                      dvert < sp->next->layout->last->vert &&
                      sp->prev->layout->last->col + 1 == sp->opts->cols &&                      sp->next->layout->last->col + 1 == sp->opts->cols)
                      (horiz || (IS_HORIZ(sp->layout->last) &&                          dvert = sp->next->layout->last->vert;
                       !IS_HORIZ(sp->prev->layout->last)))) ||                  if (sp->prev != NULL &&
                     (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX)))                      uvert < sp->prev->layout->last->vert &&
                         fc = horiz || IS_HORIZ(sp->layout->last) ? '+' : '|';                      sp->prev->layout->last->col + 1 == sp->opts->cols &&
                 else if (horiz && sp->opts->rvert)                      (horiz || (IS_HORIZ(sp->layout->last) &&
                         fc = '-';                       !IS_HORIZ(sp->prev->layout->last))))
                 if (fc != '\0') {                          uvert = sp->prev->layout->last->vert;
                   line = sp->pos == TBL_SPAN_DHORIZ ||
                       (sp->layout->last->pos == TBL_CELL_DHORIZ &&
                        sp->layout->last->col + 1 == sp->opts->cols) ? 2 :
                       sp->pos == TBL_SPAN_HORIZ ||
                       (sp->layout->last->pos == TBL_CELL_HORIZ &&
                        sp->layout->last->col + 1 == sp->opts->cols) ? 1 : 0;
                   fc = BUP * uvert + BDOWN * dvert + BLEFT * line;
                   if (uvert > 0 || dvert > 0 || (horiz && sp->opts->rvert)) {
                         if (horiz == 0 && (IS_HORIZ(sp->layout->last) == 0 ||                          if (horiz == 0 && (IS_HORIZ(sp->layout->last) == 0 ||
                             sp->layout->last->col + 1 < sp->opts->cols)) {                              sp->layout->last->col + 1 < sp->opts->cols)) {
                                 tp->tcol++;                                  tp->tcol++;
Line 412  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 541  term_tbl(struct termp *tp, const struct tbl_span *sp)
                                     tp->tcol->offset > tp->viscol ?                                      tp->tcol->offset > tp->viscol ?
                                     tp->tcol->offset - tp->viscol : 1);                                      tp->tcol->offset - tp->viscol : 1);
                         }                          }
                         (*tp->letter)(tp, fc);                          tbl_direct_border(tp, fc, 1);
                 }                  }
                 (*tp->endline)(tp);                  (*tp->endline)(tp);
                 tp->viscol = 0;                  tp->viscol = 0;
Line 429  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 558  term_tbl(struct termp *tp, const struct tbl_span *sp)
         tp->tcol->rmargin = tp->maxrmargin;          tp->tcol->rmargin = tp->maxrmargin;
         if (sp->next == NULL) {          if (sp->next == NULL) {
                 if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) {                  if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) {
                         tbl_hrule(tp, sp, 2);                          tbl_hrule(tp, sp, HRULE_UP | HRULE_ENDS);
                         tp->skipvsp = 1;                          tp->skipvsp = 1;
                 }                  }
                 if (sp->opts->opts & TBL_OPT_DBOX) {                  if (tp->enc == TERMENC_ASCII &&
                         tbl_hrule(tp, sp, 3);                      sp->opts->opts & TBL_OPT_DBOX) {
                           tbl_hrule(tp, sp, HRULE_DBOX | HRULE_ENDS);
                         tp->skipvsp = 2;                          tp->skipvsp = 2;
                 }                  }
                 assert(tp->tbl.cols);                  assert(tp->tbl.cols);
Line 443  term_tbl(struct termp *tp, const struct tbl_span *sp)
Line 573  term_tbl(struct termp *tp, const struct tbl_span *sp)
         } else if (horiz == 0 && sp->opts->opts & TBL_OPT_ALLBOX &&          } else if (horiz == 0 && sp->opts->opts & TBL_OPT_ALLBOX &&
             (sp->next == NULL || sp->next->pos == TBL_SPAN_DATA ||              (sp->next == NULL || sp->next->pos == TBL_SPAN_DATA ||
              sp->next->next != NULL))               sp->next->next != NULL))
                 tbl_hrule(tp, sp, 1);                  tbl_hrule(tp, sp,
                       HRULE_DATA | HRULE_DOWN | HRULE_UP | HRULE_ENDS);
   
         tp->flags &= ~TERMP_NONOSPACE;          tp->flags &= ~TERMP_NONOSPACE;
 }  }
   
 /*  
  * Kinds of horizontal rulers:  
  * 0: inside the table (single or double line with crossings)  
  * 1: inside the table (single or double line with crossings and ends)  
  * 2: inner frame (single line with crossings and ends)  
  * 3: outer frame (single line without crossings with ends)  
  */  
 static void  static void
 tbl_hrule(struct termp *tp, const struct tbl_span *sp, int kind)  tbl_hrule(struct termp *tp, const struct tbl_span *sp, int flags)
 {  {
         const struct tbl_cell *cp, *cpn, *cpp;          const struct tbl_cell *cp, *cpn, *cpp;
         const struct roffcol *col;          const struct roffcol *col;
         int      vert;          int cross, dvert, line, linewidth, uvert;
         char     cross, line, stdcross, stdline;  
   
         stdline = (kind < 2 && TBL_SPAN_DHORIZ == sp->pos) ? '=' : '-';  
         stdcross = (kind < 3) ? '+' : '-';  
   
         cp = sp->layout->first;          cp = sp->layout->first;
         cpp = kind || sp->prev == NULL ? NULL : sp->prev->layout->first;          cpn = cpp = NULL;
         if (cpp == cp)          if (flags & HRULE_DATA) {
                 cpp = NULL;                  linewidth = sp->pos == TBL_SPAN_DHORIZ ? 2 : 1;
         cpn = kind > 1 || sp->next == NULL ? NULL : sp->next->layout->first;                  cpn = sp->next == NULL ? NULL : sp->next->layout->first;
         if (cpn == cp)                  if (cpn == cp)
                 cpn = NULL;                          cpn = NULL;
         if (kind)          } else
                 term_word(tp,                  linewidth = tp->enc == TERMENC_UTF8 &&
                     cpn == NULL || cpn->pos != TBL_CELL_DOWN ? "+" : "|");                      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 (;;) {          for (;;) {
                 col = tp->tbl.cols + cp->col;                  col = tp->tbl.cols + cp->col;
                 if (cpn == NULL || cpn->pos != TBL_CELL_DOWN) {                  line = cpn == NULL || cpn->pos != TBL_CELL_DOWN ?
                         line = stdline;                      BHORIZ * linewidth : 0;
                         cross = stdcross;                  tbl_direct_border(tp, line, col->width + col->spacing / 2);
                 } else {                  uvert = dvert = 0;
                         line = ' ';                  if (flags & HRULE_UP &&
                         cross = (kind < 3) ? '|' : ' ';                      (tp->enc == TERMENC_ASCII || sp->pos == TBL_SPAN_DATA ||
                 }                       (sp->prev != NULL && sp->prev->layout == sp->layout)))
                 tbl_char(tp, line, col->width + col->spacing / 2);                          uvert = cp->vert;
                 vert = cp->vert;                  if (flags & HRULE_DOWN)
                           dvert = cp->vert;
                 if ((cp = cp->next) == NULL)                  if ((cp = cp->next) == NULL)
                          break;                          break;
                 if (cpp != NULL) {                  if (cpp != NULL) {
                         if (vert < cpp->vert)                          if (uvert < cpp->vert)
                                 vert = cpp->vert;                                  uvert = cpp->vert;
                         cpp = cpp->next;                          cpp = cpp->next;
                 }                  }
                 if (cpn != NULL) {                  if (cpn != NULL) {
                         if (vert < cpn->vert)                          if (dvert < cpn->vert)
                                 vert = cpn->vert;                                  dvert = cpn->vert;
                         cpn = cpn->next;                          cpn = cpn->next;
                 }                  }
                 if (cpn == NULL || cpn->pos != TBL_CELL_DOWN) {                  if (sp->opts->opts & TBL_OPT_ALLBOX) {
                         line = stdline;                          if (flags & HRULE_UP && uvert == 0)
                         cross = stdcross;                                  uvert = 1;
                 } else                          if (flags & HRULE_DOWN && dvert == 0)
                         line = ' ';                                  dvert = 1;
                 if (sp->opts->opts & TBL_OPT_ALLBOX && !vert)                  }
                         vert = 1;                  cross = BHORIZ * linewidth + BUP * uvert + BDOWN * dvert;
                 if (col->spacing)                  if (col->spacing)
                         tbl_char(tp, vert ? cross : line, 1);                          tbl_direct_border(tp, cross, 1);
                 if (col->spacing > 2)                  if (col->spacing > 2)
                         tbl_char(tp, vert > 1 ? cross : line, 1);                          tbl_direct_border(tp, tp->enc == TERMENC_ASCII &&
                               (uvert > 1 || dvert > 1) ? cross : line, 1);
                 if (col->spacing > 4)                  if (col->spacing > 4)
                         tbl_char(tp, line, (col->spacing - 3) / 2);                          tbl_direct_border(tp, line, (col->spacing - 3) / 2);
         }          }
         if (kind) {          if (flags & HRULE_ENDS) {
                 term_word(tp,                  tbl_direct_border(tp, linewidth * (BLEFT +
                     cpn == NULL || cpn->pos != TBL_CELL_DOWN ? "+" : "|");                      (flags & (HRULE_UP | HRULE_DBOX) ? BUP : 0) +
                 term_flushln(tp);                      (flags & (HRULE_DOWN | HRULE_DBOX) ? BDOWN : 0)), 1);
                   (*tp->endline)(tp);
                   tp->viscol = 0;
         }          }
 }  }
   
Line 527  tbl_data(struct termp *tp, const struct tbl_opts *opts
Line 664  tbl_data(struct termp *tp, const struct tbl_opts *opts
 {  {
         switch (cp->pos) {          switch (cp->pos) {
         case TBL_CELL_HORIZ:          case TBL_CELL_HORIZ:
                 tbl_char(tp, '-', col->width);                  tbl_fill_border(tp, BHORIZ, col->width);
                 return;                  return;
         case TBL_CELL_DHORIZ:          case TBL_CELL_DHORIZ:
                 tbl_char(tp, '=', col->width);                  tbl_fill_border(tp, BHORIZ * 2, col->width);
                 return;                  return;
         default:          default:
                 break;                  break;
Line 544  tbl_data(struct termp *tp, const struct tbl_opts *opts
Line 681  tbl_data(struct termp *tp, const struct tbl_opts *opts
                 return;                  return;
         case TBL_DATA_HORIZ:          case TBL_DATA_HORIZ:
         case TBL_DATA_NHORIZ:          case TBL_DATA_NHORIZ:
                 tbl_char(tp, '-', col->width);                  tbl_fill_border(tp, BHORIZ, col->width);
                 return;                  return;
         case TBL_DATA_NDHORIZ:          case TBL_DATA_NDHORIZ:
         case TBL_DATA_DHORIZ:          case TBL_DATA_DHORIZ:
                 tbl_char(tp, '=', col->width);                  tbl_fill_border(tp, BHORIZ * 2, col->width);
                 return;                  return;
         default:          default:
                 break;                  break;
Line 573  tbl_data(struct termp *tp, const struct tbl_opts *opts
Line 710  tbl_data(struct termp *tp, const struct tbl_opts *opts
 }  }
   
 static void  static void
 tbl_char(struct termp *tp, char c, size_t len)  tbl_fill_string(struct termp *tp, const char *cp, size_t len)
 {  {
         size_t          i, sz;          size_t   i, sz;
         char            cp[2];  
   
           sz = term_strlen(tp, cp);
           for (i = 0; i < len; i += sz)
                   term_word(tp, cp);
   }
   
   static void
   tbl_fill_char(struct termp *tp, char c, size_t len)
   {
           char     cp[2];
   
         cp[0] = c;          cp[0] = c;
         cp[1] = '\0';          cp[1] = '\0';
           tbl_fill_string(tp, cp, len);
   }
   
         sz = term_strlen(tp, cp);  static void
   tbl_fill_border(struct termp *tp, int c, size_t len)
   {
           char     buf[12];
   
         for (i = 0; i < len; i += sz)          if ((c = borders_locale[c]) > 127) {
                 term_word(tp, cp);                  (void)snprintf(buf, sizeof(buf), "\\[u%04x]", c);
                   tbl_fill_string(tp, buf, len);
           } else
                   tbl_fill_char(tp, c, len);
 }  }
   
 static void  static void
   tbl_direct_border(struct termp *tp, int c, size_t len)
   {
           size_t   i, sz;
   
           c = borders_locale[c];
           sz = (*tp->width)(tp, c);
           for (i = 0; i < len; i += sz) {
                   (*tp->letter)(tp, c);
                   tp->viscol += sz;
           }
   }
   
   static void
 tbl_literal(struct termp *tp, const struct tbl_dat *dp,  tbl_literal(struct termp *tp, const struct tbl_dat *dp,
                 const struct roffcol *col)                  const struct roffcol *col)
 {  {
Line 624  tbl_literal(struct termp *tp, const struct tbl_dat *dp
Line 791  tbl_literal(struct termp *tp, const struct tbl_dat *dp
                 break;                  break;
         }          }
   
         tbl_char(tp, ASCII_NBRSP, padl);          tbl_fill_char(tp, ASCII_NBRSP, padl);
         tbl_word(tp, dp);          tbl_word(tp, dp);
         tbl_char(tp, ASCII_NBRSP, padr);          tbl_fill_char(tp, ASCII_NBRSP, padr);
 }  }
   
 static void  static void
Line 687  tbl_number(struct termp *tp, const struct tbl_opts *op
Line 854  tbl_number(struct termp *tp, const struct tbl_opts *op
         } else if (col->width > totsz)          } else if (col->width > totsz)
                 padl = (col->width - totsz) / 2;                  padl = (col->width - totsz) / 2;
   
         tbl_char(tp, ASCII_NBRSP, padl);          tbl_fill_char(tp, ASCII_NBRSP, padl);
         tbl_word(tp, dp);          tbl_word(tp, dp);
   
         /* Pad right to fill the column.  */          /* Pad right to fill the column.  */
   
         if (col->width > padl + totsz)          if (col->width > padl + totsz)
                 tbl_char(tp, ASCII_NBRSP, col->width - padl - totsz);                  tbl_fill_char(tp, ASCII_NBRSP, col->width - padl - totsz);
 }  }
   
 static void  static void

Legend:
Removed from v.1.61  
changed lines
  Added in v.1.62

CVSweb