aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlecoanet2000-06-21 15:36:16 +0000
committerlecoanet2000-06-21 15:36:16 +0000
commit5ebfe37da09d852e0ec8fccf71081209c0ccc590 (patch)
treeb67badb78df27768b7732226ea171dc2855e569b
parent49ea4c654ae3d41afd0c8a6b52f79bebade4c887 (diff)
downloadtkzinc-5ebfe37da09d852e0ec8fccf71081209c0ccc590.zip
tkzinc-5ebfe37da09d852e0ec8fccf71081209c0ccc590.tar.gz
tkzinc-5ebfe37da09d852e0ec8fccf71081209c0ccc590.tar.bz2
tkzinc-5ebfe37da09d852e0ec8fccf71081209c0ccc590.tar.xz
* (WidgetObjCmd): Correction de la commande dtags. L'acc�s
� la table de tags n'�tait pa prot�g�. * (WidgetObjCmd): On ne reporte plus d'erreur lors d'op�rations potentiellement multiples si aucun item n'est impliqu�. * R��criture compl�te du syst�me de recherche tag/id. Cela implique la suppression de la table de tags, l'utilisation homog�ne d'un seul algorithme de recherche d�livrant les items dans l'ordre d'affichage et enfin la possibilit� d'utiliser des connecteurs bool�ens pour associer des tags/id pour effectuer une recherche complexe. * Un certain nombre de sous commandes de find/addtag admettent un param�tre suppl�mentaire optionnel pour controler la r�cursivit� de la recherche. * La sous commande atpoint de find/addtag est remplac�e par closest avec une s�mantique identique � celle du canvas. !! INCOMPATIBILITE !! * la commande hasparts a �t� remplac�e par la commande numparts a priori plus utile. !! INCOMPATIBILITE !! * Ajout de la commande verticeat qui retourne l'index de la coordonn�e la plus proche d'un point donn� pour un item donn�. Ne fonctionne que pour Curve et Bezier (pour l'instant). * Le binding des parties priv�es aux �v�nements n'est plus sp�cifi� par des nombres n�gatifs mais par des symboles : connection, speedvector, leader, position. De m�me la commande currenpart retourne ces symboles. !! INCOMPATIBILITE !! * Les bindings associ�s � un items sont tous d�truits lorsqu'un item est d�truit. Pr�c�dement les bindings associ�s aux champs et aux parties priv�es n'�taient pas pris en compte. * Destruction du timer de clignotement lors de la destruction d'un zinc. * Correction d'un bug de redessin des bordures de la fen�tre. * Correction de pleins de bugs dans la commande mapinfo qui ne fonctionnait plus depuis le passage en Tcl_Obj.
-rw-r--r--generic/tkZinc.c2241
1 files changed, 1475 insertions, 766 deletions
diff --git a/generic/tkZinc.c b/generic/tkZinc.c
index 452e80a..74cb1bd 100644
--- a/generic/tkZinc.c
+++ b/generic/tkZinc.c
@@ -63,7 +63,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ "
#include <unistd.h>
#include <X11/Xatom.h>
-
+#if 0
typedef struct TagSearch {
WidgetInfo *wi;
Tk_Uid tag;
@@ -74,6 +74,16 @@ typedef struct TagSearch {
ZnList item_stack;
ZnBool over;
} TagSearch;
+#endif
+typedef struct _TagSearchExpr {
+ struct _TagSearchExpr *next; /* for linked lists of expressions - used in bindings */
+ Tk_Uid uid; /* the uid of the whole expression */
+ Tk_Uid *uids; /* expresion compiled to an array of uids */
+ int allocated; /* available space for array of uids */
+ int length; /* length of expression */
+ int index; /* current position in expression evaluation */
+ int match; /* this expression matches event's item's tags*/
+} TagSearchExpr;
#define INTEGER_SPACE 30
@@ -116,6 +126,14 @@ static unsigned char bitmaps[NUM_ALPHA_STEPS][8];
static ZnBool inited = False;
static Tk_Uid all_uid;
static Tk_Uid current_uid;
+static Tk_Uid and_uid;
+static Tk_Uid or_uid;
+static Tk_Uid xor_uid;
+static Tk_Uid paren_uid;
+static Tk_Uid end_paren_uid;
+static Tk_Uid neg_paren_uid;
+static Tk_Uid tag_val_uid;
+static Tk_Uid neg_tag_val_uid;
/*
@@ -434,20 +452,21 @@ ZincObjCmd(ClientData client_data, /* Main window associated with
wi->map_text_font = 0;
wi->map_distance_symbol = None;
wi->cursor = None;
+ wi->hot_item = ZN_NO_ITEM;
+ wi->hot_prev = ZN_NO_ITEM;
wi->track_manage_history = False;
wi->track_managed_history_size = 0;
wi->speed_vector_length = 0;
wi->tile = ZnUnspecifiedImage;
wi->tile_name = NULL;
- wi->tag_table = (Tcl_HashTable *) ZnMalloc(sizeof(Tcl_HashTable));
- Tcl_InitHashTable(wi->tag_table, TCL_ONE_WORD_KEYS);
wi->id_table = (Tcl_HashTable *) ZnMalloc(sizeof(Tcl_HashTable));
Tcl_InitHashTable(wi->id_table, TCL_ONE_WORD_KEYS);
wi->t_table = (Tcl_HashTable *) ZnMalloc(sizeof(Tcl_HashTable));
Tcl_InitHashTable(wi->t_table, TCL_ONE_WORD_KEYS);
wi->obj_id = 1;
+ wi->num_items = 0;
wi->top_group = ITEM_P.CreateItem(wi, ZnGroup, 0, NULL);
@@ -461,12 +480,11 @@ ZincObjCmd(ClientData client_data, /* Main window associated with
wi->events_flags = 0;
wi->pick_aperture = 0;
wi->new_item = wi->current_item = ZN_NO_ITEM;
- wi->new_part = wi->current_part = 0;
+ wi->new_part = wi->current_part = ZN_NO_PART;
wi->monitoring = False;
wi->num_updates = 0;
wi->last_time = wi->total_time = 0;
- wi->num_items = 0;
wi->work_item_list = NULL;
wi->work_pts = ZnListNew(8, sizeof(ZnPoint));
@@ -571,193 +589,832 @@ EncodeItemPart(Item item,
/*
- *----------------------------------------------------------------------
+ *--------------------------------------------------------------
*
- * ZnSearchWithTagOrId
- * ZnNextWithTagOrId --
- *
- * These two functions implement an alternative way for
- * collecting items that match a tag or id. It has to
- * be used instead of ZnItemsWithTagOrId when it is
- * mandatory for the returned items to be sorted in display
- * list order.
- *
- * This is the way items are collected in the canvas, so
- * the routines are borrowed from the canvas code.
- *
- * NOTE:
- * These routines are a temporary solution primarily used in
- * raise and lower. It should be eventually replaced by a solution
- * involving only ZnItemsWithTagOrId. Especially when we'll
- * be about to implement expressions with tags (&& || ^ !, etc).
- * May be the best way is to sort the resulting list after
- * query and selection. Need to investigate how this will be
- * done.
- * Or may be it should be the other way round, discards
- * ZnItemsWithTagOrId and the tag table altogether. It
- * depends on the cost of the various operations.
+ * All tag search procs below are lifted from tkCanvas.c, then
+ * modified to match our needs.
*
- *----------------------------------------------------------------------
+ *--------------------------------------------------------------
*/
-static Item
-ZnSearchWithTagOrId(WidgetInfo *wi,
- Tcl_Obj *tag, /* NULL is the same as 'all' */
- Item group,
- TagSearch *tag_search)
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchExprInit --
+ *
+ * This procedure allocates and initializes one
+ * TagSearchExpr struct.
+ *
+ *--------------------------------------------------------------
+ */
+static void
+TagSearchExprInit(TagSearchExpr **expr_var)
{
- Tk_Uid uid, *tags;
- long id;
- char *str = NULL;
- int i, num_tags;
- Tcl_HashEntry *entry;
- Item item = ZN_NO_ITEM;
+ TagSearchExpr* expr = *expr_var;
+
+ if (! expr) {
+ expr = (TagSearchExpr *) ZnMalloc(sizeof(TagSearchExpr));
+ expr->allocated = 0;
+ expr->uids = NULL;
+ expr->next = NULL;
+ }
+ expr->uid = NULL;
+ expr->index = 0;
+ expr->length = 0;
+ *expr_var = expr;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchExprDestroy --
+ *
+ * This procedure destroys one TagSearchExpr structure.
+ *
+ *--------------------------------------------------------------
+ */
+static void
+TagSearchExprDestroy(TagSearchExpr *expr)
+{
+ if (expr) {
+ if (expr->uids) {
+ ZnFree(expr->uids);
+ }
+ ZnFree(expr);
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchScanExpr --
+ *
+ * This recursive procedure is called to scan a tag expression
+ * and compile it into an array of Tk_Uids.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression
+ * was successfully scanned (syntax).
+ * The information at *search is initialized
+ * such that a call to ZnTagSearchFirst, followed by
+ * successive calls to ZnTagSearchNext will return items
+ * that match tag.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+static int
+TagSearchScanExpr(Tcl_Interp *interp, /* Current interpreter. */
+ TagSearch *search, /* Search data */
+ TagSearchExpr *expr) /* Compiled expression result */
+{
+ int looking_for_tag; /* When true, scanner expects next char(s)
+ * to be a tag, else operand expected */
+ int found_tag; /* One or more tags found */
+ int found_endquote; /* For quoted tag string parsing */
+ int negate_result; /* Pending negation of next tag value */
+ char *tag; /* tag from tag expression string */
+ char c;
+
+ negate_result = 0;
+ found_tag = 0;
+ looking_for_tag = 1;
+ while (search->tag_index < search->tag_len) {
+ c = search->tag[search->tag_index++];
+
+ if (expr->allocated == expr->index) {
+ expr->allocated += 15;
+ if (expr->uids) {
+ expr->uids = (Tk_Uid *) ZnRealloc((char *) expr->uids,
+ expr->allocated * sizeof(Tk_Uid));
+ }
+ else {
+ expr->uids = (Tk_Uid *) ZnMalloc(expr->allocated * sizeof(Tk_Uid));
+ }
+ }
+
+ if (looking_for_tag) {
+ switch (c) {
+ case ' ': /* ignore unquoted whitespace */
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ case '!': /* negate next tag or subexpr */
+ if (looking_for_tag > 1) {
+ Tcl_AppendResult(interp, "Too many '!' in tag search expression",
+ (char *) NULL);
+ return ZN_ERROR;
+ }
+ looking_for_tag++;
+ negate_result = 1;
+ break;
+ case '(': /* scan (negated) subexpr recursively */
+ if (negate_result) {
+ expr->uids[expr->index++] = neg_paren_uid;
+ negate_result = 0;
+ }
+ else {
+ expr->uids[expr->index++] = paren_uid;
+ }
+ if (TagSearchScanExpr(interp, search, expr) != TCL_OK) {
+ /* Result string should be already set
+ * by nested call to tag_expr_scan() */
+ return ZN_ERROR;
+ }
+ looking_for_tag = 0;
+ found_tag = 1;
+ break;
+ case '"': /* quoted tag string */
+ if (negate_result) {
+ expr->uids[expr->index++] = neg_tag_val_uid;
+ negate_result = 0;
+ }
+ else {
+ expr->uids[expr->index++] = tag_val_uid;
+ }
+ tag = search->rewrite_buf;
+ found_endquote = 0;
+ while (search->tag_index < search->tag_len) {
+ c = search->tag[search->tag_index++];
+ if (c == '\\') {
+ c = search->tag[search->tag_index++];
+ }
+ if (c == '"') {
+ found_endquote = 1;
+ break;
+ }
+ *tag++ = c;
+ }
+ if (! found_endquote) {
+ Tcl_AppendResult(interp, "Missing endquote in tag search expression",
+ (char *) NULL);
+ return ZN_ERROR;
+ }
+ if (! (tag - search->rewrite_buf)) {
+ Tcl_AppendResult(interp,
+ "Null quoted tag string in tag search expression",
+ (char *) NULL);
+ return ZN_ERROR;
+ }
+ *tag++ = '\0';
+ expr->uids[expr->index++] = Tk_GetUid(search->rewrite_buf);
+ looking_for_tag = 0;
+ found_tag = 1;
+ break;
+ case '&': /* illegal chars when looking for tag */
+ case '|':
+ case '^':
+ case ')':
+ Tcl_AppendResult(interp, "Unexpected operator in tag search expression",
+ (char *) NULL);
+ return ZN_ERROR;
+ default: /* unquoted tag string */
+ if (negate_result) {
+ expr->uids[expr->index++] = neg_tag_val_uid;
+ negate_result = 0;
+ }
+ else {
+ expr->uids[expr->index++] = tag_val_uid;
+ }
+ tag = search->rewrite_buf;
+ *tag++ = c;
+ /* copy rest of tag, including any embedded whitespace */
+ while (search->tag_index < search->tag_len) {
+ c = search->tag[search->tag_index];
+ if ((c == '!') || (c == '&') || (c == '|') || (c == '^') ||
+ (c == '(') || (c == ')') || (c == '"')) {
+ break;
+ }
+ *tag++ = c;
+ search->tag_index++;
+ }
+ /* remove trailing whitespace */
+ while (1) {
+ c = *--tag;
+ /* there must have been one non-whitespace char,
+ * so this will terminate */
+ if ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r')) {
+ break;
+ }
+ }
+ *++tag = '\0';
+ expr->uids[expr->index++] = Tk_GetUid(search->rewrite_buf);
+ looking_for_tag = 0;
+ found_tag = 1;
+ }
+
+ }
+ else { /* ! looking_for_tag */
+ switch (c) {
+ case ' ' : /* ignore whitespace */
+ case '\t' :
+ case '\n' :
+ case '\r' :
+ break;
+ case '&' : /* AND operator */
+ c = search->tag[search->tag_index++];
+ if (c != '&') {
+ Tcl_AppendResult(interp, "Singleton '&' in tag search expression",
+ (char *) NULL);
+ return ZN_ERROR;
+ }
+ expr->uids[expr->index++] = and_uid;
+ looking_for_tag = 1;
+ break;
+ case '|' : /* OR operator */
+ c = search->tag[search->tag_index++];
+ if (c != '|') {
+ Tcl_AppendResult(interp, "Singleton '|' in tag search expression",
+ (char *) NULL);
+ return ZN_ERROR;
+ }
+ expr->uids[expr->index++] = or_uid;
+ looking_for_tag = 1;
+ break;
+ case '^' : /* XOR operator */
+ expr->uids[expr->index++] = xor_uid;
+ looking_for_tag = 1;
+ break;
+ case ')' : /* end subexpression */
+ expr->uids[expr->index++] = end_paren_uid;
+ goto breakwhile;
+ default : /* syntax error */
+ Tcl_AppendResult(interp,
+ "Invalid boolean operator in tag search expression",
+ (char *) NULL);
+ return ZN_ERROR;
+ }
+ }
+ }
+ breakwhile:
+ if (found_tag && ! looking_for_tag) {
+ return ZN_OK;
+ }
+ Tcl_AppendResult(interp, "Missing tag in tag search expression",
+ (char *) NULL);
+ return ZN_ERROR;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchEvalExpr --
+ *
+ * This recursive procedure is called to eval a tag expression.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression
+ * successfully matched the tags of the current item.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+static int
+TagSearchEvalExpr(TagSearchExpr *expr, /* Search expression */
+ Item item) /* Item being test for match */
+{
+ int looking_for_tag; /* When true, scanner expects next char(s)
+ * to be a tag, else operand expected */
+ int negate_result; /* Pending negation of next tag value */
+ Tk_Uid uid;
+ Tk_Uid *tags;
+ int count;
+ int result=0; /* Value of expr so far */
+ int paren_depth;
+ negate_result = 0;
+ looking_for_tag = 1;
+ while (expr->index < expr->length) {
+ uid = expr->uids[expr->index++];
+ if (looking_for_tag) {
+ if (uid == tag_val_uid) {
+ /*
+ * assert(expr->index < expr->length);
+ */
+ uid = expr->uids[expr->index++];
+ result = 0;
+ /*
+ * set result 1 if tag is found in item's tags
+ */
+ if (item->tags) {
+ tags = (Tk_Uid *) ZnListArray(item->tags);
+ count = ZnListSize(item->tags);
+ for (; count > 0; tags++, count--) {
+ if (*tags == uid) {
+ result = 1;
+ break;
+ }
+ }
+ }
+ }
+ else if (uid == neg_tag_val_uid) {
+ negate_result = ! negate_result;
+ /*
+ * assert(expr->index < expr->length);
+ */
+ uid = expr->uids[expr->index++];
+ result = 0;
+ /*
+ * set result 1 if tag is found in item's tags
+ */
+ if (item->tags) {
+ tags = (Tk_Uid *) ZnListArray(item->tags);
+ count = ZnListSize(item->tags);
+ for (; count > 0; tags++, count--) {
+ if (*tags == uid) {
+ result = 1;
+ break;
+ }
+ }
+ }
+ }
+ else if (uid == paren_uid) {
+ /*
+ * evaluate subexpressions with recursion
+ */
+ result = TagSearchEvalExpr(expr, item);
+ }
+ else if (uid == neg_paren_uid) {
+ negate_result = ! negate_result;
+ /*
+ * evaluate subexpressions with recursion
+ */
+ result = TagSearchEvalExpr(expr, item);
+ /*
+ * } else {
+ * assert(0);
+ */
+ }
+ if (negate_result) {
+ result = ! result;
+ negate_result = 0;
+ }
+ looking_for_tag = 0;
+ }
+ else { /* ! looking_for_tag */
+ if (((uid == and_uid) && (!result)) || ((uid == or_uid) && result)) {
+ /*
+ * short circuit expression evaluation
+ *
+ * if result before && is 0, or result before || is 1, then
+ * the expression is decided and no further evaluation is needed.
+ */
+ paren_depth = 0;
+ while (expr->index < expr->length) {
+ uid = expr->uids[expr->index++];
+ if ((uid == tag_val_uid) || (uid == neg_tag_val_uid)) {
+ expr->index++;
+ continue;
+ }
+ if ((uid == paren_uid) || (uid == neg_paren_uid)) {
+ paren_depth++;
+ continue;
+ }
+ if (uid == end_paren_uid) {
+ paren_depth--;
+ if (paren_depth < 0) {
+ break;
+ }
+ }
+ }
+ return result;
+
+ }
+ else if (uid == xor_uid) {
+ /*
+ * if the previous result was 1 then negate the next result.
+ */
+ negate_result = result;
+ }
+ else if (uid == end_paren_uid) {
+ return result;
+ /*
+ * } else {
+ * assert(0);
+ */
+ }
+ looking_for_tag = 1;
+ }
+ }
/*
- * First init the search iterator.
+ * assert(! looking_for_tag);
*/
- tag_search->wi = wi;
- tag_search->over = False;
- tag_search->item_stack = ZnListNew(16, sizeof(Item));
- tag_search->group = (GroupItem) group;
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ZnTagSearchScan --
+ *
+ * This procedure is called to initiate an enumeration of
+ * all items in a given zinc that contain a tag that matches
+ * the tagOrId expression.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression
+ * was successfully scanned (syntax).
+ * The information at *search is initialized such that a
+ * call to ZnTagSearchFirst, followed by successive calls
+ * to ZnTagSearchNext will return items that match tag.
+ *
+ * Side effects:
+ * search is linked into a list of searches in progress
+ * in zinc, so that elements can safely be deleted while
+ * the search is in progress.
+ *
+ *--------------------------------------------------------------
+ */
+static int
+ZnTagSearchScan(WidgetInfo *wi,
+ Tcl_Obj *tag_obj, /* Object giving tag value, NULL
+ * is the same as 'all'. */
+ TagSearch **search_var) /* Record describing tag search;
+ * will be initialized here. */
+{
+ char *tag;
+ int i;
+ TagSearch *search;
+
+ if (tag_obj) {
+ tag = Tcl_GetString(tag_obj);
+ }
+ else {
+ tag = all_uid;
+ }
+
/*
- * Try to consider the tag as an item id.
+ * Initialize the search.
*/
- if (tag) {
- str = Tcl_GetString(tag);
- if (isdigit(str[0])) {
- if (Tcl_GetLongFromObj(wi->interp, tag, &id) == ZN_OK) {
- entry = Tcl_FindHashEntry(wi->id_table, (char *) id);
- if (entry != NULL) {
- item = (Item) Tcl_GetHashValue(entry);
+ if (*search_var) {
+ search = *search_var;
+ }
+ else {
+ /* Allocate primary search struct on first call */
+ *search_var = search = (TagSearch *) ZnMalloc(sizeof(TagSearch));
+ search->expr = NULL;
+
+ /* Allocate buffer for rewritten tags (after de-escaping) */
+ search->rewrite_buf_alloc = 100;
+ search->rewrite_buf = ZnMalloc(search->rewrite_buf_alloc);
+ search->item_stack = ZnListNew(16, sizeof(Item));
+ }
+ TagSearchExprInit(&(search->expr));
+
+ /* How long is the tagOrId ? */
+ search->tag_len = strlen(tag);
+
+ /* Make sure there is enough buffer to hold rewritten tags */
+ if ((unsigned int)search->tag_len >= search->rewrite_buf_alloc) {
+ search->rewrite_buf_alloc = search->tag_len + 100;
+ search->rewrite_buf = ZnRealloc(search->rewrite_buf,
+ search->rewrite_buf_alloc);
+ }
+
+ /* Initialize search */
+ search->wi = wi;
+ search->over = False;
+ search->type = 0;
+ search->group = (GroupItem) wi->top_group;
+ search->recursive = True;
+ ZnListEmpty(search->item_stack);
+
+ /*
+ * Find the first matching item in one of several ways. If the tag
+ * is a number then it selects the single item with the matching
+ * identifier.
+ */
+ if (search->tag_len && isdigit(*tag)) {
+ char *end;
+
+ search->id = strtoul(tag, &end, 0);
+ if (*end == 0) {
+ search->type = 1;
+ return ZN_OK;
+ }
+ }
+
+ /*
+ * For all other tags and tag expressions convert to a UID.
+ * This UID is kept forever, but this should be thought of
+ * as a cache rather than as a memory leak.
+ */
+ search->expr->uid = Tk_GetUid(tag);
+
+ /* short circuit impossible searches for null tags */
+ if (search->tag_len == 0) {
+ return TCL_OK;
+ }
+
+ /*
+ * Pre-scan tag for at least one unquoted "&&" "||" "^" "!"
+ * if not found then use string as simple tag
+ */
+ for (i = 0; i < search->tag_len; i++) {
+ if (tag[i] == '"') {
+ i++;
+ for ( ; i < search->tag_len; i++) {
+ if (tag[i] == '\\') {
+ i++;
+ continue;
}
- Tcl_ResetResult(wi->interp);
- tag_search->over = True;
- return item;
+ if (tag[i] == '"') {
+ break;
+ }
+ }
+ }
+ else {
+ if (((tag[i] == '&') && (tag[i+1] == '&')) ||
+ ((tag[i] == '|') && (tag[i+1] == '|')) ||
+ (tag[i] == '^') || (tag[i] == '!')) {
+ search->type = 4;
+ break;
}
}
}
-
+
+ search->tag = tag;
+ search->tag_index = 0;
+ if (search->type == 4) {
/*
- * Now look for a tag.
- */
- if (!tag) {
- tag_search->tag = uid = all_uid;
+ * an operator was found in the prescan, so
+ * now compile the tag expression into array of Tk_Uid
+ * flagging any syntax errors found
+ */
+ if (TagSearchScanExpr(wi->interp, search, search->expr) != ZN_OK) {
+ /* Syntax error in tag expression */
+ /* Result message set by TagSearchScanExpr */
+ return ZN_ERROR;
+ }
+ search->expr->length = search->expr->index;
}
else {
- tag_search->tag = uid = Tk_GetUid(str);
+ if (search->expr->uid == all_uid) {
+ /*
+ * All items match.
+ */
+ search->type = 2;
+ }
+ else {
+ /*
+ * Optimized single-tag search
+ */
+ search->type = 3;
+ }
}
+ return ZN_OK;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ZnTagSearchFirst --
+ *
+ * This procedure is called to get the first item
+ * item that matches a preestablished search predicate
+ * that was set by TagSearchScan.
+ *
+ * Results:
+ * The return value is a pointer to the first item, or NULL
+ * if there is no such item. The information at *search
+ * is updated such that successive calls to ZnTagSearchNext
+ * will return successive items.
+ *
+ * Side effects:
+ * *search is linked into a list of searches in progress
+ * in zinc, so that elements can safely be deleted while
+ * the search is in progress.
+ *
+ *--------------------------------------------------------------
+ */
+static Item
+ZnTagSearchFirst(TagSearch *search, /* Record describing tag search */
+ Item group, /* Start group */
+ ZnBool recursive) /* Does the search walk down the
+ * tree ? */
+{
+ Item item, previous;
+ Tk_Uid uid, *tags;
+ int count;
+
+ /* short circuit impossible searches for null tags */
+ if (search->tag_len == 0) {
+ return ZN_NO_ITEM;
+ }
+
+ search->group = (GroupItem) group;
+ search->recursive = recursive;
- if (uid == all_uid) {
- tag_search->current = tag_search->group->head;
- tag_search->previous = ZN_NO_ITEM;
- return group;
+ /*
+ * Find the first matching item in one of several ways. If the tag
+ * is a number then it selects the single item with the matching
+ * identifier. In this case see if the item being requested is the
+ * hot item, in which case the search can be skipped.
+ */
+ if (search->type == 1) {
+ Tcl_HashEntry *entry;
+
+ item = search->wi->hot_item;
+ previous = search->wi->hot_prev;
+ if ((item == ZN_NO_ITEM) || (item->id != search->id) ||
+ (previous == ZN_NO_ITEM) || (previous->next != item)) {
+ entry = Tcl_FindHashEntry(search->wi->id_table, (char *) search->id);
+ if (entry != NULL) {
+ item = (Item) Tcl_GetHashValue(entry);
+ previous = item->previous;
+ }
+ else {
+ previous = item = ZN_NO_ITEM;
+ }
+ }
+ search->previous = previous;
+ search->over = True;
+ search->wi->hot_item = item;
+ search->wi->hot_prev = previous;
+ return item;
+ }
+
+ if (search->type == 2) {
+ /*
+ * All items match.
+ */
+ search->previous = ZN_NO_ITEM;
+ search->current = (Item) search->group->head;
+ return search->current;
}
- item = group;
+ uid = search->expr->uid;
+ item = (Item) search->group->head;
+ previous = ZN_NO_ITEM;
do {
while (item != ZN_NO_ITEM) {
- if (item->tags) {
- tags = (Tk_Uid *) ZnListArray(item->tags);
- num_tags = ZnListSize(item->tags);
- for (i = 0; i < num_tags; i++, tags++) {
- if (*tags == uid) {
- tag_search->current = item;
- tag_search->previous = item->previous;
- return item;
+ if (search->type == 3) {
+ /*
+ * Optimized single-tag search
+ */
+ if (item->tags) {
+ tags = (Tk_Uid *) ZnListArray(item->tags);
+ count = ZnListSize(item->tags);
+ for (; count > 0; tags++, count--) {
+ if (*tags == uid) {
+ search->previous = previous;
+ search->current = item;
+ return item;
+ }
}
}
}
- if (item->class == ZnGroup) {
+ else {
+ /*
+ * Type = 4. Search for an item matching
+ * the tag expression.
+ */
+ search->expr->index = 0;
+ if (TagSearchEvalExpr(search->expr, item)) {
+ search->previous = previous;
+ search->current = item;
+ return item;
+ }
+ }
+ if ((item->class == ZnGroup) && (search->recursive)) {
/*
* Explore the hierarchy depth first using the item stack
* to save the current node.
*/
- /*printf("ZnSearchWithTagOrId diving for tag\n");*/
- tag_search->group = (GroupItem) item;
- item = item->next;
- ZnListAdd(tag_search->item_stack, &item, ZnListTail);
- item = tag_search->group->head;
+ /*printf("ZnTagSearchFirst diving for tag '%s', detph %d\n",
+ search->tag, ZnListSize(search->item_stack)/2);*/
+ search->group = (GroupItem) item;
+ previous = item;
+ if (item == group) {
+ item = ZN_NO_ITEM;
+ }
+ else {
+ item = item->next;
+ }
+ ZnListAdd(search->item_stack, &previous, ZnListTail);
+ ZnListAdd(search->item_stack, &item, ZnListTail);
+ previous = ZN_NO_ITEM;
+ item = search->group->head;
}
else {
+ previous = item;
item = item->next;
}
}
- /*printf("ZnSearchWithTagOrId backup for tag\n");*/
- while ((item == ZN_NO_ITEM) && ZnListSize(tag_search->item_stack)) {
- item = *(Item *) ZnListAt(tag_search->item_stack, ZnListTail);
- ZnListDelete(tag_search->item_stack, ZnListTail);
+ /*
+ * Continue search on higher group level.
+ */
+ /*printf("ZnTagSearchFirst backup for tag, detph %d\n",
+ ZnListSize(search->item_stack)/2);*/
+ while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
+ item = *(Item *) ZnListAt(search->item_stack, ZnListTail);
+ ZnListDelete(search->item_stack, ZnListTail);
+ previous = *(Item *) ZnListAt(search->item_stack, ZnListTail);
+ ZnListDelete(search->item_stack, ZnListTail);
}
if (item != ZN_NO_ITEM) {
- tag_search->group = (GroupItem) item->parent;
+ search->group = (GroupItem) item->parent;
}
} while (item != ZN_NO_ITEM);
- tag_search->over = True;
- ZnListFree(tag_search->item_stack);
+ search->previous = previous;
+ search->over = True;
return ZN_NO_ITEM;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ZnTagSearchNext --
+ *
+ * This procedure returns successive items that match a given
+ * tag; it should be called only after ZnTagSearchFirst has
+ * been used to begin a search.
+ *
+ * Results:
+ * The return value is a pointer to the next item that matches
+ * the tag expr specified to TagSearchScan, or NULL if no such
+ * item exists. *search is updated so that the next call
+ * to this procedure will return the next item.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
static Item
-ZnNextWithTagOrId(TagSearch *tag_search)
+ZnTagSearchNext(TagSearch *search) /* Record describing search in progress. */
{
- Item item, previous;
- Tk_Uid uid, *tags;
- int i, num_tags;
-
- if (tag_search->over) {
+ Item item, previous;
+ Tk_Uid uid, *tags;
+ int count;
+
+ if (search->over) {
return ZN_NO_ITEM;
}
- previous = tag_search->previous;
+ /*
+ * Find next item in list (this may not actually be a suitable
+ * one to return), and return if there are no items left.
+ */
+ previous = search->previous;
if (previous == ZN_NO_ITEM) {
- item = tag_search->group->head;
+ item = search->group->head;
}
else {
item = previous->next;
}
- if (item != tag_search->current) {
+ if (item != search->current) {
/*
- * The list has been edited and the previously
- * returned item is gone. Don't step forward,
- * just process the new next item. (What happen
- * if the previous item is destroyed too. Do we
- * NULLify the next pointer in this case ?)
+ * The structure of the list has changed. Probably the
+ * previously-returned item was removed from the list.
+ * In this case, don't advance previous; just return
+ * its new successor (i.e. do nothing here).
*/
-
}
- else if (item->class == ZnGroup){
+ else if ((item->class == ZnGroup) && (search->recursive)) {
/*
* Explore the hierarchy depth first using the item stack
* to save the current node.
*/
- tag_search->group = (GroupItem) item;
+ search->group = (GroupItem) item;
+ previous = item;
item = item->next;
- /*printf("ZnNextWithTagOrId diving for all, pushing %d\n",
+ /*printf("ZnTagSearchNext diving for all, pushing %d\n",
item?item->id:0);*/
- ZnListAdd(tag_search->item_stack, &item, ZnListTail);
+ ZnListAdd(search->item_stack, &previous, ZnListTail);
+ ZnListAdd(search->item_stack, &item, ZnListTail);
previous = ZN_NO_ITEM;
- item = tag_search->group->head;
+ item = search->group->head;
}
else {
previous = item;
item = previous->next;
}
-
+
if (item == ZN_NO_ITEM) {
- /*printf("ZnNextWithTagOrId backup for all\n");*/
- while ((item == ZN_NO_ITEM) && ZnListSize(tag_search->item_stack)) {
+ while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
/*
* End of list at this level, back up one level.
*/
- item = *(Item *) ZnListAt(tag_search->item_stack, ZnListTail);
- ZnListDelete(tag_search->item_stack, ZnListTail);
+ item = *(Item *) ZnListAt(search->item_stack, ZnListTail);
+ ZnListDelete(search->item_stack, ZnListTail);
+ previous = *(Item *) ZnListAt(search->item_stack, ZnListTail);
+ ZnListDelete(search->item_stack, ZnListTail);
}
if (item != ZN_NO_ITEM) {
- tag_search->group = (GroupItem) item->parent;
- previous = item->previous;
- /*printf("ZnNextWithTagOrId popping %d, previous %d, next %d\n",
+ search->group = (GroupItem) item->parent;
+ /*printf("ZnTagSearchNext popping %d, previous %d, next %d\n",
item->id, (item->previous)?item->previous->id:0,
(item->next)?item->next->id:0);*/
}
@@ -765,78 +1422,111 @@ ZnNextWithTagOrId(TagSearch *tag_search)
/*
* Or finish the search if at top.
*/
- tag_search->over = True;
- ZnListFree(tag_search->item_stack);
+ search->over = True;
return ZN_NO_ITEM;
}
}
- /*
- * Handle the tag 'all' by returning the next item.
- */
- uid = tag_search->tag;
- if (uid == all_uid) {
- tag_search->previous = previous;
- tag_search->current = item;
- /*printf("ZnNextWithTagOrId returning %d\n", item->id);*/
+ if (search->type == 2) {
+ /*
+ * All items match.
+ */
+ search->previous = previous;
+ search->current = item;
return item;
}
-
- /*
- * Now, look for the requested tag in an item.
- */
+
+ uid = search->expr->uid;
do {
while (item != ZN_NO_ITEM) {
- if (item->tags) {
- tags = (Tk_Uid *) ZnListArray(item->tags);
- num_tags = ZnListSize(item->tags);
- for (i = 0; i < num_tags; i++, tags++) {
- if (*tags == uid) {
- tag_search->current = item;
- tag_search->previous = item->previous;
- return item;
+ if (search->type == 3) {
+ /*
+ * Optimized single-tag search
+ */
+ if (item->tags) {
+ tags = (Tk_Uid *) ZnListArray(item->tags);
+ count = ZnListSize(item->tags);
+ for ( ; count > 0; tags++, count--) {
+ if (*tags == uid) {
+ search->previous = previous;
+ search->current = item;
+ return item;
+ }
}
}
}
- if (item->class == ZnGroup) {
+ else {
+ /*
+ * Else.... evaluate tag expression
+ */
+ search->expr->index = 0;
+ if (TagSearchEvalExpr(search->expr, item)) {
+ search->previous = previous;
+ search->current = item;
+ return item;
+ }
+ }
+ if ((item->class == ZnGroup) && (search->recursive)) {
/*
* Explore the hierarchy depth first using the item stack
* to save the current node.
*/
- /*printf("ZnNextWithTagOrId diving for tag\n");*/
- tag_search->group = (GroupItem) item;
+ /*printf("ZnTagSearchNext diving for tag, depth %d\n",
+ ZnListSize(search->item_stack)/2);*/
+ search->group = (GroupItem) item;
+ previous = item;
item = item->next;
- ZnListAdd(tag_search->item_stack, &item, ZnListTail);
- item = tag_search->group->head;
+ ZnListAdd(search->item_stack, &previous, ZnListTail);
+ ZnListAdd(search->item_stack, &item, ZnListTail);
+ previous = ZN_NO_ITEM;
+ item = search->group->head;
}
else {
+ previous = item;
item = item->next;
}
}
- /*printf("ZnNextWithTagOrId backup for tag\n");*/
- while ((item == ZN_NO_ITEM) && ZnListSize(tag_search->item_stack)) {
- item = *(Item *) ZnListAt(tag_search->item_stack, ZnListTail);
- ZnListDelete(tag_search->item_stack, ZnListTail);
+ /*printf("ZnTagSearchNext backup for tag, depth %d\n",
+ ZnListSize(search->item_stack)/2);*/
+ while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
+ item = *(Item *) ZnListAt(search->item_stack, ZnListTail);
+ ZnListDelete(search->item_stack, ZnListTail);
+ previous = *(Item *) ZnListAt(search->item_stack, ZnListTail);
+ ZnListDelete(search->item_stack, ZnListTail);
}
if (item != ZN_NO_ITEM) {
- tag_search->group = (GroupItem) item->parent;
+ search->group = (GroupItem) item->parent;
}
} while (item != ZN_NO_ITEM);
/*
* Out of fuel.
*/
- tag_search->over = True;
- ZnListFree(tag_search->item_stack);
+ search->previous = previous;
+ search->over = True;
+
return ZN_NO_ITEM;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ZnTagSearchDestroy --
+ *
+ * This procedure destroys any dynamic structures that
+ * may have been allocated by TagSearchScan.
+ *
+ *--------------------------------------------------------------
+ */
void
-ZnDoneWithSearch(TagSearch *tag_search)
+ZnTagSearchDestroy(TagSearch *search) /* Record describing tag search */
{
- if (!tag_search->over) {
- tag_search->over = True;
- ZnListFree(tag_search->item_stack);
+ if (search) {
+ TagSearchExprDestroy(search->expr);
+ ZnListFree(search->item_stack);
+ ZnFree(search->rewrite_buf);
+ ZnFree(search);
}
}
@@ -844,108 +1534,27 @@ ZnDoneWithSearch(TagSearch *tag_search)
/*
*----------------------------------------------------------------------
*
- * ZnItemsWithTagOrId --
- *
- * Collect the item(s) with the given tag or id. The function
- * return the the first item matched in item and the whole
- * search result in item_list, if not NULL.
- * The function return value is always the total number of
- * items matched.
- * If nothing can be found, the function returns 0 and leave a
- * message in the interp result. No other values are returned.
+ * ZnItemWithTagOrId --
*
- * The caller must at least give the item parameter a legal
- * value.
+ * Return the first item matching the given tag or id. The
+ * function returns the item in 'item' and the operation
+ * status as the function's value.
*
*----------------------------------------------------------------------
*/
int
-ZnItemsWithTagOrId(WidgetInfo *wi,
- Tcl_Obj *tag_or_id,
- Item *item,
- Item **item_list)
+ZnItemWithTagOrId(WidgetInfo *wi,
+ Tcl_Obj *tag_or_id,
+ Item group,
+ ZnBool recursive,
+ Item *item,
+ TagSearch **search_var)
{
- unsigned long id;
- Tcl_HashEntry *entry;
- Tk_Uid tag_uid;
- ZnList items;
- int num_items;
- char *str;
-
- str = Tcl_GetString(tag_or_id);
- if (isdigit(str[0])) {
- if (Tcl_GetLongFromObj(wi->interp, tag_or_id, &id) == ZN_OK) {
- Tcl_ResetResult(wi->interp);
- entry = Tcl_FindHashEntry(wi->id_table, (char *) id);
- if (entry == NULL) {
- Tcl_AppendResult(wi->interp, "item \"", str, "\" doesn't exist", NULL);
- return 0;
- }
- *item = (Item) Tcl_GetHashValue(entry);
- if (item_list) {
- *item_list = item;
- }
- return 1;
- }
- }
-
- /*
- * It is a tag, try to find it and return the whole list.
- */
- tag_uid = Tk_GetUid(str);
-
- /*
- * If it is 'all' then build a list of all the items
- * in the display list.
- * BE CAREFUL this won't work recursively !! A tag
- * search for 'all' can't be started if the result
- * of a previous one is still in use in the same widget.
- */
- if (tag_uid == all_uid) {
- Item current;
- TagSearch ts;
-
- if (wi->work_item_list) {
- ZnListEmpty(wi->work_item_list);
- }
- else {
- wi->work_item_list = ZnListNew(128, sizeof(Item));
- }
- for (current = ZnSearchWithTagOrId(wi, NULL, wi->top_group, &ts);
- current != NULL; current = ZnNextWithTagOrId(&ts)) {
- ZnListAdd(wi->work_item_list, &current, ZnListTail);
- }
- if (ZnListSize(wi->work_item_list) != 0) {
- *item = *((Item *) ZnListAt(wi->work_item_list, 0));
- if (item_list) {
- *item_list = (Item *) ZnListArray(wi->work_item_list);
- }
- }
- return ZnListSize(wi->work_item_list);
- }
-
- /*
- * Else, probe the tag table.
- */
- entry = Tcl_FindHashEntry(wi->tag_table, tag_uid);
- if (entry) {
- items = (ZnList) Tcl_GetHashValue(entry);
- num_items = ZnListSize(items);
- if (num_items) {
- if (item_list) {
- *item_list = (Item *) ZnListArray(items);
- *item = (*item_list)[0];
- }
- else {
- *item = *((Item *) ZnListAt(items, 0));
- }
- }
- return num_items;
- }
- else {
- Tcl_AppendResult(wi->interp, "unknown tag \"", tag_uid, "\"", NULL);
- return 0;
+ if (ZnTagSearchScan(wi, tag_or_id, search_var) != ZN_OK) {
+ return ZN_ERROR;
}
+ *item = ZnTagSearchFirst(*search_var, group, recursive);
+ return ZN_OK;
}
@@ -985,27 +1594,6 @@ DoItem(Tcl_Interp *interp,
/*
*----------------------------------------------------------------------
*
- * IsHeirOf --
- * Tells if item is a descendant, either direct or indirect,
- * of group.
- *
- *----------------------------------------------------------------------
- */
-static ZnBool
-IsHeirOf(Item item,
- Item group)
-{
- while ((item != ZN_NO_ITEM) && (item != group)) {
- item = item->parent;
- }
-
- return (item != ZN_NO_ITEM);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
* FindArea --
* Search the items that are enclosed or overlapping a given
* area of the widget. It is used by FindItems.
@@ -1023,8 +1611,7 @@ static int
FindArea(WidgetInfo *wi,
Tcl_Obj *CONST args[],
Tk_Uid tag_uid,
- Item group,
- int enclosed)
+ ZnBool enclosed)
{
ZnPos pos;
ZnBBox area;
@@ -1058,9 +1645,6 @@ FindArea(WidgetInfo *wi,
area.corner.x -= wi->inset;
area.corner.y -= wi->inset;
- /*
- * BUG: The starting group should be considered instead of top_group.!!
- */
wi->top_group->class->ToArea(wi->top_group, &area, tag_uid, enclosed, False);
return ZN_OK;
@@ -1087,18 +1671,19 @@ FindItems(WidgetInfo *wi,
int argc,
Tcl_Obj *CONST args[],
Tcl_Obj *tag, /* NULL to search or tag to add tag. */
- int first) /* First arg to process in args */
+ int first, /* First arg to process in args */
+ TagSearch **search_var)
{
Tk_Uid tag_uid = NULL;
- TagSearch ts;
- int index, num_items;
+ ZnBool recursive = True;
+ int index, result;
Item item, group = wi->top_group;
static char *search_cmd_strings[] = {
- "above", "all", "atpoint", "atpriority", "below", "enclosed",
+ "above", "all", "atpriority", "below", "closest", "enclosed",
"overlapping", "withtag", "withtype", NULL
};
enum search_cmds {
- ZN_S_ABOVE, ZN_S_ALL, ZN_S_ATPOINT, ZN_S_ATPRIORITY, ZN_S_BELOW,
+ ZN_S_ABOVE, ZN_S_ALL, ZN_S_ATPRIORITY, ZN_S_BELOW, ZN_S_CLOSEST,
ZN_S_ENCLOSED, ZN_S_OVERLAPPING, ZN_S_WITHTAG, ZN_S_WITHTYPE
};
@@ -1117,18 +1702,29 @@ FindItems(WidgetInfo *wi,
*/
case ZN_S_ABOVE:
{
- if ((argc != first+2) && (argc != first+3)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId ?inGroup?");
+ if ((argc < first+2) || (argc > first+4)) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args,
+ "tagOrId ?inGroup? ?recursive?");
return ZN_ERROR;
}
- if (argc == first+3) {
- num_items = ZnItemsWithTagOrId(wi, args[first+2], &group, NULL);
- if ((num_items == 0) || (group->class != ZnGroup)) {
+ if (argc == first+4) {
+ if (Tcl_GetBooleanFromObj(wi->interp, args[first+3],
+ &recursive) != ZN_OK) {
+ return ZN_ERROR;
+ }
+ }
+ if (argc > first+2) {
+ result = ZnItemWithTagOrId(wi, args[first+2], wi->top_group, True,
+ &group, search_var);
+ if ((result == ZN_ERROR) || (group == ZN_NO_ITEM) ||
+ (group->class != ZnGroup)) {
return ZN_ERROR;
}
}
- item = ZnSearchWithTagOrId(wi, args[first+1], group, &ts);
- if ((item != ZN_NO_ITEM) && (item->previous != ZN_NO_ITEM)) {
+ result = ZnItemWithTagOrId(wi, args[first+1], group, recursive,
+ &item, search_var);
+ if ((result == ZN_OK) &&
+ (item != ZN_NO_ITEM) && (item->previous != ZN_NO_ITEM)) {
DoItem(wi->interp, item->previous, ZN_NO_PART, tag_uid);
}
}
@@ -1138,13 +1734,21 @@ FindItems(WidgetInfo *wi,
*/
case ZN_S_ALL:
{
- if ((argc != first+1) && (argc != first+2)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "?inGroup?");
+ if ((argc < first+1) || (argc > first+3)) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args, "?inGroup? ?recursive?");
return ZN_ERROR;
}
- if (argc == first+2) {
- num_items = ZnItemsWithTagOrId(wi, args[first+1], &group, NULL);
- if ((num_items == 0) || (group->class != ZnGroup)) {
+ if (argc == first+3) {
+ if (Tcl_GetBooleanFromObj(wi->interp, args[first+2],
+ &recursive) != ZN_OK) {
+ return ZN_ERROR;
+ }
+ }
+ if (argc > first+1) {
+ result = ZnItemWithTagOrId(wi, args[first+1], wi->top_group, True,
+ &group, search_var);
+ if ((result == ZN_ERROR) || (group == ZN_NO_ITEM) ||
+ (group->class != ZnGroup)) {
return ZN_ERROR;
}
}
@@ -1153,65 +1757,15 @@ FindItems(WidgetInfo *wi,
* Go through the item list and collect all item ids. They
* are sorted from most visible to least visible.
*/
- for (item = ZnSearchWithTagOrId(wi, NULL, group, &ts);
- item != ZN_NO_ITEM; item = ZnNextWithTagOrId(&ts)) {
+ if (ZnTagSearchScan(wi, NULL, search_var) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ for (item = ZnTagSearchFirst(*search_var, group, recursive);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
DoItem(wi->interp, item, ZN_NO_PART, tag_uid);
}
}
break;
- /*
- * atpoint
- */
- case ZN_S_ATPOINT:
- {
- int halo = 1;
- ZnPoint p;
- int part = ZN_NO_PART;
- Item start_item = ZN_NO_ITEM;
-
- if ((argc < first+3) || (argc > first+5)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "x y ?halo? ?start?");
- return ZN_ERROR;
- }
- if (Tcl_GetDoubleFromObj(wi->interp, args[first+1], &p.x) == ZN_ERROR) {
- return ZN_ERROR;
- }
- if (Tcl_GetDoubleFromObj(wi->interp, args[first+2], &p.y) == ZN_ERROR) {
- return ZN_ERROR;
- }
- p.x -= wi->inset;
- p.y -= wi->inset;
- if (argc > first+3) {
- if (Tcl_GetIntFromObj(wi->interp, args[first+3], &halo) == ZN_ERROR) {
- return ZN_ERROR;
- }
- if (halo < 0) {
- halo = 0;
- }
- }
- if (argc > first+4) {
- start_item = ZnSearchWithTagOrId(wi, args[first+4], group, &ts);
- if (start_item != ZN_NO_ITEM) {
- start_item = start_item->next;
- }
- }
- /*
- * We always start the search at the top group to use the
- * transform and clip machinery of the group item. The items
- * are not required to cache the device coords, etc. So we need
- * to setup the correct context before calling the Pick method
- * for each item.
- */
- wi->top_group->class->Pick(wi->top_group, &p, start_item, halo,
- &item, &part);
-
- if (item != ZN_NO_ITEM) {
- DoItem(wi->interp, item, part, tag_uid);
- /*printf("first %d %d\n", item->id, part);*/
- return TCL_OK;
- }
- }
- break;
/*
* atpriority
*/
@@ -1219,16 +1773,24 @@ FindItems(WidgetInfo *wi,
{
int pri;
- if ((argc != first+2) && (argc != first+3)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "pri ?inGroup?");
+ if ((argc < first+2) || (argc > first+4)) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args, "pri ?inGroup? ?recursive?");
return ZN_ERROR;
}
+ if (argc == first+4) {
+ if (Tcl_GetBooleanFromObj(wi->interp, args[first+3],
+ &recursive) != ZN_OK) {
+ return ZN_ERROR;
+ }
+ }
if (Tcl_GetIntFromObj(wi->interp, args[first+1], &pri) == ZN_ERROR) {
return ZN_ERROR;
}
- if (argc == first+3) {
- num_items = ZnItemsWithTagOrId(wi, args[first+2], &group, NULL);
- if ((num_items == 0) || (group->class != ZnGroup)) {
+ if (argc > first+2) {
+ result = ZnItemWithTagOrId(wi, args[first+2], wi->top_group, True,
+ &group, search_var);
+ if ((result == ZN_ERROR) || (group == ZN_NO_ITEM) ||
+ (group->class != ZnGroup)) {
return ZN_ERROR;
}
}
@@ -1237,8 +1799,11 @@ FindItems(WidgetInfo *wi,
* Go through the item table and collect all items with
* the given priority.
*/
- for (item = ZnSearchWithTagOrId(wi, NULL, group, &ts);
- item != ZN_NO_ITEM; item = ZnNextWithTagOrId(&ts)) {
+ if (ZnTagSearchScan(wi, NULL, search_var) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ for (item = ZnTagSearchFirst(*search_var, group, recursive);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
if (item->priority == pri) {
DoItem(wi->interp, item, ZN_NO_PART, tag_uid);
}
@@ -1252,19 +1817,31 @@ FindItems(WidgetInfo *wi,
{
Item next;
- if ((argc != first+2) && (argc != first+3)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId $inGroup?");
+ if ((argc < first+2) || (argc > first+4)) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args,
+ "tagOrId $inGroup? ?recursive?");
return ZN_ERROR;
}
- if (argc == first+3) {
- num_items = ZnItemsWithTagOrId(wi, args[first+2], &group, NULL);
- if ((num_items == 0) || (group->class != ZnGroup)) {
+ if (argc == first+4) {
+ if (Tcl_GetBooleanFromObj(wi->interp, args[first+3],
+ &recursive) != ZN_OK) {
+ return ZN_ERROR;
+ }
+ }
+ if (argc > first+2) {
+ result = ZnItemWithTagOrId(wi, args[first+2], wi->top_group, True,
+ &group, search_var);
+ if ((result == ZN_ERROR) || (group == ZN_NO_ITEM) ||
+ (group->class != ZnGroup)) {
return ZN_ERROR;
}
}
item = ZN_NO_ITEM;
- for (next = ZnSearchWithTagOrId(wi, args[first+1], group, &ts);
- next != ZN_NO_ITEM; item = ZnNextWithTagOrId(&ts)) {
+ if (ZnTagSearchScan(wi, args[first+1], search_var) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ for (next = ZnTagSearchFirst(*search_var, group, recursive);
+ next != ZN_NO_ITEM; next = ZnTagSearchNext(*search_var)) {
item = next;
}
if ((item != ZN_NO_ITEM) && (item->next != ZN_NO_ITEM)) {
@@ -1273,21 +1850,70 @@ FindItems(WidgetInfo *wi,
}
break;
/*
- * enclosed
+ * closest
*/
- case ZN_S_ENCLOSED:
+ case ZN_S_CLOSEST:
{
- if ((argc != first+5) && (argc != first+6)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "x1 y1 x2 y2 ?inGroup?");
+ int halo = 1;
+ ZnPoint p;
+ int part = ZN_NO_PART;
+ Item start_item = ZN_NO_ITEM;
+
+ if ((argc < first+3) || (argc > first+5)) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args, "x y ?halo? ?start?");
+ return ZN_ERROR;
+ }
+ if (Tcl_GetDoubleFromObj(wi->interp, args[first+1], &p.x) == ZN_ERROR) {
return ZN_ERROR;
}
- if (argc == first+6) {
- num_items = ZnItemsWithTagOrId(wi, args[first+5], &group, NULL);
- if ((num_items == 0) || (group->class != ZnGroup)) {
+ if (Tcl_GetDoubleFromObj(wi->interp, args[first+2], &p.y) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ p.x -= wi->inset;
+ p.y -= wi->inset;
+ if (argc > first+3) {
+ if (Tcl_GetIntFromObj(wi->interp, args[first+3], &halo) == ZN_ERROR) {
return ZN_ERROR;
}
+ if (halo < 0) {
+ halo = 0;
+ }
+ }
+ if (argc > (first+4)) {
+ result = ZnItemWithTagOrId(wi, args[first+4], wi->top_group, True,
+ &start_item, search_var);
+ if ((result == ZN_OK) && (start_item != ZN_NO_ITEM)) {
+ start_item = start_item->next;
+ }
+ }
+ /*
+ * We always start the search at the top group to use the
+ * transform and clip machinery of the group item. The items
+ * are not required to cache the device coords, etc. So we need
+ * to setup the correct context before calling the Pick method
+ * for each item.
+ */
+ wi->top_group->class->Pick(wi->top_group, &p, start_item, halo,
+ &item, &part);
+
+ if (item != ZN_NO_ITEM) {
+ DoItem(wi->interp, item, part, tag_uid);
+ /*printf("first %d %d\n", item->id, part);*/
+ return TCL_OK;
+ }
+ }
+ break;
+ /*
+ * enclosed
+ */
+ case ZN_S_ENCLOSED:
+ {
+ if (argc != first+5) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args,
+ "x1 y1 x2 y2");
+ return ZN_ERROR;
}
- return FindArea(wi, args+first+1, tag_uid, group, True);
+ return FindArea(wi, args+first+1, tag_uid, True);
}
break;
/*
@@ -1295,17 +1921,12 @@ FindItems(WidgetInfo *wi,
*/
case ZN_S_OVERLAPPING:
{
- if ((argc != first+5) && (argc != first+6)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "x1 y1 x2 y2 ?inGroup?");
+ if (argc != first+5) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args,
+ "x1 y1 x2 y2");
return ZN_ERROR;
}
- if (argc == first+6) {
- num_items = ZnItemsWithTagOrId(wi, args[first+5], &group, NULL);
- if ((num_items == 0) || (group->class != ZnGroup)) {
- return ZN_ERROR;
- }
- }
- return FindArea(wi, args+first+1, tag_uid, group, False);
+ return FindArea(wi, args+first+1, tag_uid, False);
}
break;
/*
@@ -1313,28 +1934,32 @@ FindItems(WidgetInfo *wi,
*/
case ZN_S_WITHTAG:
{
- Item *items;
- int i;
-
- if ((argc != first+2) && (argc != first+3)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId ?inGroup?");
+ if ((argc < first+2) || (argc > first+4)) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args,
+ "tagOrId ?inGroup? ?recursive?");
return ZN_ERROR;
}
- if (argc == first+3) {
- num_items = ZnItemsWithTagOrId(wi, args[first+2], &group, NULL);
- if ((num_items == 0) || (group->class != ZnGroup)) {
+ if (argc == first+4) {
+ if (Tcl_GetBooleanFromObj(wi->interp, args[first+3],
+ &recursive) != ZN_OK) {
return ZN_ERROR;
}
}
- num_items = ZnItemsWithTagOrId(wi, args[first+1], &item, &items);
- if (num_items == 0) {
- Tcl_SetObjResult(wi->interp, NewStringObj(""));
- }
- for (i = 0; i < num_items; i++) {
- if (IsHeirOf(items[i], group)) {
- DoItem(wi->interp, items[i], ZN_NO_PART, tag_uid);
+ if (argc > first+2) {
+ result = ZnItemWithTagOrId(wi, args[first+2], wi->top_group, True,
+ &group, search_var);
+ if ((result == ZN_ERROR) ||
+ (group == ZN_NO_ITEM) || (group->class != ZnGroup)) {
+ return ZN_ERROR;
}
}
+ if (ZnTagSearchScan(wi, args[first+1], search_var) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ for (item = ZnTagSearchFirst(*search_var, group, recursive);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
+ DoItem(wi->interp, item, ZN_NO_PART, tag_uid);
+ }
}
break;
/*
@@ -1344,8 +1969,9 @@ FindItems(WidgetInfo *wi,
{
ItemClass cls;
- if ((argc != first+2) && (argc != first+3)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "itemType ?inGroup?");
+ if ((argc < first+2) || (argc > first+4)) {
+ Tcl_WrongNumArgs(wi->interp, first+1, args,
+ "itemType ?inGroup? ?recursive?");
return ZN_ERROR;
}
cls = (ItemClass) ITEM_P.LookupItemClass(Tcl_GetString(args[first+1]));
@@ -1354,9 +1980,17 @@ FindItems(WidgetInfo *wi,
Tcl_GetString(args[first+1]), "\"", NULL);
return ZN_ERROR;
}
- if (argc == first+3) {
- num_items = ZnItemsWithTagOrId(wi, args[first+2], &group, NULL);
- if ((num_items == 0) || (group->class != ZnGroup)) {
+ if (argc == first+4) {
+ if (Tcl_GetBooleanFromObj(wi->interp, args[first+3],
+ &recursive) != ZN_OK) {
+ return ZN_ERROR;
+ }
+ }
+ if (argc > first+2) {
+ result = ZnItemWithTagOrId(wi, args[first+2], wi->top_group, True,
+ &group, search_var);
+ if ((result == ZN_ERROR) ||
+ (group == ZN_NO_ITEM) || (group->class != ZnGroup)) {
return ZN_ERROR;
}
}
@@ -1365,8 +1999,11 @@ FindItems(WidgetInfo *wi,
* Go through the item table and collect all items with
* the given item type.
*/
- for (item = ZnSearchWithTagOrId(wi, NULL, group, &ts);
- item != ZN_NO_ITEM; item = ZnNextWithTagOrId(&ts)) {
+ if (ZnTagSearchScan(wi, NULL, search_var) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ for (item = ZnTagSearchFirst(*search_var, group, recursive);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
if (item->class == cls) {
DoItem(wi->interp, item, ZN_NO_PART, tag_uid);
}
@@ -1430,12 +2067,13 @@ ParseCoordList(WidgetInfo *wi,
static int
Contour(WidgetInfo *wi,
int argc,
- Tcl_Obj *CONST args[])
+ Tcl_Obj *CONST args[],
+ TagSearch **search_var)
{
ZnPoint *points;
ZnPoint p[4], xp[4];
Item item, shape;
- int cmd, num_points, num, i;
+ int cmd, num_points, result, i;
ZnBool simple=False;
ZnPoly poly;
int index;
@@ -1448,8 +2086,9 @@ Contour(WidgetInfo *wi,
GPC_DIFF, GPC_INT, GPC_UNION, GPC_XOR
};
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)){
return ZN_ERROR;
}
if (!item->class->Contour) {
@@ -1464,8 +2103,9 @@ Contour(WidgetInfo *wi,
}
cmd = ops[index];
- num = ZnItemsWithTagOrId(wi, args[4], &shape, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[4], wi->top_group, True,
+ &shape, search);
+ if ((result == ZN_ERROR) || (shape == ZN_NO_ITEM)) {
Tcl_ResetResult(wi->interp);
if (ParseCoordList(wi, args[4], &points, &num_points) == ZN_ERROR) {
return ZN_ERROR;
@@ -1547,18 +2187,20 @@ Contour(WidgetInfo *wi,
static int
Coords(WidgetInfo *wi,
int argc,
- Tcl_Obj *CONST args[])
+ Tcl_Obj *CONST args[],
+ TagSearch **search_var)
{
ZnPoint *points;
Item item;
- int num_points, num = 0, i;
+ int num_points, result, i;
int cmd = COORDS_READ;
long index, contour = 0;
char *str;
Tcl_Obj *l;
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
return ZN_ERROR;
}
num_points = 0;
@@ -1748,35 +2390,36 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
{
WidgetInfo *wi = (WidgetInfo *) client_data;
int result, cmd_index, index;
- Item item, *items;
- ZnList item_list;
+ Item item, item2;
int num = 0, i, j;
- char *end, *end2, *str;
+ char *end, *str;
ZnTransfo *t = NULL;
Tcl_Obj *l, *lobjs[4];
+ TagSearch *search_var = NULL;
+ Tcl_HashEntry *entry;
static char *sub_cmd_strings[] = {
"add", "addtag", "anchorxy", "bbox", "becomes", "bind",
"cget", "chggroup", "clone", "configure", "contour",
- "coords", "currentpart", "cursor", "dchars", "dtag",
- "find", "fit", "focus", "gettags", "group",
- "hasanchors", "hasfields", "hasparts", "hastag",
+ "coords", "currentpart", "cursor", "dchars",
+ "dtag", "find", "fit", "focus", "gettags", "group",
+ "hasanchors", "hasfields", "hastag",
"index", "insert", "itemcget", "itemconfigure",
- "lower", "monitor", "postscript", "raise", "remove",
- "rotate", "scale", "select", "smooth", "tapply",
- "tdelete", "transform", "translate", "treset",
- "trestore", "tsave", "type", NULL
+ "lower", "monitor", "numparts", "postscript", "raise",
+ "remove", "rotate", "scale", "select", "smooth",
+ "tapply", "tdelete", "transform", "translate", "treset",
+ "trestore", "tsave", "type", "verticeat", NULL
};
enum sub_cmds {
ZN_W_ADD, ZN_W_ADDTAG, ZN_W_ANCHORXY, ZN_W_BBOX, ZN_W_BECOMES, ZN_W_BIND,
- ZN_W_CGET, ZN_W_CHGGROUP, ZN_W_CLONE, ZN_W_CONFIGURE, ZN_W_CONTOUR,
- ZN_W_COORDS, ZN_W_CURRENTPART, ZN_W_CURSOR, ZN_W_DCHARS, ZN_W_DTAG,
- ZN_W_FIND, ZN_W_FIT, ZN_W_FOCUS, ZN_W_GETTAGS, ZN_W_GROUP,
- ZN_W_HASANCHORS, ZN_W_HASFIELDS, ZN_W_HASPARTS, ZN_W_HASTAG,
+ ZN_W_CGET, ZN_W_CHGGROUP, ZN_W_CLONE, ZN_W_CONFIGURE,
+ ZN_W_CONTOUR, ZN_W_COORDS, ZN_W_CURRENTPART, ZN_W_CURSOR, ZN_W_DCHARS,
+ ZN_W_DTAG, ZN_W_FIND, ZN_W_FIT, ZN_W_FOCUS, ZN_W_GETTAGS, ZN_W_GROUP,
+ ZN_W_HASANCHORS, ZN_W_HASFIELDS, ZN_W_HASTAG,
ZN_W_INDEX, ZN_W_INSERT, ZN_W_ITEMCGET, ZN_W_ITEMCONFIGURE,
- ZN_W_LOWER, ZN_W_MONITOR, ZN_W_POSTSCRIPT, ZN_W_RAISE, ZN_W_REMOVE,
- ZN_W_ROTATE, ZN_W_SCALE, ZN_W_SELECT, ZN_W_SMOOTH, ZN_W_TAPPLY,
- ZN_W_TDELETE, ZN_W_TRANSFORM, ZN_W_TRANSLATE, ZN_W_TRESET,
- ZN_W_TRESTORE, ZN_W_TSAVE, ZN_W_TYPE
+ ZN_W_LOWER, ZN_W_MONITOR, ZN_W_NUMPARTS, ZN_W_POSTSCRIPT, ZN_W_RAISE,
+ ZN_W_REMOVE, ZN_W_ROTATE, ZN_W_SCALE, ZN_W_SELECT, ZN_W_SMOOTH,
+ ZN_W_TAPPLY, ZN_W_TDELETE, ZN_W_TRANSFORM, ZN_W_TRANSLATE, ZN_W_TRESET,
+ ZN_W_TRESTORE, ZN_W_TSAVE, ZN_W_TYPE, ZN_W_VERTICE_AT,
};
static char *sel_cmd_strings[] = {
"adjust", "clear", "from", "item", "to", NULL
@@ -1799,7 +2442,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
}
result = ZN_OK;
- printf("executing command \"%s\", argc=%d\n", Tcl_GetString(args[1]), argc);
+ /*printf("executing command \"%s\", argc=%d\n",
+ Tcl_GetString(args[1]), argc);*/
switch((enum sub_cmds) cmd_index) {
/*
* add
@@ -1834,8 +2478,10 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_AppendResult(interp, "unknown item type \"", str, "\"", NULL);
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[3], &group, NULL);
- if (!num || (group->class != ZnGroup)) {
+ result = ZnItemWithTagOrId(wi, args[3], wi->top_group, True,
+ &group, &search_var);
+ if ((result == ZN_ERROR) || (group == ZN_NO_ITEM) ||
+ (group->class != ZnGroup)) {
Tcl_AppendResult(interp, ", group item expected, got \"",
Tcl_GetString(args[3]), "\"", NULL);
goto error;
@@ -1851,6 +2497,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
if (ITEM.ConfigureItem(item, -1, argc, args, True) == ZN_ERROR) {
goto error;
}
+ wi->hot_item = item;
+ wi->hot_prev = item->previous;
Tcl_SetObjResult(interp, NewLongObj(item->id));
}
break;
@@ -1863,7 +2511,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "addtag tag searchCommand ?arg arg ...?");
goto error;
}
- result = FindItems(wi, argc, args, args[2], 3);
+ result = FindItems(wi, argc, args, args[2], 3, &search_var);
}
break;
/*
@@ -1878,8 +2526,10 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "anchorxy tagOrId anchor");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if ((num == 0) || !item->class->has_anchors) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM) ||
+ !item->class->has_anchors) {
Tcl_AppendResult(interp, "unknown item or doesn't support anchors \"",
Tcl_GetString(args[2]), NULL);
goto error;
@@ -1914,7 +2564,6 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
{
ZnBBox bbox;
int i;
- ZnBool found = False;
if (argc < 3) {
Tcl_WrongNumArgs(interp, 1, args, "bbox tagOrId ?tagOrId ...?");
@@ -1926,13 +2575,15 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
ITEM_P.Update(wi);
ResetBBox(&bbox);
for (i = 0; i < argc; i++) {
- num = ZnItemsWithTagOrId(wi, args[i], &item, &items);
- found |= (num != 0);
- for (j = 0; j < num; j++) {
- AddBBoxToBBox(&bbox, &items[j]->item_bounding_box);
+ if (ZnTagSearchScan(wi, args[i], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ AddBBoxToBBox(&bbox, &item->item_bounding_box);
}
}
- if (found && !IsEmptyBBox(&bbox)) {
+ if (!IsEmptyBBox(&bbox)) {
lobjs[0] = NewDoubleObj(bbox.orig.x+wi->inset);
lobjs[1] = NewDoubleObj(bbox.orig.y+wi->inset);
lobjs[2] = NewDoubleObj(bbox.corner.x+wi->inset);
@@ -1946,8 +2597,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
*/
case ZN_W_BIND:
{
- ClientData elem = 0;
- int part = ZN_NO_PART;
+ ClientData elem = 0;
+ int part = ZN_NO_PART;
if ((argc < 3) || (argc > 5)) {
Tcl_WrongNumArgs(interp, 1, args, "bind tagOrId ?sequence? ?command?");
@@ -1958,17 +2609,10 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
*/
str = Tcl_GetString(args[2]);
if (isdigit(str[0])) {
- Tcl_HashEntry *entry;
- int id;
+ int id;
id = strtoul(str, &end, 0);
- if (*end == ':') {
- part = strtoul(end+1, &end2, 0);
- if (*end2 != 0) {
- goto bind_a_tag;
- }
- }
- else if (*end != 0) {
+ if ((*end != 0) && (*end != ':')) {
goto bind_a_tag;
}
entry = Tcl_FindHashEntry(wi->id_table, (char *) id);
@@ -1981,7 +2625,17 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
goto error;
}
if (*end == ':') {
- elem = EncodeItemPart((Item) elem, part);
+ if (item->class->Part) {
+ l = NewStringObj(end+1);
+ if (item->class->Part(item, &l, &part) == ZN_ERROR) {
+ goto error;
+ }
+ elem = EncodeItemPart(item, part);
+ }
+ else {
+ Tcl_AppendResult(interp, "item \"", str, "\" doesn't have parts", NULL);
+ goto error;
+ }
}
/*printf("adding element 0x%X to the binding table of item 0x%X\n", elem, item);*/
}
@@ -2001,20 +2655,24 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
int append = 0;
unsigned long mask;
+#ifdef PTK
+ str = LangString(args[4]);
+#else
str = Tcl_GetString(args[4]);
+#endif
if (str[0] == 0) {
result = Tk_DeleteBinding(interp, wi->binding_table, elem,
Tcl_GetString(args[3]));
goto done;
- }
- if (str[0] == '+') {
- str++;
- append = 1;
- }
+ }
#ifdef PTK
mask = Tk_CreateBinding(interp, wi->binding_table,
elem, Tcl_GetString(args[3]), args[4], append);
#else
+ if (str[0] == '+') {
+ str++;
+ append = 1;
+ }
mask = Tk_CreateBinding(interp, wi->binding_table,
elem, Tcl_GetString(args[3]), str, append);
#endif
@@ -2076,20 +2734,22 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
*/
case ZN_W_CHGGROUP:
{
- Item grp;
- int adjust=0;
+ Item grp;
+ int adjust=0;
ZnTransfo inv, t, t2, *this_one=NULL;
if ((argc != 4) && (argc != 5)) {
Tcl_WrongNumArgs(interp, 1, args, "chggroup tagOrIg group ?adjustTransform?");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[3], &grp, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[3], wi->top_group, True,
+ &grp, &search_var);
+ if ((result == ZN_ERROR) || (grp == ZN_NO_ITEM)) {
goto error;
}
if (argc == 5) {
@@ -2128,20 +2788,20 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "clone tagOrId ?option value ...?");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- if (num == 0) {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
goto error;
}
argc -= 3;
args += 3;
l = Tcl_GetObjResult(interp);
- for (i = 0; i < num; i++) {
- item = ITEM.CloneItem(items[i]);
- ITEM.InsertItem(item, items[i]->parent, ZN_NO_ITEM, True);
- if (ITEM.ConfigureItem(item, -1, argc, args, False) == ZN_ERROR) {
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ item2 = ITEM.CloneItem(item);
+ ITEM.InsertItem(item2, item->parent, ZN_NO_ITEM, True);
+ if (ITEM.ConfigureItem(item2, -1, argc, args, False) == ZN_ERROR) {
goto error;
}
- Tcl_ListObjAppendElement(interp, l, NewLongObj(item->id));
+ Tcl_ListObjAppendElement(interp, l, NewLongObj(item2->id));
}
}
break;
@@ -2195,7 +2855,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
"coords tagOrId ?add/remove? ?contour? ?index? ?coordList?");
goto error;
}
- if (Coords(wi, argc, args) == ZN_ERROR) {
+ if (Coords(wi, argc, args, &search_var) == ZN_ERROR) {
goto error;
}
}
@@ -2209,7 +2869,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "currentpart");
goto error;
}
- Tcl_SetObjResult(interp, Tcl_NewIntObj(wi->current_part));
+ if (wi->current_item->class->Part != NULL) {
+ l = NULL;
+ wi->current_item->class->Part(wi->current_item, &l, &wi->current_part);
+ Tcl_SetObjResult(interp, l);
+ }
}
break;
/*
@@ -2221,20 +2885,23 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "cursor tagOrId index");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- for (i = 0; i < num; i++) {
- if ((items[i]->class->Cursor == NULL) ||
- (items[i]->class->Index == NULL)) {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ if ((item->class->Cursor == NULL) ||
+ (item->class->Index == NULL)) {
continue;
}
- result = (*items[i]->class->Index)(items[i], args[3], &index);
+ result = (*item->class->Index)(item, args[3], &index);
if (result != ZN_OK) {
goto error;
}
- (*items[i]->class->Cursor)(items[i], index);
- if ((items[i] == wi->text_info.focus_item) && wi->text_info.cursor_on) {
- ITEM.Invalidate(items[i], ZN_COORDS_FLAG);
+ (*item->class->Cursor)(item, index);
+ if ((item == wi->text_info.focus_item) && wi->text_info.cursor_on) {
+ ITEM.Invalidate(item, ZN_COORDS_FLAG);
}
}
}
@@ -2250,18 +2917,21 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "dchars tagOrId first ?last?");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- for (i = 0; i < num; i++) {
- if ((items[i]->class->Index == NULL) ||
- (items[i]->class->DeleteChars == NULL)) {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ if ((item->class->Index == NULL) ||
+ (item->class->DeleteChars == NULL)) {
continue;
}
- result = (*items[i]->class->Index)(items[i], args[3], &first);
+ result = (*item->class->Index)(item, args[3], &first);
if (result != ZN_OK) {
goto error;
}
if (argc == 5) {
- result = (*items[i]->class->Index)(items[i], args[4], &last);
+ result = (*item->class->Index)(item, args[4], &last);
if (result != ZN_OK) {
goto error;
}
@@ -2269,7 +2939,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
else {
last = first;
}
- (*items[i]->class->DeleteChars)(items[i], first, last);
+ (*item->class->DeleteChars)(item, first, last);
}
}
break;
@@ -2279,7 +2949,6 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
case ZN_W_DTAG:
{
Tk_Uid tag;
- Tcl_HashEntry *entry;
if ((argc != 3) && (argc != 4)) {
Tcl_WrongNumArgs(interp, 1, args, "dtag tagOrId ?tagToDelete?");
@@ -2291,18 +2960,13 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
else {
tag = Tk_GetUid(Tcl_GetString(args[2]));
}
- entry = Tcl_FindHashEntry(wi->tag_table, tag);
- item_list = (ZnList) Tcl_GetHashValue(entry);
- items = (Item *) ZnListArray(item_list);
- for (i = ZnListSize(item_list)-1; i >= 0; i++) {
- ITEM.RemoveTag(items[i], (char *) tag);
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ ITEM.RemoveTag(item, (char *) tag);
}
- /*
- * The RemoveTag method *must* remove the tag table
- * entry when it gets empty. Otherwise a tag probe
- * we bring back an empty item list and this would
- * not be reported as an error by ZnItemsWithTagOrId.
- */
}
break;
/*
@@ -2314,7 +2978,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "find searchCommand ?arg arg ...?");
goto error;
}
- result = FindItems(wi, argc, args, NULL, 2);
+ result = FindItems(wi, argc, args, NULL, 2, &search_var);
}
break;
/*
@@ -2372,17 +3036,16 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
wi->text_info.focus_item = ZN_NO_ITEM;
goto done;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- item = ZN_NO_ITEM;
- for (i = 0; i < num; i++) {
- if (items[i]->class->Cursor != NULL) {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ if (item->class->Cursor != NULL) {
break;
}
}
- if (num == 0) {
- goto done;
- }
- wi->text_info.focus_item = items[i];
+ wi->text_info.focus_item = item;
if (wi->text_info.got_focus) {
ITEM.Invalidate(wi->text_info.focus_item, ZN_COORDS_FLAG);
}
@@ -2399,8 +3062,9 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "gettags tagOrId");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
if (!item->tags || !ZnListSize(item->tags)) {
@@ -2425,8 +3089,9 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "group tagOrId");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
if (item->parent != ZN_NO_ITEM) {
@@ -2449,8 +3114,9 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "hasanchors tagOrId");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
Tcl_SetObjResult(interp, NewBooleanObj(item->class->has_anchors?1:0));
@@ -2465,30 +3131,15 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "hasfields tagOrId");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
Tcl_SetObjResult(interp, NewBooleanObj(item->class->has_fields?1:0));
}
break;
/*
- * hasparts
- */
- case ZN_W_HASPARTS:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "hasparts tagOrId");
- goto error;
- }
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
- goto error;
- }
- Tcl_SetObjResult(interp, NewBooleanObj(item->class->has_parts?1:0));
- }
- break;
- /*
* hastag
*/
case ZN_W_HASTAG:
@@ -2500,8 +3151,9 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "hastag tagOrId tag");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
if (!item->tags || !ZnListSize(item->tags)) {
@@ -2530,10 +3182,13 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "index tagOrId string");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- for (i = 0; i < num; i++) {
- if (items[i]->class->Index != NULL) {
- result = (*items[i]->class->Index)(items[i], args[3], &index);
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ if (item->class->Index != NULL) {
+ result = (*item->class->Index)(item, args[3], &index);
if (result != ZN_OK) {
goto error;
}
@@ -2555,17 +3210,20 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "insert tagOrId before string");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- for (i = 0; i < num; i++) {
- if ((items[i]->class->Index == NULL) ||
- (items[i]->class->InsertChars == NULL)) {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ if ((item->class->Index == NULL) ||
+ (item->class->InsertChars == NULL)) {
continue;
}
- result = (*items[i]->class->Index)(items[i], args[3], &index);
+ result = (*item->class->Index)(item, args[3], &index);
if (result != ZN_OK) {
goto error;
}
- (*items[i]->class->InsertChars)(items[i], index, Tcl_GetString(args[4]));
+ (*item->class->InsertChars)(item, index, Tcl_GetString(args[4]));
}
}
break;
@@ -2581,8 +3239,9 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "itemcget tagOrId ?field? option");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
if (argc == 5) {
@@ -2613,8 +3272,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
"itemconfigure tagOrId ?field? option value ?option value? ...");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- if (num == 0) {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
goto error;
}
if ((argc > 3) && (Tcl_GetString(args[3])[0] != '-')) {
@@ -2629,21 +3287,20 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
}
argc -= 3;
args += 3;
- if (argc < 2) {
- if (ITEM.AttributesInfo(item, field, argc, args) == ZN_ERROR) {
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ if (argc < 2) {
+ result = ITEM.AttributesInfo(item, field, argc, args);
+ }
+ else {
+ result = ITEM.ConfigureItem(item, field, argc, args, False);
+ }
+ if (result == ZN_ERROR) {
goto error;
}
- goto done;
- }
- for (i = 0; i < num; i++) {
- result = ITEM.ConfigureItem(items[i], field, argc, args, False);
- }
- /*
- * Don't report errors when configuring many items/fields. All
- * options are not supported by all item types.
- */
- if ((num == 1) && (result == ZN_ERROR)) {
- goto error;
+ if (argc < 2) {
+ goto done;
+ }
}
}
break;
@@ -2653,16 +3310,17 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
case ZN_W_LOWER:
{
Item mark = ZN_NO_ITEM;
- TagSearch search;
if (argc < 3) {
Tcl_WrongNumArgs(interp, 1, args, "lower tagOrId ?belowThis?");
goto error;
}
if (argc == 4) {
- for (item = ZnSearchWithTagOrId(wi, args[3], wi->top_group, &search);
- item != ZN_NO_ITEM;
- item = ZnNextWithTagOrId(&search)) {
+ if (ZnTagSearchScan(wi, args[3], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
mark = item;
}
if (mark == ZN_NO_ITEM) {
@@ -2671,16 +3329,17 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
goto error;
}
}
- item = ZnSearchWithTagOrId(wi, args[2], wi->top_group, &search);
- if (item == ZN_NO_ITEM) {
- Tcl_AppendResult(interp, "unknown tag or item \"",
- Tcl_GetString(args[2]), "\"", NULL);
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
goto error;
}
+ item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ if (item == ZN_NO_ITEM) {
+ goto done;
+ }
if (mark == ZN_NO_ITEM) {
mark = ((GroupItem) item->parent)->tail;
}
- for (; item != ZN_NO_ITEM; item = ZnNextWithTagOrId(&search)) {
+ for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
if (item != mark) {
ITEM.UpdateItemPriority(item, mark, False);
mark = item;
@@ -2718,6 +3377,23 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
}
break;
/*
+ * numparts
+ */
+ case ZN_W_NUMPARTS:
+ {
+ if (argc != 3) {
+ Tcl_WrongNumArgs(interp, 1, args, "numparts tagOrId");
+ goto error;
+ }
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
+ goto error;
+ }
+ Tcl_SetObjResult(interp, NewBooleanObj(item->class->num_parts!=0));
+ }
+ break;
+ /*
* postscript
*/
case ZN_W_POSTSCRIPT:
@@ -2732,7 +3408,6 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
case ZN_W_RAISE:
{
Item mark = ZN_NO_ITEM;
- TagSearch search;
if (argc < 3) {
Tcl_WrongNumArgs(interp, 1, args, "raise tagOrId ?aboveThis?");
@@ -2742,24 +3417,27 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
/*
* Find the topmost item with the tag.
*/
- mark = ZnSearchWithTagOrId(wi, args[3], wi->top_group, &search);
+ if (ZnTagSearchScan(wi, args[3], &search_var) == ZN_ERROR) {
+ goto error;
+ }
+ mark = ZnTagSearchFirst(search_var, wi->top_group, True);
if (mark == ZN_NO_ITEM) {
Tcl_AppendResult(interp, "unknown tag or item \"",
Tcl_GetString(args[3]), "\"", NULL);
goto error;
}
- ZnDoneWithSearch(&search);
}
- item = ZnSearchWithTagOrId(wi, args[2], wi->top_group, &search);
- if (item == ZN_NO_ITEM) {
- Tcl_AppendResult(interp, "unknown tag or item \"",
- Tcl_GetString(args[2]), "\"", NULL);
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
goto error;
}
+ item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ if (item == ZN_NO_ITEM) {
+ goto done;
+ }
if (mark == ZN_NO_ITEM) {
mark = ((GroupItem) item->parent)->head;
}
- for (; item != ZN_NO_ITEM; item = ZnNextWithTagOrId(&search)) {
+ for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
if (item != mark) {
ITEM.UpdateItemPriority(item, mark, True);
}
@@ -2771,29 +3449,38 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
*/
case ZN_W_REMOVE:
{
+ FieldSet fs;
+
if (argc < 3) {
Tcl_WrongNumArgs(interp, 1, args, "remove tagOrId ?tagOrId ...?");
goto error;
}
argc -= 2;
args += 2;
- for (j = 0; j < argc; j++) {
- num = ZnItemsWithTagOrId(wi, args[j], &item, &items);
- if (num == 0) {
+ for (i = 0; i < argc; i++) {
+ if (ZnTagSearchScan(wi, args[i], &search_var) == ZN_ERROR) {
goto error;
}
- for (i = num-1; i >= 0; i--) {
- if (items[i] == wi->top_group) {
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ if (item == wi->top_group) {
continue;
}
if (wi->binding_table != NULL) {
- /*
- * BUG: we can't actually destroy all the item's bindings
- * if there are field bindings registered.
- */
- Tk_DeleteAllBindings(wi->binding_table, (ClientData) items[i]);
+ Tk_DeleteAllBindings(wi->binding_table, (ClientData) item);
+ if (item->class->has_fields) {
+ fs = item->class->GetFieldSet(item);
+ for (j = 0; j < fs->num_fields; j++) {
+ Tk_DeleteAllBindings(wi->binding_table,
+ (ClientData) EncodeItemPart(item, j));
+ }
+ }
+ for (j = 0; j < item->class->num_parts; j++) {
+ Tk_DeleteAllBindings(wi->binding_table,
+ (ClientData) EncodeItemPart(item, -(j+2)));
+ }
}
- ITEM.DestroyItem(items[i]);
+ ITEM.DestroyItem(item);
}
}
}
@@ -2803,8 +3490,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
*/
case ZN_W_ROTATE:
{
- ZnReal angle;
- ZnPoint p;
+ ZnReal angle;
+ ZnPoint p;
if ((argc != 4) && (argc != 6)) {
Tcl_WrongNumArgs(interp, 1, args, "rotate tagOrId angle ?centerX centerY?");
@@ -2819,23 +3506,19 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
goto error;
}
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- if (num == 0) {
- Tcl_HashEntry *e;
- e = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (e == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp,
- "\"", Tcl_GetString(args[2]), "\" must be either a tag or ",
- "an id or a transform name", (char *) NULL);
+ entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
+ if (entry != NULL) {
+ t = (ZnTransfo *) Tcl_GetHashValue(entry);
+ }
+ else {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
goto error;
}
- t = (ZnTransfo *) Tcl_GetHashValue(e);
}
-
if (Tcl_GetDoubleFromObj(interp, args[3], &angle) == ZN_ERROR) {
goto error;
}
+
if (t) {
if (argc == 6) {
ZnTranslate(t, -p.x, -p.y);
@@ -2845,9 +3528,10 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
ZnTranslate(t, p.x, p.y);
}
}
- if (num != 0) {
- for (i = 0; i < num; i++) {
- ITEM.RotateItem(items[i], angle, (argc == 6) ? &p : NULL);
+ else {
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ ITEM.RotateItem(item, angle, (argc == 6) ? &p : NULL);
}
}
}
@@ -2863,33 +3547,29 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "scale tagOrId xFactor yFactor");
goto error;
}
- if (argc == 5) {
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- if (num == 0) {
- Tcl_HashEntry *e;
- e = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (e == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]),
- "\" must be either a tag or ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- t = (ZnTransfo *) Tcl_GetHashValue(e);
+ entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
+ if (entry != NULL) {
+ t = (ZnTransfo *) Tcl_GetHashValue(entry);
+ }
+ else {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
}
}
- if (Tcl_GetDoubleFromObj(interp, args[argc-2], &scale.x) == ZN_ERROR) {
+ if (Tcl_GetDoubleFromObj(interp, args[3], &scale.x) == ZN_ERROR) {
goto error;
}
- if (Tcl_GetDoubleFromObj(interp, args[argc-1], &scale.y) == ZN_ERROR) {
+ if (Tcl_GetDoubleFromObj(interp, args[4], &scale.y) == ZN_ERROR) {
goto error;
}
+
if (t) {
ZnScale(t, scale.x, scale.y);
}
- if (num != 0) {
- for (i = 0; i < num; i++) {
- ITEM.ScaleItem(items[i], scale.x, scale.y);
+ else {
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ ITEM.ScaleItem(item, scale.x, scale.y);
}
}
}
@@ -2904,15 +3584,13 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
goto error;
}
if (argc >= 4) {
- num = ZnItemsWithTagOrId(wi, args[3], &item, &items);
- if (num == 0) {
- goto done;
+ if (ZnTagSearchScan(wi, args[3], &search_var) == ZN_ERROR) {
+ goto error;
}
- item = ZN_NO_ITEM;
- for (i = 0; i < num; i++) {
- if ((items[i]->class->Index != NULL) &&
- (items[i]->class->Selection != NULL)) {
- item = items[i];
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ if ((item->class->Index != NULL) &&
+ (item->class->Selection != NULL)) {
break;
}
}
@@ -3048,7 +3726,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
*/
case ZN_W_TRANSFORM:
{
- int num_points;
+ int num_points;
ZnPoint *p, xp;
ZnTransfo t, t2, inv, *this_one;
Item from, to;
@@ -3059,13 +3737,15 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
}
if (argc == 5) {
- num = ZnItemsWithTagOrId(wi, args[2], &from, &items);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &from, &search_var);
+ if ((result == ZN_ERROR) || (from == ZN_NO_ITEM)) {
goto error;
}
}
- num = ZnItemsWithTagOrId(wi, args[argc-2], &to, &items);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[argc-2], wi->top_group, True,
+ &to, &search_var);
+ if ((result == ZN_ERROR) || (to == ZN_NO_ITEM)) {
Tcl_HashEntry *e;
/*
* Try to find a named transform.
@@ -3125,34 +3805,29 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "translate tagOrId xAmount yAmount");
goto error;
}
- num = 0;
- if (argc == 5) {
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- if (num == 0) {
- Tcl_HashEntry *e;
- e = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (e == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]),
- "\" must be either a tag or ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- t = (ZnTransfo *) Tcl_GetHashValue(e);
+ entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
+ if (entry != NULL) {
+ t = (ZnTransfo *) Tcl_GetHashValue(entry);
+ }
+ else {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
}
}
- if (Tcl_GetDoubleFromObj(interp, args[argc-2], &trans.x) == ZN_ERROR) {
+ if (Tcl_GetDoubleFromObj(interp, args[3], &trans.x) == ZN_ERROR) {
goto error;
}
- if (Tcl_GetDoubleFromObj(interp, args[argc-1], &trans.y) == ZN_ERROR) {
+ if (Tcl_GetDoubleFromObj(interp, args[4], &trans.y) == ZN_ERROR) {
goto error;
}
+
if (t) {
ZnTranslate(t, trans.x, trans.y);
}
- if (num != 0) {
- for (i = 0; i < num; i++) {
- ITEM.TranslateItem(items[i], trans.x, trans.y);
+ else {
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item =ZnTagSearchNext(search_var)) {
+ ITEM.TranslateItem(item, trans.x, trans.y);
}
}
}
@@ -3166,27 +3841,23 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "treset tagOrId");
goto error;
}
- if (argc == 3) {
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- if (num == 0) {
- Tcl_HashEntry *e;
- e = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (e == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]),
- "\" must be either a tag or ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- t = (ZnTransfo *) Tcl_GetHashValue(e);
+ entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
+ if (entry != NULL) {
+ t = (ZnTransfo *) Tcl_GetHashValue(entry);
+ }
+ else {
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
+ goto error;
}
}
+
if (t) {
ZnTransfoSetIdentity(t);
}
- if (num != 0) {
- for (i = 0; i < num; i++) {
- ITEM.ResetTransfo(items[i]);
+ else {
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ ITEM.ResetTransfo(item);
}
}
}
@@ -3196,25 +3867,23 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
*/
case ZN_W_TRESTORE:
{
- Tcl_HashEntry *e;
-
if (argc != 4) {
Tcl_WrongNumArgs(interp, 1, args, "trestore tagOrId tName");
goto error;
}
- e = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[argc-1]));
- if (e == NULL) {
+ entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[argc-1]));
+ if (entry == NULL) {
Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-1]),
"\" must be a transform name", (char *) NULL);
goto error;
}
- t = (ZnTransfo *) Tcl_GetHashValue(e);
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- if (num == 0) {
+ t = (ZnTransfo *) Tcl_GetHashValue(entry);
+ if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) {
goto error;
}
- for (i = 0; i < num; i++) {
- ITEM.SetTransfo(items[i], t);
+ for (item = ZnTagSearchFirst(search_var, wi->top_group, True);
+ item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
+ ITEM.SetTransfo(item, t);
}
}
break;
@@ -3223,16 +3892,16 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
*/
case ZN_W_TSAVE:
{
- Tcl_HashEntry *e;
int new, invert=0;
- ZnTransfo *inv;
+ ZnTransfo *inv;
if ((argc != 4) && (argc != 5)) {
Tcl_WrongNumArgs(interp, 1, args, "tsave tagOrId tName ?invert?");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, &items);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
if (argc == 5) {
@@ -3241,9 +3910,9 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
}
}
t = item->transfo;
- e = Tcl_CreateHashEntry(wi->t_table, Tcl_GetString(args[argc-1]), &new);
+ entry = Tcl_CreateHashEntry(wi->t_table, Tcl_GetString(args[argc-1]), &new);
if (!new) {
- ZnTransfoFree((ZnTransfo *) Tcl_GetHashValue(e));
+ ZnTransfoFree((ZnTransfo *) Tcl_GetHashValue(entry));
}
if (invert) {
inv = ZnTransfoNew();
@@ -3252,7 +3921,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
else {
inv = ZnTransfoDuplicate(t);
}
- Tcl_SetHashValue(e, inv);
+ Tcl_SetHashValue(entry, inv);
}
break;
/*
@@ -3264,16 +3933,51 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
Tcl_WrongNumArgs(interp, 1, args, "type tagOrId");
goto error;
}
- num = ZnItemsWithTagOrId(wi, args[2], &item, NULL);
- if (num == 0) {
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
goto error;
}
Tcl_SetObjResult(interp, NewStringObj(item->class->name));
}
break;
+ /*
+ * verticeat
+ */
+ case ZN_W_VERTICE_AT:
+ {
+ ZnPoint p;
+ int contour, vertex, o_vertex;
+
+ if (argc != 5) {
+ Tcl_WrongNumArgs(interp, 1, args, " verticeat tagOrId x y");
+ goto error;
+ }
+ result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True,
+ &item, &search_var);
+ if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) {
+ goto error;
+ }
+ if (Tcl_GetDoubleFromObj(interp, args[3], &p.x) == ZN_ERROR) {
+ goto error;
+ }
+ if (Tcl_GetDoubleFromObj(interp, args[4], &p.y) == ZN_ERROR) {
+ goto error;
+ }
+ p.x -= wi->inset;
+ p.y -= wi->inset;
+ if (item->class->PickVertex) {
+ item->class->PickVertex(item, &p, &contour, &vertex, &o_vertex);
+ l = Tcl_GetObjResult(interp);
+ Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(contour));
+ Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(vertex));
+ Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(o_vertex));
+ }
+ }
}
done:
+ ZnTagSearchDestroy(search_var);
if (wi->work_item_list) {
ZnListFree(wi->work_item_list);
wi->work_item_list = NULL;
@@ -3282,6 +3986,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */
return result;
error:
+ ZnTagSearchDestroy(search_var);
if (wi->work_item_list) {
ZnListFree(wi->work_item_list);
wi->work_item_list = NULL;
@@ -3774,7 +4479,7 @@ DoEvent(WidgetInfo *wi,
num_tags = 0;
its = items;
bind_part = ((wi->current_part != ZN_NO_PART) &&
- (wi->current_item->class->has_parts ||
+ (wi->current_item->class->num_parts ||
wi->current_item->class->has_fields));
/*
* This is needed to avoid generating enter and leave
@@ -3821,7 +4526,7 @@ DoEvent(WidgetInfo *wi,
if (bind_part) {
/*
- * Add here a binding for each tag suffixed by :all
+ * Add here a binding for each tag suffixed by :part
*/
for (i = 0; i < num_tags; i++) {
len = strlen(tag_list[i])+ INTEGER_SPACE;
@@ -3834,7 +4539,7 @@ DoEvent(WidgetInfo *wi,
ptr++;
}
/*
- * Add here a binding for id:all
+ * Add here a binding for id:part
*/
its[ptr] = EncodeItemPart(item, wi->current_part);
ptr++;
@@ -3952,12 +4657,17 @@ PickCurrentItem(WidgetInfo *wi,
* object, so the check for closest item can be skipped.
*/
if (wi->pick_event.type != LeaveNotify) {
- ZnPoint p;
+ ZnPoint p;
+ ZnReal dist;
p.x = wi->pick_event.xcrossing.x-wi->inset;
p.y = wi->pick_event.xcrossing.y-wi->inset;
- wi->top_group->class->Pick(wi->top_group, &p, NULL, wi->pick_aperture,
- &wi->new_item, &wi->new_part);
+ dist = wi->top_group->class->Pick(wi->top_group, &p, NULL, wi->pick_aperture,
+ &wi->new_item, &wi->new_part);
+ if (dist != 0.0) {
+ wi->new_item = ZN_NO_ITEM;
+ wi->new_part = ZN_NO_PART;
+ }
}
else {
wi->new_item = ZN_NO_ITEM;
@@ -4291,7 +5001,8 @@ static int
FetchSelection( ClientData client_data,
int offset, /* Offset within selection of first
* character to be returned. */
- char *buffer, /* Location in which to place selection. */
+ char *buffer, /* Location in which to place
+ * selection. */
int max_bytes) /* Maximum number of bytes to place
* at buffer, not including terminating
* NULL character. */
@@ -4382,10 +5093,11 @@ Destroy(char *mem_ptr) /* Info about the widget. */
/*
* Print remaining items.
*/
- /*printf("Remaining item count: %d\n", wi->num_items);*/
/* Free all items. */
+ printf("Remaining item count: %d\n", wi->num_items);
ITEM.DestroyItem(wi->top_group);
+ printf("Remaining item count: %d\n", wi->num_items);
for (num = 0; num < NUM_ALPHA_STEPS; num++) {
if (wi->alpha_stipples[num] != None) {
@@ -4397,17 +5109,7 @@ Destroy(char *mem_ptr) /* Info about the widget. */
ZnFree(wi->id_table);
/*
- * Free the table contents before the table.
- */
- entry = Tcl_FirstHashEntry(wi->tag_table, &search);
- while (entry != NULL) {
- ZnListFree((ZnList) Tcl_GetHashValue(entry));
- entry = Tcl_NextHashEntry(&search);
- }
- Tcl_DeleteHashTable(wi->tag_table);
- ZnFree(wi->tag_table);
- /*
- * Free the table contents before the table.
+ * Free the transform table contents before the table.
*/
entry = Tcl_FirstHashEntry(wi->t_table, &search);
while (entry != NULL) {
@@ -4432,6 +5134,8 @@ Destroy(char *mem_ptr) /* Info about the widget. */
XFreePixmap(wi->dpy, wi->draw_buffer);
}
+ Tcl_DeleteTimerHandler(wi->blink_handler);
+
Tk_FreeOptions(config_specs, (char *) wi, wi->dpy, 0);
/*
@@ -4538,6 +5242,23 @@ Redisplay(ClientData client_data) /* Information about the widget. */
*/
ITEM_P.Repair(wi);
+ ResetBBox(&merge);
+ CopyBBox(&wi->damaged_area, &merge);
+ AddBBoxToBBox(&merge, &wi->exposed_area);
+ if (!IsEmptyBBox(&merge)) {
+ BBox2XRect(&merge, &r);
+ /*printf("redisplay %d %d %d %d\n", r.x, r.y, r.width, r.height);*/
+ XCopyArea(wi->dpy,
+ wi->draw_buffer, ZnWindowId(wi->win), wi->gc,
+ r.x, r.y, r.width, r.height, r.x+wi->inset, r.y+wi->inset);
+ }
+
+ /*
+ * Reset the exposed & damaged areas.
+ */
+ ResetBBox(&wi->exposed_area);
+ ResetBBox(&wi->damaged_area);
+
/*
* Redraw the borders.
*/
@@ -4561,23 +5282,6 @@ Redisplay(ClientData client_data) /* Information about the widget. */
Tk_DrawFocusHighlight(wi->win, gc, wi->highlight_width, Tk_WindowId(wi->win));
}
- ResetBBox(&merge);
- CopyBBox(&wi->damaged_area, &merge);
- AddBBoxToBBox(&merge, &wi->exposed_area);
- if (!IsEmptyBBox(&merge)) {
- BBox2XRect(&merge, &r);
- /*printf("redisplay %d %d %d %d\n", r.x, r.y, r.width, r.height);*/
- XCopyArea(wi->dpy,
- wi->draw_buffer, ZnWindowId(wi->win), wi->gc,
- r.x, r.y, r.width, r.height, r.x+wi->inset, r.y+wi->inset);
- }
-
- /*
- * Reset the exposed & damaged areas.
- */
- ResetBBox(&wi->exposed_area);
- ResetBBox(&wi->damaged_area);
-
if (wi->monitoring) {
XSync(wi->dpy, 0);
gettimeofday(&end, &tz);
@@ -4932,6 +5636,8 @@ MapInfoObjCmd(ClientData client_data,
return ZN_ERROR;
}
result = TCL_OK;
+ /*printf("mapinfo command \"%s\", argc=%d\n",
+ Tcl_GetString(args[2]), argc);*/
switch((enum sub_cmds) index) {
/*
@@ -4989,7 +5695,7 @@ MapInfoObjCmd(ClientData client_data,
{
MapInfoLineStyle line_style;
MapInfoTextStyle text_style;
- int i, index;
+ int i, insert;
int coords[6];
ZnBool add_cmd = (enum sub_cmds) index == ZN_MI_ADD;
int num_param = add_cmd ? 4 : 5;
@@ -5004,14 +5710,14 @@ MapInfoObjCmd(ClientData client_data,
return ZN_ERROR;
}
if (!add_cmd) {
- if (Tcl_GetIntFromObj(interp, args[4], &index) == ZN_ERROR) {
+ if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) {
return ZN_ERROR;
}
- if (index < 0) {
- index = 0;
+ if (insert < 0) {
+ insert = 0;
}
}
- if (Tcl_GetIndexFromObj(interp, args[0], e_type_strings,
+ if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
"elementType", 0, &index2) != ZN_OK) {
return ZN_ERROR;
}
@@ -5040,7 +5746,7 @@ MapInfoObjCmd(ClientData client_data,
coords[0], coords[1], coords[2], coords[3], coords[4]);
}
else {
- MapInfoReplaceLine(master->map_info, index, NULL, line_style,
+ MapInfoReplaceLine(master->map_info, insert, NULL, line_style,
coords[0], coords[1], coords[2], coords[3], coords[4]);
}
}
@@ -5065,7 +5771,7 @@ MapInfoObjCmd(ClientData client_data,
coords[1], coords[2]);
}
else {
- MapInfoReplaceSymbol(master->map_info, index, NULL, coords[0],
+ MapInfoReplaceSymbol(master->map_info, insert, NULL, coords[0],
coords[1], coords[2]);
}
}
@@ -5097,7 +5803,7 @@ MapInfoObjCmd(ClientData client_data,
else {
/*printf("replace text ts %d ls %d %d %d %s\n", text_style,
line_style, coords[0], coords[1], Tcl_GetString(args[num_param+4]));*/
- MapInfoReplaceText(master->map_info, index, NULL, text_style,
+ MapInfoReplaceText(master->map_info, insert, NULL, text_style,
line_style, coords[0], coords[1],
Tcl_GetString(args[num_param+4]));
}
@@ -5128,7 +5834,7 @@ MapInfoObjCmd(ClientData client_data,
coords[5]);
}
else {
- MapInfoReplaceArc(master->map_info, index, NULL, line_style, coords[0],
+ MapInfoReplaceArc(master->map_info, insert, NULL, line_style, coords[0],
coords[1], coords[2], coords[3], coords[4], coords[5]);
}
}
@@ -5151,9 +5857,7 @@ MapInfoObjCmd(ClientData client_data,
if (master == NULL) {
return ZN_ERROR;
}
- args += 3;
- argc -= 3;
- if (Tcl_GetIndexFromObj(interp, args[0], e_type_strings,
+ if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
"elementType", 0, &index2) != ZN_OK) {
return ZN_ERROR;
}
@@ -5179,7 +5883,7 @@ MapInfoObjCmd(ClientData client_data,
*/
case ZN_MI_GET:
{
- int index;
+ int insert;
if (argc != 5) {
Tcl_WrongNumArgs(interp, 1, args, "mapInfo get type index");
return ZN_ERROR;
@@ -5188,15 +5892,13 @@ MapInfoObjCmd(ClientData client_data,
if (master == NULL) {
return ZN_ERROR;
}
- if (Tcl_GetIntFromObj(interp, args[4], &index) == ZN_ERROR) {
+ if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) {
return ZN_ERROR;
}
- if (index < 0) {
- index = 0;
+ if (insert < 0) {
+ insert = 0;
}
- args += 3;
- argc -= 3;
- if (Tcl_GetIndexFromObj(interp, args[0], e_type_strings,
+ if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
"elementType", 0, &index2) != ZN_OK) {
return ZN_ERROR;
}
@@ -5206,7 +5908,7 @@ MapInfoObjCmd(ClientData client_data,
MapInfoLineStyle line_style;
int line_width;
int x_from, y_from, x_to, y_to;
- MapInfoGetLine(master->map_info, index, NULL, &line_style,
+ MapInfoGetLine(master->map_info, insert, NULL, &line_style,
&line_width, &x_from, &y_from, &x_to, &y_to);
lobjs[0] = NewStringObj(MapInfoLineStyleToString(line_style));
lobjs[1] = Tcl_NewIntObj(line_width);
@@ -5221,7 +5923,7 @@ MapInfoObjCmd(ClientData client_data,
{
int x, y;
char symbol;
- MapInfoGetSymbol(master->map_info, index, NULL, &x, &y, &symbol);
+ MapInfoGetSymbol(master->map_info, insert, NULL, &x, &y, &symbol);
lobjs[0] = Tcl_NewIntObj(x);
lobjs[1] = Tcl_NewIntObj(y);
lobjs[2] = Tcl_NewIntObj(symbol);
@@ -5234,7 +5936,7 @@ MapInfoObjCmd(ClientData client_data,
char *text;
MapInfoTextStyle text_style;
MapInfoLineStyle line_style;
- MapInfoGetText(master->map_info, index, NULL, &text_style, &line_style,
+ MapInfoGetText(master->map_info, insert, NULL, &text_style, &line_style,
&x, &y, &text);
lobjs[0] = Tcl_NewIntObj(x);
lobjs[1] = Tcl_NewIntObj(y);
@@ -5250,7 +5952,7 @@ MapInfoObjCmd(ClientData client_data,
int line_width;
int center_x, center_y, start, extent;
unsigned int radius;
- MapInfoGetArc(master->map_info, index, NULL, &line_style, &line_width,
+ MapInfoGetArc(master->map_info, insert, NULL, &line_style, &line_width,
&center_x, &center_y, &radius, &start, &extent);
lobjs[0] = NewStringObj(MapInfoLineStyleToString(line_style));
lobjs[1] = Tcl_NewIntObj(line_width);
@@ -5270,7 +5972,7 @@ MapInfoObjCmd(ClientData client_data,
*/
case ZN_MI_REMOVE:
{
- int index;
+ int insert;
if (argc != 5) {
Tcl_WrongNumArgs(interp, 1, args, "mapInfo remove type index");
return ZN_ERROR;
@@ -5279,30 +5981,28 @@ MapInfoObjCmd(ClientData client_data,
if (master == NULL) {
return ZN_ERROR;
}
- if (Tcl_GetIntFromObj(interp, args[4], &index) == ZN_ERROR) {
+ if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) {
return ZN_ERROR;
}
- if (index < 0) {
- index = 0;
+ if (insert < 0) {
+ insert = 0;
}
- args += 3;
- argc -= 3;
- if (Tcl_GetIndexFromObj(interp, args[0], e_type_strings,
+ if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
"elementType", 0, &index2) != ZN_OK) {
return ZN_ERROR;
}
switch ((enum e_types) index2) {
case ZN_E_LINE:
- MapInfoRemoveLine(master->map_info, index);
+ MapInfoRemoveLine(master->map_info, insert);
break;
case ZN_E_SYMBOL:
- MapInfoRemoveSymbol(master->map_info, index);
+ MapInfoRemoveSymbol(master->map_info, insert);
break;
case ZN_E_TEXT:
- MapInfoRemoveText(master->map_info, index);
+ MapInfoRemoveText(master->map_info, insert);
break;
case ZN_E_ARC:
- MapInfoRemoveArc(master->map_info, index);
+ MapInfoRemoveArc(master->map_info, insert);
break;
}
UpdateMapInfoClients(master);
@@ -5431,22 +6131,22 @@ VideomapObjCmd(ClientData client_data,
case ZN_V_LOAD:
{
MapInfoId map_info;
- int index;
+ int insert;
if (argc != 5) {
Tcl_WrongNumArgs(interp, 1, args, "load filename index mapInfo");
return ZN_ERROR;
}
- if (Tcl_GetIntFromObj(interp, args[3], &index) == ZN_ERROR) {
+ if (Tcl_GetIntFromObj(interp, args[3], &insert) == ZN_ERROR) {
return ZN_ERROR;
}
- if (index < 0) {
- index = 0;
+ if (insert < 0) {
+ insert = 0;
}
if (ZnCreateMapInfo(interp, Tcl_GetString(args[4]), &map_info) == ZN_ERROR) {
return ZN_ERROR;
}
- if (MapInfoGetVideomap(map_info, Tcl_GetString(args[2]), index) == ZN_ERROR) {
+ if (MapInfoGetVideomap(map_info, Tcl_GetString(args[2]), insert) == ZN_ERROR) {
Tcl_AppendResult(interp, "unable to load videomap file \"",
Tcl_GetString(args[2]), ":",
Tcl_GetString(args[3]), "\"", NULL);
@@ -5507,6 +6207,14 @@ InitZinc(Tcl_Interp *interp) {
all_uid = Tk_GetUid("all");
current_uid = Tk_GetUid("current");
+ and_uid = Tk_GetUid("&&");
+ or_uid = Tk_GetUid("||");
+ xor_uid = Tk_GetUid("^");
+ paren_uid = Tk_GetUid("(");
+ end_paren_uid = Tk_GetUid(")");
+ neg_paren_uid = Tk_GetUid("!(");
+ tag_val_uid = Tk_GetUid("!!");
+ neg_tag_val_uid = Tk_GetUid("!");
inited = True;
}
@@ -5538,7 +6246,8 @@ Tkzinc_Init(Tcl_Interp *interp) /* Used for error reporting. */
}
Tcl_CreateObjCommand(interp, "zinc", ZincObjCmd,
- (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) Tk_MainWindow(interp),
+ (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "mapinfo", MapInfoObjCmd,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "videomap", VideomapObjCmd,