diff options
Diffstat (limited to '')
-rw-r--r-- | libblkid/tt.c | 1005 |
1 files changed, 0 insertions, 1005 deletions
diff --git a/libblkid/tt.c b/libblkid/tt.c deleted file mode 100644 index cbe4e3b4d..000000000 --- a/libblkid/tt.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * TT - Table or Tree, features: - * - column width could be defined as absolute or relative to the terminal width - * - allows to truncate or wrap data in columns - * - prints tree if parent->child relation is defined - * - draws the tree by ASCII or UTF8 lines (depends on terminal setting) - * - * Copyright (C) 2010 Karel Zak <kzak@redhat.com> - * - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <termios.h> -#include <ctype.h> - -#include "c.h" -#include "nls.h" -#include "widechar.h" -#include "tt.h" -#include "mbsalign.h" -#include "ttyutils.h" - -struct tt_symbols { - const char *branch; - const char *vert; - const char *right; -}; - -static const struct tt_symbols ascii_tt_symbols = { - .branch = "|-", - .vert = "| ", - .right = "`-", -}; - -#ifdef HAVE_WIDECHAR -#define UTF_V "\342\224\202" /* U+2502, Vertical line drawing char */ -#define UTF_VR "\342\224\234" /* U+251C, Vertical and right */ -#define UTF_H "\342\224\200" /* U+2500, Horizontal */ -#define UTF_UR "\342\224\224" /* U+2514, Up and right */ - -static const struct tt_symbols utf8_tt_symbols = { - .branch = UTF_VR UTF_H, - .vert = UTF_V " ", - .right = UTF_UR UTF_H, -}; -#endif /* !HAVE_WIDECHAR */ - -#define is_last_column(_tb, _cl) \ - list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns) - -/* - * Counts number of cells in multibyte string. For all control and - * non-printable chars is the result width enlarged to store \x?? hex - * sequence. See mbs_safe_encode(). - */ -static size_t mbs_safe_width(const char *s) -{ - mbstate_t st; - const char *p = s; - size_t width = 0; - - memset(&st, 0, sizeof(st)); - - while (p && *p) { - if (iscntrl((unsigned char) *p)) { - width += 4; /* *p encoded to \x?? */ - p++; - } -#ifdef HAVE_WIDECHAR - else { - wchar_t wc; - size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st); - - if (len == 0) - break; - - if (len == (size_t) -1 || len == (size_t) -2) { - len = 1; - width += (isprint((unsigned char) *p) ? 1 : 4); - - } if (!iswprint(wc)) - width += len * 4; /* hex encode whole sequence */ - else - width += wcwidth(wc); /* number of cells */ - p += len; - } -#else - else if (!isprint((unsigned char) *p)) { - width += 4; /* *p encoded to \x?? */ - p++; - } else { - width++; - p++; - } -#endif - } - - return width; -} - -/* - * Returns allocated string where all control and non-printable chars are - * replaced with \x?? hex sequence. - */ -static char *mbs_safe_encode(const char *s, size_t *width) -{ - mbstate_t st; - const char *p = s; - char *res, *r; - size_t sz = s ? strlen(s) : 0; - - - if (!sz) - return NULL; - - memset(&st, 0, sizeof(st)); - - res = malloc((sz * 4) + 1); - if (!res) - return NULL; - - r = res; - *width = 0; - - while (p && *p) { - if (iscntrl((unsigned char) *p)) { - sprintf(r, "\\x%02x", (unsigned char) *p); - r += 4; - *width += 4; - p++; - } -#ifdef HAVE_WIDECHAR - else { - wchar_t wc; - size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st); - - if (len == 0) - break; /* end of string */ - - if (len == (size_t) -1 || len == (size_t) -2) { - len = 1; - /* - * Not valid multibyte sequence -- maybe it's - * printable char according to the current locales. - */ - if (!isprint((unsigned char) *p)) { - sprintf(r, "\\x%02x", (unsigned char) *p); - r += 4; - *width += 4; - } else { - width++; - *r++ = *p; - } - } else if (!iswprint(wc)) { - size_t i; - for (i = 0; i < len; i++) { - sprintf(r, "\\x%02x", (unsigned char) *p); - r += 4; - *width += 4; - } - } else { - memcpy(r, p, len); - r += len; - *width += wcwidth(wc); - } - p += len; - } -#else - else if (!isprint((unsigned char) *p)) { - sprintf(r, "\\x%02x", (unsigned char) *p); - p++; - r += 4; - *width += 4; - } else { - *r++ = *p++; - *width++; - } -#endif - } - - *r = '\0'; - - return res; -} - -/* - * @flags: TT_FL_* flags (usually TT_FL_{ASCII,RAW}) - * - * Returns: newly allocated table - */ -struct tt *tt_new_table(int flags) -{ - struct tt *tb; - - tb = calloc(1, sizeof(struct tt)); - if (!tb) - return NULL; - - tb->flags = flags; - INIT_LIST_HEAD(&tb->tb_lines); - INIT_LIST_HEAD(&tb->tb_columns); - -#if defined(HAVE_WIDECHAR) - if (!(flags & TT_FL_ASCII) && !strcmp(nl_langinfo(CODESET), "UTF-8")) - tb->symbols = &utf8_tt_symbols; - else -#endif - tb->symbols = &ascii_tt_symbols; - - tb->first_run = TRUE; - return tb; -} - -void tt_remove_lines(struct tt *tb) -{ - if (!tb) - return; - - while (!list_empty(&tb->tb_lines)) { - struct tt_line *ln = list_entry(tb->tb_lines.next, - struct tt_line, ln_lines); - list_del(&ln->ln_lines); - free(ln->data); - free(ln); - } -} - -void tt_free_table(struct tt *tb) -{ - if (!tb) - return; - - tt_remove_lines(tb); - - while (!list_empty(&tb->tb_columns)) { - struct tt_column *cl = list_entry(tb->tb_columns.next, - struct tt_column, cl_columns); - list_del(&cl->cl_columns); - free(cl); - } - free(tb); -} - - -/* - * @tb: table - * @name: column header - * @whint: column width hint (absolute width: N > 1; relative width: N < 1) - * @flags: usually TT_FL_{TREE,TRUNCATE} - * - * The column width is possible to define by three ways: - * - * @whint = 0..1 : relative width, percent of terminal width - * - * @whint = 1..N : absolute width, empty colum will be truncated to - * the column header width - * - * @whint = 1..N - * @flags = TT_FL_STRICTWIDTH - * : absolute width, empty colum won't be truncated - * - * The column is necessary to address (for example for tt_line_set_data()) by - * sequential number. The first defined column has the colnum = 0. For example: - * - * tt_define_column(tab, "FOO", 0.5, 0); // colnum = 0 - * tt_define_column(tab, "BAR", 0.5, 0); // colnum = 1 - * . - * . - * tt_line_set_data(line, 0, "foo-data"); // FOO column - * tt_line_set_data(line, 1, "bar-data"); // BAR column - * - * Returns: newly allocated column definition - */ -struct tt_column *tt_define_column(struct tt *tb, const char *name, - double whint, int flags) -{ - struct tt_column *cl; - - if (!tb) - return NULL; - cl = calloc(1, sizeof(*cl)); - if (!cl) - return NULL; - - cl->name = name; - cl->width_hint = whint; - cl->flags = flags; - cl->seqnum = tb->ncols++; - - if (flags & TT_FL_TREE) - tb->flags |= TT_FL_TREE; - - INIT_LIST_HEAD(&cl->cl_columns); - list_add_tail(&cl->cl_columns, &tb->tb_columns); - return cl; -} - -/* - * @tb: table - * @parent: parental line or NULL - * - * Returns: newly allocate line - */ -struct tt_line *tt_add_line(struct tt *tb, struct tt_line *parent) -{ - struct tt_line *ln = NULL; - - if (!tb || !tb->ncols) - goto err; - ln = calloc(1, sizeof(*ln)); - if (!ln) - goto err; - ln->data = calloc(tb->ncols, sizeof(char *)); - if (!ln->data) - goto err; - - ln->table = tb; - ln->parent = parent; - INIT_LIST_HEAD(&ln->ln_lines); - INIT_LIST_HEAD(&ln->ln_children); - INIT_LIST_HEAD(&ln->ln_branch); - - list_add_tail(&ln->ln_lines, &tb->tb_lines); - - if (parent) - list_add_tail(&ln->ln_children, &parent->ln_branch); - return ln; -err: - free(ln); - return NULL; -} - -/* - * @tb: table - * @colnum: number of column (0..N) - * - * Returns: pointer to column or NULL - */ -struct tt_column *tt_get_column(struct tt *tb, size_t colnum) -{ - struct list_head *p; - - list_for_each(p, &tb->tb_columns) { - struct tt_column *cl = - list_entry(p, struct tt_column, cl_columns); - if (cl->seqnum == colnum) - return cl; - } - return NULL; -} - -/* - * @ln: line - * @colnum: number of column (0..N) - * @data: printable data - * - * Stores data that will be printed to the table cell. - */ -int tt_line_set_data(struct tt_line *ln, int colnum, const char *data) -{ - struct tt_column *cl; - - if (!ln) - return -1; - cl = tt_get_column(ln->table, colnum); - if (!cl) - return -1; - - if (ln->data[cl->seqnum]) { - size_t sz = strlen(ln->data[cl->seqnum]);; - ln->data_sz = ln->data_sz > sz ? ln->data_sz - sz : 0; - } - - ln->data[cl->seqnum] = data; - if (data) - ln->data_sz += strlen(data); - return 0; -} - -int tt_line_set_userdata(struct tt_line *ln, void *data) -{ - if (!ln) - return -1; - ln->userdata = data; - return 0; -} - -static char *line_get_ascii_art(struct tt_line *ln, char *buf, size_t *bufsz) -{ - const char *art; - size_t len; - - if (!ln->parent) - return buf; - - buf = line_get_ascii_art(ln->parent, buf, bufsz); - if (!buf) - return NULL; - - if (list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch)) - art = " "; - else - art = ln->table->symbols->vert; - - len = strlen(art); - if (*bufsz < len) - return NULL; /* no space, internal error */ - - memcpy(buf, art, len); - *bufsz -= len; - return buf + len; -} - -static char *line_get_data(struct tt_line *ln, struct tt_column *cl, - char *buf, size_t bufsz) -{ - const char *data = ln->data[cl->seqnum]; - const struct tt_symbols *sym; - char *p = buf; - - memset(buf, 0, bufsz); - - if (!data) - return NULL; - if (!(cl->flags & TT_FL_TREE)) { - strncpy(buf, data, bufsz); - buf[bufsz - 1] = '\0'; - return buf; - } - - /* - * Tree stuff - */ - if (ln->parent) { - p = line_get_ascii_art(ln->parent, buf, &bufsz); - if (!p) - return NULL; - } - - sym = ln->table->symbols; - - if (!ln->parent) - snprintf(p, bufsz, "%s", data); /* root node */ - else if (list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch)) - snprintf(p, bufsz, "%s%s", sym->right, data); /* last chaild */ - else - snprintf(p, bufsz, "%s%s", sym->branch, data); /* any child */ - - return buf; -} - -/* - * This function counts column width. - * - * For the TT_FL_NOEXTREMES columns is possible to call this function two - * times. The first pass counts width and average width. If the column - * contains too large fields (width greater than 2 * average) then the column - * is marked as "extreme". In the second pass all extreme fields are ignored - * and column width is counted from non-extreme fields only. - */ -static void count_column_width(struct tt *tb, struct tt_column *cl, - char *buf, size_t bufsz) -{ - struct list_head *lp; - int count = 0; - size_t sum = 0; - - cl->width = 0; - - list_for_each(lp, &tb->tb_lines) { - struct tt_line *ln = list_entry(lp, struct tt_line, ln_lines); - char *data = line_get_data(ln, cl, buf, bufsz); - size_t len = data ? mbs_safe_width(data) : 0; - - if (len == (size_t) -1) /* ignore broken multibyte strings */ - len = 0; - - if (len > cl->width_max) - cl->width_max = len; - - if (cl->is_extreme && len > cl->width_avg * 2) - continue; - else if (cl->flags & TT_FL_NOEXTREMES) { - sum += len; - count++; - } - if (len > cl->width) - cl->width = len; - } - - if (count && cl->width_avg == 0) { - cl->width_avg = sum / count; - - if (cl->width_max > cl->width_avg * 2) - cl->is_extreme = 1; - } - - /* check and set minimal column width */ - if (cl->name) - cl->width_min = mbs_safe_width(cl->name); - - /* enlarge to minimal width */ - if (cl->width < cl->width_min && !(cl->flags & TT_FL_STRICTWIDTH)) - cl->width = cl->width_min; - - /* use relative size for large columns */ - else if (cl->width_hint >= 1 && cl->width < (size_t) cl->width_hint && - cl->width_min < (size_t) cl->width_hint) - - cl->width = (size_t) cl->width_hint; -} - -/* - * This is core of the tt_* voodo... - */ -static void recount_widths(struct tt *tb, char *buf, size_t bufsz) -{ - struct list_head *p; - size_t width = 0; /* output width */ - int trunc_only; - int extremes = 0; - - /* set basic columns width - */ - list_for_each(p, &tb->tb_columns) { - struct tt_column *cl = - list_entry(p, struct tt_column, cl_columns); - - count_column_width(tb, cl, buf, bufsz); - width += cl->width + (is_last_column(tb, cl) ? 0 : 1); - extremes += cl->is_extreme; - } - - if (!tb->is_term) - return; - - /* reduce columns with extreme fields - */ - if (width > tb->termwidth && extremes) { - list_for_each(p, &tb->tb_columns) { - struct tt_column *cl = list_entry(p, struct tt_column, cl_columns); - size_t org_width; - - if (!cl->is_extreme) - continue; - - org_width = cl->width; - count_column_width(tb, cl, buf, bufsz); - - if (org_width > cl->width) - width -= org_width - cl->width; - else - extremes--; /* hmm... nothing reduced */ - } - } - - if (width < tb->termwidth) { - /* try to found extreme column which fits into available space - */ - if (extremes) { - /* enlarge the first extreme column */ - list_for_each(p, &tb->tb_columns) { - struct tt_column *cl = - list_entry(p, struct tt_column, cl_columns); - size_t add; - - if (!cl->is_extreme) - continue; - - /* this column is tooo large, ignore? - if (cl->width_max - cl->width > - (tb->termwidth - width)) - continue; - */ - - add = tb->termwidth - width; - if (add && cl->width + add > cl->width_max) - add = cl->width_max - cl->width; - - cl->width += add; - width += add; - - if (width == tb->termwidth) - break; - } - } - if (width < tb->termwidth) { - /* enalarge the last column */ - struct tt_column *cl = list_entry( - tb->tb_columns.prev, struct tt_column, cl_columns); - - if (!(cl->flags & TT_FL_RIGHT) && tb->termwidth - width > 0) { - cl->width += tb->termwidth - width; - width = tb->termwidth; - } - } - } - - /* bad, we have to reduce output width, this is done in two steps: - * 1/ reduce columns with a relative width and with truncate flag - * 2) reduce columns with a relative width without truncate flag - */ - trunc_only = 1; - while (width > tb->termwidth) { - size_t org = width; - - list_for_each(p, &tb->tb_columns) { - struct tt_column *cl = - list_entry(p, struct tt_column, cl_columns); - - if (width <= tb->termwidth) - break; - if (cl->width_hint > 1 && !(cl->flags & TT_FL_TRUNC)) - continue; /* never truncate columns with absolute sizes */ - if (cl->flags & TT_FL_TREE) - continue; /* never truncate the tree */ - if (trunc_only && !(cl->flags & TT_FL_TRUNC)) - continue; - if (cl->width == cl->width_min) - continue; - - /* truncate column with relative sizes */ - if (cl->width_hint < 1 && cl->width > 0 && width > 0 && - cl->width > cl->width_hint * tb->termwidth) { - cl->width--; - width--; - } - /* truncate column with absolute size */ - if (cl->width_hint > 1 && cl->width > 0 && width > 0 && - !trunc_only) { - cl->width--; - width--; - } - - } - if (org == width) { - if (trunc_only) - trunc_only = 0; - else - break; - } - } - -/* - fprintf(stderr, "terminal: %d, output: %d\n", tb->termwidth, width); - - list_for_each(p, &tb->tb_columns) { - struct tt_column *cl = - list_entry(p, struct tt_column, cl_columns); - - fprintf(stderr, "width: %s=%zd [hint=%d, avg=%zd, max=%zd, extreme=%s]\n", - cl->name, cl->width, - cl->width_hint > 1 ? (int) cl->width_hint : - (int) (cl->width_hint * tb->termwidth), - cl->width_avg, - cl->width_max, - cl->is_extreme ? "yes" : "not"); - } -*/ - return; -} - -void tt_fputs_quoted(const char *data, FILE *out) -{ - const char *p; - - fputc('"', out); - for (p = data; p && *p; p++) { - if ((unsigned char) *p == 0x22 || /* " */ - (unsigned char) *p == 0x5c || /* \ */ - !isprint((unsigned char) *p) || - iscntrl((unsigned char) *p)) { - - fprintf(out, "\\x%02x", (unsigned char) *p); - } else - fputc(*p, out); - } - fputc('"', out); -} - -void tt_fputs_nonblank(const char *data, FILE *out) -{ - const char *p; - - for (p = data; p && *p; p++) { - if (isblank((unsigned char) *p) || - (unsigned char) *p == 0x5c || /* \ */ - !isprint((unsigned char) *p) || - iscntrl((unsigned char) *p)) { - - fprintf(out, "\\x%02x", (unsigned char) *p); - - } else - fputc(*p, out); - } -} - -/* - * Prints data, data maybe be printed in more formats (raw, NAME=xxx pairs) and - * control and non-printable chars maybe encoded in \x?? hex encoding. - */ -static void print_data(struct tt *tb, struct tt_column *cl, char *data) -{ - size_t len = 0, i, width; - char *buf; - - if (!data) - data = ""; - - /* raw mode */ - if (tb->flags & TT_FL_RAW) { - tt_fputs_nonblank(data, stdout); - if (!is_last_column(tb, cl)) - fputc(' ', stdout); - return; - } - - /* NAME=value mode */ - if (tb->flags & TT_FL_EXPORT) { - fprintf(stdout, "%s=", cl->name); - tt_fputs_quoted(data, stdout); - if (!is_last_column(tb, cl)) - fputc(' ', stdout); - return; - } - - /* note that 'len' and 'width' are number of cells, not bytes */ - buf = mbs_safe_encode(data, &len); - data = buf; - if (!data) - data = ""; - - if (!len || len == (size_t) -1) { - len = 0; - data = NULL; - } - width = cl->width; - - if (is_last_column(tb, cl) && len < width) - width = len; - - /* truncate data */ - if (len > width && (cl->flags & TT_FL_TRUNC)) { - if (data) - len = mbs_truncate(data, &width); - if (!data || len == (size_t) -1) { - len = 0; - data = NULL; - } - } - if (data) { - if (!(tb->flags & TT_FL_RAW) && (cl->flags & TT_FL_RIGHT)) { - size_t xw = cl->width; - fprintf(stdout, "%*s", (int) xw, data); - if (len < xw) - len = xw; - } - else - fputs(data, stdout); - } - for (i = len; i < width; i++) - fputc(' ', stdout); /* padding */ - - if (!is_last_column(tb, cl)) { - if (len > width && !(cl->flags & TT_FL_TRUNC)) { - fputc('\n', stdout); - for (i = 0; i <= (size_t) cl->seqnum; i++) { - struct tt_column *x = tt_get_column(tb, i); - printf("%*s ", -((int)x->width), " "); - } - } else - fputc(' ', stdout); /* columns separator */ - } - - free(buf); -} - -static void print_line(struct tt_line *ln, char *buf, size_t bufsz) -{ - struct list_head *p; - - /* set width according to the size of data - */ - list_for_each(p, &ln->table->tb_columns) { - struct tt_column *cl = - list_entry(p, struct tt_column, cl_columns); - - print_data(ln->table, cl, line_get_data(ln, cl, buf, bufsz)); - } - fputc('\n', stdout); -} - -static void print_header(struct tt *tb, char *buf, size_t bufsz) -{ - struct list_head *p; - - if (!tb->first_run || - (tb->flags & TT_FL_NOHEADINGS) || - (tb->flags & TT_FL_EXPORT) || - list_empty(&tb->tb_lines)) - return; - - /* set width according to the size of data - */ - list_for_each(p, &tb->tb_columns) { - struct tt_column *cl = - list_entry(p, struct tt_column, cl_columns); - - strncpy(buf, cl->name, bufsz); - buf[bufsz - 1] = '\0'; - print_data(tb, cl, buf); - } - fputc('\n', stdout); -} - -static void print_table(struct tt *tb, char *buf, size_t bufsz) -{ - struct list_head *p; - - print_header(tb, buf, bufsz); - - list_for_each(p, &tb->tb_lines) { - struct tt_line *ln = list_entry(p, struct tt_line, ln_lines); - - print_line(ln, buf, bufsz); - } -} - -static void print_tree_line(struct tt_line *ln, char *buf, size_t bufsz) -{ - struct list_head *p; - - print_line(ln, buf, bufsz); - - if (list_empty(&ln->ln_branch)) - return; - - /* print all children */ - list_for_each(p, &ln->ln_branch) { - struct tt_line *chld = - list_entry(p, struct tt_line, ln_children); - print_tree_line(chld, buf, bufsz); - } -} - -static void print_tree(struct tt *tb, char *buf, size_t bufsz) -{ - struct list_head *p; - - print_header(tb, buf, bufsz); - - list_for_each(p, &tb->tb_lines) { - struct tt_line *ln = list_entry(p, struct tt_line, ln_lines); - - if (ln->parent) - continue; - - print_tree_line(ln, buf, bufsz); - } -} - -/* - * @tb: table - * - * Prints the table to stdout - */ -int tt_print_table(struct tt *tb) -{ - char *line; - size_t line_sz; - struct list_head *p; - - if (!tb) - return -1; - - if (tb->first_run) { - tb->is_term = isatty(STDOUT_FILENO); - - if (tb->is_term && !tb->termwidth) - tb->termwidth = get_terminal_width(); - if (tb->termwidth <= 0) - tb->termwidth = 80; - } - - line_sz = tb->termwidth; - - list_for_each(p, &tb->tb_lines) { - struct tt_line *ln = list_entry(p, struct tt_line, ln_lines); - if (ln->data_sz > line_sz) - line_sz = ln->data_sz; - } - - line_sz++; /* make a space for \0 */ - line = malloc(line_sz); - if (!line) - return -1; - - if (tb->first_run && - !((tb->flags & TT_FL_RAW) || (tb->flags & TT_FL_EXPORT))) - recount_widths(tb, line, line_sz); - - if (tb->flags & TT_FL_TREE) - print_tree(tb, line, line_sz); - else - print_table(tb, line, line_sz); - - free(line); - - tb->first_run = FALSE; - return 0; -} - -#ifdef TEST_PROGRAM -#include <errno.h> - -enum { MYCOL_NAME, MYCOL_FOO, MYCOL_BAR, MYCOL_PATH }; - -int main(int argc, char *argv[]) -{ - struct tt *tb; - struct tt_line *ln, *pr, *root; - int flags = 0, notree = 0, i; - - if (argc == 2 && !strcmp(argv[1], "--help")) { - printf("%s [--ascii | --raw | --list]\n", - program_invocation_short_name); - return EXIT_SUCCESS; - } else if (argc == 2 && !strcmp(argv[1], "--ascii")) { - flags |= TT_FL_ASCII; - } else if (argc == 2 && !strcmp(argv[1], "--raw")) { - flags |= TT_FL_RAW; - notree = 1; - } else if (argc == 2 && !strcmp(argv[1], "--export")) { - flags |= TT_FL_EXPORT; - notree = 1; - } else if (argc == 2 && !strcmp(argv[1], "--list")) - notree = 1; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - tb = tt_new_table(flags); - if (!tb) - err(EXIT_FAILURE, "table initialization failed"); - - tt_define_column(tb, "NAME", 0.3, notree ? 0 : TT_FL_TREE); - tt_define_column(tb, "FOO", 0.3, TT_FL_TRUNC); - tt_define_column(tb, "BAR", 0.3, 0); - tt_define_column(tb, "PATH", 0.3, 0); - - for (i = 0; i < 2; i++) { - root = ln = tt_add_line(tb, NULL); - tt_line_set_data(ln, MYCOL_NAME, "AAA"); - tt_line_set_data(ln, MYCOL_FOO, "a-foo-foo"); - tt_line_set_data(ln, MYCOL_BAR, "barBar-A"); - tt_line_set_data(ln, MYCOL_PATH, "/mnt/AAA"); - - pr = ln = tt_add_line(tb, ln); - tt_line_set_data(ln, MYCOL_NAME, "AAA.A"); - tt_line_set_data(ln, MYCOL_FOO, "a.a-foo-foo"); - tt_line_set_data(ln, MYCOL_BAR, "barBar-A.A"); - tt_line_set_data(ln, MYCOL_PATH, "/mnt/AAA/A"); - - ln = tt_add_line(tb, pr); - tt_line_set_data(ln, MYCOL_NAME, "AAA.A.AAA"); - tt_line_set_data(ln, MYCOL_FOO, "a.a.a-foo-foo"); - tt_line_set_data(ln, MYCOL_BAR, "barBar-A.A.A"); - tt_line_set_data(ln, MYCOL_PATH, "/mnt/AAA/A/AAA"); - - ln = tt_add_line(tb, root); - tt_line_set_data(ln, MYCOL_NAME, "AAA.B"); - tt_line_set_data(ln, MYCOL_FOO, "a.b-foo-foo"); - tt_line_set_data(ln, MYCOL_BAR, "barBar-A.B"); - tt_line_set_data(ln, MYCOL_PATH, "/mnt/AAA/B"); - - ln = tt_add_line(tb, pr); - tt_line_set_data(ln, MYCOL_NAME, "AAA.A.BBB"); - tt_line_set_data(ln, MYCOL_FOO, "a.a.b-foo-foo"); - tt_line_set_data(ln, MYCOL_BAR, "barBar-A.A.BBB"); - tt_line_set_data(ln, MYCOL_PATH, "/mnt/AAA/A/BBB"); - - ln = tt_add_line(tb, pr); - tt_line_set_data(ln, MYCOL_NAME, "AAA.A.CCC"); - tt_line_set_data(ln, MYCOL_FOO, "a.a.c-foo-foo"); - tt_line_set_data(ln, MYCOL_BAR, "barBar-A.A.CCC"); - tt_line_set_data(ln, MYCOL_PATH, "/mnt/AAA/A/CCC"); - - ln = tt_add_line(tb, root); - tt_line_set_data(ln, MYCOL_NAME, "AAA.C"); - tt_line_set_data(ln, MYCOL_FOO, "a.c-foo-foo"); - tt_line_set_data(ln, MYCOL_BAR, "barBar-A.C"); - tt_line_set_data(ln, MYCOL_PATH, "/mnt/AAA/C"); - } - - tt_print_table(tb); - tt_free_table(tb); - - return EXIT_SUCCESS; -} -#endif |