Blame grid.c

Packit 4d380f
#include "config.h"
Packit 4d380f
Packit 4d380f
#ifdef HAVE_ALLOCA_H
Packit 4d380f
#include <alloca.h>
Packit 4d380f
#endif
Packit 4d380f
#include <stdlib.h>
Packit 4d380f
#include <string.h>
Packit 4d380f
Packit 4d380f
#include "newt.h"
Packit 4d380f
#include "newt_pr.h"
Packit 4d380f
Packit 4d380f
struct gridField {
Packit 4d380f
    enum newtGridElement type;
Packit 4d380f
    union {
Packit 4d380f
	newtGrid grid;
Packit 4d380f
	newtComponent co;
Packit 4d380f
    } u;
Packit 4d380f
    int padLeft, padTop, padRight, padBottom;
Packit 4d380f
    int anchor;
Packit 4d380f
    int flags;
Packit 4d380f
}; 
Packit 4d380f
Packit 4d380f
struct grid_s {
Packit 4d380f
    int rows, cols;
Packit 4d380f
    int width, height;		/* totals, -1 means unknown */
Packit 4d380f
    struct gridField ** fields;
Packit 4d380f
};
Packit 4d380f
Packit 4d380f
/* this is a bit of a hack */
Packit 4d380f
extern struct componentOps formOps[];
Packit 4d380f
Packit 4d380f
newtGrid newtCreateGrid(int cols, int rows) {
Packit 4d380f
    newtGrid grid;
Packit 4d380f
Packit 4d380f
    grid = malloc(sizeof(*grid));
Packit 4d380f
    grid->rows = rows;
Packit 4d380f
    grid->cols = cols;
Packit 4d380f
Packit 4d380f
    grid->fields = malloc(sizeof(*grid->fields) * cols);
Packit 4d380f
    while (cols--) {
Packit 4d380f
	grid->fields[cols] = malloc(sizeof(**(grid->fields)) * rows);
Packit 4d380f
	memset(grid->fields[cols], 0, sizeof(**(grid->fields)) * rows);
Packit 4d380f
    }
Packit 4d380f
Packit 4d380f
    grid->width = grid->height = -1;
Packit 4d380f
Packit 4d380f
    return grid;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
void newtGridSetField(newtGrid grid, int col, int row, 
Packit 4d380f
		      enum newtGridElement type, void * val, int padLeft,
Packit 4d380f
		      int padTop, int padRight, int padBottom, int anchor,
Packit 4d380f
		      int flags) {
Packit 4d380f
    struct gridField * field = &grid->fields[col][row];
Packit 4d380f
Packit 4d380f
    if (field->type == NEWT_GRID_SUBGRID) 
Packit 4d380f
	newtGridFree(field->u.grid, 1);
Packit 4d380f
Packit 4d380f
    field->type = type;
Packit 4d380f
    field->u.co = (void *) val;
Packit 4d380f
Packit 4d380f
    field->padLeft = padLeft;
Packit 4d380f
    field->padRight = padRight;
Packit 4d380f
    field->padTop = padTop;
Packit 4d380f
    field->padBottom = padBottom;
Packit 4d380f
    field->anchor = anchor;
Packit 4d380f
    field->flags = flags;
Packit 4d380f
Packit 4d380f
    grid->width = grid->height = -1;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
static void distSpace(int extra, int items, int * list) {
Packit 4d380f
    int all, some, i;
Packit 4d380f
Packit 4d380f
    all = extra / items;
Packit 4d380f
    some = extra % items;
Packit 4d380f
    for (i = 0; i < items; i++) {
Packit 4d380f
	list[i] += all;
Packit 4d380f
	if (some) {
Packit 4d380f
	    list[i]++;
Packit 4d380f
	    some--;
Packit 4d380f
	}
Packit 4d380f
    }
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
static void shuffleGrid(newtGrid grid, int left, int top, int set) {
Packit 4d380f
    struct gridField * field;
Packit 4d380f
    int row, col;
Packit 4d380f
    int i, j;
Packit 4d380f
    int minWidth, minHeight;
Packit 4d380f
    int * widths, * heights;
Packit 4d380f
    int thisLeft, thisTop;
Packit 4d380f
    int x, y, remx, remy;
Packit 4d380f
Packit 4d380f
    widths = alloca(sizeof(*widths) * grid->cols);
Packit 4d380f
    memset(widths, 0, sizeof(*widths) * grid->cols);
Packit 4d380f
    heights = alloca(sizeof(*heights) * grid->rows);
Packit 4d380f
    memset(heights, 0, sizeof(*heights) * grid->rows);
Packit 4d380f
Packit 4d380f
    minWidth = 0;
Packit 4d380f
    for (row = 0; row < grid->rows; row++) {
Packit 4d380f
	i = 0;
Packit 4d380f
	for (col = 0; col < grid->cols; col++) {
Packit 4d380f
	    field = &grid->fields[col][row];
Packit 4d380f
	    if (field->type == NEWT_GRID_SUBGRID) {
Packit 4d380f
		/* we'll have to redo this later */
Packit 4d380f
		if (field->u.grid->width == -1) 
Packit 4d380f
		    shuffleGrid(field->u.grid, left, top, 0);
Packit 4d380f
		j = field->u.grid->width;
Packit 4d380f
	    } else if (field->type == NEWT_GRID_COMPONENT) {
Packit 4d380f
		if (field->u.co->ops == formOps)
Packit 4d380f
		    newtFormSetSize(field->u.co);
Packit 4d380f
		j = field->u.co->width;
Packit 4d380f
	    } else 
Packit 4d380f
		j = 0;
Packit 4d380f
Packit 4d380f
	    j += field->padLeft + field->padRight;
Packit 4d380f
Packit 4d380f
	    if (j > widths[col]) widths[col] = j;
Packit 4d380f
	    i += widths[col];
Packit 4d380f
	}
Packit 4d380f
Packit 4d380f
	if (i > minWidth) minWidth = i;
Packit 4d380f
    }
Packit 4d380f
Packit 4d380f
    minHeight = 0;
Packit 4d380f
    for (col = 0; col < grid->cols; col++) {
Packit 4d380f
	i = 0;
Packit 4d380f
	for (row = 0; row < grid->rows; row++) {
Packit 4d380f
	    field = &grid->fields[col][row];
Packit 4d380f
	    if (field->type == NEWT_GRID_SUBGRID) {
Packit 4d380f
		/* we'll have to redo this later */
Packit 4d380f
		if (field->u.grid->height == -1) 
Packit 4d380f
		    shuffleGrid(field->u.grid, 0, 0, 0);
Packit 4d380f
		j = field->u.grid->height;
Packit 4d380f
	    } else if (field->type == NEWT_GRID_COMPONENT){
Packit 4d380f
		j = field->u.co->height;
Packit 4d380f
	    } else 
Packit 4d380f
		j = 0;
Packit 4d380f
Packit 4d380f
	    j += field->padTop + field->padBottom;
Packit 4d380f
Packit 4d380f
	    if (j > heights[row]) heights[row] = j;
Packit 4d380f
	    i += heights[row];
Packit 4d380f
	}
Packit 4d380f
Packit 4d380f
	if (i > minHeight) minHeight = i;
Packit 4d380f
    }
Packit 4d380f
Packit 4d380f
    /* this catches the -1 case */
Packit 4d380f
    if (grid->width < minWidth) grid->width = minWidth;		/* ack! */
Packit 4d380f
    if (grid->height < minHeight) grid->height = minHeight;	/* ditto! */
Packit 4d380f
Packit 4d380f
    if (!set) return;
Packit 4d380f
Packit 4d380f
    distSpace(grid->width - minWidth, grid->cols, widths);
Packit 4d380f
    distSpace(grid->height - minHeight, grid->rows, heights);
Packit 4d380f
Packit 4d380f
    thisTop = top;
Packit 4d380f
    for (row = 0; row < grid->rows; row++) {
Packit 4d380f
	i = 0;
Packit 4d380f
	thisLeft = left;
Packit 4d380f
	for (col = 0; col < grid->cols; col++) {
Packit 4d380f
	    field = &grid->fields[col][row];
Packit 4d380f
Packit 4d380f
	    if (field->type == NEWT_GRID_EMPTY) continue;
Packit 4d380f
Packit 4d380f
	    x = thisLeft + field->padLeft;
Packit 4d380f
	    remx = widths[col] - field->padLeft - field->padRight;
Packit 4d380f
	    y = thisTop + field->padTop;
Packit 4d380f
	    remy = heights[row] - field->padTop - field->padBottom;
Packit 4d380f
Packit 4d380f
	    if (field->type == NEWT_GRID_SUBGRID) {
Packit 4d380f
		remx -= field->u.grid->width;
Packit 4d380f
		remy -= field->u.grid->height;
Packit 4d380f
	    } else if (field->type == NEWT_GRID_COMPONENT) {
Packit 4d380f
		remx -= field->u.co->width;
Packit 4d380f
		remy -= field->u.co->height;
Packit 4d380f
	    }
Packit 4d380f
Packit 4d380f
	    if (!(field->flags & NEWT_GRID_FLAG_GROWX)) {
Packit 4d380f
		if (field->anchor & NEWT_ANCHOR_RIGHT)
Packit 4d380f
		    x += remx;
Packit 4d380f
		else if (!(field->anchor & NEWT_ANCHOR_LEFT))
Packit 4d380f
		    x += (remx / 2);
Packit 4d380f
	    }
Packit 4d380f
	 
Packit 4d380f
	    if (!(field->flags & NEWT_GRID_FLAG_GROWY)) {
Packit 4d380f
		if (field->anchor & NEWT_ANCHOR_BOTTOM)
Packit 4d380f
		    y += remx;
Packit 4d380f
		else if (!(field->anchor & NEWT_ANCHOR_TOP))
Packit 4d380f
		    y += (remy / 2);
Packit 4d380f
	    }
Packit 4d380f
Packit 4d380f
	    if (field->type == NEWT_GRID_SUBGRID) {
Packit 4d380f
		if (field->flags & NEWT_GRID_FLAG_GROWX)
Packit 4d380f
		    field->u.grid->width = widths[col] - field->padLeft 
Packit 4d380f
						- field->padRight;
Packit 4d380f
		if (field->flags & NEWT_GRID_FLAG_GROWY)
Packit 4d380f
		    field->u.grid->height = heights[col] - field->padTop
Packit 4d380f
						- field->padBottom;
Packit 4d380f
Packit 4d380f
		shuffleGrid(field->u.grid, x, y, 1);
Packit 4d380f
	    } else if (field->type == NEWT_GRID_COMPONENT) {
Packit 4d380f
		field->u.co->ops->place(field->u.co, x, y);
Packit 4d380f
	    }
Packit 4d380f
Packit 4d380f
	    thisLeft += widths[col];
Packit 4d380f
	}
Packit 4d380f
Packit 4d380f
	thisTop += heights[row];
Packit 4d380f
    }
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
void newtGridPlace(newtGrid grid, int left, int top) {
Packit 4d380f
    shuffleGrid(grid, left, top, 1);
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
void newtGridFree(newtGrid grid, int recurse) {
Packit 4d380f
    int row, col;
Packit 4d380f
Packit 4d380f
    for (col = 0; col < grid->cols; col++) {
Packit 4d380f
	if (recurse) {
Packit 4d380f
	    for (row = 0; row < grid->rows; row++) {
Packit 4d380f
		if (grid->fields[col][row].type == NEWT_GRID_SUBGRID)
Packit 4d380f
		    newtGridFree(grid->fields[col][row].u.grid, 1);
Packit 4d380f
	    }
Packit 4d380f
	}
Packit 4d380f
Packit 4d380f
	free(grid->fields[col]);
Packit 4d380f
    }
Packit 4d380f
Packit 4d380f
    free(grid->fields);
Packit 4d380f
    free(grid);
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
void newtGridGetSize(newtGrid grid, int * width, int * height) {
Packit 4d380f
    if (grid->width == -1 || grid->height == -1) {
Packit 4d380f
	grid->width = grid->height = -1;
Packit 4d380f
	shuffleGrid(grid, 0, 0, 1);
Packit 4d380f
    }
Packit 4d380f
Packit 4d380f
    *width = grid->width;
Packit 4d380f
    *height = grid->height;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
void newtGridWrappedWindow(newtGrid grid, char * title) {
Packit 4d380f
    int w, width, height, offset = 0;
Packit 4d380f
Packit 4d380f
    newtGridGetSize(grid, &width, &height);
Packit 4d380f
    w = wstrlen(title,-1);
Packit 4d380f
    if (width < w + 2) {
Packit 4d380f
	offset = ((w + 2) - width) / 2; 
Packit 4d380f
	width = w + 2;
Packit 4d380f
    }
Packit 4d380f
    newtCenteredWindow(width + 2, height + 2, title);
Packit 4d380f
    newtGridPlace(grid, 1 + offset, 1);
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
void newtGridWrappedWindowAt(newtGrid grid, char * title, int left, int top) {
Packit 4d380f
    int width, height;
Packit 4d380f
Packit 4d380f
    newtGridGetSize(grid, &width, &height);
Packit 4d380f
    newtOpenWindow(left, top, width + 2, height + 2, title);
Packit 4d380f
    newtGridPlace(grid, 1, 1);
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
void newtGridAddComponentsToForm(newtGrid grid, newtComponent form, 
Packit 4d380f
				 int recurse) {
Packit 4d380f
    int row, col;
Packit 4d380f
Packit 4d380f
    for (col = 0; col < grid->cols; col++) {
Packit 4d380f
	for (row = 0; row < grid->rows; row++) {
Packit 4d380f
	    if (grid->fields[col][row].type == NEWT_GRID_SUBGRID && recurse)
Packit 4d380f
		newtGridAddComponentsToForm(grid->fields[col][row].u.grid,
Packit 4d380f
					    form, 1);
Packit 4d380f
	    else if (grid->fields[col][row].type == NEWT_GRID_COMPONENT)
Packit 4d380f
		newtFormAddComponent(form, grid->fields[col][row].u.co);
Packit 4d380f
	}
Packit 4d380f
    }
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
/* this handles up to 50 items */
Packit 4d380f
static newtGrid stackem(int isVert, enum newtGridElement type1, void * what1,
Packit 4d380f
			va_list args, int close) {
Packit 4d380f
    struct item {
Packit 4d380f
	enum newtGridElement type;
Packit 4d380f
	void * what;
Packit 4d380f
    } items[50];
Packit 4d380f
    int i, num;
Packit 4d380f
    newtGrid grid;
Packit 4d380f
    
Packit 4d380f
    items[0].type = type1, items[0].what = what1, num = 1;
Packit 4d380f
    while (1) {
Packit 4d380f
	items[num].type = va_arg(args, enum newtGridElement);
Packit 4d380f
	if (items[num].type == NEWT_GRID_EMPTY) break;
Packit 4d380f
Packit 4d380f
	items[num].what = va_arg(args, void *);
Packit 4d380f
	num++;
Packit 4d380f
    }
Packit 4d380f
Packit 4d380f
    grid = newtCreateGrid(isVert ? 1 : num, isVert ? num : 1);
Packit 4d380f
Packit 4d380f
    for (i = 0; i < num; i++) {
Packit 4d380f
	newtGridSetField(grid, isVert ? 0 : i, isVert ? i : 0, 
Packit 4d380f
			 items[i].type, items[i].what,
Packit 4d380f
			 close ? 0 : (i ? (isVert ? 0 : 1) : 0),
Packit 4d380f
			 close ? 0 : (i ? (isVert ? 1 : 0) : 0), 0, 0, 0, 0);
Packit 4d380f
    }
Packit 4d380f
Packit 4d380f
    return grid;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
newtGrid newtGridHCloseStacked(enum newtGridElement type1, void * what1, ...) {
Packit 4d380f
    va_list args;
Packit 4d380f
    newtGrid grid;
Packit 4d380f
Packit 4d380f
    va_start(args, what1);
Packit 4d380f
Packit 4d380f
    grid = stackem(0, type1, what1, args, 1);
Packit 4d380f
Packit 4d380f
    va_end(args);
Packit 4d380f
Packit 4d380f
    return grid;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
newtGrid newtGridVCloseStacked(enum newtGridElement type1, void * what1, ...) {
Packit 4d380f
    va_list args;
Packit 4d380f
    newtGrid grid;
Packit 4d380f
Packit 4d380f
    va_start(args, what1);
Packit 4d380f
Packit 4d380f
    grid = stackem(1, type1, what1, args, 1);
Packit 4d380f
Packit 4d380f
    va_end(args);
Packit 4d380f
Packit 4d380f
    return grid;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
newtGrid newtGridVStacked(enum newtGridElement type1, void * what1, ...) {
Packit 4d380f
    va_list args;
Packit 4d380f
    newtGrid grid;
Packit 4d380f
Packit 4d380f
    va_start(args, what1);
Packit 4d380f
Packit 4d380f
    grid = stackem(1, type1, what1, args, 0);
Packit 4d380f
Packit 4d380f
    va_end(args);
Packit 4d380f
Packit 4d380f
    return grid;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
newtGrid newtGridHStacked(enum newtGridElement type1, void * what1, ...) {
Packit 4d380f
    va_list args;
Packit 4d380f
    newtGrid grid;
Packit 4d380f
Packit 4d380f
    va_start(args, what1);
Packit 4d380f
Packit 4d380f
    grid = stackem(0, type1, what1, args, 0);
Packit 4d380f
Packit 4d380f
    va_end(args);
Packit 4d380f
Packit 4d380f
    return grid;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
newtGrid newtGridBasicWindow(newtComponent text, newtGrid middle,
Packit 4d380f
			     newtGrid buttons) {
Packit 4d380f
    newtGrid grid;
Packit 4d380f
Packit 4d380f
    grid = newtCreateGrid(1, 3);
Packit 4d380f
    newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
Packit 4d380f
		     0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
Packit 4d380f
    newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, middle,
Packit 4d380f
		     0, 1, 0, 0, 0, 0);
Packit 4d380f
    newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
Packit 4d380f
		     0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
Packit 4d380f
Packit 4d380f
    return grid;
Packit 4d380f
}
Packit 4d380f
Packit 4d380f
newtGrid newtGridSimpleWindow(newtComponent text, newtComponent middle,
Packit 4d380f
			     newtGrid buttons) {
Packit 4d380f
    newtGrid grid;
Packit 4d380f
Packit 4d380f
    grid = newtCreateGrid(1, 3);
Packit 4d380f
    newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
Packit 4d380f
		     0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
Packit 4d380f
    newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, middle,
Packit 4d380f
		     0, 1, 0, 0, 0, 0);
Packit 4d380f
    newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
Packit 4d380f
		     0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
Packit 4d380f
Packit 4d380f
    return grid;
Packit 4d380f
}