1*260e9a87SYuri Pankov /* $Id: tbl_term.c,v 1.40 2015/03/06 15:48:53 schwarze Exp $ */ 295c635efSGarrett D'Amore /* 395c635efSGarrett D'Amore * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4*260e9a87SYuri Pankov * Copyright (c) 2011, 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> 595c635efSGarrett D'Amore * 695c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 795c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 895c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 995c635efSGarrett D'Amore * 1095c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1195c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1295c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1395c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1495c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1595c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1695c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1795c635efSGarrett D'Amore */ 1895c635efSGarrett D'Amore #include "config.h" 19*260e9a87SYuri Pankov 20*260e9a87SYuri Pankov #include <sys/types.h> 2195c635efSGarrett D'Amore 2295c635efSGarrett D'Amore #include <assert.h> 2395c635efSGarrett D'Amore #include <stdio.h> 2495c635efSGarrett D'Amore #include <stdlib.h> 2595c635efSGarrett D'Amore #include <string.h> 2695c635efSGarrett D'Amore 2795c635efSGarrett D'Amore #include "mandoc.h" 2895c635efSGarrett D'Amore #include "out.h" 2995c635efSGarrett D'Amore #include "term.h" 3095c635efSGarrett D'Amore 3195c635efSGarrett D'Amore static size_t term_tbl_len(size_t, void *); 3295c635efSGarrett D'Amore static size_t term_tbl_strlen(const char *, void *); 3395c635efSGarrett D'Amore static void tbl_char(struct termp *, char, size_t); 34698f87a4SGarrett D'Amore static void tbl_data(struct termp *, const struct tbl_opts *, 3595c635efSGarrett D'Amore const struct tbl_dat *, 3695c635efSGarrett D'Amore const struct roffcol *); 3795c635efSGarrett D'Amore static void tbl_literal(struct termp *, const struct tbl_dat *, 3895c635efSGarrett D'Amore const struct roffcol *); 39698f87a4SGarrett D'Amore static void tbl_number(struct termp *, const struct tbl_opts *, 4095c635efSGarrett D'Amore const struct tbl_dat *, 4195c635efSGarrett D'Amore const struct roffcol *); 42*260e9a87SYuri Pankov static void tbl_hrule(struct termp *, const struct tbl_span *, int); 43*260e9a87SYuri Pankov static void tbl_word(struct termp *, const struct tbl_dat *); 4495c635efSGarrett D'Amore 4595c635efSGarrett D'Amore 4695c635efSGarrett D'Amore static size_t 4795c635efSGarrett D'Amore term_tbl_strlen(const char *p, void *arg) 4895c635efSGarrett D'Amore { 4995c635efSGarrett D'Amore 5095c635efSGarrett D'Amore return(term_strlen((const struct termp *)arg, p)); 5195c635efSGarrett D'Amore } 5295c635efSGarrett D'Amore 5395c635efSGarrett D'Amore static size_t 5495c635efSGarrett D'Amore term_tbl_len(size_t sz, void *arg) 5595c635efSGarrett D'Amore { 5695c635efSGarrett D'Amore 5795c635efSGarrett D'Amore return(term_len((const struct termp *)arg, sz)); 5895c635efSGarrett D'Amore } 5995c635efSGarrett D'Amore 6095c635efSGarrett D'Amore void 6195c635efSGarrett D'Amore term_tbl(struct termp *tp, const struct tbl_span *sp) 6295c635efSGarrett D'Amore { 63*260e9a87SYuri Pankov const struct tbl_cell *cp; 6495c635efSGarrett D'Amore const struct tbl_dat *dp; 65*260e9a87SYuri Pankov static size_t offset; 66*260e9a87SYuri Pankov size_t rmargin, maxrmargin, tsz; 67*260e9a87SYuri Pankov int ic, horiz, spans, vert; 6895c635efSGarrett D'Amore 6995c635efSGarrett D'Amore rmargin = tp->rmargin; 7095c635efSGarrett D'Amore maxrmargin = tp->maxrmargin; 7195c635efSGarrett D'Amore 7295c635efSGarrett D'Amore tp->rmargin = tp->maxrmargin = TERM_MAXMARGIN; 7395c635efSGarrett D'Amore 7495c635efSGarrett D'Amore /* Inhibit printing of spaces: we do padding ourselves. */ 7595c635efSGarrett D'Amore 7695c635efSGarrett D'Amore tp->flags |= TERMP_NONOSPACE; 7795c635efSGarrett D'Amore tp->flags |= TERMP_NOSPACE; 7895c635efSGarrett D'Amore 7995c635efSGarrett D'Amore /* 8095c635efSGarrett D'Amore * The first time we're invoked for a given table block, 8195c635efSGarrett D'Amore * calculate the table widths and decimal positions. 8295c635efSGarrett D'Amore */ 8395c635efSGarrett D'Amore 84*260e9a87SYuri Pankov if (tp->tbl.cols == NULL) { 8595c635efSGarrett D'Amore tp->tbl.len = term_tbl_len; 8695c635efSGarrett D'Amore tp->tbl.slen = term_tbl_strlen; 8795c635efSGarrett D'Amore tp->tbl.arg = tp; 8895c635efSGarrett D'Amore 89*260e9a87SYuri Pankov tblcalc(&tp->tbl, sp, rmargin - tp->offset); 90*260e9a87SYuri Pankov 91*260e9a87SYuri Pankov /* Center the table as a whole. */ 92*260e9a87SYuri Pankov 93*260e9a87SYuri Pankov offset = tp->offset; 94*260e9a87SYuri Pankov if (sp->opts->opts & TBL_OPT_CENTRE) { 95*260e9a87SYuri Pankov tsz = sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX) 96*260e9a87SYuri Pankov ? 2 : !!sp->opts->lvert + !!sp->opts->rvert; 97*260e9a87SYuri Pankov for (ic = 0; ic < sp->opts->cols; ic++) 98*260e9a87SYuri Pankov tsz += tp->tbl.cols[ic].width + 3; 99*260e9a87SYuri Pankov tsz -= 3; 100*260e9a87SYuri Pankov if (offset + tsz > rmargin) 101*260e9a87SYuri Pankov tsz -= 1; 102*260e9a87SYuri Pankov tp->offset = (offset + rmargin > tsz) ? 103*260e9a87SYuri Pankov (offset + rmargin - tsz) / 2 : 0; 10495c635efSGarrett D'Amore } 10595c635efSGarrett D'Amore 10695c635efSGarrett D'Amore /* Horizontal frame at the start of boxed tables. */ 10795c635efSGarrett D'Amore 108*260e9a87SYuri Pankov if (sp->opts->opts & TBL_OPT_DBOX) 109*260e9a87SYuri Pankov tbl_hrule(tp, sp, 2); 110*260e9a87SYuri Pankov if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) 111*260e9a87SYuri Pankov tbl_hrule(tp, sp, 1); 11295c635efSGarrett D'Amore } 11395c635efSGarrett D'Amore 11495c635efSGarrett D'Amore /* Vertical frame at the start of each row. */ 11595c635efSGarrett D'Amore 116*260e9a87SYuri Pankov horiz = sp->pos == TBL_SPAN_HORIZ || sp->pos == TBL_SPAN_DHORIZ; 117*260e9a87SYuri Pankov 118*260e9a87SYuri Pankov if (sp->layout->vert || 119*260e9a87SYuri Pankov (sp->prev != NULL && sp->prev->layout->vert) || 120*260e9a87SYuri Pankov sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX)) 121*260e9a87SYuri Pankov term_word(tp, horiz ? "+" : "|"); 122*260e9a87SYuri Pankov else if (sp->opts->lvert) 123*260e9a87SYuri Pankov tbl_char(tp, horiz ? '-' : ASCII_NBRSP, 1); 12495c635efSGarrett D'Amore 12595c635efSGarrett D'Amore /* 12695c635efSGarrett D'Amore * Now print the actual data itself depending on the span type. 127*260e9a87SYuri Pankov * Match data cells to column numbers. 12895c635efSGarrett D'Amore */ 12995c635efSGarrett D'Amore 130*260e9a87SYuri Pankov if (sp->pos == TBL_SPAN_DATA) { 131*260e9a87SYuri Pankov cp = sp->layout->first; 13295c635efSGarrett D'Amore dp = sp->first; 13395c635efSGarrett D'Amore spans = 0; 134*260e9a87SYuri Pankov for (ic = 0; ic < sp->opts->cols; ic++) { 135698f87a4SGarrett D'Amore 13695c635efSGarrett D'Amore /* 137*260e9a87SYuri Pankov * Remeber whether we need a vertical bar 138*260e9a87SYuri Pankov * after this cell. 13995c635efSGarrett D'Amore */ 14095c635efSGarrett D'Amore 141*260e9a87SYuri Pankov vert = cp == NULL ? 0 : cp->vert; 14295c635efSGarrett D'Amore 14395c635efSGarrett D'Amore /* 144*260e9a87SYuri Pankov * Print the data and advance to the next cell. 14595c635efSGarrett D'Amore */ 14695c635efSGarrett D'Amore 147*260e9a87SYuri Pankov if (spans == 0) { 148*260e9a87SYuri Pankov tbl_data(tp, sp->opts, dp, tp->tbl.cols + ic); 149*260e9a87SYuri Pankov if (dp != NULL) { 15095c635efSGarrett D'Amore spans = dp->spans; 15195c635efSGarrett D'Amore dp = dp->next; 15295c635efSGarrett D'Amore } 153*260e9a87SYuri Pankov } else 154*260e9a87SYuri Pankov spans--; 155*260e9a87SYuri Pankov if (cp != NULL) 156*260e9a87SYuri Pankov cp = cp->next; 157*260e9a87SYuri Pankov 158*260e9a87SYuri Pankov /* 159*260e9a87SYuri Pankov * Separate columns, except in the middle 160*260e9a87SYuri Pankov * of spans and after the last cell. 161*260e9a87SYuri Pankov */ 162*260e9a87SYuri Pankov 163*260e9a87SYuri Pankov if (ic + 1 == sp->opts->cols || spans) 164*260e9a87SYuri Pankov continue; 165*260e9a87SYuri Pankov 166*260e9a87SYuri Pankov tbl_char(tp, ASCII_NBRSP, 1); 167*260e9a87SYuri Pankov if (vert > 0) 168*260e9a87SYuri Pankov tbl_char(tp, '|', vert); 169*260e9a87SYuri Pankov if (vert < 2) 170*260e9a87SYuri Pankov tbl_char(tp, ASCII_NBRSP, 2 - vert); 17195c635efSGarrett D'Amore } 172*260e9a87SYuri Pankov } else if (horiz) 173*260e9a87SYuri Pankov tbl_hrule(tp, sp, 0); 17495c635efSGarrett D'Amore 17595c635efSGarrett D'Amore /* Vertical frame at the end of each row. */ 17695c635efSGarrett D'Amore 177*260e9a87SYuri Pankov if (sp->layout->last->vert || 178*260e9a87SYuri Pankov (sp->prev != NULL && sp->prev->layout->last->vert) || 179*260e9a87SYuri Pankov (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX))) 180*260e9a87SYuri Pankov term_word(tp, horiz ? "+" : " |"); 181*260e9a87SYuri Pankov else if (sp->opts->rvert) 182*260e9a87SYuri Pankov tbl_char(tp, horiz ? '-' : ASCII_NBRSP, 1); 18395c635efSGarrett D'Amore term_flushln(tp); 18495c635efSGarrett D'Amore 18595c635efSGarrett D'Amore /* 18695c635efSGarrett D'Amore * If we're the last row, clean up after ourselves: clear the 18795c635efSGarrett D'Amore * existing table configuration and set it to NULL. 18895c635efSGarrett D'Amore */ 18995c635efSGarrett D'Amore 190*260e9a87SYuri Pankov if (sp->next == NULL) { 191*260e9a87SYuri Pankov if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) { 192*260e9a87SYuri Pankov tbl_hrule(tp, sp, 1); 193698f87a4SGarrett D'Amore tp->skipvsp = 1; 194698f87a4SGarrett D'Amore } 195*260e9a87SYuri Pankov if (sp->opts->opts & TBL_OPT_DBOX) { 196*260e9a87SYuri Pankov tbl_hrule(tp, sp, 2); 197698f87a4SGarrett D'Amore tp->skipvsp = 2; 198698f87a4SGarrett D'Amore } 19995c635efSGarrett D'Amore assert(tp->tbl.cols); 20095c635efSGarrett D'Amore free(tp->tbl.cols); 20195c635efSGarrett D'Amore tp->tbl.cols = NULL; 202*260e9a87SYuri Pankov tp->offset = offset; 20395c635efSGarrett D'Amore } 20495c635efSGarrett D'Amore 20595c635efSGarrett D'Amore tp->flags &= ~TERMP_NONOSPACE; 20695c635efSGarrett D'Amore tp->rmargin = rmargin; 20795c635efSGarrett D'Amore tp->maxrmargin = maxrmargin; 20895c635efSGarrett D'Amore } 20995c635efSGarrett D'Amore 21095c635efSGarrett D'Amore /* 211*260e9a87SYuri Pankov * Kinds of horizontal rulers: 212*260e9a87SYuri Pankov * 0: inside the table (single or double line with crossings) 213*260e9a87SYuri Pankov * 1: inner frame (single line with crossings and ends) 214*260e9a87SYuri Pankov * 2: outer frame (single line without crossings with ends) 21595c635efSGarrett D'Amore */ 21695c635efSGarrett D'Amore static void 217*260e9a87SYuri Pankov tbl_hrule(struct termp *tp, const struct tbl_span *sp, int kind) 21895c635efSGarrett D'Amore { 219*260e9a87SYuri Pankov const struct tbl_cell *c1, *c2; 220*260e9a87SYuri Pankov int vert; 221*260e9a87SYuri Pankov char line, cross; 22295c635efSGarrett D'Amore 223*260e9a87SYuri Pankov line = (kind == 0 && TBL_SPAN_DHORIZ == sp->pos) ? '=' : '-'; 224*260e9a87SYuri Pankov cross = (kind < 2) ? '+' : '-'; 22595c635efSGarrett D'Amore 226*260e9a87SYuri Pankov if (kind) 22795c635efSGarrett D'Amore term_word(tp, "+"); 228*260e9a87SYuri Pankov c1 = sp->layout->first; 229*260e9a87SYuri Pankov c2 = sp->prev == NULL ? NULL : sp->prev->layout->first; 230*260e9a87SYuri Pankov if (c2 == c1) 231*260e9a87SYuri Pankov c2 = NULL; 232*260e9a87SYuri Pankov for (;;) { 233*260e9a87SYuri Pankov tbl_char(tp, line, tp->tbl.cols[c1->col].width + 1); 234*260e9a87SYuri Pankov vert = c1->vert; 235*260e9a87SYuri Pankov if ((c1 = c1->next) == NULL) 236*260e9a87SYuri Pankov break; 237*260e9a87SYuri Pankov if (c2 != NULL) { 238*260e9a87SYuri Pankov if (vert < c2->vert) 239*260e9a87SYuri Pankov vert = c2->vert; 240*260e9a87SYuri Pankov c2 = c2->next; 241698f87a4SGarrett D'Amore } 242*260e9a87SYuri Pankov if (vert) 243*260e9a87SYuri Pankov tbl_char(tp, cross, vert); 244*260e9a87SYuri Pankov if (vert < 2) 245*260e9a87SYuri Pankov tbl_char(tp, line, 2 - vert); 246*260e9a87SYuri Pankov } 247*260e9a87SYuri Pankov if (kind) { 24895c635efSGarrett D'Amore term_word(tp, "+"); 24995c635efSGarrett D'Amore term_flushln(tp); 25095c635efSGarrett D'Amore } 251*260e9a87SYuri Pankov } 25295c635efSGarrett D'Amore 25395c635efSGarrett D'Amore static void 254698f87a4SGarrett D'Amore tbl_data(struct termp *tp, const struct tbl_opts *opts, 25595c635efSGarrett D'Amore const struct tbl_dat *dp, 25695c635efSGarrett D'Amore const struct roffcol *col) 25795c635efSGarrett D'Amore { 25895c635efSGarrett D'Amore 259*260e9a87SYuri Pankov if (dp == NULL) { 26095c635efSGarrett D'Amore tbl_char(tp, ASCII_NBRSP, col->width); 26195c635efSGarrett D'Amore return; 26295c635efSGarrett D'Amore } 26395c635efSGarrett D'Amore 26495c635efSGarrett D'Amore switch (dp->pos) { 265*260e9a87SYuri Pankov case TBL_DATA_NONE: 26695c635efSGarrett D'Amore tbl_char(tp, ASCII_NBRSP, col->width); 26795c635efSGarrett D'Amore return; 268*260e9a87SYuri Pankov case TBL_DATA_HORIZ: 26995c635efSGarrett D'Amore /* FALLTHROUGH */ 270*260e9a87SYuri Pankov case TBL_DATA_NHORIZ: 27195c635efSGarrett D'Amore tbl_char(tp, '-', col->width); 27295c635efSGarrett D'Amore return; 273*260e9a87SYuri Pankov case TBL_DATA_NDHORIZ: 27495c635efSGarrett D'Amore /* FALLTHROUGH */ 275*260e9a87SYuri Pankov case TBL_DATA_DHORIZ: 27695c635efSGarrett D'Amore tbl_char(tp, '=', col->width); 27795c635efSGarrett D'Amore return; 27895c635efSGarrett D'Amore default: 27995c635efSGarrett D'Amore break; 28095c635efSGarrett D'Amore } 28195c635efSGarrett D'Amore 28295c635efSGarrett D'Amore switch (dp->layout->pos) { 283*260e9a87SYuri Pankov case TBL_CELL_HORIZ: 28495c635efSGarrett D'Amore tbl_char(tp, '-', col->width); 28595c635efSGarrett D'Amore break; 286*260e9a87SYuri Pankov case TBL_CELL_DHORIZ: 28795c635efSGarrett D'Amore tbl_char(tp, '=', col->width); 28895c635efSGarrett D'Amore break; 289*260e9a87SYuri Pankov case TBL_CELL_LONG: 29095c635efSGarrett D'Amore /* FALLTHROUGH */ 291*260e9a87SYuri Pankov case TBL_CELL_CENTRE: 29295c635efSGarrett D'Amore /* FALLTHROUGH */ 293*260e9a87SYuri Pankov case TBL_CELL_LEFT: 29495c635efSGarrett D'Amore /* FALLTHROUGH */ 295*260e9a87SYuri Pankov case TBL_CELL_RIGHT: 29695c635efSGarrett D'Amore tbl_literal(tp, dp, col); 29795c635efSGarrett D'Amore break; 298*260e9a87SYuri Pankov case TBL_CELL_NUMBER: 299698f87a4SGarrett D'Amore tbl_number(tp, opts, dp, col); 30095c635efSGarrett D'Amore break; 301*260e9a87SYuri Pankov case TBL_CELL_DOWN: 30295c635efSGarrett D'Amore tbl_char(tp, ASCII_NBRSP, col->width); 30395c635efSGarrett D'Amore break; 30495c635efSGarrett D'Amore default: 30595c635efSGarrett D'Amore abort(); 30695c635efSGarrett D'Amore /* NOTREACHED */ 30795c635efSGarrett D'Amore } 30895c635efSGarrett D'Amore } 30995c635efSGarrett D'Amore 31095c635efSGarrett D'Amore static void 31195c635efSGarrett D'Amore tbl_char(struct termp *tp, char c, size_t len) 31295c635efSGarrett D'Amore { 31395c635efSGarrett D'Amore size_t i, sz; 31495c635efSGarrett D'Amore char cp[2]; 31595c635efSGarrett D'Amore 31695c635efSGarrett D'Amore cp[0] = c; 31795c635efSGarrett D'Amore cp[1] = '\0'; 31895c635efSGarrett D'Amore 31995c635efSGarrett D'Amore sz = term_strlen(tp, cp); 32095c635efSGarrett D'Amore 32195c635efSGarrett D'Amore for (i = 0; i < len; i += sz) 32295c635efSGarrett D'Amore term_word(tp, cp); 32395c635efSGarrett D'Amore } 32495c635efSGarrett D'Amore 32595c635efSGarrett D'Amore static void 32695c635efSGarrett D'Amore tbl_literal(struct termp *tp, const struct tbl_dat *dp, 32795c635efSGarrett D'Amore const struct roffcol *col) 32895c635efSGarrett D'Amore { 329*260e9a87SYuri Pankov size_t len, padl, padr, width; 330*260e9a87SYuri Pankov int ic, spans; 33195c635efSGarrett D'Amore 33295c635efSGarrett D'Amore assert(dp->string); 33395c635efSGarrett D'Amore len = term_strlen(tp, dp->string); 334698f87a4SGarrett D'Amore width = col->width; 335*260e9a87SYuri Pankov ic = dp->layout->col; 336*260e9a87SYuri Pankov spans = dp->spans; 337*260e9a87SYuri Pankov while (spans--) 338*260e9a87SYuri Pankov width += tp->tbl.cols[++ic].width + 3; 339698f87a4SGarrett D'Amore 340698f87a4SGarrett D'Amore padr = width > len ? width - len : 0; 34195c635efSGarrett D'Amore padl = 0; 34295c635efSGarrett D'Amore 34395c635efSGarrett D'Amore switch (dp->layout->pos) { 344*260e9a87SYuri Pankov case TBL_CELL_LONG: 34595c635efSGarrett D'Amore padl = term_len(tp, 1); 34695c635efSGarrett D'Amore padr = padr > padl ? padr - padl : 0; 34795c635efSGarrett D'Amore break; 348*260e9a87SYuri Pankov case TBL_CELL_CENTRE: 34995c635efSGarrett D'Amore if (2 > padr) 35095c635efSGarrett D'Amore break; 35195c635efSGarrett D'Amore padl = padr / 2; 35295c635efSGarrett D'Amore padr -= padl; 35395c635efSGarrett D'Amore break; 354*260e9a87SYuri Pankov case TBL_CELL_RIGHT: 35595c635efSGarrett D'Amore padl = padr; 35695c635efSGarrett D'Amore padr = 0; 35795c635efSGarrett D'Amore break; 35895c635efSGarrett D'Amore default: 35995c635efSGarrett D'Amore break; 36095c635efSGarrett D'Amore } 36195c635efSGarrett D'Amore 36295c635efSGarrett D'Amore tbl_char(tp, ASCII_NBRSP, padl); 363*260e9a87SYuri Pankov tbl_word(tp, dp); 36495c635efSGarrett D'Amore tbl_char(tp, ASCII_NBRSP, padr); 36595c635efSGarrett D'Amore } 36695c635efSGarrett D'Amore 36795c635efSGarrett D'Amore static void 368698f87a4SGarrett D'Amore tbl_number(struct termp *tp, const struct tbl_opts *opts, 36995c635efSGarrett D'Amore const struct tbl_dat *dp, 37095c635efSGarrett D'Amore const struct roffcol *col) 37195c635efSGarrett D'Amore { 37295c635efSGarrett D'Amore char *cp; 37395c635efSGarrett D'Amore char buf[2]; 37495c635efSGarrett D'Amore size_t sz, psz, ssz, d, padl; 37595c635efSGarrett D'Amore int i; 37695c635efSGarrett D'Amore 37795c635efSGarrett D'Amore /* 37895c635efSGarrett D'Amore * See calc_data_number(). Left-pad by taking the offset of our 37995c635efSGarrett D'Amore * and the maximum decimal; right-pad by the remaining amount. 38095c635efSGarrett D'Amore */ 38195c635efSGarrett D'Amore 38295c635efSGarrett D'Amore assert(dp->string); 38395c635efSGarrett D'Amore 38495c635efSGarrett D'Amore sz = term_strlen(tp, dp->string); 38595c635efSGarrett D'Amore 386698f87a4SGarrett D'Amore buf[0] = opts->decimal; 38795c635efSGarrett D'Amore buf[1] = '\0'; 38895c635efSGarrett D'Amore 38995c635efSGarrett D'Amore psz = term_strlen(tp, buf); 39095c635efSGarrett D'Amore 391*260e9a87SYuri Pankov if ((cp = strrchr(dp->string, opts->decimal)) != NULL) { 39295c635efSGarrett D'Amore for (ssz = 0, i = 0; cp != &dp->string[i]; i++) { 39395c635efSGarrett D'Amore buf[0] = dp->string[i]; 39495c635efSGarrett D'Amore ssz += term_strlen(tp, buf); 39595c635efSGarrett D'Amore } 39695c635efSGarrett D'Amore d = ssz + psz; 39795c635efSGarrett D'Amore } else 39895c635efSGarrett D'Amore d = sz + psz; 39995c635efSGarrett D'Amore 400*260e9a87SYuri Pankov if (col->decimal > d && col->width > sz) { 40195c635efSGarrett D'Amore padl = col->decimal - d; 402*260e9a87SYuri Pankov if (padl + sz > col->width) 403*260e9a87SYuri Pankov padl = col->width - sz; 40495c635efSGarrett D'Amore tbl_char(tp, ASCII_NBRSP, padl); 405*260e9a87SYuri Pankov } else 406*260e9a87SYuri Pankov padl = 0; 407*260e9a87SYuri Pankov tbl_word(tp, dp); 40895c635efSGarrett D'Amore if (col->width > sz + padl) 40995c635efSGarrett D'Amore tbl_char(tp, ASCII_NBRSP, col->width - sz - padl); 41095c635efSGarrett D'Amore } 41195c635efSGarrett D'Amore 412*260e9a87SYuri Pankov static void 413*260e9a87SYuri Pankov tbl_word(struct termp *tp, const struct tbl_dat *dp) 414*260e9a87SYuri Pankov { 415*260e9a87SYuri Pankov int prev_font; 416*260e9a87SYuri Pankov 417*260e9a87SYuri Pankov prev_font = tp->fonti; 418*260e9a87SYuri Pankov if (dp->layout->flags & TBL_CELL_BOLD) 419*260e9a87SYuri Pankov term_fontpush(tp, TERMFONT_BOLD); 420*260e9a87SYuri Pankov else if (dp->layout->flags & TBL_CELL_ITALIC) 421*260e9a87SYuri Pankov term_fontpush(tp, TERMFONT_UNDER); 422*260e9a87SYuri Pankov 423*260e9a87SYuri Pankov term_word(tp, dp->string); 424*260e9a87SYuri Pankov 425*260e9a87SYuri Pankov term_fontpopq(tp, prev_font); 426*260e9a87SYuri Pankov } 427