From 10eca5c001349c8804bc4a1f359141896f8b2d71 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Mon, 8 Apr 2002 14:08:22 +0000 Subject: Support du focus sur tous les items. Support du focus sur les fields. Support de la s�lection/curseur sur les fields. Les textes des fields sont editables. Transfert des commandes sur les MapInfos dans MapInfo.c. R�cup�ration du code d'endommagement/r�paration depuis Item.c. Diverses modifs li�es � la restructuration de Item.c et � la suppression de ITEM_P. D�but de modif des routines de recherche sur les tags (transfert de param�tres entre ZnTagSearchScan et ZnTagSearchFirst). --- generic/tkZinc.c | 1882 ++++++++++++++++++++++-------------------------------- 1 file changed, 765 insertions(+), 1117 deletions(-) (limited to 'generic/tkZinc.c') diff --git a/generic/tkZinc.c b/generic/tkZinc.c index 43979d8..01c1554 100644 --- a/generic/tkZinc.c +++ b/generic/tkZinc.c @@ -42,6 +42,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " #include "Types.h" #include "Geo.h" #include "Item.h" +#include "Group.h" #include "WidgetInfo.h" #include "tkZinc.h" #include "MapInfo.h" @@ -67,18 +68,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " #include #endif -#if 0 -typedef struct TagSearch { - WidgetInfo *wi; - Tk_Uid tag; - GroupItem group; - Item current; - Item previous; /* Needed to detect changes in the linked - * list between calls. */ - 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 */ @@ -127,7 +117,6 @@ static unsigned char dither4x4[4][4] = { }; static unsigned char bitmaps[NUM_ALPHA_STEPS][32][4]; -static ZnBool inited = False; static Tk_Uid all_uid; static Tk_Uid current_uid; static Tk_Uid and_uid; @@ -280,7 +269,7 @@ static void Event _ANSI_ARGS_((ClientData client_data, XEvent *eventPtr)); static void Bind _ANSI_ARGS_((ClientData client_data, XEvent *eventPtr)); static int FetchSelection _ANSI_ARGS_((ClientData clientData, int offset, char *buffer, int maxBytes)); -static void SelectTo _ANSI_ARGS_((Item item, int index)); +static void SelectTo _ANSI_ARGS_((Item item, int field, int index)); static int WidgetObjCmd _ANSI_ARGS_((ClientData client_data, Tcl_Interp *, int argc, Tcl_Obj *CONST args[])); static int Configure _ANSI_ARGS_((Tcl_Interp *interp, WidgetInfo *wi, @@ -289,6 +278,8 @@ static void Redisplay _ANSI_ARGS_((ClientData client_data)); static void Destroy _ANSI_ARGS_((char *mem_ptr)); static void InitZinc _ANSI_ARGS_((Tcl_Interp *interp)); static void Focus _ANSI_ARGS_((WidgetInfo *wi, ZnBool got_focus)); +static void Update _ANSI_ARGS_((WidgetInfo *wi)); +static void Repair _ANSI_ARGS_((WidgetInfo *wi)); Tcl_Obj * @@ -473,9 +464,7 @@ ZincObjCmd(ClientData client_data, /* Main window associated with unsigned int num; int major_op, first_err, first_evt; - if (!inited) { - InitZinc(interp); - } + InitZinc(interp); if (argc == 1) { Tcl_AppendResult(interp, ZINCVERSION, NULL); @@ -569,7 +558,7 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->obj_id = 1; wi->num_items = 0; - wi->top_group = ITEM_P.CreateItem(wi, ZnGroup, 0, NULL); + wi->top_group = ZnCreateItem(wi, ZnGroup, 0, NULL); #ifdef OM wi->om_group_id = 0; @@ -582,6 +571,9 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->pick_aperture = 0; wi->new_item = wi->current_item = ZN_NO_ITEM; wi->new_part = wi->current_part = ZN_NO_PART; + wi->focus_item = ZN_NO_ITEM; + wi->focus_field = ZN_NO_PART; + wi->got_focus = False; wi->monitoring = False; wi->total_draw_chrono = NewChrono("Total draw time"); @@ -600,14 +592,14 @@ ZincObjCmd(ClientData client_data, /* Main window associated with */ wi->text_info.sel_color = NULL; wi->text_info.sel_item = ZN_NO_ITEM; + wi->text_info.sel_field = ZN_NO_PART; wi->text_info.sel_first = -1; wi->text_info.sel_last = -1; wi->text_info.anchor_item = ZN_NO_ITEM; + wi->text_info.anchor_field = ZN_NO_PART; wi->text_info.sel_anchor = 0; wi->text_info.insert_color = NULL; wi->text_info.insert_width = 0; - wi->text_info.focus_item = ZN_NO_ITEM; - wi->text_info.got_focus = False; wi->text_info.cursor_on = False; wi->insert_on_time = 0; wi->insert_off_time = 0; @@ -617,8 +609,8 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->highlight_color = NULL; wi->highlight_bg_color = NULL; - ITEM_P.InitClipStack(wi); - ITEM_P.InitTransformStack(wi); + ZnInitClipStack(wi); + ZnInitTransformStack(wi); for (num = 0; num < NUM_ALPHA_STEPS; num++) { char name[INTEGER_SPACE+12]; @@ -735,12 +727,12 @@ EncodeItemPart(Item item, int part) { if (part >= 0) { - FieldSet field_set; + FieldSet fs; if (!item->class->has_fields) { return item; } - field_set = item->class->GetFieldSet(item); - return (ClientData) (((char *) field_set->fields)+(part%field_set->num_fields)); + fs = item->class->GetFieldSet(item); + return (ClientData) (FIELD.GetFieldStruct(fs, part%FIELD.NumFields(fs))); } else if (part == ZN_NO_PART) { return item; @@ -1197,13 +1189,16 @@ 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; + TagSearch **search_var, /* Record describing tag search; * will be initialized here. */ + Item group, /* Start group */ + ZnBool recursive) /* Does the search walk down the + * tree ? */ { char *tag; int i; TagSearch *search; - + if (tag_obj) { tag = Tcl_GetString(tag_obj); } @@ -1232,9 +1227,24 @@ ZnTagSearchScan(WidgetInfo *wi, /* 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; + /* + * Short-circuit impossible searches for null tags and + * mark the search as 'over' for ZnTagSearchFirst and + * ZnTagSearchNext. This test must not be migrated before + * allocating search structures or special care must be + * taken in ZnTagSearchDestroy to avoid deallocating unallocated + * memory. + */ + if (search->tag_len == 0) { + search->over = True; + return ZN_OK; + } + + /* + * Make sure there is enough buffer to hold rewritten tags (30%). + */ + if ((unsigned int)search->tag_len*1.3 >= search->rewrite_buf_alloc) { + search->rewrite_buf_alloc = (unsigned int)search->tag_len*1.3; search->rewrite_buf = ZnRealloc(search->rewrite_buf, search->rewrite_buf_alloc); } @@ -1243,8 +1253,8 @@ ZnTagSearchScan(WidgetInfo *wi, search->wi = wi; search->over = False; search->type = 0; - search->group = (GroupItem) wi->top_group; - search->recursive = True; + search->group = group; + search->recursive = recursive; ZnListEmpty(search->item_stack); /* @@ -1269,11 +1279,6 @@ ZnTagSearchScan(WidgetInfo *wi, */ 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 @@ -1357,23 +1362,17 @@ ZnTagSearchScan(WidgetInfo *wi, *-------------------------------------------------------------- */ static Item -ZnTagSearchFirst(TagSearch *search, /* Record describing tag search */ - Item group, /* Start group */ - ZnBool recursive) /* Does the search walk down the - * tree ? */ +ZnTagSearchFirst(TagSearch *search) /* Record describing tag search */ { Item item, previous; Tk_Uid uid, *tags; int count; /* short circuit impossible searches for null tags */ - if (search->tag_len == 0) { + if (search->over == True) { return ZN_NO_ITEM; } - search->group = (GroupItem) group; - search->recursive = recursive; - /* * 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 @@ -1408,12 +1407,12 @@ ZnTagSearchFirst(TagSearch *search, /* Record describing tag search */ * All items match. */ search->previous = ZN_NO_ITEM; - search->current = (Item) search->group->head; + search->current = ZnGroupHead(search->group); return search->current; } uid = search->expr->uid; - item = (Item) search->group->head; + item = ZnGroupHead(search->group); previous = ZN_NO_ITEM; do { while (item != ZN_NO_ITEM) { @@ -1446,15 +1445,16 @@ ZnTagSearchFirst(TagSearch *search, /* Record describing tag search */ } } if ((item->class == ZnGroup) && (search->recursive)) { + Item prev_group = (Item) search->group; /* * Explore the hierarchy depth first using the item stack * to save the current node. */ /*printf("ZnTagSearchFirst diving for tag '%s', detph %d\n", search->tag, ZnListSize(search->item_stack)/2);*/ - search->group = (GroupItem) item; + search->group = item; previous = item; - if (item == group) { + if (item == prev_group) { item = ZN_NO_ITEM; } else { @@ -1463,7 +1463,7 @@ ZnTagSearchFirst(TagSearch *search, /* Record describing tag search */ ZnListAdd(search->item_stack, &previous, ZnListTail); ZnListAdd(search->item_stack, &item, ZnListTail); previous = ZN_NO_ITEM; - item = search->group->head; + item = ZnGroupHead(search->group); } else { previous = item; @@ -1482,7 +1482,7 @@ ZnTagSearchFirst(TagSearch *search, /* Record describing tag search */ ZnListDelete(search->item_stack, ZnListTail); } if (item != ZN_NO_ITEM) { - search->group = (GroupItem) item->parent; + search->group = item->parent; } } while (item != ZN_NO_ITEM); @@ -1529,7 +1529,7 @@ ZnTagSearchNext(TagSearch *search) /* Record describing search in progress. */ */ previous = search->previous; if (previous == ZN_NO_ITEM) { - item = search->group->head; + item = ZnGroupHead(search->group); } else { item = previous->next; @@ -1548,7 +1548,7 @@ ZnTagSearchNext(TagSearch *search) /* Record describing search in progress. */ * Explore the hierarchy depth first using the item stack * to save the current node. */ - search->group = (GroupItem) item; + search->group = item; previous = item; item = item->next; /*printf("ZnTagSearchNext diving for all, pushing %d\n", @@ -1556,7 +1556,7 @@ ZnTagSearchNext(TagSearch *search) /* Record describing search in progress. */ ZnListAdd(search->item_stack, &previous, ZnListTail); ZnListAdd(search->item_stack, &item, ZnListTail); previous = ZN_NO_ITEM; - item = search->group->head; + item = ZnGroupHead(search->group); } else { previous = item; @@ -1574,7 +1574,7 @@ ZnTagSearchNext(TagSearch *search) /* Record describing search in progress. */ ZnListDelete(search->item_stack, ZnListTail); } if (item != ZN_NO_ITEM) { - search->group = (GroupItem) item->parent; + search->group = 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);*/ @@ -1634,13 +1634,13 @@ ZnTagSearchNext(TagSearch *search) /* Record describing search in progress. */ */ /*printf("ZnTagSearchNext diving for tag, depth %d\n", ZnListSize(search->item_stack)/2);*/ - search->group = (GroupItem) item; + search->group = item; previous = item; item = item->next; ZnListAdd(search->item_stack, &previous, ZnListTail); ZnListAdd(search->item_stack, &item, ZnListTail); previous = ZN_NO_ITEM; - item = search->group->head; + item = ZnGroupHead(search->group); } else { previous = item; @@ -1656,7 +1656,7 @@ ZnTagSearchNext(TagSearch *search) /* Record describing search in progress. */ ZnListDelete(search->item_stack, ZnListTail); } if (item != ZN_NO_ITEM) { - search->group = (GroupItem) item->parent; + search->group = item->parent; } } while (item != ZN_NO_ITEM); @@ -1711,10 +1711,11 @@ ZnItemWithTagOrId(WidgetInfo *wi, Item *item, TagSearch **search_var) { - if (ZnTagSearchScan(wi, tag_or_id, search_var) != ZN_OK) { + if (ZnTagSearchScan(wi, tag_or_id, search_var, + group, recursive) != ZN_OK) { return ZN_ERROR; } - *item = ZnTagSearchFirst(*search_var, group, recursive); + *item = ZnTagSearchFirst(*search_var); return ZN_OK; } @@ -1722,7 +1723,7 @@ ZnItemWithTagOrId(WidgetInfo *wi, /* *---------------------------------------------------------------------- * - * DoItem -- + * ZnDoItem -- * * Either add a tag to an item or add the item id/part to the * interpreter result, depending on the value of tag. If tag @@ -1732,10 +1733,10 @@ ZnItemWithTagOrId(WidgetInfo *wi, *---------------------------------------------------------------------- */ void -DoItem(Tcl_Interp *interp, - Item item, - int part, - Tk_Uid tag_uid) +ZnDoItem(Tcl_Interp *interp, + Item item, + int part, + Tk_Uid tag_uid) { if (tag_uid == NULL) { Tcl_Obj *l; @@ -1882,7 +1883,7 @@ FindItems(WidgetInfo *wi, &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); + ZnDoItem(wi->interp, item->previous, ZN_NO_PART, tag_uid); } } break; @@ -1914,12 +1915,12 @@ FindItems(WidgetInfo *wi, * Go through the item list and collect all item ids. They * are sorted from most visible to least visible. */ - if (ZnTagSearchScan(wi, NULL, search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, NULL, search_var, group, recursive) == ZN_ERROR) { return ZN_ERROR; } - for (item = ZnTagSearchFirst(*search_var, group, recursive); + for (item = ZnTagSearchFirst(*search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) { - DoItem(wi->interp, item, ZN_NO_PART, tag_uid); + ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid); } } break; @@ -1956,13 +1957,13 @@ FindItems(WidgetInfo *wi, * Go through the item table and collect all items with * the given priority. */ - if (ZnTagSearchScan(wi, NULL, search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, NULL, search_var, group, recursive) == ZN_ERROR) { return ZN_ERROR; } - for (item = ZnTagSearchFirst(*search_var, group, recursive); + for (item = ZnTagSearchFirst(*search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) { if (item->priority == pri) { - DoItem(wi->interp, item, ZN_NO_PART, tag_uid); + ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid); } } } @@ -1994,15 +1995,16 @@ FindItems(WidgetInfo *wi, } } item = ZN_NO_ITEM; - if (ZnTagSearchScan(wi, args[first+1], search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[first+1], search_var, + group, recursive) == ZN_ERROR) { return ZN_ERROR; } - for (next = ZnTagSearchFirst(*search_var, group, recursive); + for (next = ZnTagSearchFirst(*search_var); next != ZN_NO_ITEM; next = ZnTagSearchNext(*search_var)) { item = next; } if ((item != ZN_NO_ITEM) && (item->next != ZN_NO_ITEM)) { - DoItem(wi->interp, item->next, ZN_NO_PART, tag_uid); + ZnDoItem(wi->interp, item->next, ZN_NO_PART, tag_uid); } } break; @@ -2052,7 +2054,7 @@ FindItems(WidgetInfo *wi, &item, &part); if (item != ZN_NO_ITEM) { - DoItem(wi->interp, item, part, tag_uid); + ZnDoItem(wi->interp, item, part, tag_uid); /*printf("first %d %d\n", item->id, part);*/ return TCL_OK; } @@ -2108,12 +2110,13 @@ FindItems(WidgetInfo *wi, return ZN_ERROR; } } - if (ZnTagSearchScan(wi, args[first+1], search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[first+1], search_var, + group, recursive) == ZN_ERROR) { return ZN_ERROR; } - for (item = ZnTagSearchFirst(*search_var, group, recursive); + for (item = ZnTagSearchFirst(*search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) { - DoItem(wi->interp, item, ZN_NO_PART, tag_uid); + ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid); } } break; @@ -2129,7 +2132,7 @@ FindItems(WidgetInfo *wi, "itemType ?inGroup? ?recursive?"); return ZN_ERROR; } - cls = (ItemClass) ITEM_P.LookupItemClass(Tcl_GetString(args[first+1])); + cls = ZnLookupItemClass(Tcl_GetString(args[first+1])); if (!cls) { Tcl_AppendResult(wi->interp, "unknown item type \"", Tcl_GetString(args[first+1]), "\"", NULL); @@ -2154,13 +2157,13 @@ FindItems(WidgetInfo *wi, * Go through the item table and collect all items with * the given item type. */ - if (ZnTagSearchScan(wi, NULL, search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, NULL, search_var, group, recursive) == ZN_ERROR) { return ZN_ERROR; } - for (item = ZnTagSearchFirst(*search_var, group, recursive); + for (item = ZnTagSearchFirst(*search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) { if (item->class == cls) { - DoItem(wi->interp, item, ZN_NO_PART, tag_uid); + ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid); } } } @@ -2178,7 +2181,7 @@ FindItems(WidgetInfo *wi, * *---------------------------------------------------------------------- */ -int +static int ParseCoordList(WidgetInfo *wi, Tcl_Obj *arg, ZnPoint **pts, @@ -2277,7 +2280,7 @@ Contour(WidgetInfo *wi, * If something has changed in the geometry we need to * update or the shape will be erroneous. */ - ITEM_P.Update(wi); + Update(wi); if (!shape->class->GetContours && !shape->class->GetClipVertices) { noshape: @@ -2574,6 +2577,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ WidgetInfo *wi = (WidgetInfo *) client_data; int result, cmd_index, index; Item item, item2; + int field = ZN_NO_PART; int num = 0, i, j; char *end, *str; ZnTransfo *t = NULL; @@ -2638,9 +2642,9 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ if (argc == 2) { /* create subcommand alone, return the list of known * object types. */ - ItemClass *classes = ZnListArray(ITEM_P.ItemClassList()); + ItemClass *classes = ZnListArray(ZnItemClassList()); - num = ZnListSize(ITEM_P.ItemClassList()); + num = ZnListSize(ZnItemClassList()); l = Tcl_GetObjResult(interp); for (i = 0; i < num; i++) { Tcl_ListObjAppendElement(interp, l, NewStringObj(classes[i]->name)); @@ -2656,7 +2660,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ if (str[0] == '-') { goto add_err; } - cls = ITEM_P.LookupItemClass(str); + cls = ZnLookupItemClass(str); if (!cls) { Tcl_AppendResult(interp, "unknown item type \"", str, "\"", NULL); goto error; @@ -2672,12 +2676,12 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ argc -= 4; args += 4; - item = ITEM_P.CreateItem(wi, cls, &argc, &args); + item = ZnCreateItem(wi, cls, &argc, &args); if (item == ZN_NO_ITEM) { goto error; } ITEM.InsertItem(item, group, ZN_NO_ITEM, True); - if (ITEM.ConfigureItem(item, -1, argc, args, True) == ZN_ERROR) { + if (ITEM.ConfigureItem(item, ZN_NO_PART, argc, args, True) == ZN_ERROR) { goto error; } wi->hot_item = item; @@ -2725,7 +2729,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ * If something has changed in the geometry we need to * update or the anchor location will be erroneous. */ - ITEM_P.Update(wi); + Update(wi); item->class->GetAnchor(item, anchor, &p); l = Tcl_GetObjResult(wi->interp); Tcl_ListObjAppendElement(wi->interp, l, NewDoubleObj(p.x)); @@ -2756,13 +2760,14 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ argc -= 2; args += 2; - ITEM_P.Update(wi); + Update(wi); ResetBBox(&bbox); for (i = 0; i < argc; i++) { - if (ZnTagSearchScan(wi, args[i], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[i], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { AddBBoxToBBox(&bbox, &item->item_bounding_box); } @@ -2950,7 +2955,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ this_one = &t; } } - ITEM.RemoveItem(item); + ITEM.ExtractItem(item); ITEM.InsertItem(item, grp, ZN_NO_ITEM, True); /* * The item can be a group in which case we must @@ -2974,17 +2979,18 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ Tcl_WrongNumArgs(interp, 1, args, "clone tagOrId ?option value ...?"); goto error; } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } argc -= 3; args += 3; l = Tcl_GetObjResult(interp); - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); 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) { + if (ITEM.ConfigureItem(item2, ZN_NO_PART, argc, args, False) == ZN_ERROR) { goto error; } Tcl_ListObjAppendElement(interp, l, NewLongObj(item2->id)); @@ -3067,26 +3073,38 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_CURSOR: { - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "cursor tagOrId index"); + if ((argc != 4) && (argc != 5)) { + Tcl_WrongNumArgs(interp, 1, args, "cursor tagOrId ?field? index"); goto error; } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + if (argc == 5) { + if (Tcl_GetIntFromObj(interp, args[3], &field) != ZN_OK) { + Tcl_AppendResult(interp, "invalid field index \"", + Tcl_GetString(args[3]), + "\", should be a positive integer", NULL); + goto error; + } + argc--; + args++; + } + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { if ((item->class->Cursor == NULL) || (item->class->Index == NULL)) { continue; } - result = (*item->class->Index)(item, args[3], &index); + result = (*item->class->Index)(item, field, args[3], &index); if (result != ZN_OK) { goto error; } - (*item->class->Cursor)(item, index); - if ((item == wi->text_info.focus_item) && wi->text_info.cursor_on) { + (*item->class->Cursor)(item, field, index); + if ((item == wi->focus_item) && (field == wi->focus_field) && + wi->text_info.cursor_on) { ITEM.Invalidate(item, ZN_COORDS_FLAG); } } @@ -3098,26 +3116,38 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ case ZN_W_DCHARS: { int first, last; - - if ((argc != 4) && (argc != 5)) { - Tcl_WrongNumArgs(interp, 1, args, "dchars tagOrId first ?last?"); + TextInfo *ti = &wi->text_info; + + if ((argc < 4) || (argc > 6)) { + Tcl_WrongNumArgs(interp, 1, args, "dchars tagOrId ?field? first ?last?"); goto error; } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + if (argc == 6) { + if (Tcl_GetIntFromObj(interp, args[3], &field) != ZN_OK) { + Tcl_AppendResult(interp, "invalid field index \"", + Tcl_GetString(args[3]), + "\", should be a positive integer", NULL); + goto error; + } + argc--; + args++; + } + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { if ((item->class->Index == NULL) || (item->class->DeleteChars == NULL)) { continue; } - result = (*item->class->Index)(item, args[3], &first); + result = (*item->class->Index)(item, field, args[3], &first); if (result != ZN_OK) { goto error; } if (argc == 5) { - result = (*item->class->Index)(item, args[4], &last); + result = (*item->class->Index)(item, field, args[4], &last); if (result != ZN_OK) { goto error; } @@ -3125,7 +3155,38 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ else { last = first; } - (*item->class->DeleteChars)(item, first, last); + (*item->class->DeleteChars)(item, field, &first, &last); + + /* + * Update indexes for the selection to reflect the + * change. + */ + if ((ti->sel_item == item) && (ti->sel_field == field)) { + int count = last + 1 - first; + if (ti->sel_first > first) { + ti->sel_first -= count; + if (ti->sel_first < first) { + ti->sel_first = first; + } + } + if (ti->sel_last >= first) { + ti->sel_last -= count; + if (ti->sel_last < (first-1)) { + ti->sel_last = (first-1); + } + } + if (ti->sel_first > ti->sel_last) { + ti->sel_item = ZN_NO_ITEM; + ti->sel_field = ZN_NO_PART; + } + if ((ti->anchor_item == item) && (ti->anchor_field == field) && + (ti->sel_anchor > first)) { + ti->sel_anchor -= count; + if (ti->sel_anchor < first) { + ti->sel_anchor = first; + } + } + } } } break; @@ -3146,10 +3207,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ else { tag = Tk_GetUid(Tcl_GetString(args[2])); } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { ITEM.RemoveTag(item, (char *) tag); } @@ -3204,37 +3266,48 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_FOCUS: { - if ((argc != 2) && (argc != 3)) { - Tcl_WrongNumArgs(interp, 1, args, "focus ?tagOrId?"); + if (argc > 4) { + Tcl_WrongNumArgs(interp, 1, args, "focus ?tagOrId? ?field?"); goto error; } - item = wi->text_info.focus_item; + item = wi->focus_item; + field = wi->focus_field; if (argc == 2) { if (item != ZN_NO_ITEM) { - l = NewLongObj(item->id); - Tcl_SetObjResult(interp, l); + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, NewLongObj(item->id)); + if (field != ZN_NO_PART) { + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(field)); + } } goto done; } - if ((item != ZN_NO_ITEM) && (wi->text_info.got_focus)) { + if ((item != ZN_NO_ITEM) && (item->class->Cursor != NULL) && + (wi->got_focus)) { ITEM.Invalidate(item, ZN_COORDS_FLAG); } if (Tcl_GetString(args[2])[0] == 0) { - wi->text_info.focus_item = ZN_NO_ITEM; + wi->focus_item = ZN_NO_ITEM; + wi->focus_field = ZN_NO_PART; goto done; } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnItemWithTagOrId(wi, args[2], wi->top_group, True, + &item, &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; + field = ZN_NO_PART; + if (argc == 4) { + if (Tcl_GetIntFromObj(interp, args[3], &field) != ZN_OK) { + Tcl_AppendResult(interp, "invalid field index \"", + Tcl_GetString(args[3]), + "\", should be a positive integer", NULL); + goto error; } } - wi->text_info.focus_item = item; - if (wi->text_info.got_focus) { - ITEM.Invalidate(wi->text_info.focus_item, ZN_COORDS_FLAG); + wi->focus_item = item; + wi->focus_field = field; + if (wi->got_focus && (item->class->Cursor != NULL)) { + ITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG); } } break; @@ -3403,17 +3476,28 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_INDEX: { - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "index tagOrId string"); + if ((argc != 4) && (argc != 5)) { + Tcl_WrongNumArgs(interp, 1, args, "index tagOrId ?field? string"); goto error; } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + if (argc == 5) { + if (Tcl_GetIntFromObj(interp, args[3], &field) != ZN_OK) { + Tcl_AppendResult(interp, "invalid field index \"", + Tcl_GetString(args[3]), + "\", should be a positive integer", NULL); + goto error; + } + argc--; + args++; + } + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { if (item->class->Index != NULL) { - result = (*item->class->Index)(item, args[3], &index); + result = (*item->class->Index)(item, field, args[3], &index); if (result != ZN_OK) { goto error; } @@ -3432,24 +3516,55 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_INSERT: { - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "insert tagOrId before string"); + TextInfo *ti = &wi->text_info; + char *chars; + + if ((argc != 5) && (argc != 6)) { + Tcl_WrongNumArgs(interp, 1, args, "insert tagOrId ?field? before string"); goto error; } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + if (argc == 6) { + if (Tcl_GetIntFromObj(interp, args[3], &field) != ZN_OK) { + Tcl_AppendResult(interp, "invalid field index \"", + Tcl_GetString(args[3]), + "\", should be a positive integer", NULL); + goto error; + } + argc--; + args++; + } + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { if ((item->class->Index == NULL) || (item->class->InsertChars == NULL)) { continue; } - result = (*item->class->Index)(item, args[3], &index); + result = (*item->class->Index)(item, field, args[3], &index); if (result != ZN_OK) { goto error; } - (*item->class->InsertChars)(item, index, Tcl_GetString(args[4])); + chars = Tcl_GetString(args[4]); + (*item->class->InsertChars)(item, field, &index, chars); + /* + * Inserting characters invalidates selection indices. + */ + if ((ti->sel_item == item) && (ti->sel_field== field)) { + int length = strlen(chars); + if (ti->sel_first >= index) { + ti->sel_first += length; + } + if (ti->sel_last >= index) { + ti->sel_last += length; + } + if ((ti->anchor_item == item) && (ti->anchor_field == field) && + (ti->sel_anchor >= index)) { + ti->sel_anchor += length; + } + } } } break; @@ -3458,8 +3573,6 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_ITEMCGET: { - int field = -1; - if (argc < 4) { itemcget_syntax: Tcl_WrongNumArgs(interp, 1, args, "itemcget tagOrId ?field? option"); @@ -3472,7 +3585,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ } if (argc == 5) { if (Tcl_GetIntFromObj(interp, args[3], &field) != ZN_OK) { - Tcl_AppendResult(interp, "invalid field index \"", Tcl_GetString(args[3]), + Tcl_AppendResult(interp, "invalid field index \"", + Tcl_GetString(args[3]), "\", should be a positive integer", NULL); goto error; } @@ -3492,13 +3606,13 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_ITEMCONFIGURE: { - int field = -1; if (argc < 3) { Tcl_WrongNumArgs(interp, 1, args, "itemconfigure tagOrId ?field? option value ?option value? ..."); goto error; } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } if ((argc > 3) && (Tcl_GetString(args[3])[0] != '-')) { @@ -3513,10 +3627,10 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ } argc -= 3; args += 3; - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { if (argc < 2) { - result = ITEM.AttributesInfo(item, field, argc, args); + result = ZnAttributesInfo(wi, item, item->class->attr_desc, argc, args); } else { result = ITEM.ConfigureItem(item, field, argc, args, False); @@ -3542,10 +3656,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ goto error; } if (argc == 4) { - if (ZnTagSearchScan(wi, args[3], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[3], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { mark = item; } @@ -3555,15 +3670,16 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ goto error; } } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - item = ZnTagSearchFirst(search_var, wi->top_group, True); + item = ZnTagSearchFirst(search_var); if (item == ZN_NO_ITEM) { goto done; } if (mark == ZN_NO_ITEM) { - mark = ((GroupItem) item->parent)->tail; + mark = ZnGroupTail(item->parent); } group = mark->parent; for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { @@ -3655,25 +3771,27 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ /* * Find the topmost item with the tag. */ - if (ZnTagSearchScan(wi, args[3], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[3], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - mark = ZnTagSearchFirst(search_var, wi->top_group, True); + mark = ZnTagSearchFirst(search_var); if (mark == ZN_NO_ITEM) { Tcl_AppendResult(interp, "unknown tag or item \"", Tcl_GetString(args[3]), "\"", NULL); goto error; } } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - item = ZnTagSearchFirst(search_var, wi->top_group, True); + item = ZnTagSearchFirst(search_var); if (item == ZN_NO_ITEM) { goto done; } if (mark == ZN_NO_ITEM) { - mark = ((GroupItem) item->parent)->head; + mark = ZnGroupHead(item->parent); } group = mark->parent; for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { @@ -3691,7 +3809,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_REMOVE: { - FieldSet fs; + int num_fields; if (argc < 3) { Tcl_WrongNumArgs(interp, 1, args, "remove tagOrId ?tagOrId ...?"); @@ -3700,10 +3818,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ argc -= 2; args += 2; for (i = 0; i < argc; i++) { - if (ZnTagSearchScan(wi, args[i], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[i], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { if (item == wi->top_group) { continue; @@ -3711,8 +3830,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ if (wi->binding_table != NULL) { 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++) { + num_fields = FIELD.NumFields(item->class->GetFieldSet(item)); + for (j = 0; j < num_fields; j++) { Tk_DeleteAllBindings(wi->binding_table, (ClientData) EncodeItemPart(item, j)); } @@ -3753,7 +3872,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ t = (ZnTransfo *) Tcl_GetHashValue(entry); } else { - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } } @@ -3771,7 +3891,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ } } else { - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { ITEM.RotateItem(item, angle, (argc == 6) ? &p : NULL); } @@ -3794,7 +3914,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ t = (ZnTransfo *) Tcl_GetHashValue(entry); } else { - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } } @@ -3809,7 +3930,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ ZnScale(t, scale.x, scale.y); } else { - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { ITEM.ScaleItem(item, scale.x, scale.y); } @@ -3821,15 +3942,18 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_SELECT: { + TextInfo *ti = &wi->text_info; + if (argc < 3) { Tcl_WrongNumArgs(interp, 1, args, "select option ?tagOrId? ?arg?"); goto error; } if (argc >= 4) { - if (ZnTagSearchScan(wi, args[3], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[3], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { if ((item->class->Index != NULL) && (item->class->Selection != NULL)) { @@ -3842,66 +3966,82 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ goto error; } } - if (argc == 5) { - result = item->class->Index(item, args[4], &index); - if (result != ZN_OK) { - goto error; - } - } if (Tcl_GetIndexFromObj(interp, args[2], sel_cmd_strings, "selection option", 0, &cmd_index) != ZN_OK) { goto error; } + if ((argc == 5) || (argc == 6)) { + if (argc == 6) { + if (Tcl_GetIntFromObj(interp, args[4], &field) != ZN_OK) { + Tcl_AppendResult(interp, "invalid field index \"", + Tcl_GetString(args[4]), + "\", should be a positive integer", NULL); + goto error; + } + argc--; + args++; + } + result = item->class->Index(item, field, args[4], &index); + if (result != ZN_OK) { + goto error; + } + } switch ((enum sel_cmds) cmd_index) { case ZN_SEL_ADJUST: if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "select adjust tagOrId index"); + Tcl_WrongNumArgs(interp, 1, args, "select adjust tagOrId ?field? index"); goto error; } - if (wi->text_info.sel_item == item) { - if (index < (wi->text_info.sel_first + wi->text_info.sel_last)/2) { - wi->text_info.sel_anchor = wi->text_info.sel_last+1; + if ((ti->sel_item == item) && (ti->sel_field == field)) { + if (index < (ti->sel_first + ti->sel_last)/2) { + ti->sel_anchor = ti->sel_last+1; } else { - wi->text_info.sel_anchor = wi->text_info.sel_first; + ti->sel_anchor = ti->sel_first; } } - SelectTo(item, index); + SelectTo(item, field, index); break; case ZN_SEL_CLEAR: if (argc != 3) { Tcl_WrongNumArgs(interp, 1, args, "select clear"); goto error; } - if (wi->text_info.sel_item != ZN_NO_ITEM) { - ITEM.Invalidate(wi->text_info.sel_item, ZN_DRAW_FLAG); - wi->text_info.sel_item = ZN_NO_ITEM; + if (ti->sel_item != ZN_NO_ITEM) { + ITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG); + ti->sel_item = ZN_NO_ITEM; + ti->sel_field = ZN_NO_PART; } break; case ZN_SEL_FROM: if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "select from tagOrId index"); + Tcl_WrongNumArgs(interp, 1, args, "select from tagOrId ?field? index"); goto error; } - wi->text_info.anchor_item = item; - wi->text_info.sel_anchor = index; + ti->anchor_item = item; + ti->anchor_field = field; + ti->sel_anchor = index; break; case ZN_SEL_ITEM: if (argc != 3) { Tcl_WrongNumArgs(interp, 1, args, "select item"); goto error; } - if (wi->text_info.sel_item != ZN_NO_ITEM) { - l = NewLongObj(wi->text_info.sel_item->id); + if (ti->sel_item != ZN_NO_ITEM) { + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, NewLongObj(ti->sel_item->id)); + if (ti->sel_field != ZN_NO_PART) { + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ti->sel_field)); + } Tcl_SetObjResult(interp, l); } break; case ZN_SEL_TO: if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "select to tagOrId index"); + Tcl_WrongNumArgs(interp, 1, args, "select to tagOrId ?field? index"); goto error; } - SelectTo(item, index); + SelectTo(item, field, index); break; } } @@ -4046,7 +4186,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ t = (ZnTransfo *) Tcl_GetHashValue(entry); } else { - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } } @@ -4061,7 +4202,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ ZnTranslate(t, trans.x, trans.y); } else { - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item =ZnTagSearchNext(search_var)) { ITEM.TranslateItem(item, trans.x, trans.y); } @@ -4082,7 +4223,8 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ t = (ZnTransfo *) Tcl_GetHashValue(entry); } else { - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } } @@ -4091,7 +4233,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ ZnTransfoSetIdentity(t); } else { - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { ITEM.ResetTransfo(item); } @@ -4114,10 +4256,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ goto error; } t = (ZnTransfo *) Tcl_GetHashValue(entry); - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { ITEM.SetTransfo(item, t); } @@ -4193,10 +4336,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ Tcl_WrongNumArgs(interp, 1, args, " vertexat tagOrId x y"); goto error; } - if (ZnTagSearchScan(wi, args[2], &search_var) == ZN_ERROR) { + if (ZnTagSearchScan(wi, args[2], &search_var, + wi->top_group, True) == ZN_ERROR) { goto error; } - for (item = ZnTagSearchFirst(search_var, wi->top_group, True); + for (item = ZnTagSearchFirst(search_var); item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { if (item->class->PickVertex != NULL) { break; @@ -4264,7 +4408,7 @@ TileChange(ClientData client_data, bbox.orig.x = bbox.orig.y = 0; bbox.corner.x = wi->width; bbox.corner.y = wi->height; - ITEM_P.Damage(wi, &bbox); + ZnDamage(wi, &bbox); ZnNeedRedisplay(wi); } @@ -4339,7 +4483,7 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ bbox.orig.x = bbox.orig.y = 0; bbox.corner.x = wi->width; bbox.corner.y = wi->height; - ITEM_P.Damage(wi, &bbox); + ZnDamage(wi, &bbox); ZnNeedRedisplay(wi); } if (CONFIG_PROBE(RELIEF_SPEC)) { @@ -4352,7 +4496,7 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ bbox.orig.x = bbox.orig.y = 0; bbox.corner.x = wi->width; bbox.corner.y = wi->height; - ITEM_P.Damage(wi, &bbox); + ZnDamage(wi, &bbox); } if (CONFIG_PROBE(SPEED_VECTOR_LENGTH_SPEC) || CONFIG_PROBE(MANAGE_HISTORY_SPEC) || @@ -4381,7 +4525,7 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ bbox.orig.x = bbox.orig.y = 0; bbox.corner.x = wi->width; bbox.corner.y = wi->height; - ITEM_P.Damage(wi, &bbox); + ZnDamage(wi, &bbox); ZnNeedRedisplay(wi); } @@ -4414,7 +4558,7 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ /* * Update the blinking cursor timing if on/off time has changed. */ - if (wi->text_info.got_focus && + if (wi->got_focus && (CONFIG_PROBE(INSERT_ON_TIME_SPEC) || CONFIG_PROBE(INSERT_OFF_TIME_SPEC))) { Focus(wi, True); @@ -4446,7 +4590,7 @@ Blink(ClientData client_data) { WidgetInfo *wi = (WidgetInfo *) client_data; - if (!wi->text_info.got_focus || (wi->insert_off_time == 0)) { + if (!wi->got_focus || (wi->insert_off_time == 0)) { return; } if (wi->text_info.cursor_on) { @@ -4459,8 +4603,9 @@ Blink(ClientData client_data) wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_on_time, Blink, client_data); } - if (wi->text_info.focus_item != ZN_NO_ITEM) { - ITEM.Invalidate(wi->text_info.focus_item, ZN_DRAW_FLAG); + if ((wi->focus_item != ZN_NO_ITEM) && + (wi->focus_item->class->Cursor != NULL)) { + ITEM.Invalidate(wi->focus_item, ZN_DRAW_FLAG); } } @@ -4470,7 +4615,7 @@ Focus(WidgetInfo *wi, { Tcl_DeleteTimerHandler(wi->blink_handler); if (got_focus) { - wi->text_info.got_focus = 1; + wi->got_focus = 1; wi->text_info.cursor_on = 1; if (wi->insert_off_time != 0) { wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time, @@ -4478,12 +4623,13 @@ Focus(WidgetInfo *wi, } } else { - wi->text_info.got_focus = 0; + wi->got_focus = 0; wi->text_info.cursor_on = 0; wi->blink_handler = (Tcl_TimerToken) NULL; } - if (wi->text_info.focus_item != ZN_NO_ITEM) { - ITEM.Invalidate(wi->text_info.focus_item, ZN_COORDS_FLAG); + if ((wi->focus_item != ZN_NO_ITEM) && + (wi->focus_item->class->Cursor != NULL)){ + ITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG); } /*printf("focus %s\n", got_focus ? "in" : "out");*/ if (wi->highlight_width > 0) { @@ -4496,7 +4642,7 @@ Focus(WidgetInfo *wi, bbox.orig.x = bbox.orig.y = 0; bbox.corner.x = Tk_Width(wi->win); bbox.corner.y = Tk_Height(wi->win); - ITEM_P.Damage(wi, &bbox); + ZnDamage(wi, &bbox); ZnNeedRedisplay(wi); } #endif @@ -4640,8 +4786,8 @@ Event(ClientData client_data, /* Information about widget. */ wi->opt_width = wi->width = int_width; wi->opt_height = wi->height = int_height; - ITEM_P.ResetTransformStack(wi); - ITEM_P.Damage(wi, &bbox); + ZnResetTransformStack(wi); + ZnDamage(wi, &bbox); ITEM.Invalidate(wi->top_group, ZN_TRANSFO_FLAG); /* @@ -4747,8 +4893,8 @@ DoEvent(WidgetInfo *wi, item = wi->current_item; part = wi->current_part; if ((event->type == KeyPress) || (event->type == KeyRelease)) { - item = wi->text_info.focus_item; - part = ZN_NO_PART; + item = wi->focus_item; + part = wi->focus_field; } if ((item == ZN_NO_ITEM) || !item->class->IsSensitive(item, ZN_NO_PART)) { @@ -5055,7 +5201,7 @@ PickCurrentItem(WidgetInfo *wi, * Add the tag 'current' to the current item under the pointer. */ /*printf("Adding 'current' to %d\n", wi->current_item->id);*/ - DoItem((Tcl_Interp *) NULL, wi->current_item, ZN_NO_PART, current_uid); + ZnDoItem((Tcl_Interp *) NULL, wi->current_item, ZN_NO_PART, current_uid); /* * Then emit a fake Enter event on it. */ @@ -5179,7 +5325,7 @@ Bind(ClientData client_data, /* Information about widget. */ bbox.orig.x = bbox.orig.y = 0; bbox.corner.x = Tk_Width(wi->win); bbox.corner.y = Tk_Height(wi->win); - ITEM_P.Damage(wi, &bbox); + ZnDamage(wi, &bbox); ZnNeedRedisplay(wi); } #endif @@ -5222,11 +5368,13 @@ static void LostSelection(ClientData client_data) { WidgetInfo *wi = (WidgetInfo *) client_data; + TextInfo *ti = &wi->text_info; - if (wi->text_info.sel_item != ZN_NO_ITEM) { - ITEM.Invalidate(wi->text_info.sel_item, ZN_DRAW_FLAG); + if (ti->sel_item != ZN_NO_ITEM) { + ITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG); } - wi->text_info.sel_item = ZN_NO_ITEM; + ti->sel_item = ZN_NO_ITEM; + ti->sel_field = ZN_NO_PART; } @@ -5247,42 +5395,46 @@ LostSelection(ClientData client_data) *---------------------------------------------------------------------- */ static void -SelectTo(Item item, - int index) +SelectTo(Item item, + int field, + int index) { WidgetInfo *wi = item->wi; - int old_first, old_last; + TextInfo *ti = &wi->text_info; + int old_first, old_last, old_field; Item old_sel_item; - old_first = wi->text_info.sel_first; - old_last = wi->text_info.sel_last; - old_sel_item = wi->text_info.sel_item; + old_first = ti->sel_first; + old_last = ti->sel_last; + old_sel_item = ti->sel_item; + old_field = ti->sel_field; /* * Grab the selection if we don't own it already. */ - if (wi->text_info.sel_item == ZN_NO_ITEM) { + if (ti->sel_item == ZN_NO_ITEM) { Tk_OwnSelection(wi->win, XA_PRIMARY, LostSelection, (ClientData) wi); } - else if (wi->text_info.sel_item != item) { - ITEM.Invalidate(wi->text_info.sel_item, ZN_DRAW_FLAG); + else if ((ti->sel_item != item) || (ti->sel_field != field)) { + ITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG); } - wi->text_info.sel_item = item; + ti->sel_item = item; - if (wi->text_info.anchor_item != item) { - wi->text_info.anchor_item = item; - wi->text_info.sel_anchor = index; + if ((ti->anchor_item != item) || (ti->anchor_field) != field) { + ti->anchor_item = item; + ti->anchor_field = field; + ti->sel_anchor = index; } - if (wi->text_info.sel_anchor <= index) { - wi->text_info.sel_first = wi->text_info.sel_anchor; - wi->text_info.sel_last = index; + if (ti->sel_anchor <= index) { + ti->sel_first = ti->sel_anchor; + ti->sel_last = index; } else { - wi->text_info.sel_first = index; - wi->text_info.sel_last = wi->text_info.sel_anchor; + ti->sel_first = index; + ti->sel_last = ti->sel_anchor; } - if ((wi->text_info.sel_first != old_first) || - (wi->text_info.sel_last != old_last) || + if ((ti->sel_first != old_first) || + (ti->sel_last != old_last) || (item != old_sel_item)) { ITEM.Invalidate(item, ZN_DRAW_FLAG); } @@ -5320,15 +5472,16 @@ FetchSelection( ClientData client_data, * NULL character. */ { WidgetInfo *wi = (WidgetInfo *) client_data; + TextInfo *ti = &wi->text_info; - if (wi->text_info.sel_item == NULL) { + if (ti->sel_item == ZN_NO_ITEM) { return -1; } - if (wi->text_info.sel_item->class->Selection == NULL) { + if (ti->sel_item->class->Selection == NULL) { return -1; } - return (*wi->text_info.sel_item->class->Selection)(wi->text_info.sel_item, offset, - buffer, max_bytes); + return (*ti->sel_item->class->Selection)(ti->sel_item, ti->sel_field, + offset, buffer, max_bytes); } @@ -5471,8 +5624,8 @@ Destroy(char *mem_ptr) /* Info about the widget. */ /* * Should be empty by now. */ - ITEM_P.FreeTransformStack(wi); - ITEM_P.FreeClipStack(wi); + ZnFreeTransformStack(wi); + ZnFreeClipStack(wi); ZnListFree(wi->work_pts); #ifdef GLX @@ -5489,966 +5642,461 @@ Destroy(char *mem_ptr) /* Info about the widget. */ /* - *---------------------------------------------------------------------- - * - * Redisplay -- - * - * This procedure redraws the contents of a Zinc window. - * It is invoked as a do-when-idle handler, so it only runs - * when there's nothing else for the application to do. - * - * Results: - * None. + ********************************************************************************** * - * Side effects: - * Information appears on the screen. + * ZnDamage -- * - *---------------------------------------------------------------------- + ********************************************************************************** */ - -static void -Redisplay(ClientData client_data) /* Information about the widget. */ +void +ZnDamage(WidgetInfo *wi, + ZnBBox *damage) { - WidgetInfo *wi = (WidgetInfo *) client_data; - - wi->update_pending = 0; - if (!wi->realized || !Tk_IsMapped(wi->win)) { + if ((damage == NULL) || IsEmptyBBox(damage)) { return; } - - if (wi->monitoring) { - XStartChrono(wi->total_draw_chrono, wi->dpy, ZnWindowId(wi->win)); - ResetChronos(wi->this_draw_chrono); - XStartChrono(wi->this_draw_chrono, wi->dpy, ZnWindowId(wi->win)); - } - do { - /* - * Update the items. - * NOTE: See above. - */ - ITEM_P.Update(wi); - - /* - * Do enter/leave processing after the overlap manager - * has finished with the items. Do it has many times - * as needed, each round may trigger callbacks that - * result in moved items and so forth. It can even - * lead to the widget destruction, this is the reason - * for Tcl_Preserve/Tcl_Release. - */ - if (ISSET(wi->events_flags, INTERNAL_NEED_REPICK)) { - Tk_Window tkwin; + /*printf("damaging area: %g %g %g %g\n", damage->orig.x, + damage->orig.y, damage->corner.x, damage->corner.y);*/ - Tcl_Preserve((ClientData) wi); - CLEAR(wi->events_flags, INTERNAL_NEED_REPICK); - PickCurrentItem(wi, &wi->pick_event); - tkwin = wi->win; - Tcl_Release((ClientData) wi); - if (tkwin == NULL) { - return; - } - } + if (IsEmptyBBox(&wi->damaged_area)) { + wi->damaged_area.orig.x = damage->orig.x; + wi->damaged_area.orig.y = damage->orig.y; + wi->damaged_area.corner.x = damage->corner.x; + wi->damaged_area.corner.y = damage->corner.y; } - while (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) || - ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG) || - ISSET(wi->events_flags, INTERNAL_NEED_REPICK)); - - /* - * Repair the scene where it is no longer up to date, - * then send the merged area back to the screen. - */ - ITEM_P.Repair(wi); - - /* - * Reset the exposed & damaged areas. - */ - ResetBBox(&wi->exposed_area); - ResetBBox(&wi->damaged_area); + else { + wi->damaged_area.orig.x = MIN(wi->damaged_area.orig.x, damage->orig.x); + wi->damaged_area.orig.y = MIN(wi->damaged_area.orig.y, damage->orig.y); + wi->damaged_area.corner.x = MAX(wi->damaged_area.corner.x, damage->corner.x); + wi->damaged_area.corner.y = MAX(wi->damaged_area.corner.y, damage->corner.y); + } + /*printf("damaged area: %g %g %g %g\n", wi->damaged_area.orig.x, + wi->damaged_area.orig.y, wi->damaged_area.corner.x, + wi->damaged_area.corner.y);*/ +} - if (wi->monitoring) { - XStopChrono(wi->total_draw_chrono, wi->dpy, ZnWindowId(wi->win)); - XStopChrono(wi->this_draw_chrono, wi->dpy, ZnWindowId(wi->win)); +static void +ClampDamageArea(WidgetInfo *wi) +{ + int width, height; + + if (wi->damaged_area.orig.x < wi->inset) { + wi->damaged_area.orig.x = wi->inset; + } + if (wi->damaged_area.orig.y < wi->inset) { + wi->damaged_area.orig.y = wi->inset; + } + if (wi->damaged_area.corner.x < wi->inset) { + wi->damaged_area.corner.x = wi->inset; + } + if (wi->damaged_area.corner.y < wi->inset) { + wi->damaged_area.corner.y = wi->inset; + } + width = wi->width - wi->inset; + height = wi->height - wi->inset; + if (wi->damaged_area.orig.x > width) { + wi->damaged_area.orig.x = width; + } + if (wi->damaged_area.orig.y > height) { + wi->damaged_area.orig.y = height; + } + if (wi->damaged_area.corner.x > width) { + wi->damaged_area.corner.x = width; + } + if (wi->damaged_area.corner.y > height) { + wi->damaged_area.corner.y = height; } } /* - *-------------------------------------------------------------------------- + ********************************************************************************** * - * MapInfo stuff that should go eventually in its own file. + * Update -- * - *-------------------------------------------------------------------------- + ********************************************************************************** */ - -static Tcl_HashTable mapInfoTable; -static ZnBool map_info_inited = False; - -typedef struct { - ClientData client_data; - MapInfoChangeProc proc; -} MapInfoClient; - -typedef struct { - MapInfoId map_info; - ZnBool deleted; - ZnList clients; -} MapInfoMaster; - static void -MapInfoInit() +Update(WidgetInfo *wi) { - Tcl_InitHashTable(&mapInfoTable, TCL_ONE_WORD_KEYS); + /* + * Give the overlap manager a chance to do its work. + */ +#ifdef OM + if ((wi->om_group != ZN_NO_ITEM) && ZnGroupCallOm(wi->om_group)) { + ZnPoint scale={1.0,1.0}; + if (wi->om_group->transfo) { + ZnTransfoDecompose(wi->om_group->transfo, &scale, + NULL, NULL, NULL); + } + OmProcessOverlap((void *) wi, wi->width, wi->height, scale.x); + ZnGroupSetCallOm(wi->om_group, False); + } +#endif - map_info_inited = True; + if (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) || + ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG)) { + wi->top_group->class->ComputeCoordinates(wi->top_group, False); + } } + +/* + ********************************************************************************** + * + * Repair -- + * + ********************************************************************************** + */ static void -UpdateMapInfoClients(MapInfoMaster *master) +Repair(WidgetInfo *wi) { - int i, num; - MapInfoClient *client; - - num = ZnListSize(master->clients); - client = (MapInfoClient *) ZnListArray(master->clients); - for (i = 0; i < num; i++, client++) { - (*client->proc)(client->client_data, master->map_info); - } -} + XGCValues values; + ZnPoint pts[2]; + ZnTriStrip tristrip; + XColor *color; + ZnReal int_width = Tk_Width(wi->win); + ZnReal int_height = Tk_Height(wi->win); -int -ZnCreateMapInfo(Tcl_Interp *interp, - char *name, - MapInfoId *map_info) -{ - Tk_Uid uid = Tk_GetUid(name); - Tcl_HashEntry *entry; - int new; - MapInfoMaster *master; - - if (!map_info_inited) { - MapInfoInit(); - } - - entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new); - if (!new) { + if (wi->render) { +#ifdef GLX +#ifdef GLX_DAMAGE + ClampDamageArea(wi); /* - * Empty the map info if it is not. + * Merge the exposed area. */ - master = (MapInfoMaster *) Tcl_GetHashValue(entry); - if (master->deleted) { - master->deleted = False; - } - else { - MapInfoEmpty(master->map_info); - UpdateMapInfoClients(master); + AddBBoxToBBox(&wi->damaged_area, &wi->exposed_area); + if (IsEmptyBBox(&wi->damaged_area)) { + return; } - } - else { - master = (MapInfoMaster *) ZnMalloc(sizeof(MapInfoMaster)); - master->map_info = MapInfoCreate(name); - master->deleted = False; - master->clients = ZnListNew(1, sizeof(MapInfoClient)); - Tcl_SetHashValue(entry, master); - } - if (map_info) { - *map_info = master->map_info; - } - return TCL_OK; -} +#endif -int -ZnDuplicateMapInfo(Tcl_Interp *interp, - char *name, - MapInfoId map_info) -{ - Tk_Uid uid = Tk_GetUid(name); - Tcl_HashEntry *entry; - int new; - MapInfoMaster *master; - - if (!map_info_inited) { - MapInfoInit(); - } - - entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new); - if (!new) { - Tcl_AppendResult(interp, "duplicate mapinfo \"", name, "\" already exists", NULL); - return ZN_ERROR; - } - master = (MapInfoMaster *) ZnMalloc(sizeof(MapInfoMaster)); - master->map_info = MapInfoDuplicate(map_info); - master->deleted = False; - master->clients = ZnListNew(1, sizeof(MapInfoClient)); - Tcl_SetHashValue(entry, master); - - return TCL_OK; -} - -MapInfoMaster * -LookupMapInfoMaster(Tcl_Interp *interp, - char *name) -{ - Tk_Uid uid = Tk_GetUid(name); - Tcl_HashEntry *entry; - MapInfoMaster *master; - - if (!map_info_inited) { - MapInfoInit(); - } - - entry = Tcl_FindHashEntry(&mapInfoTable, uid); - if (entry == NULL) { - mp_error: - Tcl_AppendResult(interp, "mapinfo \"", name, "\" doesn't exist", NULL); - return NULL; - } - master = (MapInfoMaster *) Tcl_GetHashValue(entry); - if (master->deleted) { - goto mp_error; - } - return master; -} - -int -ZnDeleteMapInfo(Tcl_Interp *interp, - char *name) -{ - MapInfoMaster *master; - Tk_Uid uid = Tk_GetUid(name); - Tcl_HashEntry *entry; - - if (!map_info_inited) { - MapInfoInit(); - } - - entry = Tcl_FindHashEntry(&mapInfoTable, uid); - if (entry == NULL) { - return ZN_ERROR; - } - - master = (MapInfoMaster *) Tcl_GetHashValue(entry); - if (ZnListSize(master->clients) != 0) { - master->deleted = True; - MapInfoEmpty(master->map_info); - UpdateMapInfoClients(master); - } - else { - MapInfoDelete(master->map_info); - ZnListFree(master->clients); - Tcl_DeleteHashEntry(entry); - ZnFree(master); - } - - return TCL_OK; -} - -MapInfoId -ZnGetMapInfo(Tcl_Interp *interp, - char *name, - MapInfoChangeProc proc, - ClientData client_data) -{ - MapInfoMaster *master; - MapInfoClient client; - - master = LookupMapInfoMaster(interp, name); - if (master == NULL) { - return NULL; - } - client.proc = proc; - client.client_data = client_data; - ZnListAdd(master->clients, &client, ZnListTail); - - return master->map_info; -} - -void -ZnFreeMapInfo(MapInfoId map_info, - MapInfoChangeProc proc, - ClientData client_data) -{ - Tk_Uid uid = Tk_GetUid(MapInfoName(map_info)); - Tcl_HashEntry *entry; - MapInfoMaster *master; - MapInfoClient *client; - int num, i; - - if (!map_info_inited) { - MapInfoInit(); - } - - entry = Tcl_FindHashEntry(&mapInfoTable, uid); - if (entry == NULL) { - return; - } - master = (MapInfoMaster *) Tcl_GetHashValue(entry); - client = (MapInfoClient *) ZnListArray(master->clients); - num = ZnListSize(master->clients); - for (i = 0; i < num; i++, client++) { - if ((client->client_data == client_data) && - (client->proc == proc)) { - ZnListDelete(master->clients, i); - return; - } - } -} - -void -ZnUpdateMapInfoClients(MapInfoId map_info) -{ - Tk_Uid uid = Tk_GetUid(MapInfoName(map_info)); - Tcl_HashEntry *entry; - MapInfoMaster *master; - - if (!map_info_inited) { - MapInfoInit(); - } - - entry = Tcl_FindHashEntry(&mapInfoTable, uid); - if (entry == NULL) { - return; - } - master = (MapInfoMaster *) Tcl_GetHashValue(entry); - UpdateMapInfoClients(master); -} - - -/* - * These arrays must be kept in sync with the MapInfoLineStyle - * and MapInfoTextStyle enums. - */ -static char *line_style_strings[] = { - "simple", - "dashed", - "dotted", - "mixed", - "marked", -}; - -static char *text_style_strings[] = { - "normal", - "underlined" -}; - -static char * -MapInfoLineStyleToString(MapInfoLineStyle line_style) -{ - return line_style_strings[line_style]; -} - -static int -MapInfoLineStyleFromString(Tcl_Interp *interp, - char *str, - MapInfoLineStyle *line_style) -{ - int i, num = sizeof(line_style_strings)/sizeof(char *); - - for (i = 0; i < num; i++) { - if (strcmp(str, line_style_strings[i]) == 0) { - *line_style = i; - return TCL_OK; - } - } - Tcl_AppendResult(interp, " incorrect mapinfo line style \"", - str,"\"", NULL); - return ZN_ERROR; -} + glXMakeCurrent(wi->dpy, ZnWindowId(wi->win), wi->gl_context); + glEnable(GL_POINT_SMOOTH); + glEnable(GL_LINE_SMOOTH); +#if 0 + glEnable(GL_POLYGON_SMOOTH); /* expensive ? */ +#endif -static char * -MapInfoTextStyleToString(MapInfoTextStyle text_style) -{ - return text_style_strings[text_style]; -} + glEnable(GL_BLEND); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -static int -MapInfoTextStyleFromString(Tcl_Interp *interp, - char *str, - MapInfoTextStyle *text_style) -{ - int i, num = sizeof(text_style_strings)/sizeof(char *); + glClearStencil(0); + color = ZnGetGradientColor(wi->back_color, 0, NULL); + glClearColor(color->red/65536.0, color->green/65536.0, + color->blue/65536.0, 0.0); - for (i = 0; i < num; i++) { - if (strcmp(str, text_style_strings[i]) == 0) { - *text_style = i; - return TCL_OK; - } - } - Tcl_AppendResult(interp, " incorrect mapinfo text style \"", - str,"\"", NULL); - return ZN_ERROR; -} + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -int -MapInfoObjCmd(ClientData client_data, - Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - Tcl_Obj *CONST args[]) -{ - int index, index2, result; - MapInfoMaster *master; - Tcl_Obj *l; - static char *sub_cmd_strings[] = { - "add", "count", "create", "delete", "duplicate", - "get", "remove", "replace", "scale", "translate", NULL - }; - static char *e_type_strings[] = { - "arc", "line", "symbol", "text", NULL - }; - enum sub_cmds { - ZN_MI_ADD, ZN_MI_COUNT, ZN_MI_CREATE, ZN_MI_DELETE, ZN_MI_DUPLICATE, - ZN_MI_GET, ZN_MI_REMOVE, ZN_MI_REPLACE, ZN_MI_SCALE, ZN_MI_TRANSLATE - }; - enum e_types { - ZN_E_ARC, ZN_E_LINE, ZN_E_SYMBOL, ZN_E_TEXT - }; - - if (!inited) { - InitZinc(interp); - } - - if (argc < 3) { - Tcl_WrongNumArgs(interp, 1, args, "mapInfo/name subCmd ?args?"); - return ZN_ERROR; - } - - if (Tcl_GetIndexFromObj(interp, args[2], sub_cmd_strings, - "subCmd", 0, &index) != ZN_OK) { - return ZN_ERROR; - } - result = TCL_OK; - /*printf("mapinfo command \"%s\", argc=%d\n", - Tcl_GetString(args[2]), argc);*/ - - switch((enum sub_cmds) index) { /* - * create + * Init the composite group alpha. */ - case ZN_MI_CREATE: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "name create"); - return ZN_ERROR; - } - if (ZnCreateMapInfo(interp, Tcl_GetString(args[1]), NULL) == ZN_ERROR) { - return ZN_ERROR; - } - } - break; + wi->alpha = 100; + + glViewport(0, 0, (GLsizei) int_width, int_height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0.0, int_width, int_height, 0.0); + glMatrixMode(GL_MODELVIEW); + +#ifdef GLX_DAMAGE + glEnable(GL_SCISSOR_TEST); + /* - * delete + * Set the damaged area as the scissor area. */ - case ZN_MI_DELETE: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "mapInfo delete"); - return ZN_ERROR; - } - if (ZnDeleteMapInfo(interp, Tcl_GetString(args[1])) == ZN_ERROR) { - return ZN_ERROR; - } - } - break; + wi->damaged_area.orig.x = REAL_TO_INT(wi->damaged_area.orig.x); + wi->damaged_area.orig.y = REAL_TO_INT(wi->damaged_area.orig.y); + wi->damaged_area.corner.x = REAL_TO_INT(wi->damaged_area.corner.x); + wi->damaged_area.corner.y = REAL_TO_INT(wi->damaged_area.corner.y); + glScissor(wi->damaged_area.orig.x, + int_height - wi->damaged_area.corner.y, + wi->damaged_area.corner.x - wi->damaged_area.orig.x, + wi->damaged_area.corner.y - wi->damaged_area.orig.y); +#else /* - * duplicate + * We do not use the damaged area for GL rendering, + * set it to the whole area. */ - case ZN_MI_DUPLICATE: - { - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "mapInfo duplicate name"); - return ZN_ERROR; - } - master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); - if (master == NULL) { - return ZN_ERROR; - } - if (ZnDuplicateMapInfo(interp, Tcl_GetString(args[3]), - master->map_info) == ZN_ERROR) { - return ZN_ERROR; - } - } - break; + wi->damaged_area.orig.x = wi->damaged_area.orig.y = wi->inset; + wi->damaged_area.corner.x = int_width-wi->inset; + wi->damaged_area.corner.y = int_height-wi->inset; +#endif + /* - * add/replace + * Clear the GL buffers. */ - case ZN_MI_ADD: - case ZN_MI_REPLACE: - { - MapInfoLineStyle line_style; - MapInfoTextStyle text_style; - int i, insert; - int coords[6]; - ZnBool add_cmd = (enum sub_cmds) index == ZN_MI_ADD; - int num_param = add_cmd ? 4 : 5; - - if (argc < num_param) { - Tcl_WrongNumArgs(interp, 3, args, - add_cmd ? "elementType ?args?" : "elementType index ?args?"); - return ZN_ERROR; - } - master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); - if (master == NULL) { - return ZN_ERROR; - } - if (!add_cmd) { - if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) { - return ZN_ERROR; - } - if (insert < 0) { - insert = 0; - } - } - 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: - { - if (argc != (num_param+6)) { - Tcl_WrongNumArgs(interp, 4, args, - add_cmd ? "style width x1 y1 x2 y2" : "index style width x1 y1 x2 y2"); - return ZN_ERROR; - } - if (MapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]), - &line_style) == ZN_ERROR) { - return ZN_ERROR; - } - for (i = 0; i < 5; i++) { - if (Tcl_GetIntFromObj(interp, args[num_param+i+1], &coords[i]) == ZN_ERROR) { - return ZN_ERROR; - } - } - if (coords[0] < 0) { - coords[0] = 0; - } - if (add_cmd) { - MapInfoAddLine(master->map_info, ZnListTail, NULL, line_style, - coords[0], coords[1], coords[2], coords[3], coords[4]); - } - else { - MapInfoReplaceLine(master->map_info, insert, NULL, line_style, - coords[0], coords[1], coords[2], coords[3], coords[4]); - } - } - break; - case ZN_E_SYMBOL: - { - if (argc != (num_param+3)) { - Tcl_WrongNumArgs(interp, 4, args, - add_cmd ? "x y intVal" : "index x y intVal"); - return ZN_ERROR; - } - for (i = 0; i < 3; i++) { - if (Tcl_GetIntFromObj(interp, args[num_param+i], &coords[i]) == ZN_ERROR) { - return ZN_ERROR; - } - } - if (coords[2] < 0) { - coords[2] = 0; - } - if (add_cmd) { - MapInfoAddSymbol(master->map_info, ZnListTail, NULL, coords[0], - coords[1], coords[2]); - } - else { - MapInfoReplaceSymbol(master->map_info, insert, NULL, coords[0], - coords[1], coords[2]); - } - } - break; - case ZN_E_TEXT: - { - if (argc != (num_param+5)) { - Tcl_WrongNumArgs(interp, 4, args, - add_cmd ? "textStyle lineStyle x y string" : "index textStyle lineStyle x y string"); - return ZN_ERROR; - } - if (MapInfoTextStyleFromString(interp, Tcl_GetString(args[num_param]), - &text_style) == ZN_ERROR) { - return ZN_ERROR; - } - if (MapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param+1]), - &line_style) == ZN_ERROR) { - return ZN_ERROR; - } - for (i = 0; i < 2; i++) { - if (Tcl_GetIntFromObj(interp, args[num_param+i+2], &coords[i]) == ZN_ERROR) { - return ZN_ERROR; - } - } - if (add_cmd) { - MapInfoAddText(master->map_info, ZnListTail, NULL, text_style, - line_style, coords[0], coords[1], - Tcl_GetString(args[num_param+4])); - } - 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, insert, NULL, text_style, - line_style, coords[0], coords[1], - Tcl_GetString(args[num_param+4])); - } - } - break; - case ZN_E_ARC: - { - if (argc != (num_param+7)) { - Tcl_WrongNumArgs(interp, 4, args, - add_cmd ? "style width cx cy radius start extent" : "index style width cx cy radius start extent"); - return ZN_ERROR; - } - if (MapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]), - &line_style) == ZN_ERROR) { - return ZN_ERROR; - } - for (i = 0; i < 6; i++) { - if (Tcl_GetIntFromObj(interp, args[num_param+i+1], &coords[i]) == ZN_ERROR) { - return ZN_ERROR; - } - } - if (coords[0] < 0) { - coords[0] = 0; - } - if (add_cmd) { - MapInfoAddArc(master->map_info, ZnListTail, NULL, line_style, - coords[0], coords[1], coords[2], coords[3], coords[4], - coords[5]); - } - else { - MapInfoReplaceArc(master->map_info, insert, NULL, line_style, coords[0], - coords[1], coords[2], coords[3], coords[4], coords[5]); - } - } - break; - } - UpdateMapInfoClients(master); - } - break; + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + /* - * count + * Setup the background tile if needed. */ - case ZN_MI_COUNT: - { - int count = 0; - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "mapInfo count type"); - return ZN_ERROR; - } - master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); - if (master == NULL) { - return ZN_ERROR; - } - 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: - count = MapInfoNumLines(master->map_info); - break; - case ZN_E_SYMBOL: - count = MapInfoNumSymbols(master->map_info); - break; - case ZN_E_TEXT: - count = MapInfoNumTexts(master->map_info); - break; - case ZN_E_ARC: - count = MapInfoNumArcs(master->map_info); - break; - } - l = Tcl_NewIntObj(count); - Tcl_SetObjResult(interp, l); + if (wi->tile != ZnUnspecifiedImage) { + ZnBBox bbox; + + bbox.orig.x = bbox.orig.y = 0.0; + bbox.corner.x = int_width; + bbox.corner.y = int_height; + + RenderTile(wi, GetImageTexture(wi->win, wi->tile_name, wi->tile), + NULL, NULL, NULL, (ZnPoint *) &bbox); } - break; - /* - * get - */ - case ZN_MI_GET: - { - int insert; - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "mapInfo get type index"); - return ZN_ERROR; - } - master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); - if (master == NULL) { - return ZN_ERROR; - } - if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) { - return ZN_ERROR; - } - if (insert < 0) { - insert = 0; - } - 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: - { - MapInfoLineStyle line_style; - int line_width; - int x_from, y_from, x_to, y_to; - MapInfoGetLine(master->map_info, insert, NULL, &line_style, - &line_width, &x_from, &y_from, &x_to, &y_to); - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(line_width)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x_from)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y_from)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x_to)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y_to)); - } - break; - case ZN_E_SYMBOL: - { - int x, y; - char symbol; - MapInfoGetSymbol(master->map_info, insert, NULL, &x, &y, &symbol); - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(symbol)); - } - break; - case ZN_E_TEXT: - { - int x, y; - char *text; - MapInfoTextStyle text_style; - MapInfoLineStyle line_style; - MapInfoGetText(master->map_info, insert, NULL, &text_style, &line_style, - &x, &y, &text); - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y)); - Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoTextStyleToString(text_style))); - Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); - Tcl_ListObjAppendElement(interp, l, NewStringObj(text)); - } - break; - case ZN_E_ARC: - { - MapInfoLineStyle line_style; - int line_width; - int center_x, center_y, start, extent; - unsigned int radius; - MapInfoGetArc(master->map_info, insert, NULL, &line_style, &line_width, - ¢er_x, ¢er_y, &radius, &start, &extent); - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(line_width)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(center_x)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(center_y)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(radius)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(start)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(extent)); - } - break; + + wi->top_group->class->Render(wi->top_group); + + if ((wi->border_width > 0) || (wi->highlight_width > 0)) { + int alpha; + +#ifdef GLX_DAMAGE + glDisable(GL_SCISSOR_TEST); +#endif + if (wi->highlight_width > 0) { + color = ZnGetGradientColor(wi->got_focus?wi->highlight_color: + wi->highlight_bg_color, 0, &alpha); + alpha = ZnComposeAlpha(alpha, 100); + glColor4us(color->red, color->green, color->blue, alpha); + + glBegin(GL_QUAD_STRIP); + glVertex2f(0.0, 0.0); + glVertex2f(wi->highlight_width, wi->highlight_width); + glVertex2f(int_width, 0); + glVertex2f(int_width - wi->highlight_width, wi->highlight_width); + glVertex2f(int_width, int_height); + glVertex2f(int_width - wi->highlight_width, int_height - wi->highlight_width); + glVertex2f(0, int_height); + glVertex2f(wi->highlight_width, int_height - wi->highlight_width); + glVertex2f(0, 0); + glVertex2f(wi->highlight_width, wi->highlight_width); + glEnd(); + } + if (wi->border_width > 0) { + ZnPoint p[5]; + + p[4].x = p[4].y = p[3].y = p[1].x = wi->highlight_width; + p[0] = p[4]; + p[3].x = p[2].x = int_width - wi->highlight_width; + p[2].y = p[1].y = int_height - wi->highlight_width; + RenderPolygonRelief(wi, wi->relief, wi->relief_grad, + False, p, 5, wi->border_width); } +#ifdef GLX_DAMAGE + glEnable(GL_SCISSOR_TEST); +#endif } - break; + /* Switch the GL buffers. */ + glXSwapBuffers(wi->dpy, ZnWindowId(wi->win)); + glFlush(); + /* - * remove + * Wait the end of GL update if we need to synchronize + * to monitor perfs. */ - case ZN_MI_REMOVE: - { - int insert; - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "mapInfo remove type index"); - return ZN_ERROR; - } - master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); - if (master == NULL) { - return ZN_ERROR; - } - if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) { - return ZN_ERROR; - } - if (insert < 0) { - insert = 0; - } - 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, insert); - break; - case ZN_E_SYMBOL: - MapInfoRemoveSymbol(master->map_info, insert); - break; - case ZN_E_TEXT: - MapInfoRemoveText(master->map_info, insert); - break; - case ZN_E_ARC: - MapInfoRemoveArc(master->map_info, insert); - break; - } - UpdateMapInfoClients(master); + if (wi->monitoring) { + glXWaitGL(); } - break; +#endif + } + else { + XRectangle r; + ZnBBox merge; + + ClampDamageArea(wi); /* - * scale + * Merge the damaged area with the exposed area. */ - case ZN_MI_SCALE: - { - double factor; + ResetBBox(&merge); + CopyBBox(&wi->damaged_area, &merge); + AddBBoxToBBox(&merge, &wi->exposed_area); + if (!IsEmptyBBox(&merge)) { - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "mapInfo scale factor"); - return ZN_ERROR; - } - master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); - if (master == NULL) { - return ZN_ERROR; - } - if (Tcl_GetDoubleFromObj(interp, args[3], &factor) == ZN_ERROR) { - return ZN_ERROR; + /* Set the whole damaged area as clip rect. */ + wi->damaged_area.orig.x = r.x = REAL_TO_INT(wi->damaged_area.orig.x); + wi->damaged_area.orig.y = r.y = REAL_TO_INT(wi->damaged_area.orig.y); + wi->damaged_area.corner.x = REAL_TO_INT(wi->damaged_area.corner.x); + wi->damaged_area.corner.y = REAL_TO_INT(wi->damaged_area.corner.y); + r.width = wi->damaged_area.corner.x - wi->damaged_area.orig.x; + r.height = wi->damaged_area.corner.y - wi->damaged_area.orig.y; + pts[0] = wi->damaged_area.orig; + pts[1] = wi->damaged_area.corner; + TRI_STRIP1(&tristrip, pts, 2); + ZnPushClip(wi, &tristrip, True, True); + + /* Fill the background of the double buffer pixmap. */ + if (wi->tile == ZnUnspecifiedImage) { + values.foreground = ZnPixel(ZnGetGradientColor(wi->back_color, 0, NULL)); + values.fill_style = FillSolid; + XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &values); } - MapInfoScale(master->map_info, factor); - UpdateMapInfoClients(master); + else { + values.fill_style = FillTiled; + values.tile = GetImagePixmap(wi->win, wi->tile_name, wi->tile, NULL); + values.ts_x_origin = values.ts_y_origin = 0; + XChangeGC(wi->dpy, wi->gc, + GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin, + &values); + } + /*printf("Repair : filling rectangle: %d %d %d %d\n", r.x, r.y, r.width, r.height);*/ + XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y, r.width, r.height); + + /* Draw the items */ + /*printf("Drawing\n");*/ + wi->top_group->class->Draw(wi->top_group); + + ZnPopClip(wi, True); + + /* + * Send the merged area back to screen. + */ + merge.orig.x = MAX(merge.orig.x, wi->inset); + merge.orig.y = MAX(merge.orig.y, wi->inset); + merge.corner.x = MIN(merge.corner.x, int_width-wi->inset); + merge.corner.y = MIN(merge.corner.y, int_height-wi->inset); + BBox2XRect(&merge, &r); + XCopyArea(wi->dpy, + wi->draw_buffer, ZnWindowId(wi->win), wi->gc, + r.x, r.y, r.width, r.height, r.x, r.y); } - break; + /* - * translate + * Redraw the borders. */ - case ZN_MI_TRANSLATE: - { - int x, y; + if (wi->border_width > 0) { + Pixmap save; + XRectangle r; - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "mapInfo translate xAmount yAmount"); - return ZN_ERROR; - } - master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); - if (master == NULL) { - return ZN_ERROR; - } - if (Tcl_GetIntFromObj(interp, args[3], &x) == ZN_ERROR) { - return ZN_ERROR; - } - if (Tcl_GetIntFromObj(interp, args[4], &y) == ZN_ERROR) { - return ZN_ERROR; - } - MapInfoTranslate(master->map_info, x, y); - UpdateMapInfoClients(master); + save = wi->draw_buffer; + wi->draw_buffer = ZnWindowId(wi->win); + r.x = r.y = wi->highlight_width; + r.width = int_width - 2*wi->highlight_width; + r.height = int_height - 2*wi->highlight_width; + DrawRectangleRelief(wi, wi->relief, wi->relief_grad, + &r, wi->border_width); + wi->draw_buffer = save; + } + if (wi->highlight_width > 0) { + XRectangle r[4]; + + XSetForeground(wi->dpy, wi->gc, + ZnPixel(ZnGetGradientColor(wi->got_focus?wi->highlight_color: + wi->highlight_bg_color, 0, NULL))); + XSetFillStyle(wi->dpy, wi->gc, FillSolid); + r[0].x = r[0].y = 0; + r[0].width = int_width; + r[0].height = wi->highlight_width; + r[1].x = int_width - wi->highlight_width; + r[1].y = 0; + r[1].width = wi->highlight_width; + r[1].height = int_height; + r[2].x = 0; + r[2].y = int_height - wi->highlight_width; + r[2].width = int_width; + r[2].height = wi->highlight_width; + r[3].x = r[3].y = 0; + r[3].width = wi->highlight_width; + r[3].height = int_height; + XFillRectangles(wi->dpy, ZnWindowId(wi->win), wi->gc, r, 4); } - break; } - - return TCL_OK; } /* *---------------------------------------------------------------------- * - * VideomapObjCmd -- + * Redisplay -- * + * This procedure redraws the contents of a Zinc window. + * It is invoked as a do-when-idle handler, so it only runs + * when there's nothing else for the application to do. + * + * Results: + * None. + * + * Side effects: + * Information appears on the screen. * *---------------------------------------------------------------------- */ -int -VideomapObjCmd(ClientData client_data, - Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - Tcl_Obj *CONST args[]) + +static void +Redisplay(ClientData client_data) /* Information about the widget. */ { - ZnList ids; - int index; - int *id_array, id_num, i; - Tcl_Obj *l; - static char *sub_cmd_strings[] = { - "ids", "load", NULL - }; - enum sub_cmds { - ZN_V_IDS, ZN_V_LOAD - }; - - if (!inited) { - InitZinc(interp); - } + WidgetInfo *wi = (WidgetInfo *) client_data; - if (argc < 2) { - Tcl_WrongNumArgs(interp, 1, args, "?subCmd? filename $args?"); - return ZN_ERROR; + wi->update_pending = 0; + if (!wi->realized || !Tk_IsMapped(wi->win)) { + return; } - if (Tcl_GetIndexFromObj(interp, args[1], sub_cmd_strings, - "subCmd", 0, &index) != ZN_OK) { - return ZN_ERROR; + if (wi->monitoring) { + XStartChrono(wi->total_draw_chrono, wi->dpy, ZnWindowId(wi->win)); + ResetChronos(wi->this_draw_chrono); + XStartChrono(wi->this_draw_chrono, wi->dpy, ZnWindowId(wi->win)); } - - switch((enum sub_cmds) index) { + + do { /* - * ids + * Update the items. + * NOTE: See above. */ - case ZN_V_IDS: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args,"ids filename"); - return ZN_ERROR; - } - ids = MapInfoVideomapIds(Tcl_GetString(args[2])); - if (ids == NULL) { - Tcl_AppendResult(interp, "unable to look at videomap file \"", - Tcl_GetString(args[2]), "\"", NULL); - return ZN_ERROR; - } - id_array = (int *) ZnListArray(ids); - id_num = ZnListSize(ids); - l = Tcl_GetObjResult(interp); - for (i = 0; i < id_num; i++) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(id_array[i])); - } - ZnListFree(ids); - } - break; + Update(wi); + /* - * load + * Do enter/leave processing after the overlap manager + * has finished with the items. Do it has many times + * as needed, each round may trigger callbacks that + * result in moved items and so forth. It can even + * lead to the widget destruction, this is the reason + * for Tcl_Preserve/Tcl_Release. */ - case ZN_V_LOAD: - { - MapInfoId map_info; - int insert; - - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "load filename index mapInfo"); - return ZN_ERROR; - } - if (Tcl_GetIntFromObj(interp, args[3], &insert) == ZN_ERROR) { - return ZN_ERROR; - } - 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]), insert) == ZN_ERROR) { - Tcl_AppendResult(interp, "unable to load videomap file \"", - Tcl_GetString(args[2]), ":", - Tcl_GetString(args[3]), "\"", NULL); - return ZN_ERROR; + if (ISSET(wi->events_flags, INTERNAL_NEED_REPICK)) { + Tk_Window tkwin; + + Tcl_Preserve((ClientData) wi); + CLEAR(wi->events_flags, INTERNAL_NEED_REPICK); + PickCurrentItem(wi, &wi->pick_event); + tkwin = wi->win; + Tcl_Release((ClientData) wi); + if (tkwin == NULL) { + return; } - ZnUpdateMapInfoClients(map_info); } - break; } + while (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) || + ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG) || + ISSET(wi->events_flags, INTERNAL_NEED_REPICK)); - return TCL_OK; + /* + * Repair the scene where it is no longer up to date, + * then send the merged area back to the screen. + */ + Repair(wi); + + /* + * Reset the exposed & damaged areas. + */ + ResetBBox(&wi->exposed_area); + ResetBBox(&wi->damaged_area); + + if (wi->monitoring) { + XStopChrono(wi->total_draw_chrono, wi->dpy, ZnWindowId(wi->win)); + XStopChrono(wi->this_draw_chrono, wi->dpy, ZnWindowId(wi->win)); + } } static void InitZinc(Tcl_Interp *interp) { + static ZnBool inited = False; unsigned int i, x, y, bit; char name[INTEGER_SPACE + 20]; + if (inited) { + return; + } + /* * Add the specific bitmaps. */ @@ -6498,7 +6146,7 @@ InitZinc(Tcl_Interp *interp) { /* * Initialize the item module. */ - ITEM_P.GlobalModuleInit(); + ZnItemInit(); all_uid = Tk_GetUid("all"); current_uid = Tk_GetUid("current"); -- cgit v1.1