blob: 8768a92a2339369f517109d769837e8130fff295 [file] [log] [blame]
/*
* TODO: - make right and centered alignment possible
*/
/*
parted - a frontend to libparted
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <config.h>
#ifdef ENABLE_NLS
# include <wchar.h>
int wcswidth (const wchar_t *s, size_t n);
# define L_(str) L##str
#else
# define L_(str) str
# ifdef wchar_t
# undef wchar_t
# endif
# include <string.h>
# define wchar_t char
# define wcslen strlen
# define wcswidth strnlen
# define wcscat strcat
# define wcsdup strdup
size_t strnlen (const char *, size_t);
#endif
#include "xalloc.h"
#include "strlist.h"
static const unsigned int MAX_WIDTH = 512;
static const wchar_t* DELIMITER = L_(" ");
static const wchar_t* COLSUFFIX = L_("\n");
typedef struct
{
unsigned int ncols;
unsigned int nrows;
wchar_t*** rows;
int* widths;
} Table;
Table* table_new(int ncols)
{
assert ( ncols >= 0 );
Table *t = malloc(sizeof(Table));
t->ncols = ncols;
t->nrows = 0;
t->rows = (wchar_t***)NULL;
t->widths = NULL;
return t;
}
void table_destroy (Table* t)
{
unsigned int r, c;
assert (t);
assert (t->ncols > 0);
for (r = 0; r < t->nrows; ++r)
{
for (c = 0; c < t->ncols; ++c)
free (t->rows[r][c]);
free (t->rows[r]);
}
if (t->rows)
free (t->rows);
if (t->widths)
free (t->widths);
free (t);
}
static int max (int x, int y)
{
return x > y ? x : y;
}
static void table_calc_column_widths (Table* t)
{
unsigned int r, c;
assert(t);
assert(t->ncols > 0);
if (!t->widths)
t->widths = (int*)malloc(t->ncols * sizeof(int));
for (c = 0; c < t->ncols; ++c)
t->widths[c] = 0;
for (r = 0; r < t->nrows; ++r)
for (c = 0; c < t->ncols; ++c)
{
t->widths[c] = max ( t->widths[c],
wcswidth(t->rows[r][c],
MAX_WIDTH) );
}
}
/*
* add a row which is a string array of ncols elements.
* 'row' will get freed by table_destroy; you must not free it
* yourself.
*/
void table_add_row (Table* t, wchar_t** row)
{
assert(t);
/*unsigned int i;
fputs ("adding row: ", stdout);
for (i = 0; i < t->ncols; ++i)
printf("[%s]", row[i]);
putchar ('\n');*/
t->rows = (wchar_t***)realloc (t->rows, (t->nrows + 1)
* sizeof(wchar_t***));
t->rows[t->nrows] = row;
++t->nrows;
table_calc_column_widths (t);
}
void table_add_row_from_strlist (Table* t, StrList* list)
{
wchar_t** row = (wchar_t**)malloc(str_list_length(list)
* sizeof(wchar_t**));
int i = 0;
while (list)
{
row[i] = (wchar_t*)list->str;
list = list->next;
++i;
}
table_add_row (t, row);
}
/* render a row */
static void table_render_row (Table* t, int rownum, int ncols, wchar_t** s)
{
wchar_t** row = t->rows[rownum];
int len = 1, i;
size_t newsize;
assert(t);
assert(s != NULL);
for (i = 0; i < ncols; ++i)
len += t->widths[i] + wcslen(DELIMITER);
len += wcslen(COLSUFFIX);
newsize = (wcslen(*s) + len + 1) * sizeof(wchar_t);
*s = xrealloc (*s, newsize);
for (i = 0; i < ncols; ++i)
{
int j;
int nspaces = max(t->widths[i] - wcswidth(row[i], MAX_WIDTH),
0);
wchar_t* pad = xmalloc ((nspaces + 1) * sizeof(wchar_t));
for (j = 0; j < nspaces; ++j)
pad[j] = L' ';
pad[nspaces] = L_('\0');
wcscat (*s, row[i]);
wcscat (*s, pad);
if (i + 1 < ncols)
wcscat (*s, DELIMITER);
free (pad);
pad = NULL;
}
wcscat (*s, COLSUFFIX);
}
/*
* Render the rows.
* \p s must be a null-terminated string.
*/
static void table_render_rows (Table* t, wchar_t** s)
{
unsigned int i;
assert (**s == L_('\0'));
for (i = 0; i < t->nrows; ++i)
table_render_row (t, i, t->ncols, s);
}
/*
* Render the table to a string.
* You are responsible for freeing the returned string.
*/
wchar_t* table_render(Table* t)
{
wchar_t* s = malloc(sizeof(wchar_t));
*s = L_('\0');
table_render_rows (t, &s);
return s;
}