1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include <libpspp/assertion.h>
28 /* Increments table_num so different procedures' output can be
33 if (subtable_num != 0)
40 /* Ejects the paper for all active devices. */
44 struct outp_driver *d;
46 for (d = outp_drivers (NULL); d; d = outp_drivers (d))
50 /* Flushes output on all active devices. */
54 struct outp_driver *d;
56 for (d = outp_drivers (NULL); d; d = outp_drivers (d))
60 /* Skip down a single line on all active devices. */
64 struct outp_driver *d;
66 for (d = outp_drivers (NULL); d; d = outp_drivers (d))
67 if (d->page_open && d->cp_y != 0)
68 d->cp_y += d->font_height;
72 static struct outp_driver *d = 0;
75 static struct som_entity *t = 0;
78 static unsigned flags;
80 /* Number of columns, rows. */
83 /* Number of columns or rows in left, right, top, bottom headers. */
84 static int hl, hr, ht, hb;
89 /* Table height, width. */
92 static void render_columns (void);
93 static void render_simple (void);
94 static void render_segments (void);
96 static void output_entity (struct outp_driver *, struct som_entity *);
98 /* Output table T to appropriate output devices. */
100 som_submit (struct som_entity *t)
105 assert (entry++ == 0);
108 if ( t->type == SOM_TABLE)
111 t->class->flags (&flags);
112 t->class->count (&nc, &nr);
113 t->class->headers (&hl, &hr, &ht, &hb);
117 if (hl + hr > nc || ht + hb > nr)
119 printf ("headers: (l,r)=(%d,%d), (t,b)=(%d,%d) in table size (%d,%d)\n",
120 hl, hr, ht, hb, nc, nr);
123 else if (hl + hr == nc)
124 printf ("warning: headers (l,r)=(%d,%d) in table width %d\n", hl, hr, nc);
125 else if (ht + hb == nr)
126 printf ("warning: headers (t,b)=(%d,%d) in table height %d\n", ht, hb, nr);
129 t->class->columns (&cs);
131 if (!(flags & SOMF_NO_TITLE))
137 struct outp_driver *d;
139 for (d = outp_drivers (NULL); d; d = outp_drivers (d))
140 output_entity (d, t);
145 assert (--entry == 0);
149 /* Output entity ENTITY to driver DRIVER. */
151 output_entity (struct outp_driver *driver, struct som_entity *entity)
153 bool fits_width, fits_length;
157 if (d->class->special || entity->type == SOM_CHART)
159 driver->class->submit (d, entity);
165 t->class->driver (d);
166 t->class->area (&tw, &th);
167 fits_width = t->class->fits_width (d->width);
168 fits_length = t->class->fits_length (d->length);
169 if (!fits_width || !fits_length)
172 tl = fits_width ? hl : 0;
173 tr = fits_width ? hr : 0;
174 tt = fits_length ? ht : 0;
175 tb = fits_length ? hb : 0;
176 t->class->set_headers (tl, tr, tt, tb);
177 t->class->driver (d);
178 t->class->area (&tw, &th);
181 if (!(flags & SOMF_NO_SPACING) && d->cp_y != 0)
182 d->cp_y += d->font_height;
184 if (cs != SOM_COL_NONE
185 && 2 * (tw + d->prop_em_width) <= d->width
186 && nr - (ht + hb) > 5)
188 else if (tw < d->width && th + d->cp_y < d->length)
193 t->class->set_headers (hl, hr, ht, hb);
196 /* Render the table into multiple columns. */
198 render_columns (void)
204 assert (cs == SOM_COL_DOWN);
205 assert (d->cp_x == 0);
207 for (y0 = ht; y0 < nr - hb; y0 = y1)
211 t->class->cumulate (SOM_ROWS, y0, &y1, d->length - d->cp_y, &len);
223 t->class->title (index++, 0);
224 t->class->render (0, y0, nc, y1);
226 d->cp_x += tw + 2 * d->prop_em_width;
227 if (d->cp_x + tw > d->width)
243 /* Render the table by itself on the current page. */
247 assert (d->cp_x == 0);
248 assert (tw < d->width && th + d->cp_y < d->length);
250 t->class->title (0, 0);
251 t->class->render (hl, ht, nc - hr, nr - hb);
255 /* General table breaking routine. */
257 render_segments (void)
264 assert (d->cp_x == 0);
266 for (x_index = 0, x0 = hl; x0 < nc - hr; x0 = x1, x_index++)
271 t->class->cumulate (SOM_COLUMNS, x0, &x1, d->width, NULL);
272 if (x_index == 0 && x1 != nc - hr)
275 for (y_index = 0, y0 = ht; y0 < nr - hb; y0 = y1, y_index++)
279 if (count++ != 0 && d->cp_y != 0)
280 d->cp_y += d->font_height;
282 t->class->cumulate (SOM_ROWS, y0, &y1, d->length - d->cp_y, &len);
283 if (y_index == 0 && y1 != nr - hb)
293 t->class->title (x_index ? x_index : y_index,
294 x_index ? y_index : 0);
295 t->class->render (x0, y0, x1, y1);