diff options
Diffstat (limited to 'generic/Item.c')
-rw-r--r-- | generic/Item.c | 2664 |
1 files changed, 0 insertions, 2664 deletions
diff --git a/generic/Item.c b/generic/Item.c deleted file mode 100644 index 8fe85f6..0000000 --- a/generic/Item.c +++ /dev/null @@ -1,2664 +0,0 @@ -/* - * Item.c -- Implementation of items. - * - * Authors : Patrick Lecoanet. - * Creation date : - * - * $Id$ - */ - -/* - * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet -- - * - * See the file "Copyright" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - */ - - -#include "Types.h" -#include "Field.h" -#include "Item.h" -#include "Group.h" -#include "WidgetInfo.h" -#include "Geo.h" -#include "Draw.h" -#include "MapInfo.h" -#include "Image.h" -#include "Color.h" -#include "tkZinc.h" -#ifdef ATC -#include "OverlapMan.h" -#endif - -#include <GL/glu.h> -#include <limits.h> /* For INT_MAX */ -#include <stdarg.h> -#include <stdio.h> -#include <string.h> - - -static const char rcsid[] = "$Id$"; -static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $"; - - -static ZnList item_classes = NULL; -static ZnList item_stack = NULL; - - -/* - * This array must be kept in sync with the - * corresponding defines in Item.h. - */ -static char *attribute_type_strings[] = { - "", - "boolean", - "bitmap", - "bitmaplist", - "string", - "font", - "edgelist", - "relief", - "dimension", - "priority", - "alignment", - "autoalignment", - "lineend", - "labelformat", - "linestyle", - "lineshape", - "item", - "angle", - "integer", - "unsignedint", - "point", - "anchor", - "taglist", - "mapinfo", - "image", - "leaderanchors", - "joinstyle", - "capstyle", - "gradient", - "gradientlist", - "window", - "alpha", - "fillrule", - "short", - "unsignedshort" - "char" - "unsignedchar" -}; - - -#ifndef PTK -static int SetAttrFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *obj)); - -/* - * The structure below defines an object type that is used to cache the - * result of looking up an attribute name. If an object has this type, then - * its internalPtr1 field points to the attr_desc table in which it was looked up, - * and the internalPtr2 field points to the entry that matched. - */ - -Tcl_ObjType ZnAttrObjType = { - "attribute", /* name */ - (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ - (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ - (Tcl_UpdateStringProc *) NULL, /* updateStringProc */ - SetAttrFromAny /* setFromAnyProc */ -}; -#endif - - -/* - ********************************************************************************** - * - * Forward functions - * - ********************************************************************************** - */ -static void Invalidate(ZnItem item, int reason); -static Tcl_Obj *AttributeToObj(Tcl_Interp *interp, void *record, ZnAttrConfig *desc); - - - -/* - ********************************************************************************** - * - * ZnUpdateItemImage -- - * - ********************************************************************************** - */ -void -ZnUpdateItemImage(void *client_data) -{ - ZnItem item = (ZnItem) client_data; - - /*printf("Invalidation of item %ld\n", item->id);*/ - Invalidate(item, ZN_CLFC_FLAG | ZN_COORDS_FLAG); -} - - -/* - ********************************************************************************** - * - * InitAttrDesc -- - * - ********************************************************************************** - */ -static void -InitAttrDesc(ZnAttrConfig *attr_desc) -{ - if (!attr_desc) { - return; - } - - while (attr_desc->type != ZN_CONFIG_END) { - attr_desc->uid = Tk_GetUid(attr_desc->name); - attr_desc++; - } -} - -/* - *---------------------------------------------------------------------- - * - * SetAttrFromAny -- - * - * This procedure is called to convert a Tcl object to an attribute - * descriptor. This is only possible if given a attr_desc table, so - * this method always returns an error. - * - *---------------------------------------------------------------------- - */ -#ifndef PTK -static int -SetAttrFromAny(Tcl_Interp *interp, - Tcl_Obj *obj) -{ - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "can't convert value to attribute except via GetAttrDesc", - -1); - return TCL_ERROR; -} -#endif - - -/* - ********************************************************************************** - * - * GetAttrDesc -- - * - ********************************************************************************** - */ -static ZnAttrConfig * -GetAttrDesc(Tcl_Interp *interp, - Tcl_Obj *arg, - ZnAttrConfig *desc_table) -{ - Tk_Uid attr_uid; - ZnAttrConfig *desc; - -#ifndef PTK - if (arg->typePtr == &ZnAttrObjType) { - if (arg->internalRep.twoPtrValue.ptr1 == (void *) desc_table) { - return (ZnAttrConfig *) arg->internalRep.twoPtrValue.ptr2; - } - } -#endif - - /* - * Answer not cached, look it up. - */ - attr_uid = Tk_GetUid(Tcl_GetString(arg)); - desc = desc_table; - - while (True) { - if (desc->type == ZN_CONFIG_END) { - Tcl_AppendResult(interp, "unknown attribute \"", attr_uid, "\"", NULL); - return NULL; - } - else if (attr_uid == desc->uid) { -#ifndef PTK - if ((arg->typePtr != NULL) && (arg->typePtr->freeIntRepProc != NULL)) { - arg->typePtr->freeIntRepProc(arg); - } - arg->internalRep.twoPtrValue.ptr1 = (void *) desc_table; - arg->internalRep.twoPtrValue.ptr2 = (void *) desc; - arg->typePtr = &ZnAttrObjType; -#endif - return desc; - } - else { - desc++; - } - } -} - - -/* - ********************************************************************************** - * - * AttributesInfo -- - * - ********************************************************************************** - */ -int -ZnAttributesInfo(Tcl_Interp *interp, - void *record, - ZnAttrConfig *desc_table, - int argc, - Tcl_Obj *CONST args[]) -{ - Tcl_Obj *l, *entries[5]; - - if (argc == 1) { - ZnAttrConfig *desc = GetAttrDesc(interp, args[0], desc_table); - if (!desc) { - return TCL_ERROR; - } - entries[0] = Tcl_NewStringObj(desc->name, -1); - entries[1] = Tcl_NewStringObj(attribute_type_strings[desc->type], -1); - entries[2] = Tcl_NewBooleanObj(desc->read_only ? 1 : 0); - entries[3] = Tcl_NewStringObj("", -1); - entries[4] = AttributeToObj(interp, record, desc); - l = Tcl_NewListObj(5, entries); - Tcl_SetObjResult(interp, l); - } - else { - l = Tcl_NewObj(); - while (desc_table->type != ZN_CONFIG_END) { - entries[0] = Tcl_NewStringObj(desc_table->name, -1); - entries[1] = Tcl_NewStringObj(attribute_type_strings[desc_table->type], -1); - entries[2] = Tcl_NewBooleanObj(desc_table->read_only ? 1 : 0); - entries[3] = Tcl_NewStringObj("", -1); - entries[4] = AttributeToObj(interp, record, desc_table); - Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(5, entries)); - desc_table++; - } - Tcl_SetObjResult(interp, l); - } - - return TCL_OK; -} - - -/* - ********************************************************************************** - * - * ZnConfigureAttributes -- - * - ********************************************************************************** - */ -int -ZnConfigureAttributes(ZnWInfo *wi, - ZnItem item, - void *record, - ZnAttrConfig *desc_table, - int argc, - Tcl_Obj *CONST args[], - int *flags) -{ - int i; - ZnAttrConfig *desc; - ZnPtr valp; - char *str; - - for (i = 0; i < argc; i += 2) { - desc = GetAttrDesc(wi->interp, args[i], desc_table); - if (!desc) { - return TCL_ERROR; - } - else if (desc->read_only) { - Tcl_AppendResult(wi->interp, "attribute \"", - Tcl_GetString(args[i]), "\" can only be read", NULL); - return TCL_ERROR; - } - - valp = ((char *) record) + desc->offset; - /*printf("record <0x%X>, valp <0x%X>, offset %d\n", record, valp, desc->offset);*/ - switch (desc->type) { - case ZN_CONFIG_GRADIENT: - { - ZnGradient *g; - Tk_Uid new_name = Tk_GetUid(Tcl_GetString(args[i+1])); - char *name = NULL; - if (*((ZnGradient **) valp)) { - name = ZnNameOfGradient(*((ZnGradient **) valp)); - } - if (name != new_name) { - g = ZnGetGradient(wi->interp, wi->win, new_name); - if (!g) { - Tcl_AppendResult(wi->interp, - " gradient expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (*((ZnGradient **) valp)) { - ZnFreeGradient(*((ZnGradient **) valp)); - } - *((ZnGradient **) valp) = g; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_GRADIENT_LIST: - { - ZnList new_grad_list = NULL; - ZnGradient **grads; - unsigned int num_grads, j, k; - Tcl_Obj **elems; - - if (Tcl_ListObjGetElements(wi->interp, args[i+1], - &num_grads, &elems) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, - " gradient list expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (num_grads) { - new_grad_list = ZnListNew(num_grads, sizeof(ZnGradient *)); - ZnListAssertSize(new_grad_list, num_grads); - grads = ZnListArray(new_grad_list); - for (j = 0; j < num_grads; j++) { - str = Tcl_GetString(elems[j]); - if (!*str) { - if (j == 0) { - goto grads_err; - } - grads[j] = grads[j-1]; - } - else { - grads[j] = ZnGetGradient(wi->interp, wi->win, str); - } - if (!grads[j]) { - grads_err: - Tcl_AppendResult(wi->interp, " invalid gradient \"", str, - "\" in gradient list", NULL); - for (k = 0; k < j; k++) { - ZnFreeGradient(grads[k]); - } - ZnListFree(new_grad_list); - return TCL_ERROR; - } - } - } - if (*((ZnList *) valp)) { - num_grads = ZnListSize(*((ZnList *) valp)); - grads = ZnListArray(*((ZnList *) valp)); - for (j = 0; j < num_grads; j++) { - if (grads[j]) { - ZnFreeGradient(grads[j]); - } - } - ZnListFree(*((ZnList *) valp)); - *((ZnList *) valp) = new_grad_list; - *flags |= desc->flags; - } - else { - if (new_grad_list) { - *((ZnList *) valp) = new_grad_list; - *flags |= desc->flags; - } - } - break; - } - case ZN_CONFIG_BOOL: - { - int b; - if (Tcl_GetBooleanFromObj(wi->interp, args[i+1], &b) != TCL_OK) { - Tcl_AppendResult(wi->interp, " boolean expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (b ^ (ISSET(*((unsigned short *) valp), desc->bool_bit) != 0)) { - ASSIGN(*((unsigned short *) valp), desc->bool_bit, b); - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_IMAGE: - case ZN_CONFIG_BITMAP: - { - ZnImage image = ZnUnspecifiedImage; - ZnBool is_bmap = True; - char *name = ""; - - if (*((ZnImage *) valp) != ZnUnspecifiedImage) { - name = ZnNameOfImage(*((ZnImage *) valp)); - } - str = Tcl_GetString(args[i+1]); - if (strcmp(name, str) != 0) { - if (strlen(str) != 0) { - if (desc->type == ZN_CONFIG_IMAGE) { - image = ZnGetImage(wi, str, ZnUpdateItemImage, record); - if (image == ZnUnspecifiedImage) { - Tcl_AppendResult(wi->interp, " image expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - } - else { - image = ZnGetImage(wi, str, NULL, NULL); - if ((image == ZnUnspecifiedImage) || - (!(is_bmap = ZnImageIsBitmap(image)))) { - if (!is_bmap) { - ZnFreeImage(image, NULL, NULL); - } - Tcl_AppendResult(wi->interp, " bitmap expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - } - } - if (*((ZnImage *) valp) != ZnUnspecifiedImage) { - ZnFreeImage(*((ZnImage *) valp), ZnUpdateItemImage, record); - } - *((ZnImage *) valp) = image; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_BITMAP_LIST: - { - ZnList new_pat_list = NULL; - ZnImage *pats; - unsigned int num_pats, j, k; - Tcl_Obj **elems; - ZnBool is_bmap = True; - - if (Tcl_ListObjGetElements(wi->interp, args[i+1], - &num_pats, &elems) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, - " pattern list expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (num_pats) { - new_pat_list = ZnListNew(num_pats, sizeof(Pixmap)); - ZnListAssertSize(new_pat_list, num_pats); - pats = ZnListArray(new_pat_list); - for (j = 0; j < num_pats; j++) { - str = Tcl_GetString(elems[j]); - if (strlen(str) != 0) { - pats[j] = ZnGetImage(wi, str, NULL, NULL); - if ((pats[j] == ZnUnspecifiedImage) || - !(is_bmap = ZnImageIsBitmap(pats[j]))) { - if (!is_bmap) { - ZnFreeImage(pats[j], NULL, NULL); - } - for (k = 0; k < j; k++) { - ZnFreeImage(pats[k], NULL, NULL); - } - ZnListFree(new_pat_list); - Tcl_AppendResult(wi->interp, " unknown pattern \"", str, - "\" in pattern list", NULL); - return TCL_ERROR; - } - } - else { - pats[j] = ZnUnspecifiedImage; - } - } - } - if (*((ZnList *) valp)) { - num_pats = ZnListSize(*((ZnList *) valp)); - pats = ZnListArray(*((ZnList *) valp)); - for (j = 0; j < num_pats; j++) { - if (pats[j] != ZnUnspecifiedImage) { - ZnFreeImage(pats[j], NULL, NULL); - } - } - ZnListFree(*((ZnList *) valp)); - *((ZnList *) valp) = new_pat_list; - *flags |= desc->flags; - } - else { - if (new_pat_list) { - *((ZnList *) valp) = new_pat_list; - *flags |= desc->flags; - } - } - break; - } - case ZN_CONFIG_TAG_LIST: - { - int num_tags, j; - Tcl_Obj **elems; - - if (Tcl_ListObjGetElements(wi->interp, args[i+1], - &num_tags, &elems) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, - " tag list expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (*((ZnList *) valp)) { - ZnITEM.FreeTags(item); - *flags |= desc->flags; - } - if (num_tags) { - for (j = 0; j < num_tags; j++) { - ZnITEM.AddTag(item, Tk_GetUid(Tcl_GetString(elems[j]))); - } - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_STRING: - case ZN_CONFIG_MAP_INFO: - { - char *text = NULL; - str = Tcl_GetString(args[i+1]); - if (!*((char **) valp) || strcmp(str, *((char **) valp)) != 0) { - if (strlen(str)) { - text = (char *) ZnMalloc(strlen(str)+1); - strcpy(text, str); - } - if (*((char **) valp)) { - ZnFree(*((char **) valp)); - } - *((char **) valp) = text; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_FONT: - { - Tk_Font font; - Tk_Uid name = ""; - if (*((Tk_Font *) valp)) { - name = Tk_NameOfFont(*((Tk_Font *) valp)); - } - str = Tcl_GetString(args[i+1]); - if (strcmp(name, str) != 0) { - font = Tk_GetFont(wi->interp, wi->win, str); - if (!font) { - Tcl_AppendResult(wi->interp, " font expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (*((Tk_Font *) valp)) { - Tk_FreeFont(*((Tk_Font *) valp)); - } - *((Tk_Font *) valp) = font; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_EDGE_LIST: - { - ZnBorder border; - - if (ZnGetBorder(wi, args[i+1], &border) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " edge list expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (border != *((ZnBorder *) valp)) { - *((ZnBorder *) valp) = border; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_LINE_SHAPE: - { - ZnLineShape line_shape; - - if (ZnGetLineShape(wi, Tcl_GetString(args[i+1]), &line_shape) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " line shape expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (line_shape != *((ZnLineShape *) valp)) { - *((ZnLineShape *) valp) = line_shape; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_LINE_STYLE: - { - ZnLineStyle line_style; - - if (ZnGetLineStyle(wi, Tcl_GetString(args[i+1]), &line_style) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " line style expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (line_style != *((ZnLineStyle *) valp)) { - *((ZnLineStyle *) valp) = line_style; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_LINE_END: - { - ZnLineEnd line_end = NULL; - str = Tcl_GetString(args[i+1]); - if (strlen(str) != 0) { - line_end = ZnLineEndCreate(wi->interp, str); - if (line_end == NULL) { - return TCL_ERROR; - } - } - if (*((ZnLineEnd *) valp) != NULL) { - ZnLineEndDelete(*((ZnLineEnd *) valp)); - *((ZnLineEnd *) valp) = line_end; - *flags |= desc->flags; - } - else { - if (line_end != NULL) { - *((ZnLineEnd *) valp) = line_end; - *flags |= desc->flags; - } - } - break; - } - case ZN_CONFIG_RELIEF: - { - ZnReliefStyle relief; - if (ZnGetRelief(wi, Tcl_GetString(args[i+1]), &relief) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " relief expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (relief != *((ZnReliefStyle *) valp)) { - /*printf("valp <0x%X>, flags <0x%X>, relief %d\n", valp, flags, relief);*/ - *((ZnReliefStyle *) valp) = relief; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_JOIN_STYLE: - { - int join; - if (Tk_GetJoinStyle(wi->interp, Tcl_GetString(args[i+1]), &join) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " join expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (join != *((int *) valp)) { - *((int *) valp) = join; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_CAP_STYLE: - { - int cap; - if (Tk_GetCapStyle(wi->interp, Tcl_GetString(args[i+1]), &cap) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " cap expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (cap != *((int *) valp)) { - *((int *) valp) = cap; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_POINT: - { - ZnPoint point; - int largc; - Tcl_Obj **largv; - double d; - - if ((Tcl_ListObjGetElements(wi->interp, args[i+1], - &largc, &largv) == TCL_ERROR) || - (largc != 2)) { - point_error: - Tcl_AppendResult(wi->interp, " position expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (Tcl_GetDoubleFromObj(wi->interp, largv[0], &d) == TCL_ERROR) { - goto point_error; - } - point.x = d; - if (Tcl_GetDoubleFromObj(wi->interp, largv[1], &d) == TCL_ERROR) { - goto point_error; - } - point.y = d; - if ((point.x != ((ZnPoint *) valp)->x) || - (point.y != ((ZnPoint *) valp)->y)) { - *((ZnPoint *) valp) = point; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_DIM: - { - ZnDim dim; - if (Tcl_GetDoubleFromObj(wi->interp, args[i+1], &dim) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " dimension expected for attribute \"", - Tcl_GetString(args[i+1]), "\"", NULL); - return TCL_ERROR; - } - if (dim != *((ZnDim *) valp)) { - *((ZnDim *) valp) = dim; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_PRI: - { - int pri; - if (Tcl_GetIntFromObj(wi->interp, args[i+1], &pri) == TCL_ERROR) { - return TCL_ERROR; - } - if (pri < 0) { - Tcl_AppendResult(wi->interp, " priority must be a positive integer \"", - Tcl_GetString(args[i+1]), "\"", NULL); - return TCL_ERROR; - } - if (pri != *((unsigned short *) valp)) { - *((unsigned short *) valp) = pri; - ZnITEM.UpdateItemPriority(item, ZN_NO_ITEM, True); - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_ITEM: - /* - * Can be an item id or a tag. In this last case - * consider only the first item (unspecified order) - * associated with the tag. - */ - { - ZnItem item2; - int result; - ZnTagSearch *search_var = NULL; - - if (strlen(Tcl_GetString(args[i+1])) == 0) { - item2 = ZN_NO_ITEM; - } - else { - result = ZnItemWithTagOrId(wi, args[i+1], &item2, &search_var); - ZnTagSearchDestroy(search_var); - if ((result == TCL_ERROR) || (item2 == ZN_NO_ITEM)) { - Tcl_AppendResult(wi->interp, " unknown item \"", - Tcl_GetString(args[i+1]), "\"", NULL); - return TCL_ERROR; - } - } - if (item2 != *((ZnItem *) valp)) { - *((ZnItem *) valp) = item2; - *flags |= desc->flags; - } - } - break; - case ZN_CONFIG_WINDOW: - { - Tk_Window win, ancestor, parent; - str = Tcl_GetString(args[i+1]); - if (strlen(str) == 0) { - win = NULL; - } - else { - win = Tk_NameToWindow(wi->interp, str, wi->win); - if (win == NULL) { - return TCL_ERROR; - } - else { - /* - * Make sure that the zinc widget is either the parent of the - * window associated with the item or a descendant of that - * parent. Also, don't allow a toplevel window or the widget - * itself to be managed. - */ - parent = Tk_Parent(win); - for (ancestor = wi->win; ; ancestor = Tk_Parent(ancestor)) { - if (ancestor == parent) { - break; - } - if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) { - badWindow: - Tcl_AppendResult(wi->interp, "can't use ", - Tk_PathName(win), - " in a window item of this zinc widget", - (char *) NULL); - win = NULL; - return TCL_ERROR; - } - } - if (((Tk_FakeWin *) (win))->flags & TK_TOP_LEVEL) { - goto badWindow; - } - if (win == wi->win) { - goto badWindow; - } - if (win != *((Tk_Window *) valp)) { - *((Tk_Window *) valp) = win; - *flags |= desc->flags; - } - } - } - } - break; - case ZN_CONFIG_CHAR: - case ZN_CONFIG_UCHAR: - case ZN_CONFIG_ALPHA: - { - int integer; - if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) { - return TCL_ERROR; - } - switch (desc->type) { - case ZN_CONFIG_UCHAR: - if (integer < 0) { - integer = 0; - } - case ZN_CONFIG_ALPHA: - if (integer < 0) { - integer = 0; - } - if (integer > 100) { - integer = 100; - } - break; - } - if (integer != *((char *) valp)) { - *((char *) valp) = integer; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_SHORT: - case ZN_CONFIG_USHORT: - { - int integer; - if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) { - return TCL_ERROR; - } - if (desc->type == ZN_CONFIG_SHORT) { - if (integer < SHRT_MIN) { - integer = SHRT_MIN; - } - else if (integer > SHRT_MAX) { - integer = SHRT_MAX; - } - if (integer != *((short *) valp)) { - *((short *) valp) = integer; - *flags |= desc->flags; - } - } - else { - if (integer < 0) { - integer = 0; - } - else if (integer > USHRT_MAX) { - integer = USHRT_MAX; - } - if (integer != *((unsigned short *) valp)) { - *((unsigned short *) valp) = integer; - *flags |= desc->flags; - } - } - break; - } - case ZN_CONFIG_INT: - case ZN_CONFIG_UINT: - case ZN_CONFIG_ANGLE: - { - int integer; - if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) { - return TCL_ERROR; - } - switch (desc->type) { - case ZN_CONFIG_ANGLE: - if ((integer > 360) || (integer < -360)) { - integer = integer % 360; - } - break; - case ZN_CONFIG_UINT: - if (integer < 0) { - integer = 0; - } - break; - } - if (integer != *((int *) valp)) { - *((int *) valp) = integer; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_FILL_RULE: - { - ZnFillRule fill_rule; - - if (ZnGetFillRule(wi, Tcl_GetString(args[i+1]), &fill_rule) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " fill rule expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (fill_rule != *((ZnFillRule *) valp)) { - *((ZnFillRule *) valp) = fill_rule; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_ALIGNMENT: - { - Tk_Justify justify; - if (Tk_GetJustify(wi->interp, Tcl_GetString(args[i+1]), &justify) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " justify expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (justify != *((Tk_Justify *) valp)) { - *((Tk_Justify *) valp) = justify; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_ANCHOR: - { - Tk_Anchor anchor; - if (Tk_GetAnchor(wi->interp, Tcl_GetString(args[i+1]), &anchor) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " anchor expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (anchor != *((Tk_Anchor *) valp)) { - *((Tk_Anchor *) valp) = anchor; - *flags |= desc->flags; - } - break; - } - case ZN_CONFIG_LABEL_FORMAT: - { - ZnLabelFormat frmt = NULL; - - str = Tcl_GetString(args[i+1]); - while (*str && (*str == ' ')) { - str++; - } - if (strlen(str) != 0) { - frmt = ZnLFCreate(wi->interp, str, - ZnFIELD.NumFields(item->class->GetFieldSet(item))); - if (frmt == NULL) { - return TCL_ERROR; - } - } - - if (*((ZnLabelFormat *) valp) != NULL) { - ZnLFDelete(*((ZnLabelFormat *) valp)); - *((ZnLabelFormat *) valp) = frmt; - *flags |= desc->flags; - } - else { - if (frmt != NULL) { - *((ZnLabelFormat *) valp) = frmt; - *flags |= desc->flags; - } - } - break; - } - - case ZN_CONFIG_AUTO_ALIGNMENT: - { - ZnAutoAlign aa; - - if (ZnGetAutoAlign(wi, Tcl_GetString(args[i+1]), &aa) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " auto alignment expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if ((aa.automatic != ((ZnAutoAlign *) valp)->automatic) || - (aa.align[0] != ((ZnAutoAlign *) valp)->align[0]) || - (aa.align[1] != ((ZnAutoAlign *) valp)->align[1]) || - (aa.align[2] != ((ZnAutoAlign *) valp)->align[2])) { - *((ZnAutoAlign *) valp) = aa; - *flags |= desc->flags; - } - break; - } - - case ZN_CONFIG_LEADER_ANCHORS: - { - ZnLeaderAnchors lanch = NULL; - if (ZnGetLeaderAnchors(wi, Tcl_GetString(args[i+1]), &lanch) == TCL_ERROR) { - Tcl_AppendResult(wi->interp, " leader anchors expected for attribute \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - if (*((ZnLeaderAnchors *) valp) != NULL) { - ZnFree(*((ZnLeaderAnchors *) valp)); - *((ZnLeaderAnchors *) valp) = lanch; - *flags |= desc->flags; - } - else { - if (lanch != NULL) { - *((ZnLeaderAnchors *) valp) = lanch; - *flags |= desc->flags; - } - } - break; - } - } - } - - return TCL_OK; -} - - -/* - ********************************************************************************** - * - * AttributeToObj -- - * - * Returns the obj representation of the attribute pointed - * by 'valp'. The attribute type is given by 'type'. The function - * never fail. - * - ********************************************************************************** - */ -static Tcl_Obj * -AttributeToObj(Tcl_Interp *interp, - void *record, - ZnAttrConfig *desc) -{ - char *valp = ((char *) record) + desc->offset; - char *str = ""; - Tcl_Obj *o, *obj; - unsigned int i; - char buffer[256]; - - switch (desc->type) { - case ZN_CONFIG_GRADIENT: - if (*((ZnGradient **) valp)) { - str = ZnNameOfGradient(*((ZnGradient **) valp)); - } - break; - case ZN_CONFIG_GRADIENT_LIST: - { - unsigned int num_grads; - ZnGradient **grads; - - if (*((ZnList *) valp)) { - grads = ZnListArray(*((ZnList *) valp)); - num_grads = ZnListSize(*((ZnList *) valp)); - - obj = Tcl_NewObj(); - for (i = 0; i < num_grads; i++) { - o = Tcl_NewStringObj(ZnNameOfGradient(grads[i]), -1); - Tcl_ListObjAppendElement(interp, obj, o); - } - return obj; - } - } - break; - case ZN_CONFIG_BOOL: - return Tcl_NewBooleanObj(ISSET(*((unsigned short *) valp), desc->bool_bit)?1:0); - case ZN_CONFIG_IMAGE: - if (*((ZnImage *) valp)) { - str = ZnNameOfImage(*((ZnImage *) valp)); -#if PTK - // Just return the perl image object, it is far more - // useful than the mere string name. - return LangObjectObj(interp, str); -#endif - } - break; - case ZN_CONFIG_BITMAP: - if (*((ZnImage *) valp)) { - str = ZnNameOfImage(*((ZnImage *) valp)); - } - break; - case ZN_CONFIG_BITMAP_LIST: - { - unsigned int num_pats=0; - ZnImage *pats; - - if (*((ZnList *) valp)) { - pats = (ZnImage *) ZnListArray(*((ZnList *) valp)); - num_pats = ZnListSize(*((ZnList *) valp)); - - obj = Tcl_NewObj(); - for (i = 0; i < num_pats; i++) { - if (pats[i] != ZnUnspecifiedImage) { - o = Tcl_NewStringObj(ZnNameOfImage(pats[i]), -1); - } - else { - o = Tcl_NewStringObj("", -1); - } - Tcl_ListObjAppendElement(interp, obj, o); - } - return obj; - } - break; - } - case ZN_CONFIG_TAG_LIST: - { - unsigned int num_tags=0; - Tk_Uid *tags; - - if (*((ZnList *) valp)) { - tags = (Tk_Uid *) ZnListArray(*((ZnList *) valp)); - num_tags = ZnListSize(*((ZnList *) valp)); - obj = Tcl_NewObj(); - for (i = 0; i < num_tags; i++) { - Tcl_ListObjAppendElement(interp, obj, - Tcl_NewStringObj(tags[i], -1)); - } - return obj; - } - break; - } - case ZN_CONFIG_STRING: - case ZN_CONFIG_MAP_INFO: - if (*((char **) valp)) { - str = *((char **) valp); - } - break; - case ZN_CONFIG_FONT: - if (*((Tk_Font *) valp)) { - str = (char *) Tk_NameOfFont(*((Tk_Font *) valp)); - } - break; - case ZN_CONFIG_EDGE_LIST: - str = buffer; - ZnNameOfBorder(*((ZnBorder *) valp), buffer); - break; - case ZN_CONFIG_LINE_SHAPE: - str = ZnNameOfLineShape(*((ZnLineShape *) valp)); - break; - case ZN_CONFIG_FILL_RULE: - str = ZnNameOfFillRule(*((ZnFillRule *) valp)); - break; - case ZN_CONFIG_LINE_STYLE: - str = ZnNameOfLineStyle(*((ZnLineStyle *) valp)); - break; - case ZN_CONFIG_LINE_END: - if (*((ZnLineEnd *) valp)) { - str = ZnLineEndGetString(*((ZnLineEnd *) valp)); - } - break; - case ZN_CONFIG_RELIEF: - str = ZnNameOfRelief(*((ZnReliefStyle *) valp)); - break; - case ZN_CONFIG_JOIN_STYLE: - str = (char *) Tk_NameOfJoinStyle(*((int *) valp)); - break; - case ZN_CONFIG_CAP_STYLE: - str = (char *) Tk_NameOfCapStyle(*((int *) valp)); - break; - case ZN_CONFIG_POINT: - obj = Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, obj, Tcl_NewDoubleObj(((ZnPoint *) valp)->x)); - Tcl_ListObjAppendElement(interp, obj, Tcl_NewDoubleObj(((ZnPoint *) valp)->y)); - return obj; - case ZN_CONFIG_ITEM: - if (*((ZnItem *) valp) != ZN_NO_ITEM) { - return Tcl_NewLongObj((int) (*((ZnItem *) valp))->id); - } - break; - case ZN_CONFIG_WINDOW: - if (*((Tk_Window *) valp) != NULL) { - str = Tk_PathName(*((Tk_Window *) valp)); - } - break; - case ZN_CONFIG_CHAR: - return Tcl_NewIntObj(*((char *) valp)); - case ZN_CONFIG_UCHAR: - case ZN_CONFIG_ALPHA: - return Tcl_NewIntObj(*((unsigned char *) valp)); - case ZN_CONFIG_USHORT: - case ZN_CONFIG_PRI: - return Tcl_NewIntObj(*((unsigned short *) valp)); - case ZN_CONFIG_SHORT: - return Tcl_NewIntObj(*((short *) valp)); - case ZN_CONFIG_UINT: - return Tcl_NewIntObj(*((unsigned int *) valp)); - case ZN_CONFIG_INT: - case ZN_CONFIG_ANGLE: - return Tcl_NewIntObj(*((int *) valp)); - case ZN_CONFIG_DIM: - return Tcl_NewDoubleObj(*((ZnDim *) valp)); - case ZN_CONFIG_ALIGNMENT: - str = (char *) Tk_NameOfJustify(*((Tk_Justify *) valp)); - break; - case ZN_CONFIG_ANCHOR: - str = (char *) Tk_NameOfAnchor(*((Tk_Anchor *) valp)); - break; - case ZN_CONFIG_LABEL_FORMAT: - if (*((ZnLabelFormat *) valp)) { - str = ZnLFGetString(*((ZnLabelFormat *) valp)); - } - break; - case ZN_CONFIG_AUTO_ALIGNMENT: - str = buffer; - ZnNameOfAutoAlign((ZnAutoAlign *) valp, buffer); - break; - case ZN_CONFIG_LEADER_ANCHORS: - str = buffer; - ZnNameOfLeaderAnchors(*((ZnLeaderAnchors *) valp), buffer); - break; - } - return Tcl_NewStringObj(str, -1); -} - - -/* - ********************************************************************************** - * - * ZnQueryAttribute -- - * - ********************************************************************************** - */ -int -ZnQueryAttribute(Tcl_Interp *interp, - void *record, - ZnAttrConfig *desc_table, - Tcl_Obj *attr_name) -{ - ZnAttrConfig *desc = GetAttrDesc(interp, attr_name, desc_table); - - if (!desc) { - return TCL_ERROR; - } - Tcl_SetObjResult(interp, AttributeToObj(interp, record, desc)); - - return TCL_OK; -} - - -/* - ********************************************************************************** - * - * ZnItemClassList -- - * - ********************************************************************************** - */ -ZnList -ZnItemClassList() -{ - return item_classes; -} - -/* - ********************************************************************************** - * - * ZnLookupItemClass -- - * - ********************************************************************************** - */ -ZnItemClass -ZnLookupItemClass(char *class_name) -{ - ZnItemClass *class; - int i, num_classes; - - class = (ZnItemClass *) ZnListArray(item_classes); - num_classes = ZnListSize(item_classes); - for (i = 0; i < num_classes; i++) { - if (strcmp((class[i])->name, class_name) == 0) { - return class[i]; - } - } - - return NULL; -} - -/* - ********************************************************************************** - * - * ZnAddItemClass -- - * - ********************************************************************************** - */ -void -ZnAddItemClass(ZnItemClass class) -{ - if (!ZnLookupItemClass(class->name)) { - ZnListAdd(item_classes, &class, ZnListTail); - InitAttrDesc(class->attr_desc); - } -} - -/* - ********************************************************************************** - * - * ZnItemInit -- - * Initialize classes static state. - * - ********************************************************************************** - */ -void -ZnItemInit() -{ - /* First check if static part already inited */ - if (item_classes == NULL) { - item_classes = ZnListNew(16, sizeof(ZnItemClass)); -#ifdef ATC - ZnAddItemClass(ZnTrack); - ZnAddItemClass(ZnWayPoint); - ZnAddItemClass(ZnMap); - ZnAddItemClass(ZnReticle); -#endif - ZnAddItemClass(ZnTabular); - ZnAddItemClass(ZnRectangle); - ZnAddItemClass(ZnArc); - ZnAddItemClass(ZnCurve); - ZnAddItemClass(ZnTriangles); - ZnAddItemClass(ZnGroup); - ZnAddItemClass(ZnIcon); - ZnAddItemClass(ZnText); - ZnAddItemClass(ZnWindow); - InitAttrDesc(ZnFIELD.attr_desc); - } -} - - -/* - ********************************************************************************** - * - * UpdateItemDependency -- Method - * Update the group dependency list following a change in the - * connection of an item. - * - ********************************************************************************** - */ -static void -UpdateItemDependency(ZnItem item, - ZnItem old_connection) -{ - if (old_connection == ZN_NO_ITEM) { - /* Add a connection */ - ZnInsertDependentItem(item); - } - else if (item->connected_item == ZN_NO_ITEM) { - /* Remove a connection */ - ZnExtractDependentItem(item); - } - else { - /* Move at end to ensure that it will be updated after - * the (new) item it depends upon. - */ - ZnExtractDependentItem(item); - ZnInsertDependentItem(item); - } -} - - -/* - ********************************************************************************** - * - * ExtractItem -- - * Extract an item from its context, includes updating graphic - * state flags. - * - ********************************************************************************** - */ -static void -ExtractItem(ZnItem item) -{ - ZnWInfo *wi = item->wi; - ZnItem group = item->parent; - - /* damage bounding boxes */ - if (ISSET(item->flags, ZN_VISIBLE_BIT)) { - ZnDamage(wi, &item->item_bounding_box); - } - - /* - * Tell that we need to repick - */ - if (item->class != ZnGroup) { - SET(wi->flags, ZN_INTERNAL_NEED_REPICK); - } - - if (group != ZN_NO_ITEM) { - /* Remove me from dependency list. */ - ZnExtractDependentItem(item); - - /* Disconnect all dependents on me. */ - ZnDisconnectDependentItems(item); - /* - * Remove me as a clip item. - */ - ZnGroupRemoveClip(group, item); - /* - * Remove me from item list. - */ - ZnGroupExtractItem(item); - } -} - - -/* - ********************************************************************************** - * - * InsertItem -- Method - * - * Insert an item in the display list according to its priority. - * It is inserted in front of items of lower or same priority. If - * mark_item is not ZN_NO_ITEM the insertion is done relative - * to this item, before it if 'before' is True, after it otherwise. - * mark_item must be in the group 'group'. - * - ********************************************************************************** - */ -static void -InsertItem(ZnItem item, - ZnItem grp, - ZnItem mark_item, - ZnBool before) -{ - if (!grp) { - grp = item->wi->top_group; - } - item->parent = grp; - - if (mark_item && (mark_item->parent != grp)) { - mark_item = ZN_NO_ITEM; - } - - ZnGroupInsertItem(grp, item, mark_item, before); -} - - -/* - ********************************************************************************** - * - * UpdateItemPriority -- Method - * Reorder a group's item list following a change in an - * item priority or a call to lower/raise. - * - ********************************************************************************** - */ -static void -UpdateItemPriority(ZnItem item, - ZnItem mark_item, - ZnBool before) -{ - ZnItem parent = item->parent; - - ZnGroupExtractItem(item); - InsertItem(item, parent, mark_item, before); - Invalidate(item, ZN_DRAW_FLAG); - SET(item->wi->flags, ZN_INTERNAL_NEED_REPICK); -} - - -/* - ********************************************************************************** - * - * SetId, - * FreeId -- Method - * Get a fresh object id from the widget and enter the new - * object with this id in the object hash table. The id is - * incremented. FreeId on the other hand suppress the item - * from the hash table and set its object id to zero. - * - ********************************************************************************** - */ -static void -SetId(ZnItem item) -{ - ZnWInfo *wi = item->wi; - Tcl_HashEntry *entry; - int dummy; - - item->id = wi->obj_id; - wi->obj_id++; - entry = Tcl_CreateHashEntry(wi->id_table, (char *) item->id, &dummy); - Tcl_SetHashValue(entry, item); -} - -static void -FreeId(ZnItem item) -{ - Tcl_HashEntry *entry; - - if (item->id) { - entry = Tcl_FindHashEntry(item->wi->id_table, (char *) item->id); - if (entry) { - Tcl_DeleteHashEntry(entry); - item->id = 0; - } - } -} - -/* - ********************************************************************************** - * - * AddTag -- Method - * Add a tag to the item. If the tag is already on the list it - * is not added. As a side effect the tag/item pair is added to - * the tag table of the widget. - * 'tag' must be a Tk_Uid. - * - ********************************************************************************** - */ -static void -AddTag(ZnItem item, - Tk_Uid tag) -{ - int num, i; - char **ptr; - - /* - * No tags yet. - */ - if (!item->tags) { - item->tags = ZnListNew(1, sizeof(char *)); - } - else { - /* - * If the tag is already there, that's done. - */ - ptr = (char **) ZnListArray(item->tags); - num = ZnListSize(item->tags); - for (i = 0; i < num; i++) { - if (ptr[i] == tag) { - return; - } - } - } - /* - * Add it. - */ - ZnListAdd(item->tags, (void *) &tag, ZnListTail); -} - -/* - ********************************************************************************** - * - * RemoveTag -- Method - * - ********************************************************************************** - */ -static void -RemoveTag(ZnItem item, - Tk_Uid tag) -{ - unsigned int indx, num; - char **ptr; - - if (!item->tags) { - return; - } - /* - * look up the tag in the list. - */ - ptr = (char **) ZnListArray(item->tags); - num = ZnListSize(item->tags); - for (indx = 0; indx < num; indx++) { - if (ptr[indx] == tag) { - /* The tag list is not freed when empty to avoid - * overhead when using tags intensively. */ - ZnListDelete(item->tags, indx); - return; - } - } -} - -/* - ********************************************************************************** - * - * FreeTags -- Method - * - ********************************************************************************** - */ -static void -FreeTags(ZnItem item) -{ - if (!item->tags) { - return; - } - ZnListFree(item->tags); - item->tags = NULL; -} - - -/* - ********************************************************************************** - * - * HasTag -- Method - * - ********************************************************************************** - */ -static ZnBool -HasTag(ZnItem item, - Tk_Uid tag) -{ - int num; - Tk_Uid *tags; - - if (!item->tags || !ZnListSize(item->tags)) { - return False; - } - else { - num = ZnListSize(item->tags); - tags = ZnListArray(item->tags); - for (tags = ZnListArray(item->tags); num > 0; tags++, num--) { - if (*tags == tag) { - return True; - } - } - } - return False; -} - - -/* - ********************************************************************************** - * - * ZnCreateItem -- - * - * InsertItem and ConfigureItem must be called after CreateItem - * to finalize the setup of a new item. This is so even if - * there are no attributes to be changed after creation. - * ConfigureItem must be called in this case with the 'init' - * parameter set to True. - * - ********************************************************************************** - */ -ZnItem -ZnCreateItem(ZnWInfo *wi, - ZnItemClass item_class, - int *argc, - Tcl_Obj *CONST *args[]) -{ - ZnItem item; - - item = ZnMalloc(item_class->size); - - /* Initialize common state */ - item->class = item_class; - item->wi = wi; - item->parent = NULL; - item->previous = ZN_NO_ITEM; - item->next = ZN_NO_ITEM; - CLEAR(item->flags, ZN_UPDATE_DEPENDENT_BIT); - item->inv_flags = 0; - item->transfo = NULL; - item->parent = NULL; - item->connected_item = ZN_NO_ITEM; -#ifdef GL -#ifdef GL_LIST - item->gl_list = 0; -#endif -#endif - ZnResetBBox(&item->item_bounding_box); - - /* Init item specific attributes */ - if (item_class->Init(item, argc, args) == TCL_ERROR) { - ZnFree(item); - return ZN_NO_ITEM; - } - - SetId(item); - item->tags = NULL; - - SET(wi->flags, ZN_INTERNAL_NEED_REPICK); - wi->num_items++; - - return (item); -} - - -/* - ********************************************************************************** - * - * CloneItem -- Method - * Can't clone the top level group. - * - ********************************************************************************** - */ -static ZnItem -CloneItem(ZnItem model) -{ - ZnWInfo *wi = model->wi; - ZnItem item; - Tk_Uid *tags; - unsigned int num_tags; - int i; - - if (!model->parent) { - return ZN_NO_ITEM; - } - - item = ZnMalloc(model->class->size); - memcpy(item, model, model->class->size); - - item->previous = ZN_NO_ITEM; - item->next = ZN_NO_ITEM; - item->connected_item = ZN_NO_ITEM; - CLEAR(item->flags, ZN_UPDATE_DEPENDENT_BIT); - item->inv_flags = 0; - SetId(item); - - if (model->tags) { - item->tags = NULL; - tags = (Tk_Uid *) ZnListArray(model->tags); - num_tags = ZnListSize(model->tags); - for (i = num_tags-1; i >= 0; i--, tags++) { - AddTag(item, *tags); - } - } - - if (item->transfo) { - item->transfo = ZnTransfoDuplicate(item->transfo); - } - - /* Call item's clone to duplicate non shared resources */ - item->class->Clone(item); - - SET(wi->flags, ZN_INTERNAL_NEED_REPICK); - wi->num_items++; - - Invalidate(item, ZN_COORDS_FLAG); - - return item; -} - - -/* - ********************************************************************************** - * - * ConfigureItem -- Method - * - ********************************************************************************** - */ -static int -ConfigureItem(ZnItem item, - int field, - int argc, - Tcl_Obj *CONST argv[], - ZnBool init) -{ - ZnWInfo *wi = item->wi; - int flags; - ZnBool previous_visible = init ? False : ISSET(item->flags, ZN_VISIBLE_BIT); - - flags = 0; - ASSIGN(flags, ZN_COORDS_FLAG, init); - if (argv) { - if (field < 0){ - if (item->class->Configure(item, argc, argv, &flags) == TCL_ERROR) { - return TCL_ERROR; - } - if (item->class->GetFieldSet && ISSET(flags, ZN_CLFC_FLAG)) { - ZnFIELD.ClearFieldCache(item->class->GetFieldSet(item), -1); - } - } - else if (item->class->GetFieldSet) { - if (ZnFIELD.ConfigureField(item->class->GetFieldSet(item), - field, argc, argv, &flags) == TCL_ERROR) { - return TCL_ERROR; - } - } - else { - return TCL_ERROR; - } - } - - if (previous_visible && ISCLEAR(item->flags, ZN_VISIBLE_BIT)) { - /* - * Special case when the item has its visibility - * just turned out. - */ - ZnDamage(wi, &item->item_bounding_box); - } - - Invalidate(item, flags); - - return TCL_OK; -} - - -/* - ********************************************************************************** - * - * QueryItem -- Method - * - ********************************************************************************** - */ -static int -QueryItem(ZnItem item, - int field, - int argc, - Tcl_Obj *CONST argv[]) -{ - if (field < 0) { - return item->class->Query(item, argc, argv); - } - else if (item->class->GetFieldSet) { - return ZnFIELD.QueryField(item->class->GetFieldSet(item), - field, argc, argv); - } - - return TCL_ERROR; -} - - -/* - ********************************************************************************** - * - * ComposeTransform -- - * Compose a transform transfo with current_t to new_t. - * - ********************************************************************************** - */ -static void -ComposeTransform(ZnTransfo *transfo, - ZnPoint *pos, - ZnTransfo *current_t, - ZnTransfo *new_t, - ZnBool compose_scale, - ZnBool compose_rot) -{ - ZnBool full; - ZnTransfo t, t2; - - full = compose_scale && compose_rot; - - if (!transfo && !pos && full) { - *new_t = *current_t; - return; - } - if (full) { - /* - * Full concatenation. - */ - /*ZnPrintTransfo(transfo);*/ - if (pos) { - if (!transfo) { - ZnTransfoSetIdentity(&t); - } - else { - t = *transfo; - } - ZnTranslate(&t, pos->x, pos->y, False); - ZnTransfoCompose(new_t, &t, current_t); - } - else { - ZnTransfoCompose(new_t, transfo, current_t); - } - } - else { - ZnPoint scale, trans, local_scale, local_trans, p; - ZnReal local_rot, rot; - - ZnTransfoSetIdentity(new_t); - ZnTransfoDecompose(transfo, &local_scale, &local_trans, &local_rot, NULL); - ZnScale(new_t, local_scale.x, local_scale.y); - ZnRotateRad(new_t, local_rot); - - ZnTransfoDecompose(current_t, &scale, &trans, &rot, NULL); - - if (pos) { - ZnTransfoSetIdentity(&t); - ZnTranslate(&t, pos->x, pos->y, False); - ZnTransfoCompose(&t2, &t, current_t); - ZnTransformPoint(&t2, &local_trans, &p); - } - else { - ZnTransformPoint(current_t, &local_trans, &p); - } - - if (compose_scale) { - ZnScale(new_t, scale.x, scale.y); - } - if (compose_rot) { - ZnRotateRad(new_t, rot); - } - ZnTranslate(new_t, p.x, p.y, False); - } -} - - -/* - ********************************************************************************** - * - * GetItemTransform -- Method - * Compute the current transform for an item. - * - ********************************************************************************** - */ -static void -GetItemTransform(ZnItem item, - ZnTransfo *t) -{ - ZnItem *items; - int i; - ZnTransfo t_tmp, *t1, *t2, *swap; - ZnPoint *pos; - - if (item_stack == NULL) { - item_stack = ZnListNew(16, sizeof(ZnItem)); - } - else { - ZnListEmpty(item_stack); - } - - while (item != ZN_NO_ITEM) { - ZnListAdd(item_stack, &item, ZnListTail); - item = item->parent; - } - - ZnTransfoSetIdentity(t); - t1 = t; - t2 = &t_tmp; - items = (ZnItem *) ZnListArray(item_stack); - for (i = ZnListSize(item_stack)-1; i >= 0; i--) { - pos = NULL; - if (items[i]->class->pos_offset >= 0) { - pos = (ZnPoint *) (((char *) items[i]) + items[i]->class->pos_offset); - if (pos->x == 0 && pos->y == 0) { - pos = NULL; - } - } - ComposeTransform(items[i]->transfo, pos, t1, t2, - ISSET(items[i]->flags, ZN_COMPOSE_SCALE_BIT), - ISSET(items[i]->flags, ZN_COMPOSE_ROTATION_BIT)); - swap = t2; - t2 = t1; - t1 = swap; - } - if (t1 != t) { - *t = *t1; - } -} - - - -/* - ********************************************************************************** - * - * ZnResetTransformStack - * ZnInitTransformStack - * ZnFreeTransformStack - * ZnCurrentTransform - * ZnPushTransform - * ZnPopTransform -- - * - ********************************************************************************** - */ -void -ZnResetTransformStack(ZnWInfo *wi) -{ - ZnListAssertSize(wi->transfo_stack, 1); - wi->current_transfo = (ZnTransfo *) ZnListAt(wi->transfo_stack, 0); - ZnTransfoSetIdentity(wi->current_transfo); -} - -void -ZnInitTransformStack(ZnWInfo *wi) -{ - wi->transfo_stack = ZnListNew(8, sizeof(ZnTransfo)); - ZnResetTransformStack(wi); -} - -void -ZnFreeTransformStack(ZnWInfo *wi) -{ - ZnListFree(wi->transfo_stack); -} - -void -ZnPushTransform(ZnWInfo *wi, - ZnTransfo *transfo, - ZnPoint *pos, - ZnBool compose_scale, - ZnBool compose_rot) -{ - ZnTransfo *next_t; - unsigned int num_t; - - /* - * Push the current transform and concatenate - * the new transform taking into account the - * combination flags. - */ - num_t = ZnListSize(wi->transfo_stack); - ZnListAssertSize(wi->transfo_stack, num_t+1); - next_t = (ZnTransfo *) ZnListAt(wi->transfo_stack, num_t); - ComposeTransform(transfo, pos, wi->current_transfo, next_t, - compose_scale, compose_rot); - wi->current_transfo = next_t; -} - -void -ZnPopTransform(ZnWInfo *wi) -{ - /* - * Restore the previous transform. - */ - ZnListDelete(wi->transfo_stack, ZnListTail); - wi->current_transfo = (ZnTransfo *) ZnListAt(wi->transfo_stack, ZnListTail); -} - - -/* - ********************************************************************************** - * - * ZnResetClipStack - * ZnInitClipStack - * ZnFreeClipStack - * ZnCurrentClip - * ZnPushClip - * ZnPopClip -- - * - ********************************************************************************** - */ -/* - * Describe the clipping at a given node - * of the item hierarchy. - */ -typedef struct _ClipState { - ZnBool simple; /* The clip is an aligned rectangle. */ - TkRegion region; /* The region used to draw and to */ - /* probe for picking. */ - ZnBBox clip_box; /* The bounding box of the clip area. */ -} ClipState; - -void -ZnResetClipStack(ZnWInfo *wi) -{ - int i; - ClipState *clips = (ClipState *) ZnListArray(wi->clip_stack); - - /* - * Should not happen, clip stack should be - * empty when this function is called. - */ - for (i = ZnListSize(wi->clip_stack)-1; i >= 0; i--) { - TkDestroyRegion(clips[i].region); - } - ZnListEmpty(wi->clip_stack); - wi->current_clip = NULL; -} - -void -ZnInitClipStack(ZnWInfo *wi) -{ - wi->clip_stack = ZnListNew(8, sizeof(ClipState)); - ZnResetClipStack(wi); -} - -void -ZnFreeClipStack(ZnWInfo *wi) -{ - ZnListFree(wi->clip_stack); -} - -ZnBool -ZnCurrentClip(ZnWInfo *wi, - TkRegion *reg, - ZnBBox **clip_box, - ZnBool *simple) -{ - if (wi->current_clip) { - if (reg) { - *reg = wi->current_clip->region; - } - if (clip_box) { - *clip_box = &wi->current_clip->clip_box; - } - if (simple) { - *simple = wi->current_clip->simple; - } - return True; - } - - return False; -} - -/* - * If simple is True poly is a pointer to an - * array of two points. In the other case it - * is a regular pointer to a multi contour poly. - */ -void -ZnPushClip(ZnWInfo *wi, - ZnTriStrip *tristrip, - ZnBool simple, - ZnBool set_gc) -{ - unsigned int i, j, num_clips; - unsigned int num_pts, max_num_pts; - ZnPoint *p; - ClipState *previous_clip=NULL; - TkRegion reg, reg_op, reg_to; - XRectangle rect; - XPoint xpts[3]; - - if (tristrip->num_strips == 0) { - return; - } - max_num_pts = tristrip->strips[0].num_points; - for (j = 0; j < tristrip->num_strips; j++) { - num_pts = tristrip->strips[j].num_points; - if (num_pts > max_num_pts) { - num_pts = max_num_pts; - } - } - if ((simple && (max_num_pts < 2)) || - (!simple && (max_num_pts < 3))) { - return; - } - - num_clips = ZnListSize(wi->clip_stack); - /* printf("PushClip: num clips %d\n", num_clips);fflush(stdout);*/ - if (num_clips != 0) { - previous_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail); - } - ZnListAssertSize(wi->clip_stack, num_clips+1); - wi->current_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail); - wi->current_clip->simple = simple; - - /* - * Compute the local region. - */ - if (simple) { - rect.x = (short) tristrip->strips[0].points[0].x; - rect.y = (short) tristrip->strips[0].points[0].y; - rect.width = ((unsigned short) (tristrip->strips[0].points[1].x - - tristrip->strips[0].points[0].x)); - rect.height = ((unsigned short) (tristrip->strips[0].points[1].y - - tristrip->strips[0].points[0].y)); - reg = TkCreateRegion(); - TkUnionRectWithRegion(&rect, reg, reg); - /*printf("Adding a simple clip: %d, %d, %d, %d\n", - rect.x, rect.y, rect.width, rect.height);*/ - } - else { - reg = TkCreateRegion(); - for (j = 0; j < tristrip->num_strips; j++) { - num_pts = tristrip->strips[j].num_points; - p = tristrip->strips[j].points; - if (tristrip->strips[j].fan) { - xpts[0].x = ZnNearestInt(p->x); - xpts[0].y = ZnNearestInt(p->y); - p++; - xpts[1].x = ZnNearestInt(p->x); - xpts[1].y = ZnNearestInt(p->y); - p++; - for (i = 2; i < num_pts; i++, p++) { - xpts[2].x = ZnNearestInt(p->x); - xpts[2].y = ZnNearestInt(p->y); - reg_op = (TkRegion) ZnPolygonRegion(xpts, 3, EvenOddRule); - reg_to = TkCreateRegion(); - ZnUnionRegion(reg, reg_op, reg_to); - TkDestroyRegion(reg); - TkDestroyRegion(reg_op); - reg = reg_to; - xpts[1] = xpts[2]; - } - } - else { - xpts[0].x = (short) p->x; - xpts[0].y = (short) p->y; - p++; - xpts[1].x = (short) p->x; - xpts[1].y = (short) p->y; - p++; - for (i = 2 ; i < num_pts; i++, p++) { - xpts[2].x = (short) p->x; - xpts[2].y = (short) p->y; - reg_op = (TkRegion) ZnPolygonRegion(xpts, 3, EvenOddRule); - reg_to = TkCreateRegion(); - ZnUnionRegion(reg, reg_op, reg_to); - TkDestroyRegion(reg); - TkDestroyRegion(reg_op); - reg = reg_to; - xpts[0] = xpts[1]; - xpts[1] = xpts[2]; - } - } - } - } - - /* - * Combine with previous region if any. - */ - if (previous_clip) { - wi->current_clip->region = TkCreateRegion(); - TkIntersectRegion(reg, previous_clip->region, wi->current_clip->region); - TkDestroyRegion(reg); - /*printf("Merging with previous clip\n");*/ - } - else { - wi->current_clip->region = reg; - } - TkClipBox(wi->current_clip->region, &rect); - wi->current_clip->clip_box.orig.x = rect.x; - wi->current_clip->clip_box.orig.y = rect.y; - wi->current_clip->clip_box.corner.x = rect.x + rect.width; - wi->current_clip->clip_box.corner.y = rect.y + rect.height; - - /* - * Set the clipping in the GC. - */ - if (set_gc) { - if (wi->render) { -#ifdef GL - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF); - glStencilOp(GL_KEEP, GL_INCR, GL_INCR); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - if (simple) { - /* printf("Clip box is : %d, %d, %d, %d, num_clips : %d\n", - rect.x, rect.y, rect.width, rect.height, num_clips);*/ - glBegin(GL_QUADS); - glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.orig.y); - glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.corner.y); - glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.corner.y); - glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.orig.y); - glEnd(); - } - else { - for (j = 0; j < tristrip->num_strips; j++) { - num_pts = tristrip->strips[j].num_points; - p = tristrip->strips[j].points; - if (tristrip->strips[j].fan) { - glBegin(GL_TRIANGLE_FAN); - } - else { - glBegin(GL_TRIANGLE_STRIP); - } - for (i = 0; i < num_pts; i++, p++) { - glVertex2d(p->x, p->y); - } - glEnd(); - } - } - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilFunc(GL_EQUAL, (GLint) (num_clips+1), 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); -#endif - } - else { - TkSetRegion(wi->dpy, wi->gc, wi->current_clip->region); - } - } -} - -void -ZnPopClip(ZnWInfo *wi, - ZnBool set_gc) -{ - int num_clips; - - if (wi->current_clip == NULL) { - return; - } - - TkDestroyRegion(wi->current_clip->region); - ZnListDelete(wi->clip_stack, ZnListTail); - num_clips = ZnListSize(wi->clip_stack); - - if (num_clips != 0) { - wi->current_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail); - } - else { - wi->current_clip = NULL; - } - - /* - * Set the clipping in the GC. - */ - if (set_gc) { - if (num_clips != 0) { - if (wi->render) { -#ifdef GL - glStencilFunc(GL_EQUAL, (GLint) (num_clips+1), 0xFF); - glStencilOp(GL_KEEP, GL_DECR, GL_DECR); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); -#if 0 - if (wi->current_clip->simple) { -#endif - glBegin(GL_QUADS); - glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.orig.y); - glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.corner.y); - glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.corner.y); - glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.orig.y); - glEnd(); -#if 0 - } - else { - } -#endif - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); -#endif - } - else { - TkSetRegion(wi->dpy, wi->gc, wi->current_clip->region); - } - } - else { - /*printf("resetting clip mask\n");*/ - if (wi->render) { -#ifdef GL - glClear(GL_STENCIL_BUFFER_BIT); - glDisable(GL_STENCIL_TEST); -#endif - } - else { - XSetClipMask(wi->dpy, wi->gc, None); - } - } - } - /*printf("PopClip: num clips %d\n", ZnListSize(wi->clip_stack));fflush(stdout);*/ -} - - -/* - ********************************************************************************** - * - * Invalidate -- Method - * - ********************************************************************************** - */ -static void -Invalidate(ZnItem item, - int reason) -{ - /* - * Why this test has to be so an abrupt shortcut ? - * It precludes addition of meaningful reasons - * by subsequent invalidations . - * - if (ISSET(item->inv_flags, ZN_TRANSFO_FLAG)) { - return; - }*/ - - if (ISSET(reason, ZN_COORDS_FLAG) || - ISSET(reason, ZN_TRANSFO_FLAG)) { - ZnItem parent = item->parent; - while ((parent != NULL) && - ISCLEAR(parent->inv_flags, ZN_COORDS_FLAG) && - ISCLEAR(parent->inv_flags, ZN_TRANSFO_FLAG)) { - SET(parent->inv_flags, ZN_COORDS_FLAG); - /*printf("invalidate coords for parent %d\n", parent->id);*/ - parent = parent->parent; - } - /* - * There is no need to set the DRAW flag to force the invalidation - * of the current bounding box. This will be done by ComputeCoordinates - * in Group. - */ - item->inv_flags |= reason; - /*printf("invalidate %s for item %d, flags %s\n", - ISSET(reason, ZN_TRANSFO_FLAG)?"TRANSFO":"COORDS", item->id, - ISSET(item->inv_flags, ZN_TRANSFO_FLAG)?"TRANSFO":"COORDS");*/ - ZnNeedRedisplay(item->wi); - } - else if (ISSET(reason, ZN_DRAW_FLAG)) { - if (ISSET(item->flags, ZN_VISIBLE_BIT)) { - /*printf("invalidate graphics for item %d\n", item->id);*/ - ZnDamage(item->wi, &item->item_bounding_box); -#ifdef GL -#ifdef GL_LIST - /* - * Remove the item display list so that it will be recreated - * to reflect the changes. - */ - if (item->gl_list) { - glDeleteLists(item->gl_list, 1); - item->gl_list = 0; - } -#endif -#endif - } - } -} - - -/* - ********************************************************************************** - * - * InvalidateItems -- Method - * Invalidate the geometric state of all items belonging - * to a given class. The search for items starts at group - * and proceed depth first. - * - ********************************************************************************** - */ -static void -InvalidateItems(ZnItem group, - ZnItemClass item_class) -{ - ZnItem item; - - if (group->class != ZnGroup) { - return; - } - item = ZnGroupHead(group); - while (item != ZN_NO_ITEM) { - if (item->class == item_class) { - Invalidate(item, ZN_COORDS_FLAG); - } - else if (item->class == ZnGroup) { - InvalidateItems(item, item_class); - } - item = item->next; - } -} - - -/* - ********************************************************************************** - * - * ResetTransfo - * SetTransfo - * TranslateItem - * ScaleItem - * SkewItem - * RotateItem -- Methods - * Set of functions that deal with item transform. They take care - * of all details including managing NULL transforms and invalidating - * the item hierarchy. - * - ********************************************************************************** - */ -static void -ResetTransfo(ZnItem item) -{ - if (item->transfo) { - ZnFree(item->transfo); - item->transfo = NULL; - } - Invalidate(item, ZN_TRANSFO_FLAG); -} - - -static void -SetTransfo(ZnItem item, - ZnTransfo *t) -{ - if (item->transfo) { - ZnFree(item->transfo); - } - if (!t || ZnTransfoIsIdentity(t)) { - item->transfo = NULL; - } - else { - item->transfo = ZnTransfoDuplicate(t); - } - Invalidate(item, ZN_TRANSFO_FLAG); -} - - -static void -TranslateItem(ZnItem item, - ZnReal dx, - ZnReal dy, - ZnBool abs) -{ - if (!item->transfo) { - item->transfo = ZnTransfoNew(); - } - ZnTranslate(item->transfo, dx, dy, abs); - Invalidate(item, ZN_TRANSFO_FLAG); -} - - -static void -ScaleItem(ZnItem item, - ZnReal sx, - ZnReal sy, - ZnPoint *p) -{ - if (!item->transfo) { - item->transfo = ZnTransfoNew(); - } - if (p) { - ZnTranslate(item->transfo, -p->x, -p->y, False); - } - ZnScale(item->transfo, sx, sy); - if (p) { - ZnTranslate(item->transfo, p->x, p->y, False); - } - Invalidate(item, ZN_TRANSFO_FLAG); -} - - -static void -SkewItem(ZnItem item, - ZnReal x_skew, - ZnReal y_skew) -{ - if (!item->transfo) { - item->transfo = ZnTransfoNew(); - } - ZnSkewRad(item->transfo, x_skew, y_skew); - Invalidate(item, ZN_TRANSFO_FLAG); -} - - -static void -RotateItem(ZnItem item, - ZnReal angle, - ZnBool deg, - ZnPoint *p) -{ - if (!item->transfo) { - item->transfo = ZnTransfoNew(); - } - if (p) { - ZnTranslate(item->transfo, -p->x, -p->y, False); - } - if (deg) { - ZnRotateDeg(item->transfo, angle); - } - else { - ZnRotateRad(item->transfo, angle); - } - if (p) { - ZnTranslate(item->transfo, p->x, p->y, False); - } - - Invalidate(item, ZN_TRANSFO_FLAG); -} - - -/* - ********************************************************************************** - * - * DestroyItem -- Method - * - ********************************************************************************** - */ -static void -DestroyItem(ZnItem item) -{ - ZnWInfo *wi = item->wi; - ZnTextInfo *ti = &wi->text_info; - - /* - * Extract it from its group. - */ - ExtractItem(item); - - /* - * Update state variables to prevent dangling pointers. - */ - if (wi->current_item == item) { - wi->current_item = ZN_NO_ITEM; - wi->current_part = ZN_NO_PART; - } - if (wi->new_item == item) { - wi->new_item = ZN_NO_ITEM; - wi->new_part = ZN_NO_PART; - } - if ((wi->hot_item == item) || (wi->hot_prev) == item) { - wi->hot_item = ZN_NO_ITEM; - } - if (ti->sel_item == item) { - ti->sel_item = ZN_NO_ITEM; - ti->sel_field = ZN_NO_PART; - } - if (ti->anchor_item == item) { - ti->anchor_item = ZN_NO_ITEM; - ti->anchor_field = ZN_NO_PART; - } - if (wi->focus_item == item) { - wi->focus_item = ZN_NO_ITEM; - wi->focus_field = ZN_NO_PART; - } - - /* - * Call per class removal code. - */ - (item->class->Destroy)(item); - /* - * Free the transform if any. - */ - if (item->transfo) { - ZnFree(item->transfo); - } - /* - * Remove the item from the item table and free - * all its tags. - */ - FreeId(item); - FreeTags(item); - /* - * Free the item own memory - */ - ZnFree(item); - wi->num_items--; -} - - -/* - ********************************************************************************** - * - * Generic methods on items -- - * - ********************************************************************************** - */ - -struct _ZnITEM ZnITEM = { - CloneItem, - DestroyItem, - ConfigureItem, - QueryItem, - InsertItem, - UpdateItemPriority, - UpdateItemDependency, - ExtractItem, - SetId, - FreeId, - AddTag, - RemoveTag, - FreeTags, - HasTag, - ResetTransfo, - SetTransfo, - TranslateItem, - ScaleItem, - SkewItem, - RotateItem, - Invalidate, - InvalidateItems, - GetItemTransform -}; |