]> git.ipfire.org Git - thirdparty/newt.git/blob - grid.c
install python modules to purelib and platlib
[thirdparty/newt.git] / grid.c
1 #include "config.h"
2
3 #ifdef HAVE_ALLOCA_H
4 #include <alloca.h>
5 #endif
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include "newt.h"
10 #include "newt_pr.h"
11
12 struct gridField {
13 enum newtGridElement type;
14 union {
15 newtGrid grid;
16 newtComponent co;
17 } u;
18 int padLeft, padTop, padRight, padBottom;
19 int anchor;
20 int flags;
21 };
22
23 struct grid_s {
24 int rows, cols;
25 int width, height; /* totals, -1 means unknown */
26 struct gridField ** fields;
27 };
28
29 /* this is a bit of a hack */
30 extern struct componentOps formOps[];
31
32 newtGrid newtCreateGrid(int cols, int rows) {
33 newtGrid grid;
34
35 grid = malloc(sizeof(*grid));
36 grid->rows = rows;
37 grid->cols = cols;
38
39 grid->fields = malloc(sizeof(*grid->fields) * cols);
40 while (cols--) {
41 grid->fields[cols] = malloc(sizeof(**(grid->fields)) * rows);
42 memset(grid->fields[cols], 0, sizeof(**(grid->fields)) * rows);
43 }
44
45 grid->width = grid->height = -1;
46
47 return grid;
48 }
49
50 void newtGridSetField(newtGrid grid, int col, int row,
51 enum newtGridElement type, void * val, int padLeft,
52 int padTop, int padRight, int padBottom, int anchor,
53 int flags) {
54 struct gridField * field = &grid->fields[col][row];
55
56 if (field->type == NEWT_GRID_SUBGRID)
57 newtGridFree(field->u.grid, 1);
58
59 field->type = type;
60 field->u.co = (void *) val;
61
62 field->padLeft = padLeft;
63 field->padRight = padRight;
64 field->padTop = padTop;
65 field->padBottom = padBottom;
66 field->anchor = anchor;
67 field->flags = flags;
68
69 grid->width = grid->height = -1;
70 }
71
72 static void distSpace(int extra, int items, int * list) {
73 int all, some, i;
74
75 all = extra / items;
76 some = extra % items;
77 for (i = 0; i < items; i++) {
78 list[i] += all;
79 if (some) {
80 list[i]++;
81 some--;
82 }
83 }
84 }
85
86 static void shuffleGrid(newtGrid grid, int left, int top, int set) {
87 struct gridField * field;
88 int row, col;
89 int i, j;
90 int minWidth, minHeight;
91 int * widths, * heights;
92 int thisLeft, thisTop;
93 int x, y, remx, remy;
94
95 widths = alloca(sizeof(*widths) * grid->cols);
96 memset(widths, 0, sizeof(*widths) * grid->cols);
97 heights = alloca(sizeof(*heights) * grid->rows);
98 memset(heights, 0, sizeof(*heights) * grid->rows);
99
100 minWidth = 0;
101 for (row = 0; row < grid->rows; row++) {
102 i = 0;
103 for (col = 0; col < grid->cols; col++) {
104 field = &grid->fields[col][row];
105 if (field->type == NEWT_GRID_SUBGRID) {
106 /* we'll have to redo this later */
107 if (field->u.grid->width == -1)
108 shuffleGrid(field->u.grid, left, top, 0);
109 j = field->u.grid->width;
110 } else if (field->type == NEWT_GRID_COMPONENT) {
111 if (field->u.co->ops == formOps)
112 newtFormSetSize(field->u.co);
113 j = field->u.co->width;
114 } else
115 j = 0;
116
117 j += field->padLeft + field->padRight;
118
119 if (j > widths[col]) widths[col] = j;
120 i += widths[col];
121 }
122
123 if (i > minWidth) minWidth = i;
124 }
125
126 minHeight = 0;
127 for (col = 0; col < grid->cols; col++) {
128 i = 0;
129 for (row = 0; row < grid->rows; row++) {
130 field = &grid->fields[col][row];
131 if (field->type == NEWT_GRID_SUBGRID) {
132 /* we'll have to redo this later */
133 if (field->u.grid->height == -1)
134 shuffleGrid(field->u.grid, 0, 0, 0);
135 j = field->u.grid->height;
136 } else if (field->type == NEWT_GRID_COMPONENT){
137 j = field->u.co->height;
138 } else
139 j = 0;
140
141 j += field->padTop + field->padBottom;
142
143 if (j > heights[row]) heights[row] = j;
144 i += heights[row];
145 }
146
147 if (i > minHeight) minHeight = i;
148 }
149
150 /* this catches the -1 case */
151 if (grid->width < minWidth) grid->width = minWidth; /* ack! */
152 if (grid->height < minHeight) grid->height = minHeight; /* ditto! */
153
154 if (!set) return;
155
156 distSpace(grid->width - minWidth, grid->cols, widths);
157 distSpace(grid->height - minHeight, grid->rows, heights);
158
159 thisTop = top;
160 for (row = 0; row < grid->rows; row++) {
161 thisLeft = left;
162 for (col = 0; col < grid->cols; col++) {
163 field = &grid->fields[col][row];
164
165 if (field->type == NEWT_GRID_EMPTY) continue;
166
167 x = thisLeft + field->padLeft;
168 remx = widths[col] - field->padLeft - field->padRight;
169 y = thisTop + field->padTop;
170 remy = heights[row] - field->padTop - field->padBottom;
171
172 if (field->type == NEWT_GRID_SUBGRID) {
173 remx -= field->u.grid->width;
174 remy -= field->u.grid->height;
175 } else if (field->type == NEWT_GRID_COMPONENT) {
176 remx -= field->u.co->width;
177 remy -= field->u.co->height;
178 }
179
180 if (!(field->flags & NEWT_GRID_FLAG_GROWX)) {
181 if (field->anchor & NEWT_ANCHOR_RIGHT)
182 x += remx;
183 else if (!(field->anchor & NEWT_ANCHOR_LEFT))
184 x += (remx / 2);
185 }
186
187 if (!(field->flags & NEWT_GRID_FLAG_GROWY)) {
188 if (field->anchor & NEWT_ANCHOR_BOTTOM)
189 y += remx;
190 else if (!(field->anchor & NEWT_ANCHOR_TOP))
191 y += (remy / 2);
192 }
193
194 if (field->type == NEWT_GRID_SUBGRID) {
195 if (field->flags & NEWT_GRID_FLAG_GROWX)
196 field->u.grid->width = widths[col] - field->padLeft
197 - field->padRight;
198 if (field->flags & NEWT_GRID_FLAG_GROWY)
199 field->u.grid->height = heights[col] - field->padTop
200 - field->padBottom;
201
202 shuffleGrid(field->u.grid, x, y, 1);
203 } else if (field->type == NEWT_GRID_COMPONENT) {
204 field->u.co->ops->place(field->u.co, x, y);
205 }
206
207 thisLeft += widths[col];
208 }
209
210 thisTop += heights[row];
211 }
212 }
213
214 void newtGridPlace(newtGrid grid, int left, int top) {
215 shuffleGrid(grid, left, top, 1);
216 }
217
218 void newtGridFree(newtGrid grid, int recurse) {
219 int row, col;
220
221 for (col = 0; col < grid->cols; col++) {
222 if (recurse) {
223 for (row = 0; row < grid->rows; row++) {
224 if (grid->fields[col][row].type == NEWT_GRID_SUBGRID)
225 newtGridFree(grid->fields[col][row].u.grid, 1);
226 }
227 }
228
229 free(grid->fields[col]);
230 }
231
232 free(grid->fields);
233 free(grid);
234 }
235
236 void newtGridGetSize(newtGrid grid, int * width, int * height) {
237 if (grid->width == -1 || grid->height == -1) {
238 grid->width = grid->height = -1;
239 shuffleGrid(grid, 0, 0, 1);
240 }
241
242 *width = grid->width;
243 *height = grid->height;
244 }
245
246 void newtGridWrappedWindow(newtGrid grid, char * title) {
247 int w, width, height, offset = 0;
248
249 newtGridGetSize(grid, &width, &height);
250 w = wstrlen(title,-1);
251 if (width < w + 2) {
252 offset = ((w + 2) - width) / 2;
253 width = w + 2;
254 }
255 newtCenteredWindow(width + 2, height + 2, title);
256 newtGridPlace(grid, 1 + offset, 1);
257 }
258
259 void newtGridWrappedWindowAt(newtGrid grid, char * title, int left, int top) {
260 int width, height;
261
262 newtGridGetSize(grid, &width, &height);
263 newtOpenWindow(left, top, width + 2, height + 2, title);
264 newtGridPlace(grid, 1, 1);
265 }
266
267 void newtGridAddComponentsToForm(newtGrid grid, newtComponent form,
268 int recurse) {
269 int row, col;
270
271 for (col = 0; col < grid->cols; col++) {
272 for (row = 0; row < grid->rows; row++) {
273 if (grid->fields[col][row].type == NEWT_GRID_SUBGRID && recurse)
274 newtGridAddComponentsToForm(grid->fields[col][row].u.grid,
275 form, 1);
276 else if (grid->fields[col][row].type == NEWT_GRID_COMPONENT)
277 newtFormAddComponent(form, grid->fields[col][row].u.co);
278 }
279 }
280 }
281
282 /* this handles up to 50 items */
283 static newtGrid stackem(int isVert, enum newtGridElement type1, void * what1,
284 va_list args, int close) {
285 struct item {
286 enum newtGridElement type;
287 void * what;
288 } items[50];
289 int i, num;
290 newtGrid grid;
291
292 items[0].type = type1, items[0].what = what1, num = 1;
293 while (1) {
294 items[num].type = va_arg(args, enum newtGridElement);
295 if (items[num].type == NEWT_GRID_EMPTY) break;
296
297 items[num].what = va_arg(args, void *);
298 num++;
299 }
300
301 grid = newtCreateGrid(isVert ? 1 : num, isVert ? num : 1);
302
303 for (i = 0; i < num; i++) {
304 newtGridSetField(grid, isVert ? 0 : i, isVert ? i : 0,
305 items[i].type, items[i].what,
306 close ? 0 : (i ? (isVert ? 0 : 1) : 0),
307 close ? 0 : (i ? (isVert ? 1 : 0) : 0), 0, 0, 0, 0);
308 }
309
310 return grid;
311 }
312
313 newtGrid newtGridHCloseStacked(enum newtGridElement type1, void * what1, ...) {
314 va_list args;
315 newtGrid grid;
316
317 va_start(args, what1);
318
319 grid = stackem(0, type1, what1, args, 1);
320
321 va_end(args);
322
323 return grid;
324 }
325
326 newtGrid newtGridVCloseStacked(enum newtGridElement type1, void * what1, ...) {
327 va_list args;
328 newtGrid grid;
329
330 va_start(args, what1);
331
332 grid = stackem(1, type1, what1, args, 1);
333
334 va_end(args);
335
336 return grid;
337 }
338
339 newtGrid newtGridVStacked(enum newtGridElement type1, void * what1, ...) {
340 va_list args;
341 newtGrid grid;
342
343 va_start(args, what1);
344
345 grid = stackem(1, type1, what1, args, 0);
346
347 va_end(args);
348
349 return grid;
350 }
351
352 newtGrid newtGridHStacked(enum newtGridElement type1, void * what1, ...) {
353 va_list args;
354 newtGrid grid;
355
356 va_start(args, what1);
357
358 grid = stackem(0, type1, what1, args, 0);
359
360 va_end(args);
361
362 return grid;
363 }
364
365 newtGrid newtGridBasicWindow(newtComponent text, newtGrid middle,
366 newtGrid buttons) {
367 newtGrid grid;
368
369 grid = newtCreateGrid(1, 3);
370 newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
371 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
372 newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, middle,
373 0, 1, 0, 0, 0, 0);
374 newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
375 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
376
377 return grid;
378 }
379
380 newtGrid newtGridSimpleWindow(newtComponent text, newtComponent middle,
381 newtGrid buttons) {
382 newtGrid grid;
383
384 grid = newtCreateGrid(1, 3);
385 newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
386 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
387 newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, middle,
388 0, 1, 0, 0, 0, 0);
389 newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
390 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
391
392 return grid;
393 }