table.c revision 9663:ace9a2ac3683
1/* 2 * TODO: - make right and centered alignment possible 3 */ 4/* 5 parted - a frontend to libparted 6 Copyright (C) 2006, 2007 Free Software Foundation, Inc. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22 23#include <config.h> 24 25#include <stdio.h> 26#include <stdlib.h> 27 28#include <assert.h> 29#include <wchar.h> 30#include <string.h> 31 32#include "xalloc.h" 33#include "strlist.h" 34 35#ifdef ENABLE_NLS 36# define L_(str) L##str 37#else 38# define L_(str) str 39# ifdef wchar_t 40# undef wchar_t 41# endif 42# define wchar_t char 43# define wcslen strlen 44# define wcswidth strnlen 45# define wcscat strcat 46# define wcsdup xstrdup 47#endif 48 49 50static const unsigned int MAX_WIDTH = 512; 51static const wchar_t* DELIMITER = L_(" "); 52static const wchar_t* COLSUFFIX = L_("\n"); 53 54typedef struct 55{ 56 unsigned int ncols; 57 unsigned int nrows; 58 wchar_t*** rows; 59 int* widths; 60} Table; 61 62 63Table* table_new(int ncols) 64{ 65 assert ( ncols >= 0 ); 66 67 Table *t = xmalloc (sizeof(*t)); 68 69 t->ncols = ncols; 70 t->nrows = 0; 71 t->rows = (wchar_t***)NULL; 72 t->widths = NULL; 73 74 return t; 75} 76 77 78void table_destroy (Table* t) 79{ 80 unsigned int r, c; 81 82 assert (t); 83 assert (t->ncols > 0); 84 85 for (r = 0; r < t->nrows; ++r) 86 { 87 for (c = 0; c < t->ncols; ++c) 88 free (t->rows[r][c]); 89 free (t->rows[r]); 90 } 91 92 if (t->rows) 93 free (t->rows); 94 95 if (t->widths) 96 free (t->widths); 97 98 free (t); 99} 100 101 102static int max (int x, int y) 103{ 104 return x > y ? x : y; 105} 106 107 108static void table_calc_column_widths (Table* t) 109{ 110 unsigned int r, c; 111 112 assert(t); 113 assert(t->ncols > 0); 114 115 if (!t->widths) 116 t->widths = xmalloc (t->ncols * sizeof(t->widths[0])); 117 118 for (c = 0; c < t->ncols; ++c) 119 t->widths[c] = 0; 120 121 for (r = 0; r < t->nrows; ++r) 122 for (c = 0; c < t->ncols; ++c) 123 { 124 t->widths[c] = max ( t->widths[c], 125 wcswidth(t->rows[r][c], 126 MAX_WIDTH) ); 127 } 128} 129 130 131/* 132 * add a row which is a string array of ncols elements. 133 * 'row' will get freed by table_destroy; you must not free it 134 * yourself. 135 */ 136void table_add_row (Table* t, wchar_t** row) 137{ 138 assert(t); 139 140 /*unsigned int i; 141 fputs ("adding row: ", stdout); 142 for (i = 0; i < t->ncols; ++i) 143 printf("[%s]", row[i]); 144 putchar ('\n');*/ 145 146 t->rows = xrealloc (t->rows, (t->nrows + 1) * sizeof(wchar_t***)); 147 148 t->rows[t->nrows] = row; 149 150 ++t->nrows; 151 152 table_calc_column_widths (t); 153} 154 155 156void table_add_row_from_strlist (Table* t, StrList* list) 157{ 158 wchar_t** row = xmalloc (str_list_length(list) * sizeof(*row)); 159 int i = 0; 160 161 while (list) 162 { 163 row[i] = wcsdup (list->str); 164 if (row[i] == NULL) 165 xalloc_die (); 166 167 168 list = list->next; 169 ++i; 170 } 171 172 table_add_row (t, row); 173} 174 175 176/* render a row */ 177static void table_render_row (Table* t, int rownum, int ncols, wchar_t** s) 178{ 179 wchar_t** row = t->rows[rownum]; 180 int len = 1, i; 181 size_t newsize; 182 183 assert(t); 184 assert(s != NULL); 185 186 for (i = 0; i < ncols; ++i) 187 len += t->widths[i] + wcslen(DELIMITER); 188 189 len += wcslen(COLSUFFIX); 190 191 newsize = (wcslen(*s) + len + 1) * sizeof(wchar_t); 192 *s = xrealloc (*s, newsize); 193 194 for (i = 0; i < ncols; ++i) 195 { 196 int j; 197 int nspaces = max(t->widths[i] - wcswidth(row[i], MAX_WIDTH), 198 0); 199 wchar_t* pad = xmalloc ((nspaces + 1) * sizeof(*pad)); 200 201 for (j = 0; j < nspaces; ++j) 202 pad[j] = L' '; 203 204 pad[nspaces] = L_('\0'); 205 206 wcscat (*s, row[i]); 207 wcscat (*s, pad); 208 if (i + 1 < ncols) 209 wcscat (*s, DELIMITER); 210 211 free (pad); 212 pad = NULL; 213 } 214 215 wcscat (*s, COLSUFFIX); 216} 217 218 219/* 220 * Render the rows. 221 * \p s must be a null-terminated string. 222 */ 223static void table_render_rows (Table* t, wchar_t** s) 224{ 225 unsigned int i; 226 227 assert (**s == L_('\0')); 228 for (i = 0; i < t->nrows; ++i) 229 table_render_row (t, i, t->ncols, s); 230} 231 232/* 233 * Render the table to a string. 234 * You are responsible for freeing the returned string. 235 */ 236wchar_t* table_render(Table* t) 237{ 238 wchar_t* s = xmalloc (sizeof(*s)); 239 240 *s = L_('\0'); 241 table_render_rows (t, &s); 242 return s; 243} 244