ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/table.C
Revision: 1.6
Committed: Sun Sep 16 18:54:45 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +7 -2 lines
Log Message:
#defines to enum

File Contents

# Content
1 /*
2 * table.C: Table rendering class.
3 *
4 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5 * Rights to this code are as documented in COPYING.
6 *
7 * NOTE: This is a work in progress and will probably change considerably
8 * later on.
9 *
10 *
11 * Portions of this file were derived from sources bearing the following license:
12 * Rights to this code are documented in doc/pod/license.pod.
13 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
14 */
15
16 static char const rcsid[] = "$Id: table.C,v 1.5 2007-08-30 19:56:26 pippijn Exp $";
17
18 #include "atheme.h"
19
20 static void
21 table_destroy (void *obj)
22 {
23 table_t *table = (table_t *) obj;
24 node_t *n, *tn;
25
26 return_if_fail (table != NULL);
27
28 LIST_FOREACH_SAFE (n, tn, table->rows.head)
29 {
30 table_row_t *r = (table_row_t *) n->data;
31 node_t *n2, *tn2;
32
33 return_if_fail (r != NULL);
34
35 LIST_FOREACH_SAFE (n2, tn2, r->cells.head)
36 {
37 table_cell_t *c = (table_cell_t *) n2->data;
38
39 sfree (c->name);
40 sfree (c->value);
41 delete c;
42 node_del (n2, &r->cells);
43 node_free (n2);
44 }
45
46 delete r;
47
48 node_del (n, &table->rows);
49 node_free (n);
50 }
51
52 delete table;
53 }
54
55 /*
56 * table_new(char const * const fmt, ...)
57 *
58 * Table constructor.
59 *
60 * Inputs:
61 * - printf-style string to name the table with.
62 *
63 * Outputs:
64 * - a table object.
65 *
66 * Side Effects:
67 * - none
68 */
69 table_t *
70 table_new (char const * const fmt, ...)
71 {
72 va_list vl;
73 char *buf;
74 table_t *out;
75
76 return_val_if_fail (fmt != NULL, NULL);
77
78 va_start (vl, fmt);
79 vasprintf (&buf, fmt, vl);
80 va_end (vl);
81
82 out = new table_t;
83 object_init (&out->parent, buf, table_destroy);
84 sfree (buf);
85
86 return out;
87 }
88
89 /*
90 * table_row_new
91 *
92 * Creates a table row. This isn't an object.
93 *
94 * Inputs:
95 * - table to associate to.
96 *
97 * Outputs:
98 * - a table row
99 *
100 * Side Effects:
101 * - none
102 */
103 table_row_t *
104 table_row_new (table_t * t)
105 {
106 table_row_t *out;
107
108 return_val_if_fail (t != NULL, NULL);
109
110 out = new table_row_t;
111
112 node_add (out, node_create (), &t->rows);
113
114 return out;
115 }
116
117 /*
118 * table_cell_associate
119 *
120 * Associates a cell with a row.
121 *
122 * Inputs:
123 * - row to add cell to.
124 *
125 * Outputs:
126 * - nothing
127 *
128 * Side Effects:
129 * - none
130 */
131 void
132 table_cell_associate (table_row_t * r, char const * const name, char const * const value)
133 {
134 table_cell_t *c;
135
136 return_if_fail (r != NULL);
137 return_if_fail (name != NULL);
138 return_if_fail (value != NULL);
139
140 c = new table_cell_t;
141
142 c->name = sstrdup (name);
143 c->value = sstrdup (value);
144
145 node_add (c, node_create (), &r->cells);
146 }
147
148 /*
149 * table_render
150 *
151 * Renders a table. This is a two-pass operation, the first one to find out
152 * the width of each cell, and then the second to render the data.
153 *
154 * Inputs:
155 * - a table
156 * - a callback function
157 * - opaque data
158 *
159 * Outputs:
160 * - none
161 *
162 * Side Effects:
163 * - a callback function is called for each row of the table.
164 */
165 void
166 table_render (table_t * t, void (*callback) (char const * const line, void *data), void *data)
167 {
168 node_t *n;
169 table_row_t *f;
170 size_t bufsz = 0;
171 char *buf = NULL;
172 char *p;
173 int i;
174
175 return_if_fail (t != NULL);
176 return_if_fail (callback != NULL);
177
178 f = (table_row_t *) t->rows.head->data;
179
180 LIST_FOREACH (n, t->rows.head)
181 {
182 table_row_t *r = (table_row_t *) n->data;
183 node_t *n2, *rn;
184
185 /* we, uhh... we don't provide a macro for dealing with two lists at once ;) */
186 for (n2 = r->cells.head, rn = f->cells.head; n2 != NULL && rn != NULL; n2 = n2->next, rn = rn->next)
187 {
188 table_cell_t *c, *rc;
189 size_t sz;
190
191 c = (table_cell_t *) n2->data;
192 rc = (table_cell_t *) rn->data;
193
194 if ((sz = strlen (c->name)) > (size_t) rc->width)
195 rc->width = sz;
196
197 if ((sz = strlen (c->value)) > (size_t) rc->width)
198 rc->width = sz;
199 }
200 }
201
202 /* now total up the result. */
203 LIST_FOREACH (n, f->cells.head)
204 {
205 table_cell_t *c = (table_cell_t *) n->data;
206 bufsz += c->width + 1;
207 }
208
209 buf = salloc<char> (bufsz);
210 *buf = '\0';
211
212 /* start outputting the header. */
213 callback (asobject (t)->name, data);
214 LIST_FOREACH (n, f->cells.head)
215 {
216 table_cell_t *c = (table_cell_t *) n->data;
217 char fmtbuf[12];
218 char buf2[1024];
219
220 /* dynamically generate the format string based on width. */
221 snprintf (fmtbuf, 12, n->next != NULL ? "%%-%ds " : "%%s", c->width);
222 snprintf (buf2, 1024, fmtbuf, c->name);
223
224 strlcat (buf, buf2, bufsz);
225 }
226 callback (buf, data);
227 *buf = '\0';
228
229 /* separator line */
230 p = buf;
231 LIST_FOREACH (n, f->cells.head)
232 {
233 table_cell_t *c = (table_cell_t *) n->data;
234
235 if (n->next != NULL)
236 {
237 for (i = 0; i < c->width; i++)
238 *p++ = '-';
239 *p++ = ' ';
240 }
241 else
242 for (i = 0; i < (int) strlen (c->name); i++)
243 *p++ = '-';
244 }
245 *p = '\0';
246 callback (buf, data);
247 *buf = '\0';
248
249 LIST_FOREACH (n, t->rows.head)
250 {
251 table_row_t *r = (table_row_t *) n->data;
252 node_t *n2, *rn;
253
254 for (n2 = r->cells.head, rn = f->cells.head; n2 != NULL && rn != NULL; n2 = n2->next, rn = rn->next)
255 {
256 table_cell_t *c, *rc;
257 char fmtbuf[12];
258 char buf2[1024];
259
260 c = (table_cell_t *) n2->data;
261 rc = (table_cell_t *) rn->data;
262
263 /* dynamically generate the format string based on width. */
264 snprintf (fmtbuf, 12, n2->next != NULL ? "%%-%ds " : "%%s", rc->width);
265 snprintf (buf2, 1024, fmtbuf, c->value);
266
267 strlcat (buf, buf2, bufsz);
268 }
269 callback (buf, data);
270 *buf = '\0';
271 }
272
273 /* separator line */
274 p = buf;
275 LIST_FOREACH (n, f->cells.head)
276 {
277 table_cell_t *c = (table_cell_t *) n->data;
278
279 if (n->next != NULL)
280 {
281 for (i = 0; i < c->width; i++)
282 *p++ = '-';
283 *p++ = ' ';
284 }
285 else
286 for (i = 0; i < (int) strlen (c->name); i++)
287 *p++ = '-';
288 }
289 *p = '\0';
290 callback (buf, data);
291 *buf = '\0';
292 }
293
294 /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
295 * vim:ts=8
296 * vim:sw=8
297 * vim:noexpandtab
298 */