xref: /onnv-gate/usr/src/cmd/parted/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 
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