#include <dialog.h>
#define each(row, data) \
row = 0, data = target; \
row < num_rows; \
++row, data = next_row(data, per_row)
static char *
column_separator(void)
{
char *result = 0;
if ((result = dialog_vars.column_separator) != 0) {
if (*result == '\0')
result = 0;
}
return result;
}
static char **
next_row(char **target, int per_row)
{
char *result = (char *) target;
result += per_row;
return (char **) (void *) result;
}
static char *
next_col(char *source, unsigned offset)
{
char *mark = column_separator();
char *result = source + offset;
if (offset)
result += strlen(mark);
return strstr(result, mark);
}
static unsigned
split_row(char *source, unsigned *offsets, unsigned *widths)
{
int mark = (int) strlen(column_separator());
char *next = 0;
unsigned result = 0;
unsigned offset = 0;
do {
if (result) {
offset = (unsigned) (mark + next - source);
widths[result - 1] = offset - offsets[result - 1] - (unsigned) mark;
}
offsets[result] = offset;
++result;
} while ((next = next_col(source, offset)) != 0);
offset = (unsigned) strlen(source);
widths[result - 1] = offset - offsets[result - 1];
return result;
}
void
dlg_align_columns(char **target, int per_row, int num_rows)
{
if (column_separator()) {
char **value;
unsigned numcols = 1;
size_t maxcols = 0;
unsigned *widths;
unsigned *offsets;
unsigned *maxwidth;
unsigned realwidth;
unsigned n;
int row;
for (each(row, value)) {
size_t len = strlen(*value);
if (maxcols < len)
maxcols = len;
}
++maxcols;
widths = dlg_calloc(unsigned, maxcols);
offsets = dlg_calloc(unsigned, maxcols);
maxwidth = dlg_calloc(unsigned, maxcols);
assert_ptr(widths, "dlg_align_columns");
assert_ptr(offsets, "dlg_align_columns");
assert_ptr(maxwidth, "dlg_align_columns");
for (each(row, value)) {
unsigned cols = split_row(*value, offsets, widths);
if (numcols < cols)
numcols = cols;
for (n = 0; n < cols; ++n) {
if (maxwidth[n] < widths[n])
maxwidth[n] = widths[n];
}
}
realwidth = numcols - 1;
for (n = 0; n < numcols; ++n) {
realwidth += maxwidth[n];
}
for (each(row, value)) {
unsigned cols = split_row(*value, offsets, widths);
unsigned offset = 0;
char *text = dlg_malloc(char, realwidth + 1);
assert_ptr(text, "dlg_align_columns");
memset(text, ' ', (size_t) realwidth);
for (n = 0; n < cols; ++n) {
memcpy(text + offset, *value + offsets[n], (size_t) widths[n]);
offset += maxwidth[n] + 1;
}
text[realwidth] = 0;
*value = text;
}
free(widths);
free(offsets);
free(maxwidth);
}
}
void
dlg_free_columns(char **target, int per_row, int num_rows)
{
if (column_separator()) {
int row;
char **value;
for (each(row, value)) {
free(*value);
}
}
}