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 50 static const unsigned int MAX_WIDTH = 512; 51 static const wchar_t* DELIMITER = L_(" "); 52 static const wchar_t* COLSUFFIX = L_("\n"); 53 54 typedef struct 55 { 56 unsigned int ncols; 57 unsigned int nrows; 58 wchar_t*** rows; 59 int* widths; 60 } Table; 61 62 63 Table* 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 78 void 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 102 static int max (int x, int y) 103 { 104 return x > y ? x : y; 105 } 106 107 108 static 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 */ 136 void 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 156 void 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 */ 177 static 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 */ 223 static 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 */ 236 wchar_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 }