summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/mbsalign.h2
-rw-r--r--lib/mbsalign.c12
-rw-r--r--libsmartcols/docs/libsmartcols-sections.txt1
-rw-r--r--libsmartcols/samples/Makemodule.am5
-rw-r--r--libsmartcols/src/column.c16
-rw-r--r--libsmartcols/src/libsmartcols.h.in2
-rw-r--r--libsmartcols/src/libsmartcols.sym5
-rw-r--r--libsmartcols/src/table_print.c85
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;