[add x3common files
raph.levien@gmail.com**20060610052318] {
addfile ./x3common.c
hunk ./x3common.c 1
+/* Functions common to more than one platform. */
+
+#include "x3.h"
+#include "x3common.h"
+
+#if defined(X3_CARBON) || defined(X3_WIN32)
+
+int n_x3needsizereqs;
+int n_x3needsizereqs_max;
+x3widget **x3needsizereqs;
+
+int n_x3needsizeallocs;
+int n_x3needsizeallocs_max;
+x3widget **x3needsizeallocs;
+
+void x3initqs(void)
+{
+    n_x3needsizereqs = 0;
+    x3needsizereqs = (x3widget **)malloc(sizeof(x3widget *) *
+					 (n_x3needsizereqs_max = 16));
+
+    n_x3needsizeallocs = 0;
+    x3needsizeallocs = (x3widget **)malloc(sizeof(x3widget *) *
+					   (n_x3needsizeallocs_max = 16));
+}
+
+void x3qsizereq(x3widget *w)
+{
+    if (w && !(w->flags & x3flag_needsizereq)) {
+	x3qsizereq(w->parent);
+	if (n_x3needsizereqs == n_x3needsizereqs_max)
+	    x3needsizereqs = (x3widget **)realloc(x3needsizereqs,
+						  sizeof(x3widget *) *
+						  (n_x3needsizereqs_max <<= 1));
+	x3needsizereqs[n_x3needsizereqs++] = w;
+	w->flags |= x3flag_needsizereq;
+    }
+}
+
+/* Widgets common to carbon and win32 platforms */
+
+typedef struct {
+    x3widget base;
+    int homogeneous;
+    int spacing;
+    int cur_child_prop;
+    int *child_props; /* bit 0=expand, bit 1=fill, bits 2:31=padding */
+} x3widget_box;
+
+void x3vbox_sizereq(x3widget *w)
+{
+    x3widget_box *wb = (x3widget_box *)w;
+    int i;
+    int spacing = wb->spacing;
+
+    w->sizerequest.left = 0;
+    w->sizerequest.top = 0;
+    w->sizerequest.right = 0;
+    w->sizerequest.bottom = 0;
+    for (i = 0; i < w->n_children; i++) {
+	x3widget *child = w->children[i];
+	int childw = child->sizerequest.right - child->sizerequest.left;
+	int childh = child->sizerequest.bottom - child->sizerequest.top;
+	int padding = wb->child_props[i] >> 2;
+
+	if (i < w->n_children - 1)
+	    childh += spacing;
+	w->sizerequest.bottom += childh + 2 * padding;
+	if (childw > w->sizerequest.right)
+	    w->sizerequest.right = childw;
+    }
+}
+
+void x3vbox_sizealloc(x3widget *w, Rect *r)
+{
+    x3widget_box *wb = (x3widget_box *)w;
+    int i;
+    Rect child_r = *r;
+    int spacing = wb->spacing;
+    int n_extend = 0;
+    int n_stretch, i_stretch = 0;
+    int extra;
+
+    /* todo: impl padding & homog, factor hbox/vbox common */
+    printf("vbox sizealloc = (%d, %d) - (%d, %d), req was %d x %d\n",
+	   r->left, r->top, r->right, r->bottom,
+	   w->sizerequest.right, w->sizerequest.bottom);
+    extra = r->bottom - r->top - w->sizerequest.bottom;
+    for (i = 0; i < w->n_children; i++)
+	if (wb->child_props[i] & 1)
+	    n_extend++;
+    n_stretch = n_extend ? n_extend : w->n_children;
+    printf("extra = %d, n_stretch = %d\n", extra, n_stretch);
+    for (i = 0; i < w->n_children; i++) {
+	x3widget *child = w->children[i];
+	int childh = child->sizerequest.bottom - child->sizerequest.top;
+	int my_extra;
+	int next_top;
+
+	if (n_extend == 0 || (wb->child_props[i] & 1)) {
+	    my_extra = (extra * (i_stretch + 1)) / n_stretch -
+		(extra * i_stretch) / n_stretch;
+	    i_stretch++;
+	} else
+	    my_extra = 0;
+	next_top = child_r.top + childh + spacing + my_extra;
+
+	if (wb->child_props[i] & 2) {
+	    childh += my_extra;
+	} else {
+	    child_r.top += my_extra >> 1;
+	}
+	child_r.bottom = child_r.top + childh;
+
+	child->type->sizealloc(child, &child_r);
+	child->flags &= ~x3flag_needsizealloc;
+
+	child_r.top = next_top;
+    }
+}
+
+void x3vbox_add(x3widget *w, x3widget *child)
+{
+    x3widget_box *wb = (x3widget_box *)w;
+    const int n_children_init = 4;
+
+    if (w->n_children == 0)
+	wb->child_props = (int *)malloc(sizeof(int) * n_children_init);
+    else if (w->n_children >= n_children_init &&
+	     !(w->n_children & (w->n_children - 1)))
+	wb->child_props = (int *)realloc(wb->child_props,
+					 sizeof(int) * (w->n_children << 1));
+    wb->child_props[w->n_children] = wb->cur_child_prop;
+    x3add_default(w, child);
+}
+
+x3type x3vboxtype = { x3vbox_sizereq,
+		      x3vbox_sizealloc,
+		      x3vbox_add };
+
+x3widget *x3vbox(x3widget *parent, int homogeneous, int spacing)
+{
+    x3widget_box *result = (x3widget_box *)malloc(sizeof(x3widget_box));
+    x3widget_init(&result->base, &x3vboxtype);
+    x3add(parent, &result->base);
+    result->homogeneous = homogeneous;
+    result->spacing = spacing;
+    result->cur_child_prop = 3;
+    x3qsizereq(&result->base);
+    return &result->base;
+}
+
+void x3setpacking(x3widget *w, int fill, int expand, int padding)
+{
+    if (w->type == &x3vboxtype) {
+	x3widget_box *wb = (x3widget_box *)w;
+	int child_props = padding << 2;
+
+	if (fill) child_props |= 1;
+	if (expand) child_props |= 2;
+	wb->cur_child_prop = child_props;
+    }
+}
+
+#endif
+
+void x3sync(void)
+{
+    int i;
+
+    for (i = n_x3needsizereqs - 1; i >= 0; i--) {
+	x3widget *w = x3needsizereqs[i];
+	w->type->sizereq(w);
+	w->flags &= ~x3flag_needsizereq;
+	w->flags |= x3flag_needsizealloc;
+    }
+    for (i = 0; i < n_x3needsizereqs; i++) {
+	x3widget *w = x3needsizereqs[i];
+	if (w->flags & x3flag_needsizealloc) {
+	    w->type->sizealloc(w, NULL);
+	    w->flags &= ~x3flag_needsizealloc;
+	}
+    }
+    n_x3needsizereqs = 0;
+}
+
addfile ./x3common.h
hunk ./x3common.h 1
+#if defined(X3_CARBON) || defined(X3_WIN32)
+
+void x3initqs(void);
+void x3qsizereq(x3widget *w);
+
+#endif
+
+void x3sync(void);
}
