diff options
-rw-r--r-- | include/mbsalign.h | 2 | ||||
-rw-r--r-- | lib/mbsalign.c | 12 | ||||
-rw-r--r-- | libsmartcols/docs/libsmartcols-sections.txt | 1 | ||||
-rw-r--r-- | libsmartcols/samples/Makemodule.am | 5 | ||||
-rw-r--r-- | libsmartcols/src/column.c | 16 | ||||
-rw-r--r-- | libsmartcols/src/libsmartcols.h.in | 2 | ||||
-rw-r--r-- | libsmartcols/src/libsmartcols.sym | 5 | ||||
-rw-r--r-- | libsmartcols/src/table_print.c | 85 |
8 files changed, 109 insertions, 19 deletions
diff --git a/include/mbsalign.h b/include/mbsalign.h index 74d25da11..6bdb50d3f 100644 --- a/include/mbsalign.h +++ b/include/mbsalign.h @@ -54,7 +54,7 @@ extern size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz); extern size_t mbs_safe_width(const char *s); extern char *mbs_safe_encode(const char *s, size_t *width); -extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf); +extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars); extern size_t mbs_safe_encode_size(size_t bytes); #endif /* UTIL_LINUX_MBSALIGN_H */ diff --git a/lib/mbsalign.c b/lib/mbsalign.c index 5c21ddeb4..c017ed1b3 100644 --- a/lib/mbsalign.c +++ b/lib/mbsalign.c @@ -107,12 +107,13 @@ size_t mbs_safe_width(const char *s) /* * Copy @s to @buf and replace control and non-printable chars with - * \x?? hex sequence. The @width returns number of cells. + * \x?? hex sequence. The @width returns number of cells. The @safechars + * are not encoded. * * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s))) * bytes. */ -char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf) +char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars) { const char *p = s; char *r; @@ -129,6 +130,11 @@ char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf) *width = 0; while (p && *p) { + if (safechars && strchr(safechars, *p)) { + *r++ = *p++; + continue; + } + if (iscntrl((unsigned char) *p)) { sprintf(r, "\\x%02x", (unsigned char) *p); r += 4; @@ -208,7 +214,7 @@ char *mbs_safe_encode(const char *s, size_t *width) if (!buf) return NULL; - return mbs_safe_encode_to_buffer(s, width, buf); + return mbs_safe_encode_to_buffer(s, width, buf, NULL); } #ifdef HAVE_WIDECHAR diff --git a/libsmartcols/docs/libsmartcols-sections.txt b/libsmartcols/docs/libsmartcols-sections.txt index 75ff0eb2c..e752e7056 100644 --- a/libsmartcols/docs/libsmartcols-sections.txt +++ b/libsmartcols/docs/libsmartcols-sections.txt @@ -29,6 +29,7 @@ scols_column_is_strict_width scols_column_is_tree scols_column_is_trunc scols_column_is_wrap +scols_column_is_wrapnl scols_column_set_cmpfunc scols_column_set_color scols_column_set_flags diff --git a/libsmartcols/samples/Makemodule.am b/libsmartcols/samples/Makemodule.am index 413da5e48..32cf8b70d 100644 --- a/libsmartcols/samples/Makemodule.am +++ b/libsmartcols/samples/Makemodule.am @@ -2,6 +2,7 @@ check_PROGRAMS += \ sample-scols-title \ sample-scols-wrap \ + sample-scols-wrapnl \ sample-scols-continuous \ sample-scols-maxout @@ -24,6 +25,10 @@ sample_scols_wrap_SOURCES = libsmartcols/samples/wrap.c sample_scols_wrap_LDADD = $(sample_scols_ldadd) sample_scols_wrap_CFLAGS = $(sample_scols_cflags) +sample_scols_wrapnl_SOURCES = libsmartcols/samples/wrapnl.c +sample_scols_wrapnl_LDADD = $(sample_scols_ldadd) libcommon.la +sample_scols_wrapnl_CFLAGS = $(sample_scols_cflags) + sample_scols_continuous_SOURCES = libsmartcols/samples/continuous.c sample_scols_continuous_LDADD = $(sample_scols_ldadd) libcommon.la sample_scols_continuous_CFLAGS = $(sample_scols_cflags) diff --git a/libsmartcols/src/column.c b/libsmartcols/src/column.c index a49d3de5c..3d4017fdc 100644 --- a/libsmartcols/src/column.c +++ b/libsmartcols/src/column.c @@ -356,3 +356,19 @@ int scols_column_is_wrap(struct libscols_column *cl) return -EINVAL; return cl->flags & SCOLS_FL_WRAP; } +/** + * scols_column_is_wrapnl: + * @cl: a pointer to a struct libscols_column instance + * + * Gets the value of @cl's flag wrap. + * + * Returns: wrapnl flag value, negative value in case of an error. + * + * Since: 2.29 + */ +int scols_column_is_wrapnl(struct libscols_column *cl) +{ + if (!cl) + return -EINVAL; + return cl->flags & SCOLS_FL_WRAPNL; +} diff --git a/libsmartcols/src/libsmartcols.h.in b/libsmartcols/src/libsmartcols.h.in index b2a750f1b..02867e2f5 100644 --- a/libsmartcols/src/libsmartcols.h.in +++ b/libsmartcols/src/libsmartcols.h.in @@ -85,6 +85,7 @@ enum { SCOLS_FL_NOEXTREMES = (1 << 4), /* ignore extreme fields when count column width*/ SCOLS_FL_HIDDEN = (1 << 5), /* maintain data, but don't print */ SCOLS_FL_WRAP = (1 << 6), /* wrap long lines to multi-line cells */ + SCOLS_FL_WRAPNL = (1 << 7) /* wrap based on '\n' char */ }; /* @@ -144,6 +145,7 @@ extern int scols_column_is_strict_width(struct libscols_column *cl); extern int scols_column_is_hidden(struct libscols_column *cl); extern int scols_column_is_noextremes(struct libscols_column *cl); extern int scols_column_is_wrap(struct libscols_column *cl); +extern int scols_column_is_wrapnl(struct libscols_column *cl); extern int scols_column_set_flags(struct libscols_column *cl, int flags); extern int scols_column_get_flags(struct libscols_column *cl); diff --git a/libsmartcols/src/libsmartcols.sym b/libsmartcols/src/libsmartcols.sym index 862262c8c..9a4997dd8 100644 --- a/libsmartcols/src/libsmartcols.sym +++ b/libsmartcols/src/libsmartcols.sym @@ -136,3 +136,8 @@ global: scols_table_print_range_to_string; scols_table_enable_nolinesep; } SMARTCOLS_2.27; + +SMARTCOLS_2.29 { +global: + scols_column_is_wrapnl; +} SMARTCOLS_2.28; diff --git a/libsmartcols/src/table_print.c b/libsmartcols/src/table_print.c index d625f8148..4d902b1d6 100644 --- a/libsmartcols/src/table_print.c +++ b/libsmartcols/src/table_print.c @@ -113,7 +113,8 @@ static char *buffer_get_data(struct libscols_buffer *buf) } /* encode data by mbs_safe_encode() to avoid control and non-printable chars */ -static char *buffer_get_safe_data(struct libscols_buffer *buf, size_t *cells) +static char *buffer_get_safe_data(struct libscols_buffer *buf, size_t *cells, + const char *safechars) { char *data = buffer_get_data(buf); char *res = NULL; @@ -127,7 +128,7 @@ static char *buffer_get_safe_data(struct libscols_buffer *buf, size_t *cells) goto nothing; } - res = mbs_safe_encode_to_buffer(data, cells, buf->encdata); + res = mbs_safe_encode_to_buffer(data, cells, buf->encdata, safechars); if (!res || !*cells || *cells == (size_t) -1) goto nothing; return res; @@ -234,7 +235,7 @@ static void print_empty_cell(struct libscols_table *tb, line_ascii_art_to_buffer(tb, ln, art); if (!list_empty(&ln->ln_branch) && has_pending_data(tb)) buffer_append_data(art, tb->symbols->vert); - data = buffer_get_safe_data(art, &len_pad); + data = buffer_get_safe_data(art, &len_pad, NULL); if (data && len_pad) fputs(data, tb->out); free_buffer(art); @@ -242,8 +243,11 @@ static void print_empty_cell(struct libscols_table *tb, } } /* fill rest of cell with space */ - for(; len_pad <= cl->width; ++len_pad) + for(; len_pad < cl->width; ++len_pad) fputc(' ', tb->out); + + if (!is_last_column(cl)) + fputs(colsep(tb), tb->out); } @@ -350,6 +354,7 @@ static int print_pending_data( size_t width = cl->width, bytes; size_t len = width, i; char *data; + char *wrapnl = NULL; if (!cl->pending_data) return 0; @@ -359,7 +364,16 @@ static int print_pending_data( data = strdup(cl->pending_data); if (!data) goto err; - bytes = mbs_truncate(data, &len); + + if (scols_column_is_wrapnl(cl) && (wrapnl = strchr(data, '\n'))) { + *wrapnl = '\0'; + wrapnl++; + bytes = wrapnl - data; + + len = mbs_safe_nwidth(data, bytes, NULL); + } else + bytes = mbs_truncate(data, &len); + if (bytes == (size_t) -1) goto err; @@ -375,10 +389,9 @@ static int print_pending_data( for (i = len; i < width; i++) fputc(' ', tb->out); /* padding */ - if (is_last_column(cl)) - return 0; + if (!is_last_column(cl)) + fputs(colsep(tb), tb->out); /* columns separator */ - fputs(colsep(tb), tb->out); /* columns separator */ return 0; err: free(data); @@ -393,7 +406,7 @@ static int print_data(struct libscols_table *tb, { size_t len = 0, i, width, bytes; const char *color = NULL; - char *data; + char *data, *wrapnl; assert(tb); assert(cl); @@ -437,18 +450,31 @@ static int print_data(struct libscols_table *tb, color = get_cell_color(tb, cl, ln, ce); - /* encode, note that 'len' and 'width' are number of cells, not bytes */ - data = buffer_get_safe_data(buf, &len); + /* Encode. Note that 'len' and 'width' are number of cells, not bytes. + * For the columns with WRAPNL we mark \n as a safe char. + */ + data = buffer_get_safe_data(buf, &len, + scols_column_is_wrapnl(cl) ? "\n" : NULL); if (!data) data = ""; - width = cl->width; bytes = strlen(data); + width = cl->width; + + /* multi-line cell based on '\n' */ + if (*data && scols_column_is_wrapnl(cl) && (wrapnl = strchr(data, '\n'))) { + *wrapnl = '\0'; + wrapnl++; + set_pending_data(cl, wrapnl, bytes - (wrapnl - data)); + bytes = wrapnl - data; + len = mbs_safe_nwidth(data, bytes, NULL); + } if (is_last_column(cl) && len < width && !scols_table_is_maxout(tb) && !scols_column_is_right(cl) - && !scols_column_is_wrap(cl)) + && !scols_column_is_wrap(cl) + && !scols_column_is_wrapnl(cl)) width = len; /* truncate data */ @@ -724,7 +750,7 @@ static int print_title(struct libscols_table *tb) goto done; } - if (!mbs_safe_encode_to_buffer(tb->title.data, &bufsz, buf) || + if (!mbs_safe_encode_to_buffer(tb->title.data, &bufsz, buf, NULL) || !bufsz || bufsz == (size_t) -1) { rc = -EINVAL; goto done; @@ -941,6 +967,29 @@ static void dbg_columns(struct libscols_table *tb) dbg_column(tb, cl); } +/* count the maximal size of \n terminated chunk in the @data + * for example for "AAA\nBBBB\nXX" the wrap size is 4 ('BBBB'). + */ +static size_t count_wrapnl_size(const char *data) +{ + size_t sum = 0; + + while (data && *data) { + const char *p = data; + + p = strchr(data, '\n'); + if (p) { + size_t sz = mbs_safe_nwidth(data, p - data, NULL); + + sum = max(sum, sz); + p++; + } + data = p;; + } + + return sum; +} + /* * This function counts column width. * @@ -985,7 +1034,13 @@ static int count_column_width(struct libscols_table *tb, goto done; data = buffer_get_data(buf); - len = data ? mbs_safe_width(data) : 0; + + if (!data) + len = 0; + else if (scols_column_is_wrapnl(cl)) + len = count_wrapnl_size(data); + else + len = mbs_safe_width(data); if (len == (size_t) -1) /* ignore broken multibyte strings */ len = 0; |