shrink_columns() calculate column width just enough to contain text and padding. relayout() uses shrink_columns() to try adding more columns after columns are shrunk. However it only try that once. Signed-off-by: Nguyán ThÃi Ngác Duy <pclouds@xxxxxxxxx> --- column.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ column.h | 1 + 2 files changed, 71 insertions(+), 0 deletions(-) diff --git a/column.c b/column.c index d6e2d70..e7facf4 100644 --- a/column.c +++ b/column.c @@ -54,6 +54,68 @@ static void layout(const struct string_list *list, *rows = DIV_ROUND_UP(list->nr, *cols); } +/* + * Tighten columns just wide enough to fit its data and padding + * Return number of chars saved after shrinking. + */ +static int shrink_columns(const struct string_list *list, int mode, + int *width, int padding, int rows, int cols) +{ + int x, y, i, len, item_len, spare = 0; + const char *s; + + for (x = 0; x < cols; x++) { + for (y = len = 0; y < rows; y++) { + i = XY2SCALAR(mode, x, y, cols, rows); + if (i >= list->nr) + break; + s = list->items[i].string; + item_len = item_length(list, mode, s); + if (len < item_len) + len = item_len; + } + len += padding; + + assert(len <= width[x]); + spare += width[x] - len; + width[x] = len; + } + return spare; +} + +/* Try to tighten the layout and see if more columns can be added.*/ +static void relayout(const struct string_list *list, + int mode, int original_width, int padding, int spare, + int *initial_width, int **width, int *rows, int *cols) +{ + int new_rows, new_cols, new_initial_width; + int i, *new_width, new_spare, total_width; + + /* + * Assume all columns have same width, we would need + * initial_width*cols. But then after shrinking, we have + * "spare" more chars. Assume a new total_width with + * additional chars, then re-shrink to see if it fits + * c->width. + */ + total_width = (*initial_width)*(*cols) + spare; + layout(list, mode, total_width, padding, + &new_initial_width, &new_rows, &new_cols); + new_width = xmalloc(sizeof(*new_width) * new_cols); + for (i = 0; i < new_cols; i++) + new_width[i] = new_initial_width; + new_spare = shrink_columns(list, mode, new_width, padding, new_rows, new_cols); + + /* Does it fit? */ + if (total_width - new_spare < original_width) { + free(*width); + *width = new_width; + *initial_width = new_initial_width; + *rows = new_rows; + *cols = new_cols; + } +} + /* Display without layout, COL_MODE_PLAIN */ static void display_plain(const struct string_list *list, const char *indent) { @@ -103,6 +165,14 @@ static void display_table(const struct string_list *list, for (i = 0; i < cols; i++) width[i] = initial_width; + if (mode & COL_DENSE) { + int spare = shrink_columns(list, mode, width, padding, rows, cols); + /* is it worth relayout? */ + if (spare >= initial_width/2) + relayout(list, mode, total_width, padding, spare, + &initial_width, &width, &rows, &cols); + } + empty_cell = xmalloc(initial_width + 1); memset(empty_cell, ' ', initial_width); empty_cell[initial_width] = '\0'; diff --git a/column.h b/column.h index 3ed5731..cef354d 100644 --- a/column.h +++ b/column.h @@ -6,6 +6,7 @@ #define COL_MODE_COLUMN 1 /* Fill columns before rows */ #define COL_MODE_ROW 2 /* Fill rows before columns */ #define COL_ANSI (1 << 4) /* Remove ANSI escapes from string length */ +#define COL_DENSE (1 << 5) /* Shrink columns when possible, making space for more columns */ extern int term_columns(void); extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent); -- 1.7.2.2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html