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
table_new(int ncols)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
table_destroy(Table * t)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
max(int x,int y)102 static int max (int x, int y)
103 {
104 return x > y ? x : y;
105 }
106
107
table_calc_column_widths(Table * t)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 */
table_add_row(Table * t,wchar_t ** row)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
table_add_row_from_strlist(Table * t,StrList * list)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 */
table_render_row(Table * t,int rownum,int ncols,wchar_t ** s)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 */
table_render_rows(Table * t,wchar_t ** s)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 */
table_render(Table * t)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 }
244