-/* FIXME: `n' modifier doesn't always do the right thing. */
-/* FIXME: `n' modifier doesn't use the cell-spacing buffer. */
-
-static inline void tbl_char(struct termp *, char, int);
-static void tbl_hframe(struct termp *,
- const struct tbl_span *);
-static void tbl_data_number(struct termp *,
- const struct tbl *,
- const struct tbl_dat *,
- const struct termp_tbl *);
-static void tbl_data_literal(struct termp *,
- const struct tbl_dat *,
- const struct termp_tbl *);
-static void tbl_data_spanner(struct termp *,
- const struct tbl_dat *,
- const struct termp_tbl *);
-static void tbl_data(struct termp *, const struct tbl *,
- const struct tbl_dat *,
- const struct termp_tbl *);
-static void tbl_spanner(struct termp *,
- const struct tbl_head *);
-static void tbl_hrule(struct termp *,
- const struct tbl_span *);
-static void tbl_vframe(struct termp *,
- const struct tbl *);
-static void tbl_calc(struct termp *,
- const struct tbl_span *);
-static void tbl_calc_data(struct termp *,
- const struct tbl *,
- const struct tbl_dat *,
- struct termp_tbl *);
-static void tbl_calc_data_literal(struct termp *,
- const struct tbl_dat *,
- struct termp_tbl *);
-static void tbl_calc_data_number(struct termp *,
- const struct tbl *,
- const struct tbl_dat *,
- struct termp_tbl *);
+#define IS_HORIZ(cp) ((cp)->pos == TBL_CELL_HORIZ || \
+ (cp)->pos == TBL_CELL_DHORIZ)
+
+
+static size_t term_tbl_len(size_t, void *);
+static size_t term_tbl_strlen(const char *, void *);
+static size_t term_tbl_sulen(const struct roffsu *, void *);
+static void tbl_data(struct termp *, const struct tbl_opts *,
+ const struct tbl_cell *,
+ const struct tbl_dat *,
+ 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 *,
+ const struct tbl_span *, const struct tbl_span *,
+ int);
+static void tbl_literal(struct termp *, const struct tbl_dat *,
+ const struct roffcol *);
+static void tbl_number(struct termp *, const struct tbl_opts *,
+ const struct tbl_dat *,
+ const struct roffcol *);
+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
+term_tbl_sulen(const struct roffsu *su, void *arg)
+{
+ int i;
+
+ i = term_hen((const struct termp *)arg, su);
+ return i > 0 ? i : 0;
+}
+
+static size_t
+term_tbl_strlen(const char *p, void *arg)
+{
+ return term_strlen((const struct termp *)arg, p);
+}
+
+static size_t
+term_tbl_len(size_t sz, void *arg)
+{
+ return term_len((const struct termp *)arg, sz);
+}
+