IPVarch/ipvtbl.c

128 lines
3.8 KiB
C

/* SPDX-License-Identifier: GPL-3.0-or-later */
/* ipvtbl.c - shared UTF-8 box-table rendering for IPVarch */
#include <stdio.h>
#include <string.h>
#include "ipvtbl.h"
/* UTF-8 encoded box drawing characters (U+2500 block). */
#define BOX_H "\xe2\x94\x80" /* horizontal line */
#define BOX_V "\xe2\x94\x82" /* vertical line */
#define BOX_TL "\xe2\x94\x8c" /* top left ┌ */
#define BOX_TR "\xe2\x94\x90" /* top right ┐ */
#define BOX_BL "\xe2\x94\x94" /* bottom left └ */
#define BOX_BR "\xe2\x94\x98" /* bottom right ┘ */
#define BOX_TJ "\xe2\x94\xac" /* top join ┬ */
#define BOX_BJ "\xe2\x94\xb4" /* bottom join ┴ */
#define BOX_LJ "\xe2\x94\x9c" /* left join ├ */
#define BOX_RJ "\xe2\x94\xa4" /* right join ┤ */
#define BOX_CJ "\xe2\x94\xbc" /* centre join ┼ */
int dwidth(const char *s) {
int w = 0;
while (*s != '\0') {
if ((((unsigned char)*s) & 0xC0) != 0x80)
w++;
s++;
}
return w;
}
static void dashes(int n) {
while (n-- > 0)
fputs(BOX_H, stdout);
return;
}
/* Emit a cell of exactly 'w' display columns: space + text + right pad. */
static void padcell(const char *s, int w) {
int d = dwidth(s) + 1;
putchar(' ');
fputs(s, stdout);
while (d < w) {
putchar(' ');
d++;
}
return;
}
/* Centre text within 'w' display columns. */
static void centercell(const char *s, int w) {
int d = dwidth(s) + 1;
int l = (w - d) / 2;
int r = w - d - l;
while (l-- > 0)
putchar(' ');
putchar(' ');
fputs(s, stdout);
while (r-- > 0)
putchar(' ');
return;
}
void print_table(const char *title, const char *rows[][2], int nrows) {
int w1 = 0, w2 = 0, tw, i;
for (i = 0; i < nrows; i++) {
int a = dwidth(rows[i][0]) + 2; /* room for cell padding */
int b = dwidth(rows[i][1]) + 2;
if (a > w1) w1 = a;
if (b > w2) w2 = b;
}
tw = dwidth(title) + 2;
if (tw > w1 + w2 - 1)
w2 = tw - w1 + 1;
fputs(BOX_TL, stdout); dashes(w1); fputs(BOX_TJ, stdout);
dashes(w2); fputs(BOX_TR "\n", stdout);
fputs(BOX_V, stdout); centercell(title, w1 + 1 + w2); fputs(BOX_V "\n", stdout);
fputs(BOX_LJ, stdout); dashes(w1); fputs(BOX_CJ, stdout);
dashes(w2); fputs(BOX_RJ "\n", stdout);
for (i = 0; i < nrows; i++) {
fputs(BOX_V, stdout); padcell(rows[i][0], w1);
fputs(BOX_V, stdout); padcell(rows[i][1], w2);
fputs(BOX_V "\n", stdout);
}
fputs(BOX_BL, stdout); dashes(w1); fputs(BOX_BJ, stdout);
dashes(w2); fputs(BOX_BR "\n", stdout);
return;
}
void print_table3(const char *title, const char *rows[][3], int nrows) {
int w1 = 0, w2 = 0, w3 = 0, tw, i;
for (i = 0; i < nrows; i++) {
int a = dwidth(rows[i][0]) + 2;
int b = dwidth(rows[i][1]) + 2;
int c = dwidth(rows[i][2]) + 2;
if (a > w1) w1 = a;
if (b > w2) w2 = b;
if (c > w3) w3 = c;
}
tw = dwidth(title) + 2;
if (tw > w1 + w2 + w3)
w3 = tw - w1 - w2 + 1;
fputs(BOX_TL, stdout); dashes(w1); fputs(BOX_TJ, stdout);
dashes(w2); fputs(BOX_TJ, stdout); dashes(w3); fputs(BOX_TR "\n", stdout);
fputs(BOX_V, stdout); centercell(title, w1 + 1 + w2 + 1 + w3);
fputs(BOX_V "\n", stdout);
fputs(BOX_LJ, stdout); dashes(w1); fputs(BOX_CJ, stdout);
dashes(w2); fputs(BOX_CJ, stdout); dashes(w3); fputs(BOX_RJ "\n", stdout);
for (i = 0; i < nrows; i++) {
fputs(BOX_V, stdout); padcell(rows[i][0], w1);
fputs(BOX_V, stdout); padcell(rows[i][1], w2);
fputs(BOX_V, stdout); padcell(rows[i][2], w3);
fputs(BOX_V "\n", stdout);
}
fputs(BOX_BL, stdout); dashes(w1); fputs(BOX_BJ, stdout);
dashes(w2); fputs(BOX_BJ, stdout); dashes(w3); fputs(BOX_BR "\n", stdout);
return;
}