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@xxxxxxxxxx> > --- > 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#uniwidth_002eh 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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list