On Thu, Aug 16, 2018 at 12:56:24PM +0200, Simon Kobyda wrote:
It solves problems with alignment of columns. Width of each column
is calculated by its biggest cell. Should solve unicode bug.
In future, it may be implemented in virsh, virt-admin...
This API has 5 public functions:
- vshTableNew - adds new table and defines its header
- vshTableRowAppend - appends new row (for same number of columns as in
header)
- vshTablePrintToStdout
- vshTablePrintToString
- vshTableFree
https://bugzilla.redhat.com/show_bug.cgi?id=1574624
https://bugzilla.redhat.com/show_bug.cgi?id=1584630
Signed-off-by: Simon Kobyda <skobyda(a)redhat.com>
---
tools/Makefile.am | 4 +-
tools/vsh-table.c | 413 ++++++++++++++++++++++++++++++++++++++++++++++
tools/vsh-table.h | 42 +++++
3 files changed, 458 insertions(+), 1 deletion(-)
create mode 100644 tools/vsh-table.c
create mode 100644 tools/vsh-table.h
+/**
+ * vshTableGetColumnsWidths:
+ * @table: table
+ * @maxwidths: maximum count of characters for each columns
+ * @widths: count of characters for each cell in the table
+ *
+ * Fill passed @maxwidths and @widths arrays with maximum number
+ * of characters for columns and number of character per each
+ * table cell, respectively.
+ *
+ * Handle unicode strings (user must have multibyte locale)
+ */
+static int
+vshTableGetColumnsWidths(vshTablePtr table,
+ size_t *maxwidths,
+ size_t **widths,
+ bool header)
+{
+ int ret = -1;
+ size_t i = 1;
+ size_t j;
+ size_t len;
+ int tmp;
+ wchar_t *wstr = NULL;
+ size_t wstrlen;
+
+ if (header)
+ i = 0;
+ else
+ i = 1;
+ for (; i < table->nrows; i++) {
+ vshTableRowPtr row = table->rows[i];
+
+ for (j = 0; j < row->ncells; j++) {
+ /* strlen should return maximum possible length needed */
+ wstrlen = strlen(row->cells[j]);
+ VIR_FREE(wstr);
+ if (VIR_ALLOC_N(wstr, wstrlen) < 0)
+ goto cleanup;
+ /* mbstowcs fails if machine is using singlebyte locale
+ * and user tries to convert unicode(multibyte)
+ * */
+ if (mbstowcs(wstr, row->cells[j], wstrlen) ==
+ (size_t) -1) {
+ len = wstrlen;
+ } else {
+ tmp = wcswidth(wstr, wstrlen);
+ if (tmp < 0)
+ goto cleanup;
+ len = (size_t)((unsigned)tmp);
+ }
+ widths[i][j] = len;
+ if (len > maxwidths[j])
+ maxwidths[j] = len;
After asking around I have found the right solution that we need to use
for measuring string width. mbstowcs()/wcswidth() will get the answer
wrong wrt zero-width characters, combining characters, non-printable
characters, etc. We need to use the libunistring library:
https://www.gnu.org/software/libunistring/manual/libunistring.html#uniwid...
Regards,
Daniel
--
|:
https://berrange.com -o-
https://www.flickr.com/photos/dberrange :|
|:
https://libvirt.org -o-
https://fstop138.berrange.com :|
|:
https://entangle-photo.org -o-
https://www.instagram.com/dberrange :|