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