From 960cdf29197bc3f5922110cf26627aa9709ac79b Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Fri, 10 Jun 2005 10:29:11 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'bogue40'. --- generic/tkZinc.c | 9059 ------------------------------------------------------ 1 file changed, 9059 deletions(-) delete mode 100644 generic/tkZinc.c (limited to 'generic/tkZinc.c') diff --git a/generic/tkZinc.c b/generic/tkZinc.c deleted file mode 100644 index 82b85b3..0000000 --- a/generic/tkZinc.c +++ /dev/null @@ -1,9059 +0,0 @@ -/* - * tkZinc.c -- Zinc widget for the Tk Toolkit. Main module. - * - * Authors : Patrick Lecoanet. - * Creation date : Mon Feb 1 12:13:24 1999 - * - * $Id$ - */ - -/* - * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet -- - * - * See the file "Copyright" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - */ - -/* - * Some functions and code excerpts in this file are from tkCanvas.c - * and thus copyrighted: - * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. - * - */ - -static const char rcs_id[]="$Id$"; -static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $"; -static const char * const zinc_version = "zinc-version-" VERSION; - - -#include "Types.h" -#include "Geo.h" -#include "Item.h" -#include "Group.h" -#include "WidgetInfo.h" -#include "tkZinc.h" -#include "MapInfo.h" -#ifdef ATC -#include "OverlapMan.h" -#include "Track.h" -#endif -#include "Transfo.h" -#include "Image.h" -#include "Draw.h" -#include "Color.h" -#ifndef _WIN32 -#include "perfos.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#if defined(_WIN32) && defined(PTK) && !defined(PTK_800) -#include -#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 SYMBOL_WIDTH 8 -#define SYMBOL_HEIGHT 8 -static unsigned char SYMBOLS_BITS[][SYMBOL_WIDTH*SYMBOL_HEIGHT/8] = { - { 0x18, 0x18, 0x24, 0x24, 0x5a, 0x5a, 0x81, 0xff }, - { 0xff, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0xff }, - { 0x18, 0x24, 0x42, 0x99, 0x99, 0x42, 0x24, 0x18 }, - { 0x18, 0x3c, 0x5a, 0xff, 0xff, 0x5a, 0x3c, 0x18 }, - { 0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18 }, - { 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c }, - { 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81, 0xff }, - { 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff }, - { 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xff, 0xff }, - { 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff }, - { 0x18, 0x3c, 0x7e, 0xe7, 0xe7, 0x7e, 0x3c, 0x18 }, - { 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x18 }, - { 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18 }, - { 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c }, - { 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0x18, 0x7e, 0x7e, 0xff, 0xff, 0x7e, 0x7e, 0x18 }, - { 0x18, 0x66, 0x42, 0x81, 0x81, 0x42, 0x66, 0x18 }, - { 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00 }, - { 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00 }, - { 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18 }, - { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }, -}; - -static unsigned char dither4x4[4][4] = { - { 0, 8, 2, 10 }, - { 12, 4, 14, 6 }, - { 3, 11, 1, 9 }, - { 15, 7, 13, 5 } -}; - -static unsigned char bitmaps[ZN_NUM_ALPHA_STEPS][32][4]; - -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; -static Tk_Uid dot_uid; -static Tk_Uid star_uid; - -#ifdef GL -static ZnGLContextEntry *gl_contexts = NULL; -#ifndef _WIN32 -static int ZnMajorGlx, ZnMinorGlx; -static int ZnGLAttribs[] = { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_STENCIL_SIZE, 8, - /*GLX_ALPHA_SIZE, 8,*/ - GLX_DEPTH_SIZE, 0, - None -}; -#endif -#endif - -/* - * Temporary object lists - */ - ZnList ZnWorkPoints; - ZnList ZnWorkXPoints; - ZnList ZnWorkStrings; - -/* - * Tesselator - */ - ZnTess ZnTesselator; - - -static void PickCurrentItem _ANSI_ARGS_((ZnWInfo *wi, XEvent *event)); -#ifdef PTK_800 -static int ZnReliefParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj *ovalue, - char *widget_rec, int offset)); -static Tcl_Obj *ZnReliefPrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, - char *widget_rec, int offset, - Tcl_FreeProc **free_proc)); -static int ZnGradientParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj *ovalue, - char *widget_rec, int offset)); -static Tcl_Obj *ZnGradientPrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, - char *widget_rec, int offset, - Tcl_FreeProc **free_proc)); -static int ZnImageParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj *ovalue, - char *widget_rec, int offset)); -static int ZnBitmapParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj *ovalue, - char *widget_rec, int offset)); -static Tcl_Obj *ZnImagePrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, - char *widget_rec, int offset, - Tcl_FreeProc **free_proc)); -static Tk_CustomOption reliefOption = { - (Tk_OptionParseProc *) ZnReliefParse, - (Tk_OptionPrintProc *) ZnReliefPrint, - NULL -}; -static Tk_CustomOption gradientOption = { - (Tk_OptionParseProc *) ZnGradientParse, - (Tk_OptionPrintProc *) ZnGradientPrint, - NULL -}; -static Tk_CustomOption imageOption = { - (Tk_OptionParseProc *) ZnImageParse, - (Tk_OptionPrintProc *) ZnImagePrint, - NULL -}; -static Tk_CustomOption bitmapOption = { - (Tk_OptionParseProc *) ZnBitmapParse, - (Tk_OptionPrintProc *) ZnImagePrint, - NULL -}; -#else -static int ZnSetReliefOpt _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj **ovalue, - char *widget_rec, int offset, char *old_val_ptr, int flags)); -static Tcl_Obj *ZnGetReliefOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, - char *widget_rec, int offset)); -static void ZnRestoreReliefOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, - char *val_ptr, char *old_val_ptr)); -static int ZnSetGradientOpt _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj **ovalue, - char *widget_rec, int offset, char *old_val_ptr, int flags)); -static Tcl_Obj *ZnGetGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, - char *widget_rec, int offset)); -static void ZnRestoreGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, - char *val_ptr, char *old_val_ptr)); -static void ZnFreeGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, char *val_ptr)); - -static Tk_ObjCustomOption reliefOption = { - "znrelief", - ZnSetReliefOpt, - ZnGetReliefOpt, - ZnRestoreReliefOpt, - NULL, - 0 -}; -static Tk_ObjCustomOption gradientOption = { - "zngradient", - ZnSetGradientOpt, - ZnGetGradientOpt, - ZnRestoreGradientOpt, - ZnFreeGradientOpt, - NULL -}; -#endif - -#ifdef PTK_800 -#define BORDER_WIDTH_SPEC 0 -#define BACK_COLOR_SPEC 1 -#define CONFINE_SPEC 2 -#define CURSOR_SPEC 3 -#define FONT_SPEC 4 -#define FORE_COLOR_SPEC 5 -#define FULL_RESHAPE_SPEC 6 -#define HEIGHT_SPEC 7 -#define HIGHLIGHT_BACK_COLOR_SPEC 8 -#define HIGHLIGHT_COLOR_SPEC 9 -#define HIGHLIGHT_THICKNESS_SPEC 10 -#define INSERT_COLOR_SPEC 11 -#define INSERT_OFF_TIME_SPEC 12 -#define INSERT_ON_TIME_SPEC 13 -#define INSERT_WIDTH_SPEC 14 -#define MAP_DISTANCE_SYMBOL_SPEC 15 -#define MAP_TEXT_FONT_SPEC 16 -#define OVERLAP_MANAGER_SPEC 17 -#define PICK_APERTURE_SPEC 18 -#define RELIEF_SPEC 19 -#define RENDER_SPEC 20 -#define RESHAPE_SPEC 21 -#define SCROLL_REGION_SPEC 22 -#define SELECT_COLOR_SPEC 23 -#define SPEED_VECTOR_LENGTH_SPEC 24 -#define TAKE_FOCUS_SPEC 25 -#define TILE_SPEC 26 -#define VISIBLE_HISTORY_SIZE_SPEC 27 -#define MANAGED_HISTORY_SIZE_SPEC 28 -#define TRACK_SYMBOL_SPEC 29 -#define WIDTH_SPEC 30 -#define X_SCROLL_CMD_SPEC 31 -#define X_SCROLL_INCREMENT_SPEC 32 -#define Y_SCROLL_CMD_SPEC 33 -#define Y_SCROLL_INCREMENT_SPEC 34 -#define BBOXES_SPEC 35 -#define BBOXES_COLOR_SPEC 36 -#define LIGHT_ANGLE_SPEC 37 -#define FOLLOW_POINTER_SPEC 38 -#else -#define CONFIG_FONT 1<<0 -#define CONFIG_MAP_FONT 1<<1 -#define CONFIG_BACK_COLOR 1<<2 -#define CONFIG_REDISPLAY 1<<3 -#define CONFIG_DAMAGE_ALL 1<<4 -#define CONFIG_INVALIDATE_TRACKS 1<<5 -#define CONFIG_INVALIDATE_WPS 1<<6 -#define CONFIG_INVALIDATE_MAPS 1<<7 -#define CONFIG_REQUEST_GEOM 1<<8 -#define CONFIG_OM 1<<9 -#define CONFIG_FOCUS 1<<10 -#define CONFIG_FOCUS_ITEM 1<<11 -#define CONFIG_SCROLL_REGION 1<<12 -#define CONFIG_SET_ORIGIN 1<<13 -#define CONFIG_FOLLOW_POINTER 1<<14 -#define CONFIG_MAP_SYMBOL 1<<15 -#define CONFIG_TRACK_SYMBOL 1<<16 -#define CONFIG_TILE 1<<17 -#define CONFIG_DEBUG 1<<18 -#endif - -/* - * Information used for argv parsing. - */ -#ifdef PTK_800 -static Tk_ConfigSpec config_specs[] = { - {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - "2", Tk_Offset(ZnWInfo, border_width), 0, NULL}, - {TK_CONFIG_CUSTOM, "-backcolor", "backColor", "BackColor", - "#c3c3c3", Tk_Offset(ZnWInfo, back_color), 0, &gradientOption}, - {TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine", - "1", Tk_Offset(ZnWInfo, confine), 0, NULL}, - {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", - "", Tk_Offset(ZnWInfo, cursor), TK_CONFIG_NULL_OK, NULL}, - {TK_CONFIG_FONT, "-font", "font", "Font", - "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*", - Tk_Offset(ZnWInfo, font), 0, NULL}, - {TK_CONFIG_CUSTOM, "-forecolor", "foreColor", "Foreground", - "Black", Tk_Offset(ZnWInfo, fore_color), 0, &gradientOption}, - {TK_CONFIG_BOOLEAN, "-fullreshape", "fullReshape", "FullReshape", - "1", Tk_Offset(ZnWInfo, full_reshape), 0, NULL}, - {TK_CONFIG_PIXELS, "-height", "height", "Height", - "7c", Tk_Offset(ZnWInfo, opt_height), 0, NULL}, - {TK_CONFIG_CUSTOM, "-highlightbackground", "highlightBackground", "HighlightBackground", - "#c3c3c3", Tk_Offset(ZnWInfo, highlight_bg_color), 0, &gradientOption}, - {TK_CONFIG_CUSTOM, "-highlightcolor", "highlightColor", "HighlightColor", - "Black", Tk_Offset(ZnWInfo, highlight_color), 0, &gradientOption}, - {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", - "2", Tk_Offset(ZnWInfo, highlight_width), 0, NULL}, - {TK_CONFIG_CUSTOM, "-insertbackground", "insertBackground", "Foreground", - "Black", Tk_Offset(ZnWInfo, text_info.insert_color), 0, &gradientOption}, - {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime", - "300", Tk_Offset(ZnWInfo, insert_off_time), 0, NULL}, - {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime", - "600", Tk_Offset(ZnWInfo, insert_on_time), 0, NULL}, - {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - "2", Tk_Offset(ZnWInfo, text_info.insert_width), 0, NULL}, -#ifdef ATC - {TK_CONFIG_CUSTOM, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol", - "AtcSymbol19", Tk_Offset(ZnWInfo, map_distance_symbol), - TK_CONFIG_NULL_OK, &bitmapOption}, - {TK_CONFIG_FONT, "-maptextfont", "mapTextFont", "MapTextFont", - "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*", - Tk_Offset(ZnWInfo, map_text_font), 0, NULL}, - {TK_CONFIG_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1", - Tk_Offset(ZnWInfo, om_group_id), 0, NULL}, -#endif - {TK_CONFIG_INT, "-pickaperture", "pickAperture", "PickAperture", - "1", Tk_Offset(ZnWInfo, pick_aperture), 0, NULL}, - {TK_CONFIG_CUSTOM, "-relief", "relief", "Relief", - "flat", Tk_Offset(ZnWInfo, relief), 0, &reliefOption}, - {TK_CONFIG_INT, "-render", "render", "Render", - "0", Tk_Offset(ZnWInfo, render), 0, NULL}, - {TK_CONFIG_BOOLEAN, "-reshape", "reshape", "Reshape", - "1", Tk_Offset(ZnWInfo, reshape), 0, NULL}, - {TK_CONFIG_LANGARG, "-scrollregion", "scrollRegion", "ScrollRegion", - "", Tk_Offset(ZnWInfo, region), TK_CONFIG_NULL_OK, NULL}, - {TK_CONFIG_CUSTOM, "-selectbackground", "selectBackground", "Foreground", - "#a0a0a0", Tk_Offset(ZnWInfo, text_info.sel_color), 0, &gradientOption}, -#ifdef ATC - {TK_CONFIG_DOUBLE, "-speedvectorlength", "speedVectorLength", - "SpeedVectorLength", "3", Tk_Offset(ZnWInfo, speed_vector_length), 0, NULL}, -#endif - {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", - NULL, Tk_Offset(ZnWInfo, take_focus), TK_CONFIG_NULL_OK, NULL}, - {TK_CONFIG_CUSTOM, "-tile", "tile", "Tile", - "", Tk_Offset(ZnWInfo, tile), 0, &imageOption}, -#ifdef ATC - {TK_CONFIG_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize", - "6", Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL}, - {TK_CONFIG_INT, "-trackmanagedhistorysize", "trackManagedHistorySize", - "TrackManagedHistorySize", "6", Tk_Offset(ZnWInfo, track_managed_history_size), 0, NULL}, - {TK_CONFIG_CUSTOM, "-tracksymbol", "trackSymbol", "TrackSymbol", - "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol), TK_CONFIG_NULL_OK, &bitmapOption}, -#endif - {TK_CONFIG_PIXELS, "-width", "width", "Width", - "10c", Tk_Offset(ZnWInfo, opt_width), 0, NULL}, - {TK_CONFIG_CALLBACK, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - "", Tk_Offset(ZnWInfo, x_scroll_cmd), TK_CONFIG_NULL_OK, NULL}, - {TK_CONFIG_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement", - "0", Tk_Offset(ZnWInfo, x_scroll_incr), 0, NULL}, - {TK_CONFIG_CALLBACK, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - "", Tk_Offset(ZnWInfo, y_scroll_cmd), TK_CONFIG_NULL_OK, NULL}, - {TK_CONFIG_PIXELS, "-yscrollincrement", "yScrollIncrement", "ScrollIncrement", - "0", Tk_Offset(ZnWInfo, y_scroll_incr), 0, NULL}, - /* - * Debug options. - */ - {TK_CONFIG_BOOLEAN, "-drawbboxes", "drawBBoxes", - "DrawBBoxes", "0", Tk_Offset(ZnWInfo, draw_bboxes), 0, NULL}, - {TK_CONFIG_CUSTOM, "-bboxcolor", "bboxColor", "BBoxColor", - "Pink", Tk_Offset(ZnWInfo, bbox_color), 0, &gradientOption}, - {TK_CONFIG_INT, "-lightangle", "lightAngle", "LightAngle", - "120", Tk_Offset(ZnWInfo, light_angle), 0, NULL}, - {TK_CONFIG_BOOLEAN, "-followpointer", "followPointer", - "FollowPointer", "1", Tk_Offset(ZnWInfo, follow_pointer), 0, NULL}, - - {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} -}; -#else -static Tk_OptionSpec option_specs[] = { - {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - "2", -1, Tk_Offset(ZnWInfo, border_width), 0, NULL, CONFIG_DAMAGE_ALL|CONFIG_REQUEST_GEOM}, - {TK_OPTION_CUSTOM, "-backcolor", "backColor", "BackColor", - "#c3c3c3", -1, Tk_Offset(ZnWInfo, back_color), 0, &gradientOption, - CONFIG_BACK_COLOR|CONFIG_DAMAGE_ALL}, - {TK_OPTION_BOOLEAN, "-confine", "confine", "Confine", - "1", -1, Tk_Offset(ZnWInfo, confine), 0, NULL, CONFIG_SET_ORIGIN}, - {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - "", -1, Tk_Offset(ZnWInfo, cursor), TK_CONFIG_NULL_OK, NULL, 0}, - {TK_OPTION_INT, "-debug", "debug", "Debug", - "0", -1, Tk_Offset(ZnWInfo, debug), 0, NULL, 0}, - {TK_OPTION_FONT, "-font", "font", "Font", - "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*", - -1, Tk_Offset(ZnWInfo, font), 0, NULL, CONFIG_FONT}, - {TK_OPTION_CUSTOM, "-forecolor", "foreColor", "Foreground", - "Black", -1, Tk_Offset(ZnWInfo, fore_color), 0, &gradientOption, 0}, - {TK_OPTION_BOOLEAN, "-fullreshape", "fullReshape", "FullReshape", - "1", -1, Tk_Offset(ZnWInfo, full_reshape), 0, NULL, 0}, - {TK_OPTION_PIXELS, "-height", "height", "Height", - "7c", -1, Tk_Offset(ZnWInfo, opt_height), 0, NULL, CONFIG_REQUEST_GEOM}, - {TK_OPTION_CUSTOM, "-highlightbackground", "highlightBackground", "HighlightBackground", - "#c3c3c3", -1, Tk_Offset(ZnWInfo, highlight_bg_color), 0, &gradientOption, - CONFIG_REDISPLAY}, - {TK_OPTION_CUSTOM, "-highlightcolor", "highlightColor", "HighlightColor", - "Black", -1, Tk_Offset(ZnWInfo, highlight_color), 0, &gradientOption, CONFIG_REDISPLAY}, - {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", - "2", -1, Tk_Offset(ZnWInfo, highlight_width), 0, NULL, CONFIG_REQUEST_GEOM|CONFIG_DAMAGE_ALL}, - {TK_OPTION_CUSTOM, "-insertbackground", "insertBackground", "Foreground", - "Black", -1, Tk_Offset(ZnWInfo, text_info.insert_color), 0, &gradientOption, 0}, - {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime", - "300", -1, Tk_Offset(ZnWInfo, insert_off_time), 0, NULL, CONFIG_FOCUS}, - {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime", - "600", -1, Tk_Offset(ZnWInfo, insert_on_time), 0, NULL, CONFIG_FOCUS}, - {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - "2", -1, Tk_Offset(ZnWInfo, text_info.insert_width), 0, NULL, CONFIG_FOCUS_ITEM}, -#ifdef ATC - {TK_OPTION_STRING, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol", - "AtcSymbol19", Tk_Offset(ZnWInfo, map_symbol_obj), -1, - TK_CONFIG_NULL_OK, NULL, CONFIG_MAP_SYMBOL|CONFIG_INVALIDATE_MAPS}, - {TK_OPTION_FONT, "-maptextfont", "mapTextFont", "MapTextFont", - "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*", - -1, Tk_Offset(ZnWInfo, map_text_font), 0, NULL, CONFIG_MAP_FONT}, - {TK_OPTION_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1", - -1, Tk_Offset(ZnWInfo, om_group_id), 0, NULL, CONFIG_OM}, -#endif - {TK_OPTION_INT, "-pickaperture", "pickAperture", "PickAperture", - "1", -1, Tk_Offset(ZnWInfo, pick_aperture), 0, NULL, 0}, - {TK_OPTION_CUSTOM, "-relief", "relief", "Relief", - "flat", -1, Tk_Offset(ZnWInfo, relief), 0, &reliefOption, CONFIG_REDISPLAY}, - {TK_OPTION_INT, "-render", "render", "Render", - "-1", -1, Tk_Offset(ZnWInfo, render), 0, NULL, 0}, - {TK_OPTION_BOOLEAN, "-reshape", "reshape", "Reshape", - "1", -1, Tk_Offset(ZnWInfo, reshape), 0, NULL, 0}, - {TK_OPTION_STRING, "-scrollregion", "scrollRegion", "ScrollRegion", - "", Tk_Offset(ZnWInfo, region), -1, - TK_CONFIG_NULL_OK, NULL, CONFIG_SET_ORIGIN|CONFIG_SCROLL_REGION}, - {TK_OPTION_CUSTOM, "-selectbackground", "selectBackground", "Foreground", - "#a0a0a0", -1, Tk_Offset(ZnWInfo, text_info.sel_color), 0, &gradientOption, 0}, -#ifdef ATC - {TK_OPTION_DOUBLE, "-speedvectorlength", "speedVectorLength", - "SpeedVectorLength", "3", -1, Tk_Offset(ZnWInfo, speed_vector_length), - 0, NULL, CONFIG_INVALIDATE_TRACKS}, -#endif - {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - NULL, Tk_Offset(ZnWInfo, take_focus), -1, TK_CONFIG_NULL_OK, NULL, 0}, - {TK_OPTION_STRING, "-tile", "tile", "Tile", - "", Tk_Offset(ZnWInfo, tile_obj), -1, TK_CONFIG_NULL_OK, NULL, CONFIG_TILE|CONFIG_DAMAGE_ALL}, -#ifdef ATC - {TK_OPTION_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize", - "6", -1, Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL, CONFIG_INVALIDATE_TRACKS}, - {TK_OPTION_INT, "-trackmanagedhistorysize", "trackManagedHistorySize", - "TrackManagedHistorySize", "6", -1, Tk_Offset(ZnWInfo, track_managed_history_size), - 0, NULL, CONFIG_INVALIDATE_TRACKS}, - {TK_OPTION_STRING, "-tracksymbol", "trackSymbol", "TrackSymbol", - "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol_obj), -1, - 0, NULL, CONFIG_TRACK_SYMBOL|CONFIG_INVALIDATE_TRACKS|CONFIG_INVALIDATE_WPS}, -#endif - {TK_OPTION_PIXELS, "-width", "width", "Width", - "10c", -1, Tk_Offset(ZnWInfo, opt_width), 0, NULL, CONFIG_DAMAGE_ALL|CONFIG_REQUEST_GEOM}, -#ifdef PTK - {TK_OPTION_CALLBACK, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - "", -1, Tk_Offset(ZnWInfo, x_scroll_cmd), TK_CONFIG_NULL_OK, NULL, 0}, -#else - {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - "", Tk_Offset(ZnWInfo, x_scroll_cmd), -1, TK_CONFIG_NULL_OK, NULL, 0}, -#endif - {TK_OPTION_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement", - "0", -1, Tk_Offset(ZnWInfo, x_scroll_incr), 0, NULL, 0}, -#ifdef PTK - {TK_OPTION_CALLBACK, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - "", -1, Tk_Offset(ZnWInfo, y_scroll_cmd), TK_CONFIG_NULL_OK, NULL, 0}, -#else - {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - "", Tk_Offset(ZnWInfo, y_scroll_cmd), -1, TK_CONFIG_NULL_OK, NULL, 0}, -#endif - {TK_OPTION_PIXELS, "-yscrollincrement", "yScrollIncrement", "ScrollIncrement", - "0", -1, Tk_Offset(ZnWInfo, y_scroll_incr), 0, NULL, 0}, - /* - * Debug options. - */ - {TK_OPTION_BOOLEAN, "-drawbboxes", "drawBBoxes", - "DrawBBoxes", "0", -1, Tk_Offset(ZnWInfo, draw_bboxes), 0, NULL, 0}, - {TK_OPTION_CUSTOM, "-bboxcolor", "bboxColor", "BBoxColor", - "Pink", -1, Tk_Offset(ZnWInfo, bbox_color), 0, &gradientOption, 0}, - {TK_OPTION_INT, "-lightangle", "lightAngle", "LightAngle", - "120", -1, Tk_Offset(ZnWInfo, light_angle), 0, NULL, CONFIG_DAMAGE_ALL}, - {TK_OPTION_BOOLEAN, "-followpointer", "followPointer", - "FollowPointer", "1", -1, Tk_Offset(ZnWInfo, follow_pointer), 0, NULL, CONFIG_FOLLOW_POINTER}, - - {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} -}; -#endif - -static void CmdDeleted _ANSI_ARGS_((ClientData client_data)); -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_((ZnItem item, int field, int index)); -static int WidgetObjCmd _ANSI_ARGS_((ClientData client_data, - Tcl_Interp *, int argc, Tcl_Obj *CONST args[])); -#ifdef PTK_800 -static int Configure _ANSI_ARGS_((Tcl_Interp *interp, ZnWInfo *wi, - int argc, Tcl_Obj *CONST args[], int flags)); -#else -static int Configure _ANSI_ARGS_((Tcl_Interp *interp, ZnWInfo *wi, - int argc, Tcl_Obj *CONST args[])); -#endif -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_((ZnWInfo *wi, ZnBool got_focus)); -static void Update _ANSI_ARGS_((ZnWInfo *wi)); -static void Repair _ANSI_ARGS_((ZnWInfo *wi)); - - -#ifdef PTK_800 -/* - *---------------------------------------------------------------------- - * - * ZnReliefParse - * ZnReliefPrint -- - * Converter for the -relief option. - * - *---------------------------------------------------------------------- - */ -static int -ZnReliefParse(ClientData client_data, - Tcl_Interp *interp, - Tk_Window tkwin, - Tcl_Obj *ovalue, - char *widget_rec, - int offset) -{ - ZnReliefStyle *relief_ptr = (ZnReliefStyle *) (widget_rec + offset); - ZnReliefStyle relief; - char *value = Tcl_GetString(ovalue); - int result = TCL_OK; - - if (value != NULL) { - result = ZnGetRelief((ZnWInfo *) widget_rec, value, &relief); - if (result == TCL_OK) { - *relief_ptr = relief; - } - } - return result; -} - -static Tcl_Obj * -ZnReliefPrint(ClientData client_data, - Tk_Window tkwin, - char *widget_rec, - int offset, - Tcl_FreeProc **free_proc) -{ - ZnReliefStyle relief = *(ZnReliefStyle *) (widget_rec + offset); - return Tcl_NewStringObj(ZnNameOfRelief(relief), -1); -} - - -/* - *---------------------------------------------------------------------- - * - * ZnGradientParse - * ZnGradientPrint -- - * Converter for the -*color* options. - * - *---------------------------------------------------------------------- - */ -static int -ZnGradientParse(ClientData client_data, - Tcl_Interp *interp, - Tk_Window tkwin, - Tcl_Obj *ovalue, - char *widget_rec, - int offset) -{ - ZnGradient **grad_ptr = (ZnGradient **) (widget_rec + offset); - ZnGradient *grad, *prev_grad; - char *value = Tcl_GetString(ovalue); - - prev_grad = *grad_ptr; - if ((value != NULL) && (*value != '\0')) { - grad = ZnGetGradient(interp, tkwin, value); - if (grad == NULL) { - return TCL_ERROR; - } - if (prev_grad != NULL) { - ZnFreeGradient(prev_grad); - } - *grad_ptr = grad; - } - return TCL_OK; -} - -static Tcl_Obj * -ZnGradientPrint(ClientData client_data, - Tk_Window tkwin, - char *widget_rec, - int offset, - Tcl_FreeProc **free_proc) -{ - ZnGradient *gradient = *(ZnGradient **) (widget_rec + offset); - return Tcl_NewStringObj(ZnNameOfGradient(gradient), -1); -} - - -/* - *---------------------------------------------------------------------- - * - * ZnBitmapParse - * ZnImageParse - * ZnImagePrint -- - * Converter for the -*image* options. - * - *---------------------------------------------------------------------- - */ -static int -ZnBitmapParse(ClientData client_data, - Tcl_Interp *interp, - Tk_Window tkwin, - Tcl_Obj *ovalue, - char *widget_rec, - int offset) -{ - ZnImage *image_ptr = (ZnImage *) (widget_rec + offset); - ZnImage image, prev_image; - char *value = Tcl_GetString(ovalue); - ZnWInfo *wi = (ZnWInfo*) widget_rec; - ZnBool is_bmap = True; - - prev_image = *image_ptr; - if ((value != NULL) && (*value != '\0')) { - image = ZnGetImage(wi, value, NULL, NULL); - if ((image == ZnUnspecifiedImage) || - ! (is_bmap = ZnImageIsBitmap(image))) { - if (!is_bmap) { - ZnFreeImage(image, NULL, NULL); - } - return TCL_ERROR; - } - if (prev_image != NULL) { - ZnFreeImage(prev_image, NULL, NULL); - } - *image_ptr = image; - } - else if (prev_image != NULL) { - ZnFreeImage(prev_image, NULL, NULL); - *image_ptr = NULL; - } - - return TCL_OK; -} - -static void -ZnImageUpdate(void *client_data) -{ - ZnWInfo *wi = (ZnWInfo*) client_data; - - ZnDamageAll(wi); -} - -static int -ZnImageParse(ClientData client_data, - Tcl_Interp *interp, - Tk_Window tkwin, - Tcl_Obj *ovalue, - char *widget_rec, - int offset) -{ - ZnImage *image_ptr = (ZnImage *) (widget_rec + offset); - ZnImage image, prev_image; - char *value = Tcl_GetString(ovalue); - ZnWInfo *wi = (ZnWInfo*) widget_rec; - - prev_image = *image_ptr; - if ((value != NULL) && (*value != '\0')) { - image = ZnGetImage(wi, value, ZnImageUpdate, wi); - if (image == NULL) { - return TCL_ERROR; - } - if (prev_image != NULL) { - ZnFreeImage(prev_image, ZnImageUpdate, wi); - } - *image_ptr = image; - } - else if (prev_image != NULL) { - ZnFreeImage(prev_image, ZnImageUpdate, wi); - *image_ptr = NULL; - } - return TCL_OK; -} - -static Tcl_Obj * -ZnImagePrint(ClientData client_data, - Tk_Window tkwin, - char *widget_rec, - int offset, - Tcl_FreeProc **free_proc) -{ - ZnImage image = *(ZnImage *) (widget_rec + offset); - return Tcl_NewStringObj(image?ZnNameOfImage(image):"", -1); -} -#else -/* - *---------------------------------------------------------------------- - * - * ZnSetReliefOpt - * ZnGetReliefOpt - * ZnRestoreReliefOpt -- - * Converter for the -relief option. - * - *---------------------------------------------------------------------- - */ -static int -ZnSetReliefOpt(ClientData client_data, - Tcl_Interp *interp, - Tk_Window tkwin, - Tcl_Obj **ovalue, - char *widget_rec, - int offset, - char *old_val_ptr, - int flags) -{ - ZnReliefStyle *relief_ptr; - ZnReliefStyle relief; - char *value = Tcl_GetString(*ovalue); - - if (ZnGetRelief((ZnWInfo *) widget_rec, value, &relief) == TCL_ERROR) { - return TCL_ERROR; - } - if (offset >= 0) { - relief_ptr = (ZnReliefStyle *) (widget_rec + offset); - *((ZnReliefStyle *) old_val_ptr) = *relief_ptr; - *relief_ptr = relief; - } - return TCL_OK; -} - -static Tcl_Obj * -ZnGetReliefOpt(ClientData client_data, - Tk_Window tkwin, - char *widget_rec, - int offset) -{ - ZnReliefStyle relief = *(ZnReliefStyle *) (widget_rec + offset); - return Tcl_NewStringObj(ZnNameOfRelief(relief), -1); -} - -static void -ZnRestoreReliefOpt(ClientData client_data, - Tk_Window tkwin, - char *val_ptr, - char *old_val_ptr) -{ - *(ZnReliefStyle *) val_ptr = *(ZnReliefStyle *) old_val_ptr; -} - -/* - *---------------------------------------------------------------------- - * - * ZnSetGradientOpt - * ZnGetGradientOpt - * ZnRestoreGradientOpt -- - * Converter for the -*color* options. - * - *---------------------------------------------------------------------- - */ -static int -ZnSetGradientOpt(ClientData client_data, - Tcl_Interp *interp, - Tk_Window tkwin, - Tcl_Obj **ovalue, - char *widget_rec, - int offset, - char *old_val_ptr, - int flags) -{ - ZnGradient **grad_ptr; - ZnGradient *grad; - char *value = Tcl_GetString(*ovalue); - - if (offset >= 0) { - if (*value == '\0') { - grad = NULL; - } - else { - grad = ZnGetGradient(interp, tkwin, value); - if (grad == NULL) { - return TCL_ERROR; - } - } - grad_ptr = (ZnGradient **) (widget_rec + offset); - *(ZnGradient **) old_val_ptr = *grad_ptr; - *grad_ptr = grad; - } - return TCL_OK; -} - -static Tcl_Obj * -ZnGetGradientOpt(ClientData client_data, - Tk_Window tkwin, - char *widget_rec, - int offset) -{ - ZnGradient *gradient = *(ZnGradient **) (widget_rec + offset); - return Tcl_NewStringObj(ZnNameOfGradient(gradient), -1); -} - -static void -ZnRestoreGradientOpt(ClientData client_data, - Tk_Window tkwin, - char *val_ptr, - char *old_val_ptr) -{ - if (*(ZnGradient **) val_ptr != NULL) { - ZnFreeGradient(*(ZnGradient **) val_ptr); - } - *(ZnGradient **) val_ptr = *(ZnGradient **) old_val_ptr; -} - -static void -ZnFreeGradientOpt(ClientData client_data, - Tk_Window tkwin, - char *val_ptr) -{ - if (*(ZnGradient **) val_ptr != NULL) { - ZnFreeGradient(*(ZnGradient **) val_ptr); - } -} -#endif - - -/* - *---------------------------------------------------------------------- - * - * ZnGetAlphaStipple -- - * Need to be handled per screen/dpy toolkit wide, not on a - * widget basis. - * - *---------------------------------------------------------------------- - */ -static Pixmap -ZnGetAlphaStipple(ZnWInfo *wi, - unsigned int val) -{ - if (val >= 255) - return None; - else - return wi->alpha_stipples[(int) (val / 16)]; -} - -/* - *---------------------------------------------------------------------- - * - * ZnGetInactiveStipple -- - * - *---------------------------------------------------------------------- - */ -Pixmap -ZnGetInactiveStipple(ZnWInfo *wi) -{ - return ZnGetAlphaStipple(wi, 128); -} - - -/* - *---------------------------------------------------------------------- - * - * ZnNeedRedisplay -- - * - *---------------------------------------------------------------------- - */ -void -ZnNeedRedisplay(ZnWInfo *wi) -{ - if (ISCLEAR(wi->flags, ZN_UPDATE_PENDING) && ISSET(wi->flags, ZN_REALIZED)) { - /*printf("scheduling an update\n");*/ - Tcl_DoWhenIdle(Redisplay, (ClientData) wi); - SET(wi->flags, ZN_UPDATE_PENDING); - } -} - -/* - *---------------------------------------------------------------------- - * - * ZnGetGlContext -- - * - *---------------------------------------------------------------------- - */ -#ifdef GL -ZnGLContextEntry * -ZnGetGLContext(Display *dpy) -{ - ZnGLContextEntry *context_entry; - - for (context_entry = gl_contexts; - context_entry && context_entry->dpy != dpy; - context_entry = context_entry->next); - - return context_entry; -} - -ZnGLContextEntry * -ZnGLMakeCurrent(Display *dpy, - ZnWInfo *wi) -{ - ZnGLContextEntry *ce; - - ce = ZnGetGLContext(dpy); - - if (!wi) { - /* Get a zinc widget from the context struct - * for this display. If no more are left, - * returns, nothing can be done. This can - * happen only when freeing images or fonts - * after the last zinc on a given display has - * been deleted. In this case the context should - * be deleted, freeing all resources including - * textures. - */ - ZnWInfo **wip = ZnListArray(ce->widgets); - int i, num = ZnListSize(ce->widgets); - - for (i = 0; i win != NULL) { - wi = *wip; - break; - } - } - if (!wi) { - return NULL; - } - } -#ifdef _WIN32 - ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win)); - ce->hdc = GetDC(ce->hwnd); - SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd); - - if (!wglMakeCurrent(ce->hdc, ce->context)) { - fprintf(stderr, "Can't make the GL context current: %d\n", GetLastError()); - } -#else - glXMakeCurrent(dpy, Tk_WindowId(wi->win), ce->context); -#endif - return ce; -} - -void -ZnGLReleaseContext(ZnGLContextEntry *ce) -{ - if (ce) { -#ifdef _WIN32 - wglMakeCurrent(NULL, NULL); - ReleaseDC(ce->hwnd, ce->hdc); -#else - /*glXMakeCurrent(ce->dpy, None, NULL);*/ -#endif - } -} - -static void -ZnGLSwapBuffers(ZnGLContextEntry *ce, - ZnWInfo *wi) -{ - if (ce) { -#ifdef _WIN32 - SwapBuffers(ce->hdc); -#else - glXSwapBuffers(ce->dpy, Tk_WindowId(wi->win)); -#endif - } -} -#endif - - -#ifdef GL -static void -InitRendering1(ZnWInfo *wi) -{ - - if (wi->render) { -# ifndef _WIN32 - ZnGLContextEntry *ce; - ZnGLContext gl_context; - XVisualInfo *gl_visual = NULL; - Colormap colormap = 0; - - ASSIGN(wi->flags, ZN_PRINT_CONFIG, (getenv("ZINC_GLX_INFO") != NULL)); - - if (ISSET(wi->flags, ZN_PRINT_CONFIG)) { - fprintf(stderr, "GLX version %d.%d\n", ZnMajorGlx, ZnMinorGlx); - } - - /* - * Look for a matching context already available. - */ - ce = ZnGetGLContext(wi->dpy); - if (ce) { - gl_context = ce->context; - gl_visual = ce->visual; - colormap = ce->colormap; - ZnListAdd(ce->widgets, &wi, ZnListTail); - } - else { - int val; - - gl_visual = glXChooseVisual(wi->dpy, - XScreenNumberOfScreen(wi->screen), - ZnGLAttribs); - if (!gl_visual) { - fprintf(stderr, "No glx visual\n"); - } - else { - gl_context = glXCreateContext(wi->dpy, gl_visual, - NULL, wi->render==1); - if (!gl_context) { - fprintf(stderr, "No glx context\n"); - } - else { - colormap = XCreateColormap(wi->dpy, RootWindowOfScreen(wi->screen), - gl_visual->visual, AllocNone); - ce = ZnMalloc(sizeof(ZnGLContextEntry)); - ce->context = gl_context; - ce->visual = gl_visual; - ce->colormap = colormap; - ce->dpy = wi->dpy; - ce->max_tex_size = 64; /* Minimum value is always valid */ - ce->max_line_width = 1; - ce->max_point_width = 1; - ce->next = gl_contexts; - gl_contexts = ce; - ce->widgets = ZnListNew(1, sizeof(ZnWInfo *)); - ZnListAdd(ce->widgets, &wi, ZnListTail); - - if (ISSET(wi->flags, ZN_PRINT_CONFIG)) { - fprintf(stderr, " Visual : 0x%x, ", - (int) gl_visual->visualid); - glXGetConfig(wi->dpy, gl_visual, GLX_RGBA, &val); - fprintf(stderr, "RGBA : %d, ", val); - glXGetConfig(wi->dpy, gl_visual, GLX_DOUBLEBUFFER, &val); - fprintf(stderr, "Double Buffer : %d, ", val); - glXGetConfig(wi->dpy, gl_visual, GLX_STENCIL_SIZE, &val); - fprintf(stderr, "Stencil : %d, ", val); - glXGetConfig(wi->dpy, gl_visual, GLX_BUFFER_SIZE, &val); - fprintf(stderr, "depth : %d, ", val); - glXGetConfig(wi->dpy, gl_visual, GLX_RED_SIZE, &val); - fprintf(stderr, "red : %d, ", val); - glXGetConfig(wi->dpy, gl_visual, GLX_GREEN_SIZE, &val); - fprintf(stderr, "green : %d, ", val); - glXGetConfig(wi->dpy, gl_visual, GLX_BLUE_SIZE, &val); - fprintf(stderr, "blue : %d, ", val); - glXGetConfig(wi->dpy, gl_visual, GLX_ALPHA_SIZE, &val); - fprintf(stderr, "alpha : %d\n", val); - fprintf(stderr, " Direct Rendering: %d\n", - glXIsDirect(wi->dpy, gl_context)); - } - } - } - } - if (gl_visual && colormap) { - Tk_SetWindowVisual(wi->win, gl_visual->visual, 24, colormap); - } -# endif /* _WIN32 */ - } -} - -static void -InitRendering2(ZnWInfo *wi) -{ - ZnGLContextEntry *ce; - ZnGLContext gl_context; - GLfloat r[2]; /* Min, Max */ - GLint i[1]; - - if (wi->render) { -# ifdef _WIN32 - /* - * Look for a matching context already available. - */ - ce = ZnGetGLContext(wi->dpy); - if (ce) { - gl_context = ce->context; - ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win)); - ce->hdc = GetDC(ce->hwnd); - ZnListAdd(ce->widgets, &wi, ZnListTail); - SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd); - } - else { - ce = ZnMalloc(sizeof(ZnGLContextEntry)); - ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win)); - ce->hdc = GetDC(ce->hwnd); - ce->widgets = ZnListNew(1, sizeof(ZnWInfo *)); - ZnListAdd(ce->widgets, &wi, ZnListTail); - - memset(&ce->pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); - ce->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); - ce->pfd.nVersion = 1; - ce->pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - ce->pfd.iPixelType = PFD_TYPE_RGBA; - ce->pfd.cRedBits = 8; - ce->pfd.cGreenBits = 8; - ce->pfd.cBlueBits = 8; - ce->pfd.cAlphaBits = 8; - ce->pfd.cStencilBits = 8; - ce->pfd.iLayerType = PFD_MAIN_PLANE; - ce->ipixel = ChoosePixelFormat(ce->hdc, &ce->pfd); - /*printf("ipixel=%d dwFlags=0x%x req=0x%x iPixelType=%d hdc=%d\n", - ce->ipixel, ce->pfd.dwFlags, - PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER, - ce->pfd.iPixelType==PFD_TYPE_RGBA, - ce->hdc);*/ - if (!ce->ipixel || - (ce->pfd.cRedBits != 8) || (ce->pfd.cGreenBits != 8) || (ce->pfd.cBlueBits != 8) || - (ce->pfd.cStencilBits != 8)) { - fprintf(stderr, "ChoosePixelFormat failed\n"); - } - - if (SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd) == TRUE) { - gl_context = wglCreateContext(ce->hdc); - if (gl_context) { - ce->context = gl_context; - ce->dpy = wi->dpy; - ce->max_tex_size = 64; /* Minimum value is always valid */ - ce->max_line_width = 1; - ce->max_point_width = 1; - ce->next = gl_contexts; - gl_contexts = ce; - } - else { - fprintf(stderr, "wglCreateContext failed\n"); - ZnFree(ce); - } - } - else { - ZnFree(ce); - } - } - ReleaseDC(ce->hwnd, ce->hdc); -#endif - - ce = ZnGLMakeCurrent(wi->dpy, wi); - glGetFloatv(ZN_GL_LINE_WIDTH_RANGE, r); - ce->max_line_width = r[1]; - glGetFloatv(ZN_GL_POINT_SIZE_RANGE, r); - ce->max_point_width = r[1]; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, i); - ce->max_tex_size = (unsigned int) i[0]; - - if (ISSET(wi->flags, ZN_PRINT_CONFIG)) { - fprintf(stderr, "OpenGL version %s\n", - (char *) glGetString(GL_VERSION)); - fprintf(stderr, " Rendering engine: %s, ", - (char *) glGetString(GL_RENDERER)); - fprintf(stderr, " Vendor: %s\n", - (char *) glGetString(GL_VENDOR)); - fprintf(stderr, " Available extensions: %s\n", - (char *) glGetString(GL_EXTENSIONS)); - fprintf(stderr, "Max antialiased line width: %g\n", - ce->max_line_width); - fprintf(stderr, "Max antialiased point size: %g\n", - ce->max_point_width); - fprintf(stderr, "Max texture size: %d\n", - ce->max_tex_size); - } - - ZnGLReleaseContext(ce); - } -} -#endif /* GL */ - - -/* - *---------------------------------------------------------------------- - * - * ZincObjCmd -- - * - * This procedure is invoked to process the "zinc" Tcl - * command. It creates a new "zinc" widget. - * - *---------------------------------------------------------------------- - */ -EXTERN int -ZincObjCmd(ClientData client_data, /* Main window associated with - * interpreter. */ - Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - Tcl_Obj *CONST args[]) /* Argument strings. */ -{ - Tk_Window top_w = (Tk_Window) client_data; - ZnWInfo *wi; - Tk_Window tkwin; -#ifndef PTK_800 - Tk_OptionTable opt_table; -#endif - unsigned int num; - ZnBool has_gl = False; -#ifndef _WIN32 -# if defined(GL) || defined(SHAPE) - int major_op, first_err, first_evt; -# endif -# ifdef GL - Display *dpy = Tk_Display(top_w); - Screen *screen = Tk_Screen(top_w); -# endif -#endif - - InitZinc(interp); - -#ifdef GL -# ifdef _WIN32 - has_gl = True; -# else - if (XQueryExtension(dpy, "GLX", &major_op, &first_evt, &first_err)) { - if (glXQueryExtension(dpy, &first_err, &first_evt)) { - if (glXQueryVersion(dpy, &ZnMajorGlx, &ZnMinorGlx)) { - if ((ZnMajorGlx == 1) && (ZnMinorGlx >= 1)) { - has_gl = True; - } - } - } - } - if (has_gl) { - XVisualInfo *visual = glXChooseVisual(dpy, - XScreenNumberOfScreen(screen), - ZnGLAttribs); - if (visual) { - XFree(visual); - } - else { - has_gl = False; - } - } -# endif -#endif - - if (argc == 1) { - Tcl_AppendResult(interp, VERSION, NULL); - Tcl_AppendResult(interp, " X11", NULL); -#ifdef GL -# ifdef _WIN32 - Tcl_AppendResult(interp, " GL", NULL); -# else - if (has_gl) { - Tcl_AppendResult(interp, " GL", NULL); - } -# endif -#endif - return TCL_OK; - } - - tkwin = Tk_CreateWindowFromPath(interp, top_w, Tcl_GetString(args[1]), NULL); - if (tkwin == NULL) { - return TCL_ERROR; - } - -#ifndef PTK_800 - opt_table = Tk_CreateOptionTable(interp, option_specs); - #endif - - Tk_SetClass(tkwin, "Zinc"); - - /* - * Allocate and initialize the widget record. - */ - wi = (ZnWInfo *) ZnMalloc(sizeof(ZnWInfo)); - wi->win = tkwin; - wi->interp = interp; - wi->dpy = Tk_Display(tkwin); - wi->screen = Tk_Screen(tkwin); - wi->flags = 0; - wi->render = -1; - wi->real_top = None; - - ASSIGN(wi->flags, ZN_HAS_GL, has_gl); -#if defined(SHAPE) && !defined(_WIN32) - ASSIGN(wi->flags, ZN_HAS_X_SHAPE, - XQueryExtension(wi->dpy, "SHAPE", &major_op, &first_evt, &first_err)); - wi->reshape = wi->full_reshape = True; -#else - CLEAR(wi->flags, ZN_HAS_X_SHAPE); - wi->reshape = wi->full_reshape = False; -#endif - -#ifdef PTK -#ifdef PTK_800 - wi->cmd = Lang_CreateWidget(interp, tkwin, (Tcl_CmdProc *) WidgetObjCmd, - (ClientData) wi, CmdDeleted); -#else - wi->cmd = Lang_CreateWidget(interp, tkwin, WidgetObjCmd, (ClientData) wi, CmdDeleted); -#endif -#else - wi->cmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin), WidgetObjCmd, - (ClientData) wi, CmdDeleted); -#endif -#ifndef PTK_800 - wi->opt_table = opt_table; -#endif - wi->binding_table = 0; - wi->fore_color = NULL; - wi->back_color = NULL; - wi->relief_grad = NULL; - wi->bbox_color = NULL; - wi->draw_bboxes = 0; - wi->light_angle = 120; - wi->follow_pointer = 0; - wi->border_width = 0; - wi->relief = ZN_RELIEF_FLAT; - wi->opt_width = None; - wi->opt_height = None; - wi->font = 0; -#ifdef ATC - wi->track_visible_history_size = 0; - wi->track_managed_history_size = 0; - wi->speed_vector_length = 0; - wi->map_text_font = 0; -# ifdef GL - wi->font_tfi = NULL; - wi->map_font_tfi = NULL; -# endif - wi->map_distance_symbol = ZnUnspecifiedImage; - wi->track_symbol = ZnUnspecifiedImage; -# ifndef PTK_800 - wi->map_symbol_obj = NULL; - wi->track_symbol_obj = NULL; -# endif -#endif - wi->tile = ZnUnspecifiedImage; -#ifndef PTK_800 - wi->tile_obj = NULL; -#endif - wi->cursor = None; - wi->hot_item = ZN_NO_ITEM; - wi->hot_prev = ZN_NO_ITEM; - wi->confine = 0; - wi->origin.x = wi->origin.y = 0; - wi->scroll_xo = wi->scroll_yo = 0; - wi->scroll_xc = wi->scroll_yc = 0; - wi->x_scroll_incr = wi->y_scroll_incr = 0; - wi->x_scroll_cmd = wi->y_scroll_cmd = NULL; - wi->region = NULL; - - 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_STRING_KEYS); - - wi->obj_id = 1; - wi->num_items = 0; - - wi->top_group = ZnCreateItem(wi, ZnGroup, 0, NULL); - -#ifdef ATC - wi->om_group_id = 0; - wi->om_group = wi->top_group; - OmRegister((void *) wi, ZnSendTrackToOm, ZnSetLabelAngleFromOm, ZnQueryLabelPosition); -#endif - wi->gc = 0; - wi->draw_buffer = 0; - wi->pick_aperture = 0; - wi->state = 0; - memset(&wi->pick_event, 0, sizeof(XEvent)); - 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; - - CLEAR(wi->flags, ZN_MONITORING); -#ifndef _WIN32 - wi->total_draw_chrono = ZnNewChrono("Total draw time"); - wi->this_draw_chrono = ZnNewChrono("Last draw time"); -#endif - wi->damaged_area_w = wi->damaged_area_h = 0; - - /* - * Text management init. - */ - 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.cursor_on = False; - wi->insert_on_time = 0; - wi->insert_off_time = 0; - wi->blink_handler = NULL; - wi->take_focus = NULL; - wi->highlight_width = 0; - wi->highlight_color = NULL; - wi->highlight_bg_color = NULL; - ZnResetBBox(&wi->exposed_area); - ZnResetBBox(&wi->damaged_area); - - ZnInitClipStack(wi); - ZnInitTransformStack(wi); - - for (num = 0; num < ZN_NUM_ALPHA_STEPS; num++) { - char name[TCL_INTEGER_SPACE+12]; - - sprintf(name, "AlphaStipple%d", num); - wi->alpha_stipples[num] = Tk_GetBitmap(interp, tkwin, Tk_GetUid(name)); - } - - Tk_CreateEventHandler(tkwin, - ExposureMask|StructureNotifyMask|FocusChangeMask, - Event, (ClientData) wi); - Tk_CreateEventHandler(tkwin, KeyPressMask|KeyReleaseMask| - ButtonPressMask|ButtonReleaseMask|EnterWindowMask| - LeaveWindowMask|PointerMotionMask|VirtualEventMask, - Bind, (ClientData) wi); - Tk_CreateSelHandler(tkwin, XA_PRIMARY, XA_STRING, - FetchSelection, (ClientData) wi, XA_STRING); - -#ifdef PTK_800 - if (Configure(interp, wi, argc-2, args+2, 0) != TCL_OK) { - Tk_DestroyWindow(tkwin); - return TCL_ERROR; - } -#else - if (Tk_InitOptions(interp, (char *) wi, opt_table, tkwin) != TCL_OK) { - Tk_DestroyWindow(tkwin); - return TCL_ERROR; - } - - if (Configure(interp, wi, argc-2, args+2) != TCL_OK) { - Tk_DestroyWindow(tkwin); - return TCL_ERROR; - } -#endif - - wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0; - wi->damaged_area.corner.x = wi->width = wi->opt_width; - wi->damaged_area.corner.y = wi->height = wi->opt_height; - - if (!wi->render) { - /* - * Allocate double buffer pixmap/image. - */ - wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen), - wi->width, wi->height, Tk_Depth(wi->win)); - } -#ifdef GL - else { - InitRendering1(wi); - } -#endif - -#ifdef PTK - Tcl_SetObjResult(interp, LangWidgetObj(interp, tkwin)); -#else - Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin), -1)); -#endif - return TCL_OK; -} - - -/* - *---------------------------------------------------------------------- - * - * EncodeItemPart -- - * - * Form a ClientData value from an item/part that is suitable - * as a key in a binding table. - * - *---------------------------------------------------------------------- - */ -ClientData -EncodeItemPart(ZnItem item, - int part) -{ - if (part >= 0) { - ZnFieldSet fs; - if (!item->class->GetFieldSet) { - return item; - } - fs = item->class->GetFieldSet(item); - return (ClientData) (ZnFIELD.GetFieldStruct(fs, part % (int) ZnFIELD.NumFields(fs))); - } - else if (part == ZN_NO_PART) { - return item; - } - return (ClientData) (((char *) item)-part); -} - - -/* - *-------------------------------------------------------------- - * - * All tag search procs below are lifted from tkCanvas.c, then - * modified to match our needs. - * - *-------------------------------------------------------------- - */ - -/* - *-------------------------------------------------------------- - * - * TagSearchExprInit -- - * - * This procedure allocates and initializes one - * TagSearchExpr struct. - * - *-------------------------------------------------------------- - */ -static void -TagSearchExprInit(TagSearchExpr **expr_var) -{ - 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. */ - ZnTagSearch *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 TCL_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 TCL_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 TCL_ERROR; - } - if (! (tag - search->rewrite_buf)) { - Tcl_AppendResult(interp, - "Null quoted tag string in tag search expression", - (char *) NULL); - return TCL_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 TCL_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 TCL_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 TCL_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 TCL_ERROR; - } - } - } - breakwhile: - if (found_tag && ! looking_for_tag) { - return TCL_OK; - } - Tcl_AppendResult(interp, "Missing tag in tag search expression", - (char *) NULL); - return TCL_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 */ - ZnItem 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; - 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++]; - /* - * set result 1 if tag is found in item's tags - */ - result = ZnITEM.HasTag(item, uid) ? 1 : 0; - } - else if (uid == neg_tag_val_uid) { - negate_result = ! negate_result; - /* - * assert(expr->index < expr->length); - */ - uid = expr->uids[expr->index++]; - /* - * set result 1 if tag is found in item's tags - */ - result = ZnITEM.HasTag(item, uid) ? 1 : 0; - } - 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; - } - } - /* - * assert(! looking_for_tag); - */ - return result; -} - - -static ZnItem -LookupGroupFromPath(ZnItem start, - Tk_Uid *names, - unsigned int num_names) -{ - Tk_Uid name, *tags; - unsigned int count; - ZnBool recursive; - ZnItem result, current = ZnGroupHead(start); - - if (num_names == 0) { - return start; - } - - name = names[1]; - recursive = (names[0] == star_uid); - /* printf("LookupGroupFromPath; group: %d, nom: %s, recursive: %s\n", - start->id, name, names[0]);*/ - while (current != ZN_NO_ITEM) { - if ((current->class == ZnGroup) && (current->tags)) { - tags = ZnListArray(current->tags); - count = ZnListSize(current->tags); - for (; count > 0; tags++, count--) { - if (name == *tags) { - if (num_names > 2) { - result = LookupGroupFromPath(current, names+2, num_names-2); - return result; - } - else { - return current; - } - } - } - /* - * This group doesn't match try to search depth first. - */ - if (recursive) { - result = LookupGroupFromPath(current, names, num_names); - if (result != ZN_NO_ITEM) { - return result; - } - } - } - current = current->next; - } - - return ZN_NO_ITEM; -} - - -/* - *-------------------------------------------------------------- - * - * 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(ZnWInfo *wi, - Tcl_Obj *tag_obj, /* Object giving tag value, NULL - * is the same as 'all'. */ - ZnTagSearch **search_var) /* Record describing tag search; - * will be initialized here. */ -{ - Tk_Uid tag; - int i; - ZnTagSearch *search; - ZnItem group = wi->top_group; - ZnBool recursive = True; - - if (tag_obj) { - tag = Tcl_GetString(tag_obj); - } - else { - tag = all_uid; - } - - /* - * Initialize the search. - */ - if (*search_var) { - search = *search_var; - } - else { - /* Allocate primary search struct on first call */ - *search_var = search = (ZnTagSearch *) ZnMalloc(sizeof(ZnTagSearch)); - 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(ZnItem)); - } - TagSearchExprInit(&(search->expr)); - - /* How long is the tagOrId ? */ - search->tag_len = strlen(tag); - - /* - * 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 TCL_OK; - } - - /* - * If a path specification exists in the tag, strip it from the - * tag and search for a matching group. - */ - if (strpbrk(tag, ".*")) { - Tk_Uid path; - char c, *next; - unsigned int id; - Tcl_HashEntry *entry; - - ZnListEmpty(ZnWorkStrings); - recursive = False; - if ((*tag == '.') || (*tag == '*')) { - recursive = (*tag == '*'); - tag++; - } - path = tag; - while ((next = strpbrk(path, ".*"))) { - if (isdigit(*path)) { - if (path == tag) { /* Group id is ok only in first section. */ - c = *next; - *next = '\0'; - id = strtoul(path, NULL, 10); - *next = c; - group = wi->hot_item; - if ((group == ZN_NO_ITEM) || (group->id != id)) { - entry = Tcl_FindHashEntry(wi->id_table, (char *) id); - if (entry != NULL) { - group = (ZnItem) Tcl_GetHashValue(entry); - } - else { - Tcl_AppendResult(wi->interp, "unknown group in path \"", - tag, "\"", NULL); - return TCL_ERROR; - } - } - if (group->class != ZnGroup) { - Tcl_AppendResult(wi->interp, "item is not a group in path \"", - tag, "\"", NULL); - return TCL_ERROR; - } - } - else { - Tcl_AppendResult(wi->interp, "misplaced group id in path \"", - tag, "\"", NULL); - return TCL_ERROR; - } - } - else { - ZnListAdd(ZnWorkStrings, - (void *) (recursive ? &star_uid : &dot_uid), - ZnListTail); - c = *next; - *next = '\0'; - path = Tk_GetUid(path); - *next = c; - ZnListAdd(ZnWorkStrings, (void *) &path, ZnListTail); - } - recursive = (*next == '*'); - path = next+1; - } - - group = LookupGroupFromPath(group, - ZnListArray(ZnWorkStrings), - ZnListSize(ZnWorkStrings)); - if (group == ZN_NO_ITEM) { - Tcl_AppendResult(wi->interp, "path does not lead to a valid group\"", - tag, "\"", NULL); - return TCL_ERROR; - } - - /* - * Adjust tag to strip the path. - */ - tag = path; - search->tag_len = strlen(tag); - /* - * If the tag consist only in a path description - * assume that the tag all is implied. - */ - if (search->tag_len == 0) { - tag = all_uid; - search->tag_len = strlen(tag); - } - } - - /* - * 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); - } - - /* Initialize search */ - search->wi = wi; - search->over = False; - search->type = 0; - search->group = group; - search->recursive = recursive; - 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 (isdigit(*tag)) { - char *end; - - search->id = strtoul(tag, &end, 0); - if (*end == 0) { - search->type = 1; - 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; - } - 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) { - /* - * 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) != TCL_OK) { - /* Syntax error in tag expression */ - /* Result message set by TagSearchScanExpr */ - return TCL_ERROR; - } - search->expr->length = search->expr->index; - } - else { - /* - * For all other tags convert to a UID. - */ - search->expr->uid = Tk_GetUid(tag); - - if (search->expr->uid == all_uid) { - /* - * All items match. - */ - search->type = 2; - } - else { - /* - * Optimized single-tag search - */ - search->type = 3; - } - } - return TCL_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 ZnItem -ZnTagSearchFirst(ZnTagSearch *search) /* Record describing tag search */ -{ - ZnItem item, previous; - - /* short circuit impossible searches for null tags */ - if (search->over == True) { - return ZN_NO_ITEM; - } - - /* - * 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 = (ZnItem) 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 = ZnGroupHead(search->group); - return search->current; - } - - item = ZnGroupHead(search->group); - previous = ZN_NO_ITEM; - do { - while (item != ZN_NO_ITEM) { - if (search->type == 3) { - /* - * Optimized single-tag search - */ - if (ZnITEM.HasTag(item, search->expr->uid)) { - search->previous = previous; - search->current = item; - return item; - } - } - 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)) { - ZnItem prev_group = (ZnItem) 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 = item; - previous = item; - if (item == prev_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 = ZnGroupHead(search->group); - } - else { - previous = item; - item = item->next; - } - } - /* - * 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 = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail); - ZnListDelete(search->item_stack, ZnListTail); - previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail); - ZnListDelete(search->item_stack, ZnListTail); - } - if (item != ZN_NO_ITEM) { - search->group = item->parent; - } - } while (item != ZN_NO_ITEM); - - 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 ZnItem -ZnTagSearchNext(ZnTagSearch *search) /* Record describing search in progress. */ -{ - ZnItem item, previous; - - if (search->over) { - return ZN_NO_ITEM; - } - /* - * 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 = ZnGroupHead(search->group); - } - else { - item = previous->next; - } - - if (item != search->current) { - /* - * 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) && (search->recursive)) { - /* - * Explore the hierarchy depth first using the item stack - * to save the current node. - */ - search->group = item; - previous = item; - item = item->next; - /*printf("ZnTagSearchNext diving for all, pushing %d\n", - item?item->id:0);*/ - ZnListAdd(search->item_stack, &previous, ZnListTail); - ZnListAdd(search->item_stack, &item, ZnListTail); - previous = ZN_NO_ITEM; - item = ZnGroupHead(search->group); - } - else { - previous = item; - item = previous->next; - } - - if (item == ZN_NO_ITEM) { - while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) { - /* - * End of list at this level, back up one level. - */ - item = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail); - ZnListDelete(search->item_stack, ZnListTail); - previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail); - ZnListDelete(search->item_stack, ZnListTail); - } - if (item != ZN_NO_ITEM) { - 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);*/ - } - else { - /* - * Or finish the search if at top. - */ - search->over = True; - return ZN_NO_ITEM; - } - } - - if (search->type == 2) { - /* - * All items match. - */ - search->previous = previous; - search->current = item; - return item; - } - - do { - while (item != ZN_NO_ITEM) { - if (search->type == 3) { - /* - * Optimized single-tag search - */ - if (ZnITEM.HasTag(item, search->expr->uid)) { - search->previous = previous; - search->current = item; - return item; - } - } - 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("ZnTagSearchNext diving for tag, depth %d\n", - ZnListSize(search->item_stack)/2);*/ - 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 = ZnGroupHead(search->group); - } - else { - previous = item; - item = item->next; - } - } - /*printf("ZnTagSearchNext backup for tag, depth %d\n", - ZnListSize(search->item_stack)/2);*/ - while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) { - item = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail); - ZnListDelete(search->item_stack, ZnListTail); - previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail); - ZnListDelete(search->item_stack, ZnListTail); - } - if (item != ZN_NO_ITEM) { - search->group = item->parent; - } - } while (item != ZN_NO_ITEM); - - /* - * Out of fuel. - */ - 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 -ZnTagSearchDestroy(ZnTagSearch *search) /* Record describing tag search */ -{ - if (search) { - TagSearchExprDestroy(search->expr); - ZnListFree(search->item_stack); - ZnFree(search->rewrite_buf); - ZnFree(search); - } -} - - -/* - *---------------------------------------------------------------------- - * - * ZnItemWithTagOrId -- - * - * 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 -ZnItemWithTagOrId(ZnWInfo *wi, - Tcl_Obj *tag_or_id, - ZnItem *item, - ZnTagSearch **search_var) -{ - if (ZnTagSearchScan(wi, tag_or_id, search_var) != TCL_OK) { - return TCL_ERROR; - } - *item = ZnTagSearchFirst(*search_var); - return TCL_OK; -} - - -/* - *---------------------------------------------------------------------- - * - * LayoutItems -- - * - * Perform layouts on items. It can position items horizontally, - * vertically, along a path or with respect to a reference item. - * It can also align on a grid, evenly space items and resize - * items to a common reference. - * - *---------------------------------------------------------------------- - */ -static int -LayoutItems(ZnWInfo *wi, - int argc, - Tcl_Obj *CONST args[]) -{ - int index/*, result*/; - /*ZnItem item;*/ -#ifdef PTK_800 - static char *layout_cmd_strings[] = - #else - static CONST char *layout_cmd_strings[] = -#endif - { - "align", "grid", "position", "scale", "space", NULL - }; - enum layout_cmds { - ZN_L_ALIGN, ZN_L_GRID, ZN_L_POSITION, ZN_L_SCALE, ZN_L_SPACE - }; - - if (Tcl_GetIndexFromObj(wi->interp, args[0], layout_cmd_strings, - "layout command", 0, &index) != TCL_OK) { - return TCL_ERROR; - } - switch((enum layout_cmds) index) { - /* - * align - */ - case ZN_L_ALIGN: - break; - /* - * grid - */ - case ZN_L_GRID: - break; - /* - * position - */ - case ZN_L_POSITION: - break; - /* - * scale - */ - case ZN_L_SCALE: - break; - /* - * space - */ - case ZN_L_SPACE: - break; - } - - return TCL_OK; -} - - -/* - *---------------------------------------------------------------------- - * - * SetOrigin -- - * - * This procedure is invoked to translate the viewed area so - * that the given point is displayed in the top left corner. - * - * Results: - * None. - * - * Side effects: - * Zinc will be redisplayed to reflect the change in ciew. - * The scrollbars will be updated if there are any. - * The top group transform is modified to achieve the effect, - * it is not a good idea to mix view control and application - * control of the top group transform. - * - *---------------------------------------------------------------------- - */ -static void -SetOrigin(ZnWInfo *wi, - ZnReal x_origin, - ZnReal y_origin) -{ - int left, right, top, bottom, delta; - - /* - * If scroll increments have been set, round the window origin - * to the nearest multiple of the increments. - */ - if (wi->x_scroll_incr > 0) { - if (x_origin >= 0) { - x_origin += wi->x_scroll_incr/2; - } - else { - x_origin = (-x_origin) + wi->x_scroll_incr/2; - } - } - if (wi->y_scroll_incr > 0) { - if (y_origin >= 0) { - y_origin += wi->y_scroll_incr/2; - } - else { - y_origin = (-y_origin) + wi->y_scroll_incr/2; - } - } - - /* - * Adjust the origin if necessary to keep as much as possible of the - * canvas in the view. The variables left, right, etc. keep track of - * how much extra space there is on each side of the view before it - * will stick out past the scroll region. If one side sticks out past - * the edge of the scroll region, adjust the view to bring that side - * back to the edge of the scrollregion (but don't move it so much that - * the other side sticks out now). If scroll increments are in effect, - * be sure to adjust only by full increments. - */ - if (wi->confine && (wi->region != NULL)) { - left = (int) (x_origin - wi->scroll_xo); - right = (int) (wi->scroll_xc - (x_origin + Tk_Width(wi->win))); - top = (int) (y_origin - wi->scroll_yo); - bottom = (int) (wi->scroll_yc - (y_origin + Tk_Height(wi->win))); - if ((left < 0) && (right > 0)) { - delta = (right > -left) ? -left : right; - if (wi->x_scroll_incr > 0) { - delta -= delta % wi->x_scroll_incr; - } - x_origin += delta; - } - else if ((right < 0) && (left > 0)) { - delta = (left > -right) ? -right : left; - if (wi->x_scroll_incr > 0) { - delta -= delta % wi->x_scroll_incr; - } - x_origin -= delta; - } - if ((top < 0) && (bottom > 0)) { - delta = (bottom > -top) ? -top : bottom; - if (wi->y_scroll_incr > 0) { - delta -= delta % wi->y_scroll_incr; - } - y_origin += delta; - } - else if ((bottom < 0) && (top > 0)) { - delta = (top > -bottom) ? -bottom : top; - if (wi->y_scroll_incr > 0) { - delta -= delta % wi->y_scroll_incr; - } - y_origin -= delta; - } - } - - /* - * If the requested origin is not already set, translate the - * top group and update the scrollbars. - */ - if ((wi->origin.x != x_origin) || (wi->origin.y != y_origin)) { - wi->origin.x = x_origin; - wi->origin.y = y_origin; - ZnITEM.ResetTransfo(wi->top_group); - ZnITEM.TranslateItem(wi->top_group, -x_origin, -y_origin, False); - SET(wi->flags, ZN_UPDATE_SCROLLBARS); - } -} - - -/* - *---------------------------------------------------------------------- - * - * ScrollFractions -- - * - * Given the range that's visible in the window and the "100% - * range", return a list of two real representing the scroll - * fractions. This procedure is used for both x and y scrolling. - * - * Results: - * Return a string as a Tcl_Obj holding two real numbers - * describing the scroll fraction (between 0 and 1) corresponding - * to the arguments. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -#ifdef PTK -static void -ScrollFractions(ZnReal view1, /* Lowest coordinate visible in the window. */ - ZnReal view2, /* Highest coordinate visible in the window. */ - ZnReal region1,/* Lowest coordinate in the object. */ - ZnReal region2,/* Highest coordinate in the object. */ - ZnReal *first, - ZnReal *last) -#else -static Tcl_Obj * -ScrollFractions(ZnReal view1, /* Lowest coordinate visible in the window. */ - ZnReal view2, /* Highest coordinate visible in the window. */ - ZnReal region1,/* Lowest coordinate in the object. */ - ZnReal region2)/* Highest coordinate in the object. */ -#endif -{ - ZnReal range, f1, f2; - char buffer[2*TCL_DOUBLE_SPACE+2]; - - range = region2 - region1; - if (range <= 0) { - f1 = 0; - f2 = 1.0; - } - else { - f1 = (view1 - region1)/range; - if (f1 < 0) { - f1 = 0.0; - } - f2 = (view2 - region1)/range; - if (f2 > 1.0) { - f2 = 1.0; - } - if (f2 < f1) { - f2 = f1; - } - } -#ifdef PTK - *first = f1; - *last = f2; -#else - sprintf(buffer, "%g %g", f1, f2); - return Tcl_NewStringObj(buffer, -1); -#endif -} - - -/* - *-------------------------------------------------------------- - * - * UpdateScrollbars -- - * - * This procedure is invoked whenever zinc has changed in - * a way that requires scrollbars to be redisplayed (e.g. - * the view has changed). - * - * Results: - * None. - * - * Side effects: - * If there are scrollbars associated with zinc, then - * their scrolling commands are invoked to cause them to - * redisplay. If errors occur, additional Tcl commands may - * be invoked to process the errors. - * - *-------------------------------------------------------------- - */ -static void -UpdateScrollbars(ZnWInfo *wi) -{ - int result; - Tcl_Interp *interp; - int x_origin, y_origin, width, height; - int scroll_xo, scroll_xc, scroll_yo, scroll_yc; -#ifdef PTK - LangCallback *x_scroll_cmd, *y_scroll_cmd; -#else - Tcl_Obj *x_scroll_cmd, *y_scroll_cmd; -#endif - Tcl_Obj *fractions; - - /* - * Save all the relevant values from wi, because it might be - * deleted as part of either of the two calls to Tcl_VarEval below. - */ - interp = wi->interp; - Tcl_Preserve((ClientData) interp); - x_scroll_cmd = wi->x_scroll_cmd; - if (x_scroll_cmd != NULL) { - Tcl_Preserve((ClientData) x_scroll_cmd); - } - y_scroll_cmd = wi->y_scroll_cmd; - if (y_scroll_cmd != NULL) { - Tcl_Preserve((ClientData) y_scroll_cmd); - } - x_origin = (int) wi->origin.x; - y_origin = (int) wi->origin.y; - width = Tk_Width(wi->win); - height = Tk_Height(wi->win); - scroll_xo = wi->scroll_xo; - scroll_xc = wi->scroll_xc; - scroll_yo = wi->scroll_yo; - scroll_yc = wi->scroll_yc; - CLEAR(wi->flags, ZN_UPDATE_SCROLLBARS); - if (wi->x_scroll_cmd != NULL) { -#ifdef PTK - ZnReal first, last; - ScrollFractions(x_origin, x_origin + width, scroll_xo, scroll_xc, &first, &last); - result = LangDoCallback(interp, x_scroll_cmd, 0, 2, " %g %g", first, last); -#else - fractions = ScrollFractions(x_origin, x_origin + width, scroll_xo, scroll_xc); - result = Tcl_VarEval(interp, Tcl_GetString(x_scroll_cmd), " ", Tcl_GetString(fractions), NULL); - Tcl_DecrRefCount(fractions); -#endif - if (result != TCL_OK) { - Tcl_BackgroundError(interp); - } - Tcl_ResetResult(interp); - Tcl_Release((ClientData) x_scroll_cmd); - } - - if (y_scroll_cmd != NULL) { -#ifdef PTK - ZnReal first, last; - ScrollFractions(y_origin, y_origin + height, scroll_yo, scroll_yc, &first, &last); - result = LangDoCallback(interp, y_scroll_cmd, 0, 2, " %g %g", first, last); -#else - fractions = ScrollFractions(y_origin, y_origin + height, scroll_yo, scroll_yc); - result = Tcl_VarEval(interp, Tcl_GetString(y_scroll_cmd), " ", Tcl_GetString(fractions), NULL); - Tcl_DecrRefCount(fractions); -#endif - if (result != TCL_OK) { - Tcl_BackgroundError(interp); - } - Tcl_ResetResult(interp); - Tcl_Release((ClientData) y_scroll_cmd); - } - Tcl_Release((ClientData) interp); -} - - -/* - *---------------------------------------------------------------------- - * - * 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 - * is NULL, the item id/part is added to the result, otherwise - * the tag is added to the item. - * - *---------------------------------------------------------------------- - */ -void -ZnDoItem(Tcl_Interp *interp, - ZnItem item, - int part, - Tk_Uid tag_uid) -{ - if (tag_uid == NULL) { - Tcl_Obj *l; - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(item->id)); - if (part != ZN_NO_PART) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(part)); - } - } - else { - /*printf("Adding tag %s to item %d\n", tag_uid, item->id);*/ - ZnITEM.AddTag(item, tag_uid); - } -} - - -/* - *---------------------------------------------------------------------- - * - * FindArea -- - * Search the items that are enclosed or overlapping a given - * area of the widget. It is used by FindItems. - * If tag_uid is not NULL, all the items found are tagged with - * tag_uid. If tag_uid is NULL, the items found are added to the - * interp result. If enclosed is 1, the search look for - * items enclosed in the area. If enclosed is 0, it looks - * for overlapping and enclosed items. - * If an error occurs, a message is left in the interp result - * and TCL_ERROR is returned. - * - *---------------------------------------------------------------------- - */ -static int -FindArea(ZnWInfo *wi, - Tcl_Obj *CONST args[], - Tk_Uid tag_uid, - ZnBool enclosed, - ZnBool recursive, - ZnBool override_atomic, - ZnItem group) -{ - ZnPos pos; - ZnBBox area; - ZnToAreaStruct ta; - double d; - - if (Tcl_GetDoubleFromObj(wi->interp, args[0], &d) == TCL_ERROR) { - return TCL_ERROR; - } - area.orig.x = d; - if (Tcl_GetDoubleFromObj(wi->interp, args[1], &d) == TCL_ERROR) { - return TCL_ERROR; - } - area.orig.y = d; - if (Tcl_GetDoubleFromObj(wi->interp, args[2], &d) == TCL_ERROR) { - return TCL_ERROR; - } - area.corner.x = d; - if (Tcl_GetDoubleFromObj(wi->interp, args[3], &d) == TCL_ERROR) { - return TCL_ERROR; - } - area.corner.y = d; - if (area.corner.x < area.orig.x) { - pos = area.orig.x; - area.orig.x = area.corner.x; - area.corner.x = pos; - } - if (area.corner.y < area.orig.y) { - pos = area.orig.y; - area.orig.y = area.corner.y; - area.corner.y = pos; - } - area.corner.x += 1; - area.corner.y += 1; - - ta.tag_uid = tag_uid; - ta.enclosed = enclosed; - ta.in_group = group; - ta.recursive = recursive; - ta.override_atomic = override_atomic; - ta.report = False; - ta.area = &area; - wi->top_group->class->ToArea(wi->top_group, &ta); - - return TCL_OK; -} - - -/* - *---------------------------------------------------------------------- - * - * FindItems -- - * - * This procedure interprets the small object query langage for - * commands like addtag and find. - * If new_tag is NULL, the procedure collects all the objects - * matching the request and return them in the interpreter result. - * If new_tag is non NULL, it is interpreted as the tag to add to - * all matching objects. In this case the interpreter result is - * left empty. - * - *---------------------------------------------------------------------- - */ -static int -FindItems(ZnWInfo *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 */ - ZnTagSearch **search_var) -{ - Tk_Uid tag_uid = NULL; - int index, result; - ZnItem item; - ZnPickStruct ps; - char *str; -#ifdef PTK_800 - static char *search_cmd_strings[] = -#else - static CONST char *search_cmd_strings[] = -#endif - { - "above", "ancestors", "atpriority", "below", "closest", "enclosed", - "overlapping", "withtag", "withtype", NULL - }; - enum search_cmds { - ZN_S_ABOVE, ZN_S_ANCESTORS, ZN_S_ATPRIORITY, ZN_S_BELOW, ZN_S_CLOSEST, - ZN_S_ENCLOSED, ZN_S_OVERLAPPING, ZN_S_WITHTAG, ZN_S_WITHTYPE - }; - - if (Tcl_GetIndexFromObj(wi->interp, args[first], search_cmd_strings, - "search command", 0, &index) != TCL_OK) { - return TCL_ERROR; - } - - if (tag) { - tag_uid = Tk_GetUid(Tcl_GetString(tag)); - } - - switch((enum search_cmds) index) { - /* - * above - */ - case ZN_S_ABOVE: - { - if (argc != first+2) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId"); - return TCL_ERROR; - } - result = ZnItemWithTagOrId(wi, args[first+1], &item, search_var); - if (result == TCL_OK) { - if ((item != ZN_NO_ITEM) && (item->previous != ZN_NO_ITEM)) { - ZnDoItem(wi->interp, item->previous, ZN_NO_PART, tag_uid); - } - } - else { - return TCL_ERROR; - } - } - break; - /* - * ancestors - */ - case ZN_S_ANCESTORS: - { - Tk_Uid uid = NULL; - if ((argc != first+2) && (argc != first+3)) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId ?withTag?"); - return TCL_ERROR; - } - result = ZnItemWithTagOrId(wi, args[first+1], &item, search_var); - if (result == TCL_ERROR) { - return TCL_ERROR; - } - if (item) { - item = item->parent; - if (argc == first+3) { - uid = Tk_GetUid(Tcl_GetString(args[first+2])); - } - while (item != ZN_NO_ITEM) { - if (!uid || ZnITEM.HasTag(item, uid)) { - ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid); - } - item = item->parent; - } - } - } - break; - /* - * atpriority - */ - case ZN_S_ATPRIORITY: - { - int pri; - - if ((argc != first+2) && (argc != first+3)) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "pri ?tagOrId?"); - return TCL_ERROR; - } - if ((Tcl_GetIntFromObj(wi->interp, args[first+1], &pri) == TCL_ERROR) || - (pri < 0)){ - return TCL_ERROR; - } - - /* - * Go through the item table and collect all items with - * the given priority. - */ - if (ZnTagSearchScan(wi, (argc == first+3) ? args[first+2] : NULL, - search_var) == TCL_ERROR) { - return TCL_ERROR; - } - for (item = ZnTagSearchFirst(*search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) { - if (item->priority == (unsigned int) pri) { - ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid); - } - } - } - break; - /* - * below - */ - case ZN_S_BELOW: - { - ZnItem next; - - if (argc != first+2) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId"); - return TCL_ERROR; - } - item = ZN_NO_ITEM; - if (ZnTagSearchScan(wi, args[first+1], search_var) == TCL_ERROR) { - return TCL_ERROR; - } - 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)) { - ZnDoItem(wi->interp, item->next, ZN_NO_PART, tag_uid); - } - } - break; - /* - * closest - */ - case ZN_S_CLOSEST: - { - int halo = 1; - ZnPoint p; - double d; - - if ((argc < first+3) || (argc > first+6)) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "x y ?halo? ?start?, ?recursive?"); - return TCL_ERROR; - } - if (Tcl_GetDoubleFromObj(wi->interp, args[first+1], &d) == TCL_ERROR) { - return TCL_ERROR; - } - p.x = d; - if (Tcl_GetDoubleFromObj(wi->interp, args[first+2], &d) == TCL_ERROR) { - return TCL_ERROR; - } - p.y = d; - if (argc > first+3) { - if (Tcl_GetIntFromObj(wi->interp, args[first+3], &halo) == TCL_ERROR) { - return TCL_ERROR; - } - if (halo < 0) { - halo = 0; - } - } - - ps.in_group = ZN_NO_ITEM; - ps.start_item = ZN_NO_ITEM; - item = ZN_NO_ITEM; - if (argc > (first+4)) { - result = ZnItemWithTagOrId(wi, args[first+4], &item, search_var); - if ((result == TCL_OK) && (item != ZN_NO_ITEM)) { - if ((item->class == ZnGroup) && !ZnGroupAtomic(item)) { - ps.in_group = item; - } - else { - ps.in_group = item->parent; - ps.start_item = item->next; - } - } - } - ps.recursive = True; - ps.override_atomic = False; - if (argc > first+5) { - result = Tcl_GetBooleanFromObj(wi->interp, args[first+5], &ps.recursive); - if (result != TCL_OK) { - str = Tcl_GetString(args[first+5]); - if (strcmp(str, "override") != 0) { - Tcl_AppendResult(wi->interp, - "recursive should be a boolean value or ", - "override \"", str, "\"", NULL); - return TCL_ERROR; - } - ps.recursive = True; - ps.override_atomic = True; - } - } - /* - * 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. - */ - ps.aperture = halo; - ps.point = &p; - wi->top_group->class->Pick(wi->top_group, &ps); - - if (ps.a_item != ZN_NO_ITEM) { - ZnDoItem(wi->interp, ps.a_item, ps.a_part, tag_uid); - /*printf("first %d %d\n", ps.a_item->id, ps.a_part);*/ - } - } - break; - /* - * enclosed - */ - case ZN_S_ENCLOSED: - { - if ((argc < first+5) || (argc > first+7)) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "x1 y1 x2 y2 ?inGroup? ?recursive?"); - return TCL_ERROR; - } - item = wi->top_group; - if (argc > first+5) { - result = ZnItemWithTagOrId(wi, args[first+5], &item, search_var); - if ((result != TCL_OK) || (item == ZN_NO_ITEM) || (item->class != ZnGroup)) { - return TCL_ERROR; - } - } - ps.recursive = True; - ps.override_atomic = False; - if (argc > first+6) { - result = Tcl_GetBooleanFromObj(wi->interp, args[first+6], &ps.recursive); - if (result != TCL_OK) { - str = Tcl_GetString(args[first+6]); - if (strcmp(str, "override") != 0) { - Tcl_AppendResult(wi->interp, - "recursive should be a boolean value or ", - "override \"", str, "\"", NULL); - return TCL_ERROR; - } - ps.recursive = True; - ps.override_atomic = True; - } - } - return FindArea(wi, args+first+1, tag_uid, - True, ps.recursive, ps.override_atomic, - item); - } - break; - /* - * overlapping - */ - case ZN_S_OVERLAPPING: - { - if ((argc < first+5) || (argc > first+7)) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "x1 y1 x2 y2 ?inGroup? ?recursive?"); - return TCL_ERROR; - } - item = wi->top_group; - if (argc > first+5) { - result = ZnItemWithTagOrId(wi, args[first+5], &item, search_var); - if ((result != TCL_OK) || (item == ZN_NO_ITEM) || (item->class != ZnGroup)) { - return TCL_ERROR; - } - } - ps.recursive = True; - ps.override_atomic = False; - if (argc > first+6) { - result = Tcl_GetBooleanFromObj(wi->interp, args[first+6], &ps.recursive); - if (result != TCL_OK) { - str = Tcl_GetString(args[first+6]); - if (strcmp(str, "override") != 0) { - Tcl_AppendResult(wi->interp, - "recursive should be a boolean value or ", - "override \"", str, "\"", NULL); - return TCL_ERROR; - } - ps.recursive = True; - ps.override_atomic = True; - } - } - return FindArea(wi, args+first+1, tag_uid, - False, ps.recursive, ps.override_atomic, - item); - } - break; - /* - * withtag - */ - case ZN_S_WITHTAG: - { - if (argc != first+2) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId"); - return TCL_ERROR; - } - if (ZnTagSearchScan(wi, args[first+1], search_var) == TCL_ERROR) { - return TCL_ERROR; - } - for (item = ZnTagSearchFirst(*search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) { - ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid); - } - } - break; - /* - * withtype - */ - case ZN_S_WITHTYPE: - { - ZnItemClass cls; - - if ((argc != first+2) && (argc != first+3)) { - Tcl_WrongNumArgs(wi->interp, first+1, args, "itemType ?tagOrId?"); - return TCL_ERROR; - } - cls = ZnLookupItemClass(Tcl_GetString(args[first+1])); - if (!cls) { - Tcl_AppendResult(wi->interp, "unknown item type \"", - Tcl_GetString(args[first+1]), "\"", NULL); - return TCL_ERROR; - } - - /* - * Go through the item table and collect all items with - * the given item type. - */ - if (ZnTagSearchScan(wi, (argc == first+3) ? args[first+2] : NULL, - search_var) == TCL_ERROR) { - return TCL_ERROR; - } - for (item = ZnTagSearchFirst(*search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) { - if (item->class == cls) { - ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid); - } - } - } - break; - } - - return TCL_OK; -} - - -/* - *---------------------------------------------------------------------- - * - * ZnParseCoordList -- - * - *---------------------------------------------------------------------- - */ -int -ZnParseCoordList(ZnWInfo *wi, - Tcl_Obj *arg, - ZnPoint **pts, - char **controls, - unsigned int *num_pts, - ZnBool *old_format) -{ - Tcl_Obj **elems, **selems; - int i, result, num_elems, num_selems; - ZnPoint *p; - int old_style, len; - char *str; - double d; - - if (controls) { - *controls = NULL; - } - if (old_format) { - *old_format = True; - } - result = Tcl_ListObjGetElements(wi->interp, arg, &num_elems, &elems); - if (result == TCL_ERROR) { - coord_error: - Tcl_AppendResult(wi->interp, " malformed coord list", NULL); - return TCL_ERROR; - } - if (num_elems == 0) { - *num_pts = 0; - *pts = NULL; - return TCL_OK; - } - - /* - * If first element is not a sublist, consider the whole list - * as a flat array of coordinates in the old style. It can still - * be a single point with or without a control flag. - * If not, the list consists in sublists describing each point - * with its control flag. - */ - result = Tcl_GetDoubleFromObj(wi->interp, elems[0], &d); - old_style = (result == TCL_OK); - - if (old_style) { - if ((num_elems%2) == 0) { - *num_pts = num_elems/2; - ZnListAssertSize(ZnWorkPoints, *num_pts); - *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints); - for (i = 0; i < num_elems; i += 2, p++) { - if (Tcl_GetDoubleFromObj(wi->interp, elems[i], &d) == TCL_ERROR) { - goto coord_error; - } - p->x = d; - if (Tcl_GetDoubleFromObj(wi->interp, elems[i+1], &d) == TCL_ERROR) { - goto coord_error; - } - p->y = d; - /*printf("Parsed a point: %g@%g, ", p->x, p->y);*/ - } - /*printf("\n");*/ - } - else if (num_elems == 3) { - *num_pts = 1; - ZnListAssertSize(ZnWorkPoints, *num_pts); - *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints); - if (Tcl_GetDoubleFromObj(wi->interp, elems[0], &d) == TCL_ERROR) { - goto coord_error; - } - p->x = d; - if (Tcl_GetDoubleFromObj(wi->interp, elems[1], &d) == TCL_ERROR) { - goto coord_error; - } - p->y = d; - if (controls) { - if (! *controls) { - *controls = ZnMalloc(*num_pts * sizeof(char)); - memset(*controls, 0, *num_pts * sizeof(char)); - } - str = Tcl_GetStringFromObj(elems[2], &len); - if (len) { - (*controls)[0] = str[0]; - } - } - } - else { - goto coord_error; - } - } - else { - Tcl_ResetResult(wi->interp); - *num_pts = num_elems; - ZnListAssertSize(ZnWorkPoints, *num_pts); - *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints); - for (i = 0; i < num_elems; i++, p++) { - result = Tcl_ListObjGetElements(wi->interp, elems[i], &num_selems, &selems); - if ((result == TCL_ERROR) || (num_selems < 2) || (num_selems > 3)) { - goto coord_error; - } - if (Tcl_GetDoubleFromObj(wi->interp, selems[0], &d) == TCL_ERROR) { - goto coord_error; - } - p->x = d; - if (Tcl_GetDoubleFromObj(wi->interp, selems[1], &d) == TCL_ERROR) { - goto coord_error; - } - p->y = d; - if (controls) { - if (num_selems == 3) { - if (! *controls) { - *controls = ZnMalloc(*num_pts * sizeof(char)); - memset(*controls, 0, *num_pts * sizeof(char)); - } - str = Tcl_GetStringFromObj(selems[2], &len); - if (len) { - (*controls)[i] = str[0]; - } - } - } - } - } - - if (old_format) { - *old_format = old_style; - } - return TCL_OK; -} - - -/* - *---------------------------------------------------------------------- - * - * Contour -- - * - *---------------------------------------------------------------------- - */ -static int -Contour(ZnWInfo *wi, - int argc, - Tcl_Obj *CONST args[], - ZnTagSearch **search_var) -{ - ZnPoint *points; - ZnItem item, shape; - unsigned int i, j, k,num_points; - int cmd, cw, result; - int winding_flag, revert = False; - long index; - char *controls; - ZnBool simple=False; - ZnPoly poly; - ZnTransfo t, inv; - ZnContour *contours; - - /* Keep this array in sync with ZnContourCmd in Types.h */ -#ifdef PTK_800 - static char *op_strings[] = -#else - static CONST char *op_strings[] = -#endif - { - "add", "remove", NULL - }; - - result = ZnItemWithTagOrId(wi, args[2], &item, search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)){ - Tcl_AppendResult(wi->interp, "unknown item \"", Tcl_GetString(args[2]), - "\"", NULL); - return TCL_ERROR; - } - if (!item->class->Contour) { - if (item->class->GetClipVertices || - item->class->GetContours) { - Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(1)); - } - else { - Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(0)); - } - return TCL_OK; - } - if (argc == 3) { - /* - * Requesting the number of contours. - */ - Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(item->class->Contour(item, -1, 0, NULL))); - return TCL_OK; - } - /* - * Get the sub-command - */ - if (Tcl_GetIndexFromObj(wi->interp, args[3], op_strings, - "contour operation", 0, &cmd) != TCL_OK) { - return TCL_ERROR; - } - /* - * Get the winding flag. - */ - if ((Tcl_GetIntFromObj(wi->interp, args[4], &winding_flag) != TCL_OK) || - (winding_flag < -1) || (winding_flag > 1)) { - Tcl_AppendResult(wi->interp, " incorrect winding flag, should be -1, 0, 1, \"", - Tcl_GetString(args[4]), "\"", NULL); - return TCL_ERROR; - } - index = ZnListTail; - if (((argc == 6) && (cmd == ZN_CONTOUR_REMOVE)) || (argc == 7)) { - /* Look for an index value. */ - if (Tcl_GetLongFromObj(wi->interp, args[5], &index) != TCL_OK) { - Tcl_AppendResult(wi->interp, " incorrect contour index \"", - Tcl_GetString(args[5]), "\"", NULL); - return TCL_ERROR; - } - argc--; - args++; - } - - if (cmd == ZN_CONTOUR_REMOVE) { - Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(item->class->Contour(item, ZN_CONTOUR_REMOVE, index, NULL))); - } - else { - result = ZnItemWithTagOrId(wi, args[5], &shape, search_var); - if ((result == TCL_ERROR) || (shape == ZN_NO_ITEM)) { - Tcl_ResetResult(wi->interp); - if (ZnParseCoordList(wi, args[5], &points, - &controls, &num_points, NULL) == TCL_ERROR) { - return TCL_ERROR; - } - /* - * Processing contours from an explicit list. - */ - ZnPolyContour1(&poly, NULL, num_points, False); - /* - * Allocate a fresh point array, ZnParseCoordList returns a shared - * array. The control array is not shared and can be passed along. - */ - poly.contours[0].points = ZnMalloc(num_points*sizeof(ZnPoint)); - cw = poly.contours[0].cw = !ZnTestCCW(points, num_points); - if (winding_flag != 0) { - revert = cw ^ (winding_flag == -1); - } - if (revert) { - /* Revert the contour */ - for (i = 0; i < num_points; i++) { - poly.contours[0].points[num_points-i-1] = points[i]; - } - if (controls) { - char ch; - for (i = 0, j = num_points-1; i < j; i++, j--) { - ch = controls[i]; - controls[i] = controls[j]; - controls[j] = ch; - } - } - } - else { - memcpy(poly.contours[0].points, points, num_points*sizeof(ZnPoint)); - } - poly.contours[0].controls = controls; - } - else { - /* - * Processing contours from an item - */ - if (winding_flag == 0) { - Tcl_AppendResult(wi->interp, - "Must supply an explicit winding direction (-1, 1)\nwhen adding a contour from an item", - NULL); - return TCL_ERROR; - } - /* - * If something has changed in the geometry we need to - * update or the shape will be erroneous. - */ - Update(wi); - if (!shape->class->GetContours && - !shape->class->GetClipVertices) { - Tcl_AppendResult(wi->interp, "class: \"", shape->class->name, - "\" can't give a polygonal shape", NULL); - return TCL_ERROR; - } - if (!shape->class->GetContours) { - ZnTriStrip tristrip; - /* - * If there is no GetContours method try to use - * the GetClipVertices. It works only for simple - * shapes (i.e tose returning a bounding box). - */ - tristrip.num_strips = 0; - /* - * GetClipVertices _may_ return a tristrip describing a fan - * this would lead to strange results. For now, this case - * should not appear, the items candidates to such a behavior - * export a GetContours method which has higher precedence. - */ - simple = shape->class->GetClipVertices(shape, &tristrip); - ZnPolyContour1(&poly, tristrip.strip1.points, tristrip.strip1.num_points, - False); - poly.contours[0].controls = NULL; - } - else { - poly.num_contours = 0; - simple = shape->class->GetContours(shape, &poly); - } - if (poly.num_contours == 0) { - return TCL_OK; - } - /* - * Compute the tranform to map the device points - * into the coordinate space of item. - */ - ZnITEM.GetItemTransform(item, &t); - ZnTransfoInvert(&t, &inv); - /* - * Make a new transformed poly and unshare - * the contour(s) returned by the item. - */ - if (simple) { - ZnPoint p[4]; - p[0] = poly.contours[0].points[0]; - p[2] = poly.contours[0].points[1]; - if (winding_flag == -1) { - p[1].x = p[2].x; - p[1].y = p[0].y; - p[3].x = p[0].x; - p[3].y = p[2].y; - } - else { - p[1].x = p[0].x; - p[1].y = p[2].y; - p[3].x = p[2].x; - p[3].y = p[0].y; - } - points = ZnMalloc(4*sizeof(ZnPoint)); - ZnTransformPoints(&inv, p, points, 4); - poly.contours[0].points = points; - poly.contours[0].num_points = 4; - poly.contours[0].cw = (winding_flag == -1); - poly.contours[0].controls = NULL; - } - else { - /* Unshare the contour array or use the static storage */ - contours = poly.contours; - if (poly.num_contours == 1) { - poly.contours = &poly.contour1; - } - else { - poly.contours = ZnMalloc(poly.num_contours*sizeof(ZnContour)); - } - for (i = 0; i < poly.num_contours; i++) { - points = contours[i].points; - num_points = contours[i].num_points; - cw = contours[i].cw; - poly.contours[i].num_points = num_points; - poly.contours[i].cw = cw; - if (contours[i].controls) { - /* - * The controls array returned by GetContour is shared. - * Here we unshare it. - */ - poly.contours[i].controls = ZnMalloc(num_points*sizeof(char)); - } - /* - * Unshare the point array. - */ - poly.contours[i].points = ZnMalloc(num_points*sizeof(ZnPoint)); - ZnTransformPoints(&inv, points, poly.contours[i].points, num_points); - - if ((((poly.num_contours == 1) && ((winding_flag == -1) ^ cw)) || - ((poly.num_contours > 1) && (winding_flag == -1)))) { - ZnPoint p; - - revert = True; - /* Revert the points */ - poly.contours[i].cw = ! cw; - for (j = 0, k = num_points-1; j < k; j++, k--) { - p = poly.contours[i].points[j]; - poly.contours[i].points[j] = poly.contours[i].points[k]; - poly.contours[i].points[k] = p; - } - - /* Revert the controls */ - if (contours[i].controls) { - for (j = 0; j < num_points; j++) { - poly.contours[i].controls[num_points-j-1] = contours[i].controls[j]; - } - } - } - else { - if (contours[i].controls) { - memcpy(poly.contours[i].controls, contours[i].controls, num_points); - } - } - } - } - } - - result = item->class->Contour(item, ZN_CONTOUR_ADD, index, &poly); - if (revert) { - result = -result; - } - Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(result)); - - if (poly.contours != &poly.contour1) { - /* - * Must not use ZnPolyFree: the point and controls arrays - * are passed along to the item and no longer ours. - */ - ZnFree(poly.contours); - } - } - - return TCL_OK; -} - - -/* - *---------------------------------------------------------------------- - * - * Coords -- - * - *---------------------------------------------------------------------- - */ -static int -Coords(ZnWInfo *wi, - int argc, - Tcl_Obj *CONST args[], - ZnTagSearch **search_var) -{ - ZnPoint *points; - ZnItem item; - unsigned int num_points, i; - int result, cmd = ZN_COORDS_READ; - long index, contour = 0; - char *str, *controls = NULL; - Tcl_Obj *l, *entries[3]; - - result = ZnItemWithTagOrId(wi, args[2], &item, search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - Tcl_AppendResult(wi->interp, " unknown item \"", - Tcl_GetString(args[2]), "\"", NULL); - return TCL_ERROR; - } - if (!item->class->Coords) { - Tcl_AppendResult(wi->interp, " ", item->class->name, - " does not support the coords command", NULL); - return TCL_ERROR; - } - num_points = 0; - /*printf(" coords: argc=%d, item %d class: %s\n", - argc, item->id, item->class->name);*/ - if (argc == 3) { - /* Get all coords of default contour (0). */ - if (item->class->Coords(item, 0, 0, ZN_COORDS_READ_ALL, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - coords_read: - /*printf(" coords: read %d points, first is %g@%g\n", - num_points, points->x, points->y);*/ - l = Tcl_GetObjResult(wi->interp); - if (ISSET(item->class->flags, ZN_CLASS_ONE_COORD)) { - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->x)); - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->y)); - if (controls && *controls) { - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewStringObj(controls, 1)); - } - } - else { - for (i = 0; i < num_points; i++, points++) { - entries[0] = Tcl_NewDoubleObj(points->x); - entries[1] = Tcl_NewDoubleObj(points->y); - if (controls && controls[i]) { - entries[2] = Tcl_NewStringObj(&controls[i], 1); - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewListObj(3, entries)); - } - else { - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewListObj(2, entries)); - } - } - } - return TCL_OK; - } - - /* - * See if it is an ADD or REMOVE op. - */ - i = 3; - str = Tcl_GetString(args[3]); - if ((str[0] == 'a') && (strcmp(str, "add") == 0)) { - if ((argc < 5) || (argc > 7)) { - Tcl_WrongNumArgs(wi->interp, 1, args, - "coords tagOrId add ?contour? ?index? coordList"); - return TCL_ERROR; - } - cmd = ZN_COORDS_ADD; - i++; - } - else if ((str[0] == 'r') && (strcmp(str, "remove") == 0)) { - if ((argc != 5) && (argc != 6)) { - Tcl_WrongNumArgs(wi->interp, 1, args, - "coords tagOrId remove ?contour? index"); - return TCL_ERROR; - } - cmd = ZN_COORDS_REMOVE; - i++; - } - - /* - * Try to see if the next param is a vertex index, - * a contour index or a coord list. - */ - /* printf(" coords: arg %d is %s\n", i, Tcl_GetString(args[i])); */ - if (Tcl_GetLongFromObj(wi->interp, args[i], &index) != TCL_OK) { - Tcl_ResetResult(wi->interp); - if (((argc == 5) && (cmd != ZN_COORDS_ADD) && (cmd != ZN_COORDS_REMOVE)) || - (argc == 6) || (argc == 7)) { - Tcl_AppendResult(wi->interp, " incorrect contour index \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - else if ((argc == 5) && (cmd != ZN_COORDS_ADD)) { - Tcl_AppendResult(wi->interp, " incorrect coord index \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - else if (ZnParseCoordList(wi, args[argc-1], &points, - &controls, &num_points, NULL) == TCL_ERROR) { - return TCL_ERROR; - } - if (cmd == ZN_COORDS_ADD) { - /* Append coords at end of default contour (0). */ - if (item->class->Coords(item, 0, 0, ZN_COORDS_ADD_LAST, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - } - else { - /* Set all coords of default contour (0). */ - if (item->class->Coords(item, 0, 0, ZN_COORDS_REPLACE_ALL, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - } - if (controls) { - ZnFree(controls); - } - return TCL_OK; - } - - contour = index; - if (argc == 4) { - /* Get all coords of contour. */ - if (item->class->Coords(item, contour, 0, ZN_COORDS_READ_ALL, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - goto coords_read; - } - else if ((argc == 5) && (cmd == ZN_COORDS_REMOVE)) { - /* Remove coord at index in default contour (0). */ - if (item->class->Coords(item, 0, index, ZN_COORDS_REMOVE, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - return TCL_OK; - } - /* - * Try to see if the next param is a vertex index or a coord list. - */ - i++; - /*printf(" coords: arg %d is %s\n", i, Tcl_GetString(args[i]));*/ - if (Tcl_GetLongFromObj(wi->interp, args[i], &index) != TCL_OK) { - Tcl_ResetResult(wi->interp); - if ((argc == 7) || ((argc == 6) && (cmd != ZN_COORDS_ADD))) { - Tcl_AppendResult(wi->interp, " incorrect coord index \"", - Tcl_GetString(args[i]), "\"", NULL); - return TCL_ERROR; - } - else if (ZnParseCoordList(wi, args[argc-1], &points, - &controls, &num_points, NULL) == TCL_ERROR) { - return TCL_ERROR; - } - if (cmd == ZN_COORDS_ADD) { - /* Append coords at end of contour. */ - if (item->class->Coords(item, contour, 0, ZN_COORDS_ADD_LAST, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - } - else { - /* Set all coords of contour. */ - if (item->class->Coords(item, contour, 0, ZN_COORDS_REPLACE_ALL, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - } - if (controls) { - ZnFree(controls); - } - return TCL_OK; - } - if (argc == 5) { - /* Get coord of contour at index. */ - if (item->class->Coords(item, contour, index, ZN_COORDS_READ, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - if (num_points) { - /*printf(" coords: read contour:%d, index:%d, point is %g@%g\n", - contour, index, points->x, points->y); */ - l = Tcl_GetObjResult(wi->interp); - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->x)); - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->y)); - if (controls && *controls) { - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewStringObj(controls, 1)); - } - } - return TCL_OK; - } - else if ((argc == 6) && (cmd == ZN_COORDS_REMOVE)) { - /* Remove coord of contour at index. */ - if (item->class->Coords(item, contour, index, ZN_COORDS_REMOVE, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - return TCL_OK; - } - - /* Set a single coord or add coords at index in contour. */ - if (ZnParseCoordList(wi, args[argc-1], &points, - &controls, &num_points, NULL) == TCL_ERROR) { - return TCL_ERROR; - } - if (argc == 6) { - num_points = 1; - cmd = ZN_COORDS_REPLACE; - } - if (item->class->Coords(item, contour, index, cmd, - &points, &controls, &num_points) == TCL_ERROR) { - return TCL_ERROR; - } - if (controls) { - ZnFree(controls); - } - return TCL_OK; -} - - -/* - *---------------------------------------------------------------------- - * - * WidgetObjCmd -- - * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * See the user documentation. - * - *---------------------------------------------------------------------- - */ -static int -WidgetObjCmd(ClientData client_data, /* Information about the widget. */ - Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - Tcl_Obj *CONST args[]) /* Arguments. */ -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - int length, result, cmd_index, index; - ZnItem item, item2; - int field = ZN_NO_PART; - unsigned int num = 0, i, j; - char *end, *str; - ZnTransfo *t = NULL; - Tcl_Obj *l; - ZnTagSearch *search_var = NULL; - Tcl_HashEntry *entry; - ZnPoint *points; - ZnPoint p; - unsigned int num_points; - ZnList to_points; - Tcl_Obj *entries[3]; - char c[] = "c"; - double d; - -#ifdef PTK_800 - static char *sub_cmd_strings[] = -#else - static CONST char *sub_cmd_strings[] = -#endif - { - "add", "addtag", "anchorxy", "bbox", "becomes", "bind", - "cget", "chggroup", "clone", "configure", "contour", - "coords", "currentpart", "cursor", "dchars", - "dtag", "find", "fit", "focus", "gdelete", - "gettags", "gname", "group", "hasanchors", "hasfields", - "hastag", "index", "insert", "itemcget", "itemconfigure", - "layout", "lower", "monitor", "numparts", "postscript", - "raise", "remove", "rotate", "scale", "select", "skew", - "smooth", "tapply", "tcompose", "tdelete", "tget", - "transform", "translate", "treset", "trestore", "tsave", - "tset", "type", "vertexat", "xview", "yview", 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_GDELETE, - ZN_W_GETTAGS, ZN_W_GNAME, 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_LAYOUT, 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_SKEW, - ZN_W_SMOOTH, ZN_W_TAPPLY, ZN_W_TCOMPOSE, ZN_W_TDELETE, ZN_W_TGET, - ZN_W_TRANSFORM, ZN_W_TRANSLATE, ZN_W_TRESET, ZN_W_TRESTORE, ZN_W_TSAVE, - ZN_W_TSET, ZN_W_TYPE, ZN_W_VERTEX_AT, ZN_W_XVIEW, ZN_W_YVIEW - }; -#ifdef PTK_800 - static char *sel_cmd_strings[] = -#else - static CONST char *sel_cmd_strings[] = -#endif - { - "adjust", "clear", "from", "item", "to", NULL - }; - enum sel_cmds { - ZN_SEL_ADJUST, ZN_SEL_CLEAR, ZN_SEL_FROM, ZN_SEL_ITEM, ZN_SEL_TO - }; - - - if (argc < 2) { - Tcl_WrongNumArgs(interp, 1, args, "subcommand ?args?"); - return TCL_ERROR; - } - - Tcl_Preserve((ClientData) wi); - - if (Tcl_GetIndexFromObj(interp, args[1], sub_cmd_strings, - "subcommand", 0, &cmd_index) != TCL_OK) { - goto error; - } - result = TCL_OK; - - /*printf("executing command \"%s\", argc=%d\n", - Tcl_GetString(args[1]), argc);*/ - switch((enum sub_cmds) cmd_index) { - /* - * add - */ - case ZN_W_ADD: - { - ZnItem group; - ZnItemClass cls; - - if (argc == 2) { /* create subcommand alone, return the list of known - * object types. */ - ZnItemClass *classes = ZnListArray(ZnItemClassList()); - - num = ZnListSize(ZnItemClassList()); - l = Tcl_GetObjResult(interp); - for (i = 0; i < num; i++) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(classes[i]->name, -1)); - } - goto done; - } - if ((argc < 4)) { - add_err: - Tcl_WrongNumArgs(interp, 1, args, "add type group ?args?"); - goto error; - } - str = Tcl_GetString(args[2]); - if (str[0] == '-') { - goto add_err; - } - cls = ZnLookupItemClass(str); - if (!cls) { - Tcl_AppendResult(interp, "unknown item type \"", str, "\"", NULL); - goto error; - } - result = ZnItemWithTagOrId(wi, args[3], &group, &search_var); - if ((result == TCL_ERROR) || (group == ZN_NO_ITEM) || - (group->class != ZnGroup)) { - Tcl_AppendResult(interp, ", group item expected, got \"", - Tcl_GetString(args[3]), "\"", NULL); - goto error; - } - - argc -= 4; - args += 4; - item = ZnCreateItem(wi, cls, &argc, &args); - if (item == ZN_NO_ITEM) { - goto error; - } - ZnITEM.InsertItem(item, group, ZN_NO_ITEM, True); - if (ZnITEM.ConfigureItem(item, ZN_NO_PART, argc, args, True) == TCL_ERROR) { - goto error; - } - wi->hot_item = item; - wi->hot_prev = item->previous; - l = Tcl_NewLongObj(item->id); - Tcl_SetObjResult(interp, l); - } - break; - /* - * addtag - */ - case ZN_W_ADDTAG: - { - if (argc < 4) { - Tcl_WrongNumArgs(interp, 1, args, "addtag tag searchCommand ?arg arg ...?"); - goto error; - } - result = FindItems(wi, argc, args, args[2], 3, &search_var); - } - break; - /* - * anchorxy - */ - case ZN_W_ANCHORXY: - { - Tk_Anchor anchor; - - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "anchorxy tagOrId anchor"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM) || - ISCLEAR(item->class->flags, ZN_CLASS_HAS_ANCHORS)) { - Tcl_AppendResult(interp, "unknown item or doesn't support anchors \"", - Tcl_GetString(args[2]), NULL); - goto error; - } - if (Tk_GetAnchor(interp, Tcl_GetString(args[3]), &anchor)) { - goto error; - } - /* - * If something has changed in the geometry we need to - * update or the anchor location will be erroneous. - */ - Update(wi); - item->class->GetAnchor(item, anchor, &p); - l = Tcl_GetObjResult(wi->interp); - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(p.x)); - Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(p.y)); - } - break; - /* - * becomes - */ - case ZN_W_BECOMES: - { - Tcl_AppendResult(interp, "Command not yet implemented", NULL); - goto error; - } - break; - /* - * bbox - */ - case ZN_W_BBOX: - { - ZnBBox bbox; - ZnDim width, height; - ZnFieldSet fs; - - if (argc < 3) { - Tcl_WrongNumArgs(interp, 1, args, "bbox ?-field fieldNo? ?-label? tagOrId ?tagOrId ...?"); - goto error; - } - argc -= 2; - args += 2; - - Update(wi); - ZnResetBBox(&bbox); - - str = Tcl_GetString(args[0]); - if (*str == '-') { - if ((strcmp(str, "-field") == 0) && (argc > 2)) { - if (Tcl_GetIntFromObj(wi->interp, args[1], &field) == TCL_ERROR) { - goto error; - } - argc -= 2; - args += 2; - } - else if ((strcmp(str, "-label") == 0) && (argc > 1)) { - field = -1; - argc--; - args++; - } - else { - Tcl_AppendResult(interp, "bbox option should be -field numField or -label", - NULL); - goto error; - } - result = ZnItemWithTagOrId(wi, args[0], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM) || - ! item->class->GetFieldSet) { - Tcl_AppendResult(interp, "unknown item or doesn't support fields \"", - Tcl_GetString(args[0]), "\"", NULL); - goto error; - } - fs = item->class->GetFieldSet(item); - if (field >= 0) { - if ((unsigned int) field >= fs->num_fields) { - Tcl_AppendResult(interp, "field index is out of bounds", NULL); - goto error; - } - ZnFIELD.GetFieldBBox(fs, field, &bbox); - } - else { - ZnFIELD.GetLabelBBox(fs, &width, &height); - if (width && height) { - p.x = ZnNearestInt(fs->label_pos.x); - p.y = ZnNearestInt(fs->label_pos.y); - ZnAddPointToBBox(&bbox, p.x, p.y); - p.x += width; - p.y += height; - ZnAddPointToBBox(&bbox, p.x, p.y); - } - } - } - else { - for (i = 0; i < (unsigned int) argc; i++) { - /* - * Check for options in wrong place amidst tags. - */ - str = Tcl_GetString(args[i]); - if (*str == '-') { - Tcl_AppendResult(interp, "bbox options should be specified before any tag", NULL); - goto error; - } - if (ZnTagSearchScan(wi, args[i], &search_var) == TCL_ERROR) { - goto error; - } - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - ZnAddBBoxToBBox(&bbox, &item->item_bounding_box); - } - } - } - - if (!ZnIsEmptyBBox(&bbox)) { - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.orig.x)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.orig.y)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.corner.x)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.corner.y)); - } - } - break; - /* - * bind - */ - case ZN_W_BIND: - { - ClientData elem = 0; - int part = ZN_NO_PART; - - if ((argc < 3) || (argc > 6)) { - Tcl_WrongNumArgs(interp, 1, args, - "bind tagOrId ?part? ?sequence? ?command?"); - goto error; - } - /* - * Test if (a) an itemid or (b) an itemid:part or - * (c) an item part or (d) a tag is provided. - */ - str = Tcl_GetString(args[2]); - - argc -= 3; - args += 3; - - if (isdigit(str[0])) { - int id; - - id = strtoul(str, &end, 0); - if ((*end != 0) && (*end != ':')) { - goto bind_a_tag; - } - entry = Tcl_FindHashEntry(wi->id_table, (char *) id); - if (entry == NULL) { - Tcl_AppendResult(interp, "item \"", str, "\" doesn't exist", NULL); - goto error; - } - item = elem = Tcl_GetHashValue(entry); - if (!elem) { - goto error; - } - - if (*end == ':') { - /* - * The part is provided with the id (old method). - */ - end++; - part_encode: - if (item->class->Part) { - l = Tcl_NewStringObj(end, -1); - if (item->class->Part(item, &l, &part) == TCL_ERROR) { - goto error; - } - elem = EncodeItemPart(item, part); - } - else { - Tcl_AppendResult(interp, "item \"", str, "\" doesn't have parts", NULL); - goto error; - } - } - else { - /* - * Check if a part is given in the next parameter - * (alternative method for providing a part). - */ - if (argc > 3) { - str = Tcl_GetString(args[0]); - if (str[0] != '<') { - end = str; - argc--; - args++; - goto part_encode; - } - } - } - /*printf("adding element 0x%X to the binding table of item 0x%X\n", elem, item);*/ - } - else { - bind_a_tag: - elem = (ClientData) Tk_GetUid(str); - } - - /* - * Make a binding table if the widget doesn't already have one. - */ - if (wi->binding_table == NULL) { - wi->binding_table = Tk_CreateBindingTable(interp); - } - - if (argc == 2) { - int append = 0; - unsigned long mask; - - str = Tcl_GetString(args[1]); - if (str[0] == 0) { - result = Tk_DeleteBinding(interp, wi->binding_table, elem, - Tcl_GetString(args[0])); - goto done; - } -#ifdef PTK - mask = Tk_CreateBinding(interp, wi->binding_table, - elem, Tcl_GetString(args[0]), args[1], append); -#else - if (str[0] == '+') { - str++; - append = 1; - } - mask = Tk_CreateBinding(interp, wi->binding_table, - elem, Tcl_GetString(args[0]), str, append); -#endif - if (mask == 0) { - goto error; - } - if (mask & (unsigned) ~(ButtonMotionMask | Button1MotionMask | - Button2MotionMask | Button3MotionMask | - Button4MotionMask | Button5MotionMask | - ButtonPressMask | ButtonReleaseMask | - EnterWindowMask | LeaveWindowMask | - KeyPressMask | KeyReleaseMask | - PointerMotionMask | VirtualEventMask)) { - Tk_DeleteBinding(interp, wi->binding_table, elem, Tcl_GetString(args[3])); - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "requested illegal events; ", - "only key, button, motion, enter, leave ", - "and virtual events may be used", NULL); - goto error; - } - } - else if (argc == 1) { -#ifdef PTK - Tcl_Obj *command; - command = Tk_GetBinding(interp, wi->binding_table, elem, - Tcl_GetString(args[0])); - if (command == NULL) { - char *string = Tcl_GetString(Tcl_GetObjResult(interp)); - /* - * Ignore missing binding errors. This is a special hack - * that relies on the error message returned by FindSequence - * in tkBind.c. - */ - if (string[0] != '\0') { - goto error; - } - else { - Tcl_ResetResult(interp); - } - } - else { - Tcl_SetObjResult(interp, command); - } -#else - CONST char *command; - command = Tk_GetBinding(interp, wi->binding_table, elem, - Tcl_GetString(args[0])); - if (command == NULL) { - goto error; - } - Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1)); -#endif - } - else { - Tk_GetAllBindings(interp, wi->binding_table, elem); - } - } - break; - /* - * cget - */ - case ZN_W_CGET: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "cget option"); - goto error; - } -#ifdef PTK_800 - result = Tk_ConfigureValue(interp, wi->win, config_specs, - (char *) wi, Tcl_GetString(args[2]), 0); -#else - l = Tk_GetOptionValue(interp, (char *) wi, wi->opt_table, args[2], wi->win); - if (l == NULL) { - goto error; - } - Tcl_SetObjResult(interp, l); -#endif - } - break; - /* - * chggroup - */ - case ZN_W_CHGGROUP: - { - ZnItem grp, scan; - 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; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - result = ZnItemWithTagOrId(wi, args[3], &grp, &search_var); - if ((result == TCL_ERROR) || (grp == ZN_NO_ITEM)|| (grp->class != ZnGroup)) { - goto error; - } - if (item->parent == grp) { - /* - * Nothing to be done, the item is already in the - * target group. - */ - goto done; - } - /* - * Check the ancestors to find if item is an - * ancestor of grp, which would lead to a - * forbidden move. - */ - for (scan = grp; scan && (scan != item); scan = scan->parent); - if (scan == item) { - Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]), - "\" is a descendant of \"", Tcl_GetString(args[2]), - "\" and can't be used as its parent", NULL); - goto error; - } - if (argc == 5) { - if (Tcl_GetBooleanFromObj(interp, args[4], &adjust) != TCL_OK) { - goto error; - } - } - if ((item->parent == grp) || (item->parent == ZN_NO_ITEM)) { - goto done; - } - if (adjust) { - ZnITEM.GetItemTransform(grp, &t); - ZnTransfoInvert(&t, &inv); - ZnITEM.GetItemTransform(item->parent, &t); - ZnTransfoCompose(&t2, &t, &inv); - this_one = &t2; - if (item->transfo) { - ZnTransfoCompose(&t, item->transfo, &t2); - this_one = &t; - } - } - ZnITEM.ExtractItem(item); - ZnITEM.InsertItem(item, grp, ZN_NO_ITEM, True); - /* - * The item can be a group in which case we must - * use the ZN_TRANSFO_FLAG to force an update of - * the children. In all other case ZN_COORDS_FLAG - * is enough. - */ - ZnITEM.Invalidate(item, - item->class==ZnGroup?ZN_TRANSFO_FLAG:ZN_COORDS_FLAG); - if (adjust) { - ZnITEM.SetTransfo(item, this_one); - } - } - break; - /* - * clone - */ - case ZN_W_CLONE: - { - if (argc < 3) { - Tcl_WrongNumArgs(interp, 1, args, "clone tagOrId ?option value ...?"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || - (item == ZN_NO_ITEM) || (item == wi->top_group)) { - goto error; - } - argc -= 3; - args += 3; - item2 = ZnITEM.CloneItem(item); - ZnITEM.InsertItem(item2, item->parent, ZN_NO_ITEM, True); - if (ZnITEM.ConfigureItem(item2, ZN_NO_PART, argc, args, False) == TCL_ERROR) { - goto error; - } - l = Tcl_NewLongObj(item2->id); - Tcl_SetObjResult(interp, l); - } - break; - /* - * configure - */ - case ZN_W_CONFIGURE: - { -#ifdef PTK_800 - if (argc == 2) { - result = Tk_ConfigureInfo(interp, wi->win, config_specs, - (char *) wi, (char *) NULL, 0); - } - else if (argc == 3) { - result = Tk_ConfigureInfo(interp, wi->win, config_specs, - (char *) wi, Tcl_GetString(args[2]), 0); - } - else { - result = Configure(interp, wi, argc-2, args+2, TK_CONFIG_ARGV_ONLY); - } -#else - if (argc == 2) { - l = Tk_GetOptionInfo(interp, (char *) wi, wi->opt_table, - (argc == 3) ? args[2] : NULL, wi->win); - if (l == NULL) { - goto error; - } - else { - Tcl_SetObjResult(interp, l); - } - } - else { - result = Configure(interp, wi, argc-2, args+2); - } -#endif - } - break; - /* - * contour - */ - case ZN_W_CONTOUR: - { - if ((argc < 3) || (argc > 7)) { - Tcl_WrongNumArgs(interp, 1, args, - "contour tagOrId ?operator windingFlag? ?index? ?coordListOrTagOrId?"); - goto error; - } - if (Contour(wi, argc, args, &search_var) == TCL_ERROR) { - goto error; - } - break; - } - /* - * coords - */ - case ZN_W_COORDS: - { - if ((argc < 3) || (argc > 7)) { - Tcl_WrongNumArgs(interp, 1, args, - "coords tagOrId ?add/remove? ?contour? ?index? ?coordList?"); - goto error; - } - if (Coords(wi, argc, args, &search_var) == TCL_ERROR) { - goto error; - } - } - break; - /* - * currentpart - */ - case ZN_W_CURRENTPART: - { - ZnBool only_fields = False; - if ((argc != 2) && (argc != 3)) { - Tcl_WrongNumArgs(interp, 1, args, "currentpart ?onlyFields?"); - goto error; - } - if (argc == 3) { - if (Tcl_GetBooleanFromObj(interp, args[2], &only_fields) != TCL_OK) { - goto error; - } - } - if ((wi->current_item != ZN_NO_ITEM) && - (wi->current_item->class->Part != NULL) && - ((wi->current_part >= 0) || !only_fields)) { - l = NULL; - wi->current_item->class->Part(wi->current_item, &l, &wi->current_part); - Tcl_SetObjResult(interp, l); - } - } - break; - /* - * cursor - */ - case ZN_W_CURSOR: - { - if ((argc != 4) && (argc != 5)) { - Tcl_WrongNumArgs(interp, 1, args, "cursor tagOrId ?field? index"); - goto error; - } - if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) { - goto error; - } - if (argc == 5) { - if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) { - field = ZN_NO_PART; - if (Tcl_GetString(args[3])[0] != 0) { - 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, field, args[3], &index); - if (result != TCL_OK) { - goto error; - } - - (*item->class->Cursor)(item, field, index); - if ((item == wi->focus_item) && (field == wi->focus_field) && - wi->text_info.cursor_on) { - ZnITEM.Invalidate(item, ZN_DRAW_FLAG); - } - } - } - break; - /* - * dchars - */ - case ZN_W_DCHARS: - { - int first, last; - ZnTextInfo *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) == TCL_ERROR) { - goto error; - } - if (argc == 6) { - if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) { - field = ZN_NO_PART; - if (Tcl_GetString(args[3])[0] != 0) { - 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, field, args[3], &first); - if (result != TCL_OK) { - goto error; - } - if (argc == 5) { - result = (*item->class->Index)(item, field, args[4], &last); - if (result != TCL_OK) { - goto error; - } - } - else { - last = first; - } - (*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; - /* - * dtag - */ - case ZN_W_DTAG: - { - Tk_Uid tag; - - if ((argc != 3) && (argc != 4)) { - Tcl_WrongNumArgs(interp, 1, args, "dtag tagOrId ?tagToDelete?"); - goto error; - } - if (argc == 4) { - tag = Tk_GetUid(Tcl_GetString(args[3])); - } - else { - tag = Tk_GetUid(Tcl_GetString(args[2])); - } - if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) { - goto error; - } - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - ZnITEM.RemoveTag(item, (char *) tag); - } - } - break; - /* - * find - */ - case ZN_W_FIND: - { - if (argc < 3) { - Tcl_WrongNumArgs(interp, 1, args, "find searchCommand ?arg arg ...?"); - goto error; - } - result = FindItems(wi, argc, args, NULL, 2, &search_var); - } - break; - /* - * fit - */ - case ZN_W_FIT: - { - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "fit coordList error"); - goto error; - } - if (ZnParseCoordList(wi, args[2], &points, - NULL, &num_points, NULL) == TCL_ERROR) { - return TCL_ERROR; - } - if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) { - goto error; - } - to_points = ZnListNew(32, sizeof(ZnPoint)); - ZnFitBezier(points, num_points, d, to_points); - points = (ZnPoint *) ZnListArray(to_points); - num_points = ZnListSize(to_points); - l = Tcl_GetObjResult(interp); - for (i = 0; i < num_points; i++, points++) { - entries[0] = Tcl_NewDoubleObj(points->x); - entries[1] = Tcl_NewDoubleObj(points->y); - if (i % 3) { - entries[2] = Tcl_NewStringObj(c, -1); - Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(3, entries)); - } - else { - Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries)); - } - } - ZnListFree(to_points); - } - break; - /* - * focus - */ - case ZN_W_FOCUS: - { - if (argc > 4) { - Tcl_WrongNumArgs(interp, 1, args, "focus ?tagOrId? ?field?"); - goto error; - } - item = wi->focus_item; - if (argc == 2) { - field = wi->focus_field; - if (item != ZN_NO_ITEM) { - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(item->id)); - if (field != ZN_NO_PART) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(field)); - } - else { - Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj("", -1)); - } - } - break; - } - if ((item != ZN_NO_ITEM) && (item->class->Cursor != NULL) && - ISSET(wi->flags, ZN_GOT_FOCUS)) { - ZnITEM.Invalidate(item, ZN_COORDS_FLAG); - } - if (Tcl_GetString(args[2])[0] == 0) { - wi->focus_item = ZN_NO_ITEM; - wi->focus_field = ZN_NO_PART; - break; - } - if (ZnItemWithTagOrId(wi, args[2], &item, &search_var) == TCL_ERROR) { - goto error; - } - if (argc == 4) { - if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) { - field = ZN_NO_PART; - if (Tcl_GetString(args[3])[0] != 0) { - Tcl_AppendResult(interp, "invalid field index \"", - Tcl_GetString(args[3]), - "\", should be a positive integer", NULL); - goto error; - } - } - } - wi->focus_item = item; - wi->focus_field = field; - if (ISSET(wi->flags, ZN_GOT_FOCUS) && (item->class->Cursor != NULL)) { - ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG); - } - } - break; - /* - * gdelete - */ - case ZN_W_GDELETE: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "gdelete gName"); - goto error; - } - ZnDeleteGradientName(Tcl_GetString(args[2])); - } - break; - /* - * gettags - */ - case ZN_W_GETTAGS: - { - Tk_Uid *tags; - - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "gettags tagOrId"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - if (!item->tags || !ZnListSize(item->tags)) { - goto done; - } - else { - num = ZnListSize(item->tags); - tags = (Tk_Uid *) ZnListArray(item->tags); - l = Tcl_GetObjResult(interp); - for (i = 0; i < num; i++) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(tags[i], -1)); - } - } - } - break; - /* - * gname - */ - case ZN_W_GNAME: - { - ZnBool ok; - - if ((argc != 3) && (argc != 4)) { - Tcl_WrongNumArgs(interp, 1, args, "gname ?grad? gName"); - goto error; - } - if (argc == 3) { - l = Tcl_NewBooleanObj(ZnGradientNameExists(Tcl_GetString(args[2]))); - Tcl_SetObjResult(interp, l); - } - else { - ok = ZnNameGradient(interp, wi->win, Tcl_GetString(args[2]), - Tcl_GetString(args[3])); - if (!ok) { - goto error; - } - } - } - break; - /* - * group - */ - case ZN_W_GROUP: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "group tagOrId"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - if (item->parent != ZN_NO_ITEM) { - l = Tcl_NewLongObj(item->parent->id); - Tcl_SetObjResult(interp, l); - } - else { - /* - * Top group is its own parent. - */ - l = Tcl_NewLongObj(item->id); - Tcl_SetObjResult(interp, l); - } - } - break; - /* - * hasanchors - */ - case ZN_W_HASANCHORS: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "hasanchors tagOrId"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - l = Tcl_NewBooleanObj(ISSET(item->class->flags, ZN_CLASS_HAS_ANCHORS) ? 1 : 0); - Tcl_SetObjResult(interp, l); - } - break; - /* - * hasfields - */ - case ZN_W_HASFIELDS: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "hasfields tagOrId"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - l = Tcl_NewBooleanObj(item->class->GetFieldSet?1:0); - Tcl_SetObjResult(interp, l); - } - break; - /* - * hastag - */ - case ZN_W_HASTAG: - { - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "hastag tagOrId tag"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - l = Tcl_NewBooleanObj(ZnITEM.HasTag(item, - Tk_GetUid(Tcl_GetString(args[3])))); - Tcl_SetObjResult(interp, l); - } - break; - /* - * index - */ - case ZN_W_INDEX: - { - if ((argc != 4) && (argc != 5)) { - Tcl_WrongNumArgs(interp, 1, args, "index tagOrId ?field? string"); - goto error; - } - if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) { - goto error; - } - if (argc == 5) { - if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) { - field = ZN_NO_PART; - if (Tcl_GetString(args[3])[0] != 0) { - 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, field, args[3], &index); - if (result != TCL_OK) { - goto error; - } - l = Tcl_NewIntObj(index); - Tcl_SetObjResult(interp, l); - goto done; - } - } - Tcl_AppendResult(interp, "can't find an indexable item \"", - Tcl_GetString(args[2]), "\"", NULL); - goto error; - } - break; - /* - * insert - */ - case ZN_W_INSERT: - { - ZnTextInfo *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) == TCL_ERROR) { - goto error; - } - if (argc == 6) { - if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) { - field = ZN_NO_PART; - if (Tcl_GetString(args[3])[0] != 0) { - 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, field, args[3], &index); - if (result != TCL_OK) { - goto error; - } - 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)) { - 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; - /* - * itemcget - */ - case ZN_W_ITEMCGET: - { - if (argc < 4) { - itemcget_syntax: - Tcl_WrongNumArgs(interp, 1, args, "itemcget tagOrId ?field? option"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - if (argc == 5) { - if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) { - field = ZN_NO_PART; - if (Tcl_GetString(args[3])[0] != 0) { - Tcl_AppendResult(interp, "invalid field index \"", - Tcl_GetString(args[3]), - "\", should be a positive integer", NULL); - goto error; - } - } - argc--; - args++; - } - if (argc != 4) { - goto itemcget_syntax; - } - if (ZnITEM.QueryItem(item, field, 1, &args[3]) != TCL_OK) { - goto error; - } - } - break; - /* - * itemconfigure - */ - case ZN_W_ITEMCONFIGURE: - { - if (argc < 3) { - Tcl_WrongNumArgs(interp, 1, args, - "itemconfigure tagOrId ?field? option value ?option value? ..."); - goto error; - } - if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) { - goto error; - } - if ((argc > 3) && (Tcl_GetString(args[3])[0] != '-')) { - if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) { - field = ZN_NO_PART; - if (Tcl_GetString(args[3])[0] != 0) { - Tcl_AppendResult(interp, "invalid field index \"", - Tcl_GetString(args[3]), - "\", should be a positive integer", NULL); - goto error; - } - } - argc--; - args++; - } - argc -= 3; - args += 3; - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - if (argc < 2) { - if (field == ZN_NO_PART) { - result = ZnAttributesInfo(wi->interp, item, item->class->attr_desc, argc, args); - } - else if (item->class->GetFieldSet) { - ZnFieldSet fs = item->class->GetFieldSet(item); - if (field < (int) ZnFIELD.NumFields(fs)) { - result = ZnAttributesInfo(wi->interp, ZnFIELD.GetFieldStruct(fs, field), - ZnFIELD.attr_desc, argc, args); - } - else { - Tcl_AppendResult(interp, "field index out of bound", NULL); - goto error; - } - } - else { - Tcl_AppendResult(interp, "the item does not support fields", NULL); - goto error; - } - goto done; - } - else { - result = ZnITEM.ConfigureItem(item, field, argc, args, False); - } - if (result == TCL_ERROR) { - goto error; - } - } - } - break; - /* - * layout - */ - case ZN_W_LAYOUT: - { - if (argc < 4) { - Tcl_WrongNumArgs(interp, 1, args, - "layout operator ?args...? tagOrId ?tagOrId...?"); - goto error; - } - if (LayoutItems(wi, argc-2, args+2) == TCL_ERROR) { - goto error; - } - } - break; - /* - * lower - */ - case ZN_W_LOWER: - { - ZnItem first, group, mark = ZN_NO_ITEM; - - if (argc < 3) { - Tcl_WrongNumArgs(interp, 1, args, "lower tagOrId ?belowThis?"); - goto error; - } - if (argc == 4) { - if (ZnTagSearchScan(wi, args[3], &search_var) == TCL_ERROR) { - goto error; - } - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - mark = item; - } - 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) == TCL_ERROR) { - goto error; - } - item = ZnTagSearchFirst(search_var); - if ((item == ZN_NO_ITEM) || (item == wi->top_group)) { - goto done; - } - first = item; - if (mark == ZN_NO_ITEM) { - mark = ZnGroupTail(item->parent); - } - group = mark->parent; - do { - if ((item->parent == group) && (item != mark)) { - ZnITEM.UpdateItemPriority(item, mark, False); - mark = item; - } - item = ZnTagSearchNext(search_var); - } - while ((item != ZN_NO_ITEM) && (item != first)); - } - break; - /* - * monitor - */ - case ZN_W_MONITOR: - { -#ifndef _WIN32 - ZnBool on_off; - - if ((argc != 2) && (argc != 3)) { - Tcl_WrongNumArgs(interp, 1, args, "monitor ?onOff?"); - goto error; - } - if (argc == 3) { - if (Tcl_GetBooleanFromObj(interp, args[2], &on_off) != TCL_OK) { - goto error; - } - ASSIGN(wi->flags, ZN_MONITORING, on_off); - if (on_off == True) { - ZnResetChronos(wi->total_draw_chrono); - ZnResetChronos(wi->this_draw_chrono); - } - } - if ((argc == 2) || (on_off == False)) { - long ttime, ltime; - int num_actions; - ZnGetChrono(wi->total_draw_chrono, &ttime, &num_actions); - ZnGetChrono(wi->this_draw_chrono, <ime, NULL); - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(num_actions)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ltime)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ttime)); - /*Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(wi->damaged_area_w)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(wi->damaged_area_h)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ttime));*/ - } -#endif - } - break; - /* - * numparts - */ - case ZN_W_NUMPARTS: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "numparts tagOrId"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - l = Tcl_NewIntObj((int) item->class->num_parts); - Tcl_SetObjResult(interp, l); - } - break; - /* - * postscript - */ - case ZN_W_POSTSCRIPT: - { - if (ZnPostScriptCmd(wi, argc, args) != TCL_OK) { - goto error; - } - } - break; - /* - * raise - */ - case ZN_W_RAISE: - { - ZnItem group, mark = ZN_NO_ITEM; - - if (argc < 3) { - Tcl_WrongNumArgs(interp, 1, args, "raise tagOrId ?aboveThis?"); - goto error; - } - if (argc == 4) { - /* - * Find the topmost item with the tag. - */ - if (ZnTagSearchScan(wi, args[3], &search_var) == TCL_ERROR) { - goto error; - } - 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) == TCL_ERROR) { - goto error; - } - item = ZnTagSearchFirst(search_var); - if ((item == ZN_NO_ITEM) || (item == wi->top_group)) { - goto done; - } - if (mark == ZN_NO_ITEM) { - mark = ZnGroupHead(item->parent); - } - group = mark->parent; - for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - if (item->parent != group) { - continue; - } - if (item != mark) { - ZnITEM.UpdateItemPriority(item, mark, True); - } - } - } - break; - /* - * remove - */ - case ZN_W_REMOVE: - { - unsigned int num_fields; - - if (argc < 3) { - Tcl_WrongNumArgs(interp, 1, args, "remove tagOrId ?tagOrId ...?"); - goto error; - } - argc -= 2; - args += 2; - for (i = 0; i < (unsigned int) argc; i++) { - if (ZnTagSearchScan(wi, args[i], &search_var) == TCL_ERROR) { - goto error; - } - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - if (item == wi->top_group) { - continue; - } - if (wi->binding_table != NULL) { - Tk_DeleteAllBindings(wi->binding_table, (ClientData) item); - if (item->class->GetFieldSet) { - num_fields = ZnFIELD.NumFields(item->class->GetFieldSet(item)); - for (j = 0; j < 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, -(int)(j+2))); - } - } - ZnITEM.DestroyItem(item); - } - } - } - break; - /* - * rotate - */ - case ZN_W_ROTATE: - { - ZnBool deg=False; - - if ((argc < 4) && (argc > 7)) { - Tcl_WrongNumArgs(interp, 1, args, "rotate tagOrIdOrTransform angle ?degree? ?centerX centerY?"); - goto error; - } - - if (argc > 5) { - if (Tcl_GetDoubleFromObj(interp, args[argc-2], &d) == TCL_ERROR) { - goto error; - } - p.x = d; - if (Tcl_GetDoubleFromObj(interp, args[argc-1], &d) == TCL_ERROR) { - goto error; - } - p.y = d; - } - if ((argc == 5) || (argc == 7)) { - if (Tcl_GetBooleanFromObj(interp, args[4], °) != TCL_OK) { - goto error; - } - - } - 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) == TCL_ERROR) { - goto error; - } - } - if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) { - goto error; - } - - if (t) { - if (argc > 5) { - ZnTranslate(t, -p.x, -p.y, False); - } - if (deg) { - ZnRotateDeg(t, d); - } - else { - ZnRotateRad(t, d); - } - if (argc > 5) { - ZnTranslate(t, p.x, p.y, False); - } - } - else { - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - ZnITEM.RotateItem(item, d, deg, (argc > 5) ? &p : NULL); - } - } - } - break; - /* - * scale - */ - case ZN_W_SCALE: - { - ZnPoint scale; - - if ((argc != 5) && (argc != 7)) { - Tcl_WrongNumArgs(interp, 1, args, - "scale tagOrIdOrTransform xFactor yFactor ?centerX centerY?"); - goto error; - } - 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) == TCL_ERROR) { - goto error; - } - } - if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) { - goto error; - } - scale.x = d; - if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) { - goto error; - } - scale.y = d; - if (argc == 7) { - if (Tcl_GetDoubleFromObj(interp, args[5], &d) == TCL_ERROR) { - goto error; - } - p.x = d; - if (Tcl_GetDoubleFromObj(interp, args[6], &d) == TCL_ERROR) { - goto error; - } - p.y = d; - } - - if (t) { - if (argc == 7) { - ZnTranslate(t, -p.x, -p.y, False); - } - ZnScale(t, scale.x, scale.y); - if (argc == 7) { - ZnTranslate(t, p.x, p.y, False); - } - } - else { - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - ZnITEM.ScaleItem(item, scale.x, scale.y, (argc == 7) ? &p : NULL); - } - } - } - break; - /* - * select - */ - case ZN_W_SELECT: - { - ZnTextInfo *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) == TCL_ERROR) { - goto error; - } - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - if ((item->class->Index != NULL) && - (item->class->Selection != NULL)) { - break; - } - } - if (item == ZN_NO_ITEM) { - Tcl_AppendResult(interp, "can't find an indexable item \"", - Tcl_GetString(args[3]), "\"", NULL); - goto error; - } - } - if (Tcl_GetIndexFromObj(interp, args[2], sel_cmd_strings, - "selection option", 0, &cmd_index) != TCL_OK) { - goto error; - } - if ((argc == 5) || (argc == 6)) { - if (argc == 6) { - if (Tcl_GetIntFromObj(interp, args[4], &field) != TCL_OK) { - field = ZN_NO_PART; - if (Tcl_GetString(args[4])[0] != 0) { - 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 != TCL_OK) { - goto error; - } - } - switch ((enum sel_cmds) cmd_index) { - case ZN_SEL_ADJUST: - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "select adjust tagOrId ?field? index"); - goto error; - } - 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 { - ti->sel_anchor = ti->sel_first; - } - } - SelectTo(item, field, index); - break; - case ZN_SEL_CLEAR: - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "select clear"); - goto error; - } - if (ti->sel_item != ZN_NO_ITEM) { - ZnITEM.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 ?field? index"); - goto error; - } - 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 (ti->sel_item != ZN_NO_ITEM) { - l = Tcl_GetObjResult(interp); - Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(ti->sel_item->id)); - if (ti->sel_field != ZN_NO_PART) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ti->sel_field)); - } - else { - Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj("", -1)); - } - } - break; - case ZN_SEL_TO: - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "select to tagOrId ?field? index"); - goto error; - } - SelectTo(item, field, index); - break; - } - } - break; - /* - * Skew - */ - case ZN_W_SKEW: - { - double x_skew, y_skew; - - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, "skew tagOrIdOrTransform xSkewAngle ySkewAngle"); - goto error; - } - 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) == TCL_ERROR) { - goto error; - } - } - if (Tcl_GetDoubleFromObj(interp, args[3], &x_skew) == TCL_ERROR) { - goto error; - } - if (Tcl_GetDoubleFromObj(interp, args[4], &y_skew) == TCL_ERROR) { - goto error; - } - - if (t) { - ZnSkewRad(t, x_skew, y_skew); - } - else { - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - ZnITEM.SkewItem(item, x_skew, y_skew); - } - } - } - break; - /* - * smooth - */ - case ZN_W_SMOOTH: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "smooth coordList"); - goto error; - } - if (ZnParseCoordList(wi, args[2], &points, - NULL, &num_points, NULL) == TCL_ERROR) { - return TCL_ERROR; - } - to_points = ZnListNew(32, sizeof(ZnPoint)); - ZnSmoothPathWithBezier(points, num_points, to_points); - points = (ZnPoint *) ZnListArray(to_points); - num_points = ZnListSize(to_points); - l = Tcl_GetObjResult(interp); - for (i = 0; i < num_points; i++, points++) { - entries[0] = Tcl_NewDoubleObj(points->x); - entries[1] = Tcl_NewDoubleObj(points->y); - Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries)); - } - ZnListFree(to_points); - } - break; - /* - * tapply - */ - case ZN_W_TAPPLY: - { - Tcl_AppendResult(interp, "Command not yet implemented", NULL); - goto error; - } - break; - /* - * tcompose - */ - case ZN_W_TCOMPOSE: - { - ZnTransfo *to; - ZnBool invert=False; - ZnTransfo res_t, inv_t; - - if ((argc != 4) && (argc != 5)) { - Tcl_WrongNumArgs(interp, 1, args, "tcompose transformTo aTransform ?invert?"); - goto error; - } - if (argc == 5) { - if (Tcl_GetBooleanFromObj(interp, args[4], &invert) != TCL_OK) { - goto error; - } - argc--; - } - - entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[3])); - if (entry != NULL) { - t = (ZnTransfo *) Tcl_GetHashValue(entry); - } - else { - result = ZnItemWithTagOrId(wi, args[3], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]), - "\" must be either a tag, ", - "an id or a transform name", (char *) NULL); - goto error; - } - t = item->transfo; - } - - entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2])); - if (entry != NULL) { - to = (ZnTransfo *) Tcl_GetHashValue(entry); - } - else { - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]), - "\" must be either a tag, ", - "an id or a transform name", (char *) NULL); - goto error; - } - to = item->transfo; - } - - if (invert) { - ZnTransfoInvert(t, &inv_t); - ZnTransfoCompose(&res_t, to, &inv_t); - } - else { - ZnTransfoCompose(&res_t, to, t); - } - - if (item != ZN_NO_ITEM) { - /* Set back the transform in the item */ - ZnITEM.SetTransfo(item, &res_t); - } - else { - ZnTransfoFree(to); - Tcl_SetHashValue(entry, ZnTransfoDuplicate(&res_t)); - } - - break; - } - /* - * tdelete - */ - case ZN_W_TDELETE: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "tdelete tName"); - goto error; - } - entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2])); - if (entry == NULL) { - Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]), - "\" must be a transform name", (char *) NULL); - goto error; - } - t = (ZnTransfo *) Tcl_GetHashValue(entry); - ZnTransfoFree(t); - Tcl_DeleteHashEntry(entry); - } - break; - /* - * tget - */ - case ZN_W_TGET: - { - ZnPoint scale, trans; - ZnReal rotation, skewxy; - ZnBool raw=1, get_trans=0, get_rot=0; - ZnBool get_scale=0, get_skew=0; - ZnTransfo tid; - - if ((argc != 3) && (argc != 4)) { - err_tget: - Tcl_WrongNumArgs(interp, 1, args, "tget transform ?all|translation|scale|rotation|skew?"); - goto error; - } - if (argc == 4) { - raw = 0; - str = Tcl_GetString(args[3]); - length = strlen(str); - if (strncmp(str, "all", length) == 0) { - get_scale = get_rot = get_trans = get_skew = 1; - } - else if (strncmp(str, "translation", length) == 0) { - get_trans = 1; - } - else if (strncmp(str, "scale", length) == 0) { - get_scale = 1; - } - else if (strncmp(str, "rotation", length) == 0) { - get_rot = 1; - } - else if (strncmp(str, "skew", length) == 0) { - get_skew = 1; - } - else { - goto err_tget; - } - } - entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2])); - if (entry != NULL) { - t = (ZnTransfo *) Tcl_GetHashValue(entry); - } - else { - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]), - "\" must be either a tag, ", - "an id or a transform name", (char *) NULL); - goto error; - } - t = item->transfo; - } - l = Tcl_GetObjResult(interp); - if (raw) { - if (!t) { - ZnTransfoSetIdentity(&tid); - t = &tid; - } - for (i = 0; i < 6; i++) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(t->_[i/2][i%2])); - } - } - else { - ZnTransfoDecompose(t, get_scale?&scale:NULL, get_trans?&trans:NULL, - get_rot?&rotation:NULL, get_skew?&skewxy:NULL); - if (get_trans) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(trans.x)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(trans.y)); - } - if (get_scale) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(scale.x)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(scale.y)); - } - if (get_rot) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(rotation)); - } - if (get_skew) { - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(skewxy)); - } - } - break; - } - /* - * transform - */ - case ZN_W_TRANSFORM: - { - char *controls, *tag; - ZnPoint *p, xp; - ZnTransfo *from_t=NULL, *to_t=NULL, *result_t; - ZnTransfo t1, t2, t3; - ZnBool old_format; - - if ((argc != 4) && (argc != 5)) { - Tcl_WrongNumArgs(interp, 1, args, "transform ?tagOrIdFrom? tagOrIdTo coordlist"); - goto error; - } - - if (argc == 5) { - /* - * Setup the source transform. - */ - tag = Tcl_GetString(args[2]); - if (strcmp(tag, "device") == 0) { - from_t = &t1; - ZnTransfoSetIdentity(from_t); - } - else { - entry = Tcl_FindHashEntry(wi->t_table, tag); - if (entry != NULL) { - /* from is a named transform */ - from_t = (ZnTransfo *) Tcl_GetHashValue(entry); - } - else { - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-2]), - "\" must be either identity or a tag or ", - "an id or a transform name", (char *) NULL); - goto error; - } - ZnITEM.GetItemTransform(item, &t1); - from_t = &t1; - } - } - } - /* - * Setup the destination transform - */ - tag = Tcl_GetString(args[argc-2]); - if (strcmp(tag, "device") == 0) { - to_t = &t2; - ZnTransfoSetIdentity(to_t); - } - else { - entry = Tcl_FindHashEntry(wi->t_table, tag); - if (entry != NULL) { - /* to is a named transform */ - to_t = (ZnTransfo *) Tcl_GetHashValue(entry); - } - else { - result = ZnItemWithTagOrId(wi, args[argc-2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-2]), - "\" must be either identity a tag or ", - "an id or a transform name", (char *) NULL); - goto error; - } - ZnITEM.GetItemTransform(item, &t2); - to_t = &t2; - } - } - ZnTransfoInvert(to_t, &t3); - to_t = &t3; - result_t = to_t; - - if (argc == 5) { - ZnTransfoCompose(&t2, from_t, to_t); - result_t = &t2; - } - /*ZnPrintTransfo(&t); - ZnPrintTransfo(&inv);*/ - - if (ZnParseCoordList(wi, args[argc-1], &p, - &controls, &num_points, &old_format) == TCL_ERROR) { - Tcl_AppendResult(interp, " invalid coord list \"", - Tcl_GetString(args[argc-1]), "\"", NULL); - goto error; - } - l = Tcl_GetObjResult(interp); - if (old_format) { - for (i = 0; i < num_points; i++, p++) { - ZnTransformPoint(result_t, p, &xp); - /*printf("p->x=%g, p->y=%g, xp.x=%g, xp.y=%g\n", p->x, p->y, xp.x, xp.y);*/ - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(xp.x)); - Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(xp.y)); - /* The next case only applies for a one point - * list with a control flag. - */ - if (controls && controls[i]) { - c[0] = controls[i]; - Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(c, -1)); - } - } - } - else { - for (i = 0; i < num_points; i++, p++) { - ZnTransformPoint(result_t, p, &xp); - /*printf("p->x=%g, p->y=%g, xp.x=%g, xp.y=%g\n", p->x, p->y, xp.x, xp.y);*/ - entries[0] = Tcl_NewDoubleObj(xp.x); - entries[1] = Tcl_NewDoubleObj(xp.y); - if (controls && controls[i]) { - c[0] = controls[i]; - entries[2] = Tcl_NewStringObj(c, -1); - Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(3, entries)); - } - else { - Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries)); - } - } - } - } - break; - /* - * translate - */ - case ZN_W_TRANSLATE: - { - ZnBool abs = False; - - if ((argc != 5) && (argc != 6)) { - Tcl_WrongNumArgs(interp, 1, args, "translate tagOrIdorTransform xAmount yAmount ?abs?"); - goto error; - } - 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) == TCL_ERROR) { - goto error; - } - } - if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) { - goto error; - } - p.x = d; - if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) { - goto error; - } - p.y = d; - if (argc == 6) { - if (Tcl_GetBooleanFromObj(interp, args[5], &abs) == TCL_ERROR) { - goto error; - } - } - - if (t) { - ZnTranslate(t, p.x, p.y, abs); - } - else { - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item =ZnTagSearchNext(search_var)) { - ZnITEM.TranslateItem(item, p.x, p.y, abs); - } - } - } - break; - /* - * treset - */ - case ZN_W_TRESET: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "treset tagOrIdOrTransform"); - goto error; - } - 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) == TCL_ERROR) { - goto error; - } - } - - if (t) { - ZnTransfoSetIdentity(t); - } - else { - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - ZnITEM.ResetTransfo(item); - } - } - } - break; - /* - * trestore - */ - case ZN_W_TRESTORE: - { - if (argc != 4) { - Tcl_WrongNumArgs(interp, 1, args, "trestore tagOrId tName"); - goto error; - } - 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(entry); - if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) { - goto error; - } - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - ZnITEM.SetTransfo(item, t); - } - } - break; - /* - * tsave - */ - case ZN_W_TSAVE: - { - int is_ident, new, invert=0; - ZnTransfo *inv, ident; - char *from; - - if ((argc != 3) && (argc != 4) && (argc != 5)) { - Tcl_WrongNumArgs(interp, 1, args, "tsave ?tagOrIdOrTransform? tName ?invert?"); - goto error; - } - if (argc == 3) { - entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2])); - l = Tcl_NewBooleanObj(entry != NULL); - Tcl_SetObjResult(interp, l); - goto done; - } - from = Tcl_GetString(args[2]); - is_ident = strcmp(from, "identity") == 0; - if (is_ident) { - t = &ident; - ZnTransfoSetIdentity(t); - } - else { - entry = Tcl_FindHashEntry(wi->t_table, from); - if (entry != NULL) { - t = (ZnTransfo *) Tcl_GetHashValue(entry); - } - else { - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - goto error; - } - t = item->transfo; - } - } - if (argc == 5) { - if (Tcl_GetBooleanFromObj(interp, args[4], &invert) != TCL_OK) { - goto error; - } - argc--; - } - entry = Tcl_CreateHashEntry(wi->t_table, Tcl_GetString(args[argc-1]), &new); - if (!new) { - ZnTransfoFree((ZnTransfo *) Tcl_GetHashValue(entry)); - } - if (invert && !is_ident) { - inv = ZnTransfoNew(); - ZnTransfoInvert(t, inv); - Tcl_SetHashValue(entry, inv); - } - else { - Tcl_SetHashValue(entry, ZnTransfoDuplicate(t)); - } - } - break; - /* - * tset - */ - case ZN_W_TSET: - { - ZnTransfo new; - - if (argc != 9) { - Tcl_WrongNumArgs(interp, 1, args, - "tset tagOrIdorTransform m00 m01 m10 m11 m20 m21"); - goto error; - } - - for (i = 0; i < 6; i++) { - if (Tcl_GetDoubleFromObj(interp, args[3+i], &d) == TCL_ERROR) { - goto error; - } - new._[i/2][i%2] = (float) d; - } - entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2])); - if (entry != NULL) { - t = (ZnTransfo *) Tcl_GetHashValue(entry); - *t = new; - } - else { - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]), - "\" must be either a tag, ", - "an id or a transform name", (char *) NULL); - goto error; - } - ZnITEM.SetTransfo(item, &new); - } - break; - } - /* - * type - */ - case ZN_W_TYPE: - { - if (argc != 3) { - Tcl_WrongNumArgs(interp, 1, args, "type tagOrId"); - goto error; - } - result = ZnItemWithTagOrId(wi, args[2], &item, &search_var); - if (result == TCL_ERROR) { - goto error; - } - if (item != ZN_NO_ITEM) { - l = Tcl_NewStringObj(item->class->name, -1); - Tcl_SetObjResult(interp, l); - } - } - break; - /* - * vertexat - */ - case ZN_W_VERTEX_AT: - { - int contour, vertex, o_vertex; - - if (argc != 5) { - Tcl_WrongNumArgs(interp, 1, args, " vertexat tagOrId x y"); - goto error; - } - if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) { - goto error; - } - for (item = ZnTagSearchFirst(search_var); - item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { - if (item->class->PickVertex != NULL) { - break; - } - } - if (item == ZN_NO_ITEM) { - Tcl_AppendResult(interp, "can't find a suitable item \"", - Tcl_GetString(args[2]), "\"", NULL); - goto error; - } - if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) { - goto error; - } - p.x = d; - if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) { - goto error; - } - p.y = d; - 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)); - break; - } - - /* xview */ - case ZN_W_XVIEW: - { - int count, type; - ZnReal new_x=0.0, fraction; - - if (argc == 2) { -#ifdef PTK - ZnReal first, last; - ScrollFractions(wi->origin.x, wi->origin.x + Tk_Width(wi->win), - wi->scroll_xo, wi->scroll_xc, &first, &last); - Tcl_DoubleResults(interp, 2, 0, first, last); -#else - Tcl_SetObjResult(interp, - ScrollFractions(wi->origin.x, wi->origin.x + Tk_Width(wi->win), - wi->scroll_xo, wi->scroll_xc)); -#endif - } - else { - type = Tk_GetScrollInfoObj(interp, argc, args, &fraction, &count); - switch (type) { - case TK_SCROLL_ERROR: - result = TCL_ERROR; - goto done; - case TK_SCROLL_MOVETO: - new_x = (wi->scroll_xo + (int) (fraction * (wi->scroll_xc - wi->scroll_xo) + 0.5)); - break; - case TK_SCROLL_PAGES: - new_x = (int) (wi->origin.x + count * 0.9 * Tk_Width(wi->win)); - break; - case TK_SCROLL_UNITS: - if (wi->x_scroll_incr > 0) { - new_x = wi->origin.x + count * wi->x_scroll_incr; - } - else { - new_x = (int) (wi->origin.x + count * 0.1 * Tk_Width(wi->win)); - } - break; - } - SetOrigin(wi, new_x, wi->origin.y); - } - break; - } - - /*yview */ - case ZN_W_YVIEW: - { - int count, type; - ZnReal new_y = 0.0, fraction; - - if (argc == 2) { -#ifdef PTK - ZnReal first, last; - ScrollFractions(wi->origin.y, wi->origin.y + Tk_Height(wi->win), - wi->scroll_yo, wi->scroll_yc, &first, &last); - Tcl_DoubleResults(interp, 2, 0, first, last); -#else - Tcl_SetObjResult(interp, - ScrollFractions(wi->origin.y, wi->origin.y + Tk_Height(wi->win), - wi->scroll_yo, wi->scroll_yc)); -#endif - } - else { - type = Tk_GetScrollInfoObj(interp, argc, args, &fraction, &count); - switch (type) { - case TK_SCROLL_ERROR: - result = TCL_ERROR; - goto done; - case TK_SCROLL_MOVETO: - new_y = (wi->scroll_yo + (int) (fraction * (wi->scroll_yc - wi->scroll_yo) + 0.5)); - break; - case TK_SCROLL_PAGES: - new_y = (int) (wi->origin.y + count * 0.9 * Tk_Height(wi->win)); - break; - case TK_SCROLL_UNITS: - if (wi->y_scroll_incr > 0) { - new_y = wi->origin.y + count * wi->y_scroll_incr; - } - else { - new_y = (int) (wi->origin.y + count * 0.1 * Tk_Height(wi->win)); - } - break; - } - SetOrigin(wi, wi->origin.x, new_y); - } - break; - } - } - - done: - ZnTagSearchDestroy(search_var); - Tcl_Release((ClientData) wi); - return result; - - error: - result = TCL_ERROR; - goto done; -} - - -/* - *---------------------------------------------------------------------- - * - * Configure -- - * - * This procedure is called to process an args/argc list in - * conjunction with the Tk option database to configure (or - * reconfigure) a Zinc widget. - * - * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then interp->result contains an error message. - * - * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for the widget; old resources get freed, - * if there were any. - * - *---------------------------------------------------------------------- - */ -#ifdef PTK_800 -static int -Configure(Tcl_Interp *interp,/* Used for error reporting. */ - ZnWInfo *wi, /* Information about widget. */ - int argc, /* Number of valid entries in args. */ - Tcl_Obj *CONST args[], /* Arguments. */ - int flags) /* Flags to pass to Tk_ConfigureWidget. */ -{ -#define CONFIG_PROBE(offset) (ISSET(config_specs[offset].specFlags, \ - TK_CONFIG_OPTION_SPECIFIED)) - ZnBool init; - int render; - - init = wi->fore_color == NULL; - render = wi->render; - if (Tk_ConfigureWidget(interp, wi->win, config_specs, argc, -#ifdef PTK - (Tcl_Obj **) args, (char *) wi, flags) != TCL_OK) -#else - (CONST char **) args, (char *) wi, flags|TK_CONFIG_OBJS) != TCL_OK) -#endif - { - return TCL_ERROR; - } - if (!init) { - if (wi->render != render) { - ZnWarning("It is not possible to change the -render option after widget creation.\n"); - } - wi->render = render; - } - /* - * Reset the render mode if GL is not available. It'll be too late - * to do this after images or fonts have been allocated. - */ - if ((wi->render != 0) && ISCLEAR(wi->flags, ZN_HAS_GL)) { - fprintf(stderr, "GLX not available (need at least a 24 bits buffer with stencil)\n"); - wi->render = 0; - } - -#ifdef GL - if (CONFIG_PROBE(FONT_SPEC) || !wi->font_tfi) { - if (wi->font_tfi) { - ZnFreeTexFont(wi->font_tfi); - } - wi->font_tfi = ZnGetTexFont(wi, wi->font); - } -#ifdef ATC - if (CONFIG_PROBE(MAP_TEXT_FONT_SPEC) || !wi->map_font_tfi) { - if (wi->map_font_tfi) { - ZnFreeTexFont(wi->map_font_tfi); - } - wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font); - } -#endif -#endif - - /* - * Maintain the pick aperture within meaningful bounds. - */ - if (wi->pick_aperture < 0) { - wi->pick_aperture = 0; - } - if (CONFIG_PROBE(BACK_COLOR_SPEC) || !wi->relief_grad) { - XColor *color; - unsigned short alpha; - - Tk_SetWindowBackground(wi->win, ZnGetGradientPixel(wi->back_color, 0.0)); - if (wi->relief_grad) { - ZnFreeGradient(wi->relief_grad); - wi->relief_grad = NULL; - } - if (wi->relief != ZN_RELIEF_FLAT) { - color = ZnGetGradientColor(wi->back_color, 0.0, &alpha); - wi->relief_grad = ZnGetReliefGradient(interp, wi->win, - Tk_NameOfColor(color), alpha); - } - } - if (CONFIG_PROBE(BACK_COLOR_SPEC) || CONFIG_PROBE(LIGHT_ANGLE_SPEC)) { - ZnDamageAll(wi); - } - if (CONFIG_PROBE(RELIEF_SPEC)) { - ZnNeedRedisplay(wi); - } - - wi->inset = wi->border_width + wi->highlight_width; - if (CONFIG_PROBE(BORDER_WIDTH_SPEC) || - CONFIG_PROBE(HIGHLIGHT_THICKNESS_SPEC)) { - ZnDamageAll(wi); - } -#ifdef ATC - if (CONFIG_PROBE(SPEED_VECTOR_LENGTH_SPEC) || - CONFIG_PROBE(VISIBLE_HISTORY_SIZE_SPEC) || - CONFIG_PROBE(MANAGED_HISTORY_SIZE_SPEC)) { - ZnITEM.InvalidateItems(wi->top_group, ZnTrack); - } - if (CONFIG_PROBE(MAP_DISTANCE_SYMBOL_SPEC)) { - ZnITEM.InvalidateItems(wi->top_group, ZnMap); - } - if (CONFIG_PROBE(TRACK_SYMBOL_SPEC)) { - ZnITEM.InvalidateItems(wi->top_group, ZnTrack); - ZnITEM.InvalidateItems(wi->top_group, ZnWayPoint); - } -#endif - - /* - * Request the new geometry. - */ - if (CONFIG_PROBE(WIDTH_SPEC) || CONFIG_PROBE(HEIGHT_SPEC) || - CONFIG_PROBE(BORDER_WIDTH_SPEC) || - CONFIG_PROBE(HIGHLIGHT_THICKNESS_SPEC) || ISCLEAR(wi->flags, ZN_REALIZED)) { - Tk_GeometryRequest(wi->win, wi->opt_width, wi->opt_height); - } - - if (CONFIG_PROBE(TILE_SPEC)) { - ZnDamageAll(wi); - } - - /* - * Update the registration with the overlap manager. - */ -#ifdef ATC - if (CONFIG_PROBE(OVERLAP_MANAGER_SPEC)) { - Tcl_HashEntry *entry; - ZnItem grp; - - if (wi->om_group != ZN_NO_ITEM) { - OmUnregister((void *) wi); - wi->om_group = ZN_NO_ITEM; - } - if (wi->om_group_id != 0) { - entry = Tcl_FindHashEntry(wi->id_table, (char *) wi->om_group_id); - if (entry != NULL) { - grp = (ZnItem) Tcl_GetHashValue(entry); - if (grp->class == ZnGroup) { - OmRegister((void *) wi, ZnSendTrackToOm, - ZnSetLabelAngleFromOm, ZnQueryLabelPosition); - wi->om_group = grp; - } - } - } - } -#endif - - if (CONFIG_PROBE(INSERT_WIDTH_SPEC) && wi->focus_item) { - ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG); - } - /* - * Update the blinking cursor timing if on/off time has changed. - */ - if (ISSET(wi->flags, ZN_GOT_FOCUS) && - (CONFIG_PROBE(INSERT_ON_TIME_SPEC) || - CONFIG_PROBE(INSERT_OFF_TIME_SPEC))) { - Focus(wi, True); - } - - if (CONFIG_PROBE(SCROLL_REGION_SPEC)) { - /* - * Compute the scroll region - */ - wi->scroll_xo = wi->scroll_yo = 0; - wi->scroll_xc = wi->scroll_yc = 0; - if (wi->region != NULL) { - int argc2; -#ifdef PTK - Arg *args2; -#else - CONST char **args2; -#endif - -#ifdef PTK - if (Tcl_ListObjGetElements(interp, wi->region, &argc2, &args2) != TCL_OK) -#else - if (Tcl_SplitList(interp, wi->region, &argc2, &args2) != TCL_OK) -#endif - { - return TCL_ERROR; - } - if (argc2 != 4) { - Tcl_AppendResult(interp, "bad scrollRegion \"", wi->region, "\"", (char *) NULL); - badRegion: -#ifndef PTK - ZnFree(wi->region); - ZnFree(args2); -#endif - wi->region = NULL; - return TCL_ERROR; - } -#ifdef PTK -#ifdef PTK_800 - if ((Tk_GetPixels(interp, wi->win, LangString(args2[0]), &wi->scroll_xo) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, LangString(args2[1]), &wi->scroll_yo) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, LangString(args2[2]), &wi->scroll_xc) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, LangString(args2[3]), &wi->scroll_yc) != TCL_OK)) -#else - if ((Tk_GetPixelsFromObj(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) || - (Tk_GetPixelsFromObj(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) || - (Tk_GetPixelsFromObj(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) || - (Tk_GetPixelsFromObj(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK)) -#endif -#else - if ((Tk_GetPixels(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK)) -#endif - { - goto badRegion; - } - } - } - - if (CONFIG_PROBE(SCROLL_REGION_SPEC) || - CONFIG_PROBE(CONFINE_SPEC)) { - SetOrigin(wi, wi->origin.x, wi->origin.y); - SET(wi->flags, ZN_UPDATE_SCROLLBARS); - } - - if (CONFIG_PROBE(FOLLOW_POINTER_SPEC)) { - if (wi->follow_pointer) { - /* Flag has just been turned on, process - * the last known positional event to update - * the item under pointer. - */ - if (wi->pick_event.type == ButtonPress || - wi->pick_event.type == ButtonRelease || - wi->pick_event.type == MotionNotify || - wi->pick_event.type == EnterNotify || - wi->pick_event.type == LeaveNotify) { - Tcl_Preserve((ClientData) wi); - CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK); - PickCurrentItem(wi, &wi->pick_event); - Tcl_Release((ClientData) wi); - } - } - } - - return TCL_OK; -} -#else -static void -TileUpdate(void *client_data) -{ - ZnWInfo *wi = (ZnWInfo*) client_data; - - ZnDamageAll(wi); -} - -static int -Configure(Tcl_Interp *interp,/* Used for error reporting. */ - ZnWInfo *wi, /* Information about widget. */ - int argc, /* Number of valid entries in args. */ - Tcl_Obj *CONST args[]) /* Arguments. */ -{ - ZnBool init; - int render, mask, error; - Tk_SavedOptions saved_options; - Tcl_Obj *error_result = NULL; - - render = wi->render; - init = render < 0; - - for (error = 0; error <= 1; error++) { - if (!error) { - if (Tk_SetOptions(interp, (char *) wi, wi->opt_table, argc, args, - wi->win, &saved_options, &mask) != TCL_OK) { - continue; - } - } - else { - /* Save the error value for later report */ - error_result = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(error_result); - Tk_RestoreSavedOptions(&saved_options); - } - - if (!init) { - if (render != wi->render) { - ZnWarning("It is not possible to change the -render option after widget creation.\n"); - wi->render = render; - } - } - else if (wi->render < 0) { - wi->render = 0; - } - /* - * Reset the render mode if GL is not available. It'll be too late - * to do this after images or fonts have been allocated. - */ - else if ((wi->render != 0) && ISCLEAR(wi->flags, ZN_HAS_GL)) { - fprintf(stderr, "GLX not available (need at least a 24 bits buffer with stencil)\n"); - wi->render = 0; - } - - if ((mask & CONFIG_SCROLL_REGION) || init) { - /* - * Compute the scroll region - */ - wi->scroll_xo = wi->scroll_yo = 0; - wi->scroll_xc = wi->scroll_yc = 0; - if (wi->region != NULL) { - int argc2; - Tcl_Obj **args2; - - if (Tcl_ListObjGetElements(interp, wi->region, &argc2, &args2) != TCL_OK) { - badRegion: - Tcl_AppendResult(interp, "bad scrollRegion \"", - Tcl_GetString(wi->region), "\"", (char *) NULL); - continue; - } - if (argc2 != 4) { - goto badRegion; - } -#ifdef PTK_800 - if ((Tk_GetPixels(interp, wi->win, LangString(args2[0]), &wi->scroll_xo) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, LangString(args2[1]), &wi->scroll_yo) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, LangString(args2[2]), &wi->scroll_xc) != TCL_OK) || - (Tk_GetPixels(interp, wi->win, LangString(args2[3]), &wi->scroll_yc) != TCL_OK)) -#else - if ((Tk_GetPixelsFromObj(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) || - (Tk_GetPixelsFromObj(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) || - (Tk_GetPixelsFromObj(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) || - (Tk_GetPixelsFromObj(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK)) -#endif - { - goto badRegion; - } - } - } - - if ((mask & CONFIG_SET_ORIGIN) || init) { - SetOrigin(wi, wi->origin.x, wi->origin.y); - SET(wi->flags, ZN_UPDATE_SCROLLBARS); - } - -#ifdef GL - if ((mask & CONFIG_FONT) || !wi->font_tfi) { - if (wi->font_tfi) { - ZnFreeTexFont(wi->font_tfi); - } - wi->font_tfi = ZnGetTexFont(wi, wi->font); - } -#ifdef ATC - if ((mask & CONFIG_MAP_FONT) || !wi->map_font_tfi) { - if (wi->map_font_tfi) { - ZnFreeTexFont(wi->map_font_tfi); - } - wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font); - } -#endif -#endif - - if ((mask & CONFIG_TILE) || init) { - char *tile_name; - if (wi->tile) { - ZnFreeImage(wi->tile, TileUpdate, wi); - } - if (!wi->tile_obj || !*(tile_name = Tcl_GetString(wi->tile_obj))) { - wi->tile = ZnUnspecifiedImage; - } - else { - wi->tile = ZnGetImage(wi, tile_name, TileUpdate, wi); - if (wi->tile == ZnUnspecifiedImage) { - Tcl_AppendResult(interp, "Incorrect tile \"", tile_name, "\"", (char *) NULL); - continue; - } - } - } - -#ifdef ATC - if ((mask & CONFIG_MAP_SYMBOL) || init) { - if (wi->map_distance_symbol) { - ZnFreeImage(wi->map_distance_symbol, NULL, NULL); - } - wi->map_distance_symbol = ZnGetImage(wi, Tcl_GetString(wi->map_symbol_obj), NULL, NULL); - if ((wi->map_distance_symbol == ZnUnspecifiedImage) || - ! ZnImageIsBitmap(wi->map_distance_symbol)) { - Tcl_AppendResult(interp, "Incorrect bitmap \"", - Tcl_GetString(wi->map_symbol_obj), "\"", (char *) NULL); - continue; - } - } - - if ((mask & CONFIG_TRACK_SYMBOL) || init) { - if (wi->track_symbol) { - ZnFreeImage(wi->track_symbol, NULL, NULL); - } - wi->track_symbol = ZnGetImage(wi, Tcl_GetString(wi->track_symbol_obj), NULL, NULL); - if ((wi->track_symbol == ZnUnspecifiedImage) || - ! ZnImageIsBitmap(wi->track_symbol)) { - Tcl_AppendResult(interp, "Incorrect bitmap \"", - Tcl_GetString(wi->track_symbol_obj), "\"", (char *) NULL); - continue; - - } - } -#endif - - /* - * Maintain the pick aperture within meaningful bounds. - */ - if (wi->pick_aperture < 0) { - wi->pick_aperture = 0; - } - - if ((mask & CONFIG_BACK_COLOR) || !wi->relief_grad) { - XColor *color; - unsigned short alpha; - - Tk_SetWindowBackground(wi->win, ZnGetGradientPixel(wi->back_color, 0.0)); - if (wi->relief_grad) { - ZnFreeGradient(wi->relief_grad); - wi->relief_grad = NULL; - } - if (wi->relief != ZN_RELIEF_FLAT) { - color = ZnGetGradientColor(wi->back_color, 0.0, &alpha); - wi->relief_grad = ZnGetReliefGradient(interp, wi->win, - Tk_NameOfColor(color), alpha); - } - } - if (mask & CONFIG_DAMAGE_ALL) { - ZnDamageAll(wi); - } - if ((mask & CONFIG_REDISPLAY) || init) { - ZnNeedRedisplay(wi); - } - - wi->inset = wi->border_width + wi->highlight_width; - -#ifdef ATC - if (mask & CONFIG_INVALIDATE_TRACKS) { - ZnITEM.InvalidateItems(wi->top_group, ZnTrack); - } - if (mask & CONFIG_INVALIDATE_MAPS) { - ZnITEM.InvalidateItems(wi->top_group, ZnMap); - } - if (mask & CONFIG_INVALIDATE_WPS) { - ZnITEM.InvalidateItems(wi->top_group, ZnWayPoint); - } -#endif - - /* - * Request the new geometry. - */ - if ((mask & CONFIG_REQUEST_GEOM) || init) { - Tk_GeometryRequest(wi->win, wi->opt_width, wi->opt_height); - } - - /* - * Update the registration with the overlap manager. - */ -#ifdef ATC - if (mask & CONFIG_OM) { - Tcl_HashEntry *entry; - ZnItem grp; - - if (wi->om_group != ZN_NO_ITEM) { - OmUnregister((void *) wi); - wi->om_group = ZN_NO_ITEM; - } - if (wi->om_group_id != 0) { - entry = Tcl_FindHashEntry(wi->id_table, (char *) wi->om_group_id); - if (entry != NULL) { - grp = (ZnItem) Tcl_GetHashValue(entry); - if (grp->class == ZnGroup) { - OmRegister((void *) wi, ZnSendTrackToOm, - ZnSetLabelAngleFromOm, ZnQueryLabelPosition); - wi->om_group = grp; - } - } - } - } -#endif - - if ((mask & CONFIG_FOCUS_ITEM) && wi->focus_item) { - ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG); - } - /* - * Update the blinking cursor timing if on/off time has changed. - */ - if (ISSET(wi->flags, ZN_GOT_FOCUS) && (mask & CONFIG_FOCUS)) { - Focus(wi, True); - } - - if (mask & CONFIG_FOLLOW_POINTER) { - if (wi->follow_pointer) { - /* Flag has just been turned on, process - * the last known positional event to update - * the item under pointer. - */ - if (wi->pick_event.type == ButtonPress || - wi->pick_event.type == ButtonRelease || - wi->pick_event.type == MotionNotify || - wi->pick_event.type == EnterNotify || - wi->pick_event.type == LeaveNotify) { - Tcl_Preserve((ClientData) wi); - CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK); - PickCurrentItem(wi, &wi->pick_event); - Tcl_Release((ClientData) wi); - } - } - } - break; - } - - if (error) { - Tcl_SetObjResult(interp, error_result); - Tcl_DecrRefCount(error_result); - return TCL_ERROR; - } - else { - Tk_FreeSavedOptions(&saved_options); - return TCL_OK; - } -} -#endif - -/* - *---------------------------------------------------------------------- - * - * Focus -- - * - * This procedure is called whenever a zinc gets or loses the - * input focus. It's also called whenever the window is - * reconfigured while it has the focus. - * - * Results: - * None. - * - * Side effects: - * The cursor gets turned on or off. - * - *---------------------------------------------------------------------- - */ -static void -Blink(ClientData client_data) -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - - if (ISCLEAR(wi->flags, ZN_GOT_FOCUS) || (wi->insert_off_time == 0)) { - return; - } - if (wi->text_info.cursor_on) { - wi->text_info.cursor_on = 0; - wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time, - Blink, client_data); - } - else { - wi->text_info.cursor_on = 1; - wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_on_time, - Blink, client_data); - } - if ((wi->focus_item != ZN_NO_ITEM) && - (wi->focus_item->class->Cursor != NULL)) { - ZnITEM.Invalidate(wi->focus_item, ZN_DRAW_FLAG); - } -} - -static void -Focus(ZnWInfo *wi, - ZnBool got_focus) -{ - Tcl_DeleteTimerHandler(wi->blink_handler); - if (got_focus) { - SET(wi->flags, ZN_GOT_FOCUS); - wi->text_info.cursor_on = 1; - if (wi->insert_off_time != 0) { - wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time, - Blink, (ClientData) wi); - } - } - else { - CLEAR(wi->flags, ZN_GOT_FOCUS); - wi->text_info.cursor_on = 0; - wi->blink_handler = (Tcl_TimerToken) NULL; - } - if ((wi->focus_item != ZN_NO_ITEM) && - (wi->focus_item->class->Cursor != NULL)){ - ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG); - } - /*printf("focus %s\n", got_focus ? "in" : "out");*/ - if (wi->highlight_width > 0) { - ZnNeedRedisplay(wi); - } -} - - -/* - *---------------------------------------------------------------------- - * - * Event -- - * - * This procedure is invoked by the Tk dispatcher for various - * events on Zincs. - * - * Results: - * None. - * - * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. - * - *---------------------------------------------------------------------- - */ -static void -TopEvent(ClientData client_data, /* Information about widget. */ - XEvent *event) -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - if (event->type == ConfigureNotify) { - /*printf("Window moved\n");*/ - SET(wi->flags, ZN_CONFIGURE_EVENT); - } -} - -static void -Event(ClientData client_data, /* Information about widget. */ - XEvent *event) /* Information about event. */ -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - XGCValues values; - ZnBBox bbox; - - /*printf("=============== DEBUT %s %d EVENT ==================\n", - event->type == MapNotify ? "MAP": - event->type == Expose? "EXPOSE" : - event->type == ConfigureNotify ? "CONFIGURE" : - event->type == VisibilityNotify ? "VISIBILITY" : - event->type == DestroyNotify ? "DESTROY" : - "??", event->type);*/ - if (event->type == MapNotify) { - SET(wi->flags, ZN_CONFIGURE_EVENT); - if (!wi->gc) { - SET(wi->flags, ZN_REALIZED); -#ifdef GL - InitRendering2(wi); -#endif - - /* - * Get the work GC and suppress GraphicExpose - * and NoExpose events reception. - */ - wi->gc = XCreateGC(wi->dpy, Tk_WindowId(wi->win), 0, NULL); - values.graphics_exposures = False; - XChangeGC(wi->dpy, wi->gc, GCGraphicsExposures, &values); - - /* - * Set the real top window above us. - */ - { - Window parent, root, *children=NULL; - Tk_Window top_level; - int num_children, success; - - top_level = wi->win; - while (!Tk_IsTopLevel(top_level)) { - top_level = Tk_Parent(top_level); - } - success = XQueryTree(wi->dpy, Tk_WindowId(top_level), &root, &parent, - &children, &num_children); - if (!success || (root == parent)) { - wi->real_top = Tk_WindowId(top_level); - } - else { - wi->real_top = parent; - } - /* - * Needed under glx to suspend update with scissors after - * a move to synchronise the two buffers. Fix a refresh - * bug when the window is partially clipped by the display - * border. Can be usefull under Windows too. - */ - Tk_CreateEventHandler(top_level, StructureNotifyMask, TopEvent, (ClientData) wi); - if (children && success) { - XFree(children); - } - } - } - ZnNeedRedisplay(wi); - } - else if (event->type == Expose) { - ZnDim width, height; - - SET(wi->flags, ZN_CONFIGURE_EVENT); - - bbox.orig.x = (((XExposeEvent*) event)->x); - bbox.orig.y = (((XExposeEvent*) event)->y); - width = ((XExposeEvent*) event)->width; - height = ((XExposeEvent*) event)->height; - if (bbox.orig.x < 0) { - width += bbox.orig.x; - bbox.orig.x = 0; - } - if (bbox.orig.y < 0) { - height += bbox.orig.y; - bbox.orig.y = 0; - } - bbox.corner.x = MIN(wi->width, bbox.orig.x + width); - bbox.corner.y = MIN(wi->height, bbox.orig.y + height); - - /*printf("expose %d %d %d %d\n", - ((XExposeEvent*) event)->x, ((XExposeEvent*) event)->y, - ((XExposeEvent*) event)->width, ((XExposeEvent*) event)->height);*/ - /* - * Add the exposed area to the expose region and - * schedule an asynchronous redisplay of the window - * if we are done adding exposed parts. - */ - ZnAddBBoxToBBox(&wi->exposed_area, &bbox); - if (/*(((XExposeEvent*) event)->count == 0) &&*/ - !ZnIsEmptyBBox(&wi->exposed_area)) { - ZnNeedRedisplay(wi); - } - } - /* - * Resize the double buffer pixmap and prepare to redisplay - * the whole scene. The transform parameters are not - * modified as a result of the resize. If the application - * need such change, it can bind a handler on . - */ - else if (event->type == ConfigureNotify) { - int int_width, int_height; - - SET(wi->flags, ZN_CONFIGURE_EVENT); - - int_width = Tk_Width(wi->win); - int_height = Tk_Height(wi->win); - - if ((wi->width != int_width) || (wi->height != int_height)) { - bbox.orig.x = bbox.orig.y = 0; - bbox.corner.x = MAX(wi->width, int_width); - bbox.corner.y = MAX(wi->height, int_height); - wi->opt_width = wi->width = int_width; - wi->opt_height = wi->height = int_height; - - ZnResetTransformStack(wi); - - SET(wi->flags, ZN_UPDATE_SCROLLBARS); - /* - * The call below is needed in order to recenter the view if - * it's confined and the scroll region is smaller than the - * window. - */ - SetOrigin(wi, wi->origin.x, wi->origin.y); - - ZnDamage(wi, &bbox); - ZnITEM.Invalidate(wi->top_group, ZN_TRANSFO_FLAG); - - /* - * Reallocate the double buffer pixmap/image. - */ - if (!wi->render) { - /*printf("reallocating double buffer\n");*/ - if (wi->draw_buffer) { - Tk_FreePixmap(wi->dpy, wi->draw_buffer); - } - wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen), - int_width, int_height, - DefaultDepthOfScreen(wi->screen)); - } - } - else { - /* - * In case of a window reconfiguration following a change - * of border size, set the exposed area to force a copy - * of the back buffer to the screen. - */ - bbox.orig.x = bbox.orig.y = 0; - bbox.corner.x = Tk_Width(wi->win); - bbox.corner.y = Tk_Height(wi->win); - ZnAddBBoxToBBox(&wi->exposed_area, &bbox); - } - ZnNeedRedisplay(wi); - } - /* - * Take into account that the window has been actually cancelled. - * Remove the corresponding widget command, unregister any - * pending Redisplay and eventually free the widget's memory. - */ - else if (event->type == DestroyNotify) { - if (wi->win != NULL) { - wi->win = NULL; - CLEAR(wi->flags, ZN_REALIZED); -#ifdef PTK - Lang_DeleteWidget(wi->interp, wi->cmd); -#else - Tcl_DeleteCommandFromToken(wi->interp, wi->cmd); -#endif - } - if (ISSET(wi->flags, ZN_UPDATE_PENDING)) { - Tcl_CancelIdleCall(Redisplay, (ClientData) wi); - } - Tcl_EventuallyFree((ClientData) wi, Destroy); - } - else if (event->type == FocusIn) { - if (event->xfocus.detail != NotifyInferior) { - Focus(wi, True); - } - } - else if (event->type == FocusOut) { - if (event->xfocus.detail != NotifyInferior) { - Focus(wi, False); - } - } - - /*printf("=============== FIN %s EVENT ==================\n", - event->type == MapNotify ? "MAP": - event->type == Expose? "EXPOSE" : - event->type == ConfigureNotify ? "CONFIGURE" : - event->type == VisibilityNotify ? "VISIBILITY" : - event->type == DestroyNotify ? "DESTROY" : - "??");*/ -} - - -/* - *---------------------------------------------------------------------- - * - * DoEvent -- - * - * Trigger the bindings associated with an event. - * - *---------------------------------------------------------------------- - */ -static void -DoEvent(ZnWInfo *wi, - XEvent *event, - ZnBool bind_item, /* Controls whether item bindings will trigger. - * Useful for Enter/Leaves between fields */ - ZnBool bind_part) /* Controls whether part bindings will trigger. - * Useful for precise control of Enter/Leaves - * during grabs. */ -{ -#define NUM_STATIC 4 - ClientData items[NUM_STATIC], *its; - static unsigned int worksize = 128, len, num, num_tags; - static char *workspace = NULL; - unsigned int i, ptr; - ClientData *tag_list = NULL; - ZnItem item; - int part; - -#define BIND_ITEM(test) \ - if (bind_item && (test)) { \ - its[ptr] = (ClientData) all_uid; \ - ptr++; \ - for (i = 0; i < num_tags; i++) { \ - its[ptr] = tag_list[i]; \ - ptr++; \ - } \ - its[ptr] = (ClientData) item; \ - ptr++; \ - } - - if (wi->binding_table == NULL) { - //printf("no bindings\n"); - return; - } - - item = wi->current_item; - part = wi->current_part; - if ((event->type == KeyPress) || (event->type == KeyRelease)) { - item = wi->focus_item; - part = wi->focus_field; - } - - if ((item == ZN_NO_ITEM) || !item->class->IsSensitive(item, ZN_NO_PART)) { - return; - } - - /* - * Set up an array with all the relevant elements for processing - * this event. The relevant elements are (a) the event's item/part - * tag (i.e item:part), (b) the event's item, (c) the tags - * associated with the event's item, and (d) the tag 'all'. - */ - num = 0; - num_tags = 0; - its = items; - bind_part = (bind_part && - (part != ZN_NO_PART) && - item->class->IsSensitive(item, part) && - ((wi->current_item != ZN_NO_ITEM) && - (wi->current_item->class->num_parts || - wi->current_item->class->GetFieldSet))); - - //printf("type=%s, current=%d, new=%d --> %s, currentp %d, newp %d\n", - // event->type==EnterNotify?"": - // event->type==LeaveNotify?"": - // event->type==MotionNotify?"":"other", - // wi->current_item?wi->current_item->id:0, - // wi->new_item?wi->new_item->id:0, - // bind_item?"bind":"nobind", - // wi->current_part, wi->new_part); - if (bind_item) { - num += 2; - } - if (bind_part) { - num++; - if (!workspace) { - workspace = ZnMalloc(worksize); - } - } - if (item->tags) { - num_tags = ZnListSize(item->tags); - if (bind_item) { - num += num_tags; - } - if (bind_part) { - num += num_tags; - } - tag_list = (ClientData *) ZnListArray(item->tags); - if (num > NUM_STATIC) { - its = (ClientData *) ZnMalloc(num*sizeof(ClientData)); - } - } - - ptr = 0; - - BIND_ITEM(event->type != LeaveNotify); - - if (bind_part) { - /* - * Add here a binding for each tag suffixed by :part - */ - for (i = 0; i < num_tags; i++) { - len = strlen(tag_list[i])+ TCL_INTEGER_SPACE; - if (worksize < len) { - worksize = len + 10; - workspace = ZnRealloc(workspace, len); - } - sprintf(workspace, "%s:%d", (char *) tag_list[i], part); - its[ptr] = (ClientData) Tk_GetUid(workspace); - ptr++; - } - /* - * Add here a binding for id:part - */ - its[ptr] = EncodeItemPart(item, part); - ptr++; - } - - BIND_ITEM(event->type == LeaveNotify); - - /* - * Invoke the binding system. - */ - if (wi->win != NULL) { - Tk_BindEvent(wi->binding_table, event, wi->win, (int) num, its); - } - if (its != items) { - ZnFree(its); - } - -#undef BIND_ITEM -} - - -/* - *---------------------------------------------------------------------- - * - * PickCurrentItem -- - * - * Finds the topmost item/field that contains the pointer and mark - * it has the current item. Generates Enter/leave events on the - * old and new current items/fields has necessary. - * - * Results: - * None. - * - * Side effects: - * The current item/field may change. If it does, - * then the commands associated with item entry and exit - * could do just about anything. A binding script could - * delete the widget, so callers should protect themselves - * with Tcl_Preserve and Tcl_Release. - * - * Note: - * See the Bind function's note. - * - *---------------------------------------------------------------------- - */ -static void -PickCurrentItem(ZnWInfo *wi, - XEvent *event) -{ - int button_down; - ZnBool enter_item; - ZnBool grab_release = False; - - /*printf("PickCurrent current=%d, new=%d\n", - wi->current_item?wi->current_item->id:0, - wi->new_item?wi->new_item->id:0);*/ - /* - * Check whether or not a button is down. If so, we'll log entry - * and exit into and out of the current item, but not entry into - * any other item. This implements a form of grabbing equivalent - * to what the X server does for windows. - */ - button_down = wi->state - & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask); - if (!button_down) { - grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM); - CLEAR(wi->flags, ZN_GRABBED_ITEM); - CLEAR(wi->flags, ZN_GRABBED_PART); - } - - /* - * Save information about this event in the widget. The saved event - * is used for two purposes: - * - * 1. Event bindings: if the current item changes, fake events are - * generated to allow item-enter and item-leave bindings to trigger. - * 2. Reselection: if the current item gets deleted, can use the - * saved event to find a new current item. - * Translate MotionNotify events into EnterNotify events, since that's - * what gets reported to item handlers. - */ - if (event != &wi->pick_event) { - if ((event->type == MotionNotify) || (event->type == ButtonRelease)) { - wi->pick_event.xcrossing.type = EnterNotify; - wi->pick_event.xcrossing.serial = event->xmotion.serial; - wi->pick_event.xcrossing.send_event = event->xmotion.send_event; - wi->pick_event.xcrossing.display = event->xmotion.display; - wi->pick_event.xcrossing.window = event->xmotion.window; - wi->pick_event.xcrossing.root = event->xmotion.root; - wi->pick_event.xcrossing.subwindow = None; - wi->pick_event.xcrossing.time = event->xmotion.time; - wi->pick_event.xcrossing.x = event->xmotion.x; - wi->pick_event.xcrossing.y = event->xmotion.y; - wi->pick_event.xcrossing.x_root = event->xmotion.x_root; - wi->pick_event.xcrossing.y_root = event->xmotion.y_root; - wi->pick_event.xcrossing.mode = NotifyNormal; - wi->pick_event.xcrossing.detail = NotifyNonlinear; - wi->pick_event.xcrossing.same_screen = event->xmotion.same_screen; - wi->pick_event.xcrossing.focus = False; - wi->pick_event.xcrossing.state = event->xmotion.state; - } - else { - wi->pick_event = *event; - } - } - - /* - * If this is a recursive call (there's already a partially completed - * call pending on the stack; it's in the middle of processing a - * Leave event handler for the old current item) then just return; - * the pending call will do everything that's needed. - */ - if (ISSET(wi->flags, ZN_REPICK_IN_PROGRESS)) { - fprintf(stderr, "PickCurrentItem recursive\n"); - return; - } - - /* - * A LeaveNotify event automatically means that there's no current - * object, so the check for closest item can be skipped. - */ - if (wi->pick_event.type != LeaveNotify) { - ZnPickStruct ps; - ZnReal dist; - ZnPoint p; - - p.x = wi->pick_event.xcrossing.x; - p.y = wi->pick_event.xcrossing.y; - ps.point = &p; - ps.in_group = ZN_NO_ITEM; - ps.start_item = ZN_NO_ITEM; - ps.aperture = wi->pick_aperture; - ps.recursive = True; - ps.override_atomic = False; - dist = wi->top_group->class->Pick(wi->top_group, &ps); - if (dist == 0.0) { - wi->new_item = ps.a_item; - wi->new_part = ps.a_part; - } - else { - wi->new_item = ZN_NO_ITEM; - wi->new_part = ZN_NO_PART; - } - } - else { - wi->new_item = ZN_NO_ITEM; - wi->new_part = ZN_NO_PART; - } - /* - * This state is needed to do a valid detection - * of Enter during a grab. - */ - enter_item = ((wi->new_item != wi->current_item) || ISSET(wi->flags, ZN_GRABBED_ITEM)); - - /*printf("------ PickCurrentItem current: %d %d, new %d %d\n", - wi->current_item==ZN_NO_ITEM?0:wi->current_item->id, wi->current_part, - wi->new_item==ZN_NO_ITEM?0:wi->new_item->id, wi->new_part);*/ - - if ((wi->new_item == wi->current_item) && - (wi->new_part == wi->current_part) && - ISCLEAR(wi->flags, ZN_GRABBED_ITEM) && - ISCLEAR(wi->flags, ZN_GRABBED_PART)) { - /* - * Nothing to do: the current item/part hasn't changed. - */ - return; - } - - /* - * Simulate a LeaveNotify event on the previous current item. - * Remove the "current" tag from the previous current item. - */ - if ((wi->current_item != ZN_NO_ITEM) && - (((wi->new_item != wi->current_item) || (wi->new_part != wi->current_part)) && - ISCLEAR(wi->flags, ZN_GRABBED_ITEM))) { - ZnItem item = wi->current_item; - /* - * Actually emit the event only if not releasing a grab - * on button up. - */ - if (!grab_release) { - XEvent event; - event = wi->pick_event; - event.type = LeaveNotify; - - /*printf("== LEAVE %d %d ==\n", wi->current_item->id, wi->current_part);*/ - /* - * If the event's detail happens to be NotifyInferior the - * binding mechanism will discard the event. To be consistent, - * always use NotifyAncestor. - */ - event.xcrossing.detail = NotifyAncestor; - SET(wi->flags, ZN_REPICK_IN_PROGRESS); - DoEvent(wi, &event, - wi->new_item != wi->current_item, ISCLEAR(wi->flags, ZN_GRABBED_PART)); - CLEAR(wi->flags, ZN_REPICK_IN_PROGRESS); - } - - /* - * In all cases, if a grab is not current, remove the current tag. - * - * The check on item below is needed because there could be an - * event handler for that deletes the current item. - */ - if ((item == wi->current_item) && !button_down) { - /*printf("^^^ Removing 'current' from %d\n", wi->current_item->id);*/ - ZnITEM.RemoveTag(item, current_uid); - } - /* - * Note: during DoEvent above, it's possible that - * wi->new_item got reset to NULL because the - * item was deleted. - */ - } - - /* - * Special note: it's possible that wi->new_item == wi->current_item - * here. This can happen, for example, if a grab was set or - * if there is only a change in the part number. - */ - if ((wi->new_item != wi->current_item) && button_down) { - SET(wi->flags, ZN_GRABBED_ITEM); - } - else { - if (button_down) { - grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM); - } - CLEAR(wi->flags, ZN_GRABBED_ITEM); - wi->current_item = wi->new_item; - } - if ((wi->new_part != wi->current_part) && button_down) { - SET(wi->flags, ZN_GRABBED_PART); - } - else { - CLEAR(wi->flags, ZN_GRABBED_PART); - wi->current_part = wi->new_part; - } - - if (!grab_release && - (ISSET(wi->flags, ZN_GRABBED_PART) || ISSET(wi->flags, ZN_GRABBED_ITEM))) { - return; - } - - if (wi->current_item != ZN_NO_ITEM) { - XEvent event; - /* - * Add the tag 'current' to the current item under the pointer. - */ - /*printf("Adding 'current' to %d\n", wi->current_item->id);*/ - ZnDoItem((Tcl_Interp *) NULL, wi->current_item, ZN_NO_PART, current_uid); - /* - * Then emit a fake Enter event on it. - */ - /*printf("== ENTER %d %d ==\n",wi->current_item->id, wi->current_part);*/ - event = wi->pick_event; - event.type = EnterNotify; - event.xcrossing.detail = NotifyAncestor; - DoEvent(wi, &event, - enter_item, !(grab_release && ISSET(wi->flags, ZN_GRABBED_PART))); - } -} - - -/* - *---------------------------------------------------------------------- - * - * Bind -- - * - * This procedure is invoked by the Tk dispatcher to handle - * events associated with bindings on items. - * - * Results: - * None. - * - * Side effects: - * Depends on the command invoked as part of the binding - * (if there was any). - * - * Note: - * This has been taken as is from the Tk canvas. It might not - * not be fully adequate for the purpose. But at least this - * provides two benefits: a/ It is believe to be correct and - * b/ users are accustomed to its behavior. - * - *---------------------------------------------------------------------- - */ -static void -Bind(ClientData client_data, /* Information about widget. */ - XEvent *event) /* Information about event. */ -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - - Tcl_Preserve((ClientData) wi); - - /* - * This code below keeps track of the current modifier state in - * wi->state. This information is used to defer repicks of - * the current item while buttons are down. - */ - if ((event->type == ButtonPress) || (event->type == ButtonRelease)) { - int mask; - - switch (event->xbutton.button) { - case Button1: - mask = Button1Mask; - break; - case Button2: - mask = Button2Mask; - break; - case Button3: - mask = Button3Mask; - break; - case Button4: - mask = Button4Mask; - break; - case Button5: - mask = Button5Mask; - break; - default: - mask = 0; - break; - } - /* - * For button press events, repick the current item using the - * button state before the event, then process the event. For - * button release events, first process the event, then repick - * the current item using the button state *after* the event - * (the button has logically gone up before we change the - * current item). - */ - - if (event->type == ButtonPress) { - /* - * On a button press, first repick the current item using - * the button state before the event, then process the event. - */ - wi->state = event->xbutton.state; - PickCurrentItem(wi, event); - wi->state ^= mask; - if (wi->current_item != ZN_NO_ITEM) { - DoEvent(wi, event, True, True); - } - } - else { - /* - * Button release: first process the event, with the button - * still considered to be down. Then repick the current - * item under the assumption that the button is no longer down. - */ - wi->state = event->xbutton.state; - DoEvent(wi, event, True, True); - event->xbutton.state ^= mask; - wi->state = event->xbutton.state; - PickCurrentItem(wi, event); - event->xbutton.state ^= mask; - } - goto done; - } - - else if ((event->type == EnterNotify) || (event->type == LeaveNotify)) { - wi->state = event->xcrossing.state; - PickCurrentItem(wi, event); - goto done; - } - - else if (event->type == MotionNotify) { - wi->state = event->xmotion.state; - if (wi->follow_pointer) { - PickCurrentItem(wi, event); - } - else { - /* Copy the event for later processing - * and skip the picking phase. - */ - wi->pick_event = *event; - } - } - - DoEvent(wi, event, True, True); - -done: - Tcl_Release((ClientData) wi); -} - - -/* - *---------------------------------------------------------------------- - * - * LostSelection -- - * - * This procedure is called back by Tk when the selection is - * grabbed away from a zinc widget. - * - * Results: - * None. - * - * Side effects: - * The existing selection is unhighlighted, and the window is - * marked as not containing a selection. - * - *---------------------------------------------------------------------- - */ -static void -LostSelection(ClientData client_data) -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - ZnTextInfo *ti = &wi->text_info; - - if (ti->sel_item != ZN_NO_ITEM) { - ZnITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG); - } - ti->sel_item = ZN_NO_ITEM; - ti->sel_field = ZN_NO_PART; -} - - -/* - *---------------------------------------------------------------------- - * - * SelectTo -- - * - * Modify the selection by moving its un-anchored end. This could - * make the selection either larger or smaller. - * - * Results: - * None. - * - * Side effects: - * The selection changes. - * - *---------------------------------------------------------------------- - */ -static void -SelectTo(ZnItem item, - int field, - int index) -{ - ZnWInfo *wi = item->wi; - ZnTextInfo *ti = &wi->text_info; - int old_first, old_last, old_field; - ZnItem old_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 (ti->sel_item == ZN_NO_ITEM) { - Tk_OwnSelection(wi->win, XA_PRIMARY, LostSelection, (ClientData) wi); - } - else if ((ti->sel_item != item) || (ti->sel_field != field)) { - ZnITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG); - } - ti->sel_item = item; - ti->sel_field = field; - - if ((ti->anchor_item != item) || (ti->anchor_field) != field) { - ti->anchor_item = item; - ti->anchor_field = field; - ti->sel_anchor = index; - } - if (ti->sel_anchor <= index) { - ti->sel_first = ti->sel_anchor; - ti->sel_last = index; - } - else { - ti->sel_first = index; - ti->sel_last = ti->sel_anchor; - } - if ((ti->sel_first != old_first) || - (ti->sel_last != old_last) || - (item != old_sel_item)) { - ZnITEM.Invalidate(item, ZN_DRAW_FLAG); - } -} - - -/* - *-------------------------------------------------------------- - * - * FetchSelection -- - * - * This procedure is invoked by Tk to return part or all of - * the selection, when the selection is in a zinc widget. - * This procedure always returns the selection as a STRING. - * - * Results: - * The return value is the number of non-NULL bytes stored - * at buffer. Buffer is filled (or partially filled) with a - * NULL-terminated string containing part or all of the selection, - * as given by offset and maxBytes. - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ -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. */ - int max_bytes) /* Maximum number of bytes to place - * at buffer, not including terminating - * NULL character. */ -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - ZnTextInfo *ti = &wi->text_info; - - if (ti->sel_item == ZN_NO_ITEM) { - return -1; - } - if (ti->sel_item->class->Selection == NULL) { - return -1; - } - return (*ti->sel_item->class->Selection)(ti->sel_item, ti->sel_field, - offset, buffer, max_bytes); -} - - -/* - *---------------------------------------------------------------------- - * - * CmdDeleted -- - * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. - * - * Results: - * None. - * - * Side effects: - * The widget is destroyed. - * - *---------------------------------------------------------------------- - */ -static void -CmdDeleted(ClientData client_data) /* Pointer to widget record for widget. */ -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - - if (wi->win != NULL) { - Tk_DestroyWindow(wi->win); - wi->win = NULL; - } -} - - -/* - *---------------------------------------------------------------------- - * - * Destroy -- - * - * This procedure is invoked by Tk_EventuallyFree or Tk_Release - * to clean up the internal structure of the widget at a safe time - * (when no-one is using it anymore). - * - * Results: - * None. - * - * Side effects: - * Everything associated with the widget is freed up. - * - *---------------------------------------------------------------------- - */ -static void -Destroy(char *mem_ptr) /* Info about the widget. */ -{ - ZnWInfo *wi = (ZnWInfo *) mem_ptr; - unsigned int num; - Tcl_HashSearch search; - Tcl_HashEntry *entry; -#ifdef GL - unsigned int i; - ZnGLContextEntry *ce; - ZnWInfo **wip; -#endif - - /*printf("Destroy begining\n");*/ - /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case win - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. - */ - /* - * Unregister form the overlap manager. - */ -#ifdef ATC - if (wi->om_group != ZN_NO_ITEM) { - OmUnregister((void *) wi); - } -#endif - - /* - * Print remaining items. - */ - - /* Free all items. */ - /*fprintf(stderr, "Item count before cleanup: %d\n", wi->num_items);*/ - ZnITEM.DestroyItem(wi->top_group); - /*fprintf(stderr, "Remaining item count: %d\n", wi->num_items);*/ - /* - * Remove the redisplay scheduled by the cleanup. - * It will fire when the widget will be gone and - * will corrupt memory. - */ - if (ISSET(wi->flags, ZN_UPDATE_PENDING)) { - Tcl_CancelIdleCall(Redisplay, (ClientData) wi); - } - - for (num = 0; num < ZN_NUM_ALPHA_STEPS; num++) { - if (wi->alpha_stipples[num] != None) { - Tk_FreeBitmap(wi->dpy, wi->alpha_stipples[num]); - wi->alpha_stipples[num] = None; - } - } - - Tcl_DeleteHashTable(wi->id_table); - ZnFree(wi->id_table); - - /* - * Free the transform table contents. - */ - entry = Tcl_FirstHashEntry(wi->t_table, &search); - while (entry != NULL) { - ZnTransfoFree((ZnTransfo *) Tcl_GetHashValue(entry)); - entry = Tcl_NextHashEntry(&search); - } - Tcl_DeleteHashTable(wi->t_table); - ZnFree(wi->t_table); - - if (wi->binding_table != NULL) { - Tk_DeleteBindingTable(wi->binding_table); - } - - /* Free the tile */ - if (wi->tile != ZnUnspecifiedImage) { -#ifdef PTK_800 - ZnFreeImage(wi->tile, ZnImageUpdate, wi); -#else - ZnFreeImage(wi->tile, TileUpdate, wi); -#endif - wi->tile = ZnUnspecifiedImage; - } - -#ifdef ATC - /* Free the symbols */ - if (wi->map_distance_symbol != ZnUnspecifiedImage) { - ZnFreeImage(wi->map_distance_symbol, NULL, NULL); - wi->map_distance_symbol = ZnUnspecifiedImage; - } - if (wi->track_symbol != ZnUnspecifiedImage) { - ZnFreeImage(wi->track_symbol, NULL, NULL); - wi->track_symbol = ZnUnspecifiedImage; - } -#endif - - /* Free the double buffer pixmap/image */ - if (wi->draw_buffer) { - Tk_FreePixmap(wi->dpy, wi->draw_buffer); - wi->draw_buffer = 0; - } - -#ifdef PTK_800 - if (wi->fore_color) { - ZnFreeGradient(wi->fore_color); - wi->fore_color = NULL; - } - if (wi->back_color) { - ZnFreeGradient(wi->back_color); - wi->back_color = NULL; - } -#endif - if (wi->relief_grad) { - ZnFreeGradient(wi->relief_grad); - wi->relief_grad = NULL; - } - if (wi->gc) { - XFreeGC(wi->dpy, wi->gc); - wi->gc = 0; - } - - Tcl_DeleteTimerHandler(wi->blink_handler); - -#ifdef PTK_800 - Tk_FreeOptions(config_specs, (char *) wi, wi->dpy, 0); -#else - Tk_FreeConfigOptions((char *) wi, wi->opt_table, wi->win); -#endif - -#ifdef GL - if (wi->font_tfi) { - ZnFreeTexFont(wi->font_tfi); - wi->font_tfi = NULL; - } -#ifdef ATC - if (wi->map_font_tfi) { - ZnFreeTexFont(wi->map_font_tfi); - wi->map_font_tfi = NULL; - } -#endif - /* - * Remove the widget from the context list and - * free the context if no more widgets are active. - */ - ce = ZnGetGLContext(wi->dpy); - if (ce) { - wip = ZnListArray(ce->widgets); - num = ZnListSize(ce->widgets); - for (i = 0; i < num; i++, wip++) { - if (*wip == wi) { - ZnListDelete(ce->widgets, i); - } - } - /* - * This code cause spurious X11 server reboots - * with nvidia drivers (not tested with others - * though). Thus it has been limited to WIN for - * the time being. - */ -#if 1 /*def _WIN32*/ - if (ZnListSize(ce->widgets) == 0) { - ZnGLContextEntry *prev, *next; - /*printf("Freeing a GL context\n");*/ - if (ce == gl_contexts) { - gl_contexts = ce->next; - } - else { - for (prev = gl_contexts, next = gl_contexts->next; next; - prev = next, next = next->next) { - if (next == ce) { - prev->next = next->next; - break; - } - } - } -#ifdef _WIN32 - ZnGLReleaseContext(ce); - wglDeleteContext(ce->context); -#else - glXDestroyContext(ce->dpy, ce->context); - /* - * This call seems to be a problem for X11/Mesa - */ - /*XFreeColormap(ce->dpy, ce->colormap);*/ - XFree(ce->visual); -#endif - ZnListFree(ce->widgets); - ZnFree(ce); - } -#endif - } -#endif - /* - if (wi->font) { - Tk_FreeFont(wi->font); - } - if (wi->map_text_font) { - Tk_FreeFont(wi->map_text_font); - }*/ - - /* - * Should be empty by now. - */ - ZnFreeTransformStack(wi); - ZnFreeClipStack(wi); - -#ifndef _WIN32 - ZnFreeChrono(wi->total_draw_chrono); - ZnFreeChrono(wi->this_draw_chrono); -#endif - - ZnFree(wi); - /*printf("Destroy ending\n");*/ -} - - -/* - ********************************************************************************** - * - * ZnDamage -- - * - ********************************************************************************** - */ -void -ZnDamage(ZnWInfo *wi, - ZnBBox *damage) -{ - if ((damage == NULL) || ZnIsEmptyBBox(damage)) { - return; - } - - /*printf("damaging area: %g %g %g %g\n", damage->orig.x, - damage->orig.y, damage->corner.x, damage->corner.y);*/ - - if (ZnIsEmptyBBox(&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; - ZnNeedRedisplay(wi); - } - 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);*/ -} - -void -ZnDamageAll(ZnWInfo *wi) -{ - ZnBBox bbox; - - bbox.orig.x = bbox.orig.y = 0; - bbox.corner.x = Tk_Width(wi->win); - bbox.corner.y = Tk_Height(wi->win); - ZnDamage(wi, &bbox); -} - -static void -ClampDamageArea(ZnWInfo *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; - } -} - - -/* - ********************************************************************************** - * - * Update -- - * - ********************************************************************************** - */ -static void -Update(ZnWInfo *wi) -{ - /* - * Give the overlap manager a chance to do its work. - */ -#ifdef ATC - 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 - 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 -Repair(ZnWInfo *wi) -{ - XGCValues values; - ZnPoint p[5]; - ZnTriStrip tristrip; -#ifdef GL - XColor *color; - ZnGLContextEntry *ce; -#endif - int int_width = Tk_Width(wi->win); - int int_height = Tk_Height(wi->win); - - /*SET(wi->flags, ZN_CONFIGURE_EVENT);*/ - if (wi->render) { -#ifdef GL - /* Load deferred font glyphs just before making the context - * current. Mandatory under Windows (probably due to hdc use conflict). - */ - ZnGetDeferredGLGlyphs(); - - ZnGLWaitX(); -#ifdef GL_DAMAGE - if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) { - ClampDamageArea(wi); - /* - * Merge the exposed area. - */ - ZnAddBBoxToBBox(&wi->damaged_area, &wi->exposed_area); - if (ZnIsEmptyBBox(&wi->damaged_area)) { - return; - } - } -#endif - - /*printf("Repair, scissors: %d\n", ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT));*/ - ce = ZnGLMakeCurrent(wi->dpy, wi); - glEnable(GL_POINT_SMOOTH); - glEnable(GL_LINE_SMOOTH); -#if 0 - glEnable(GL_POLYGON_SMOOTH); /* expensive ? */ -#endif - - glEnable(GL_BLEND); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glClearStencil(0); - color = ZnGetGradientColor(wi->back_color, 0.0, NULL); - glClearColor((GLfloat) color->red/65536, (GLfloat) color->green/65536, - (GLfloat) color->blue/65536, 0.0); - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - /* - * Init the composite group alpha. - */ - wi->alpha = 100; - - glViewport(0, 0, (GLsizei) int_width, int_height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, (GLfloat) int_width, (GLfloat) int_height, 0.0, -1.0, 1.0); - glMatrixMode(GL_MODELVIEW); - -#ifdef GL_DAMAGE - if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) { - glEnable(GL_SCISSOR_TEST); - - /* - * Set the damaged area as the scissor area. - */ - wi->damaged_area.orig.x = ZnNearestInt(wi->damaged_area.orig.x); - wi->damaged_area.orig.y = ZnNearestInt(wi->damaged_area.orig.y); - wi->damaged_area.corner.x = ZnNearestInt(wi->damaged_area.corner.x); - wi->damaged_area.corner.y = ZnNearestInt(wi->damaged_area.corner.y); - glScissor((int) wi->damaged_area.orig.x, - int_height - (int) wi->damaged_area.corner.y, - (int) (wi->damaged_area.corner.x - wi->damaged_area.orig.x), - (int) (wi->damaged_area.corner.y - wi->damaged_area.orig.y)); - } - else { - glDisable(GL_SCISSOR_TEST); - 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; - } -#else - /* - * We do not use the damaged area set it to the whole area. - */ - 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 - - /* - * Clear the GL buffers. - */ - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - /* - * Setup the background tile if needed. - */ - if (wi->tile != ZnUnspecifiedImage) { - ZnBBox bbox; - - bbox.orig.x = bbox.orig.y = 0.0; - bbox.corner.x = int_width; - bbox.corner.y = int_height; - - ZnRenderTile(wi, wi->tile, NULL, NULL, NULL, (ZnPoint *) &bbox); - } - - wi->top_group->class->Render(wi->top_group); - - if ((wi->border_width > 0) || (wi->highlight_width > 0)) { - unsigned short alpha; - -#ifdef GL_DAMAGE - if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) { - glDisable(GL_SCISSOR_TEST); - } -#endif - if (wi->highlight_width > 0) { - color = ZnGetGradientColor(ISSET(wi->flags, ZN_GOT_FOCUS)?wi->highlight_color: - wi->highlight_bg_color, 0.0, &alpha); - alpha = ZnComposeAlpha(alpha, 100); - glColor4us(color->red, color->green, color->blue, alpha); - - glBegin(GL_QUAD_STRIP); - glVertex2d(0.0, 0.0); - glVertex2i(wi->highlight_width, wi->highlight_width); - glVertex2i(int_width, 0); - glVertex2i(int_width - wi->highlight_width, wi->highlight_width); - glVertex2i(int_width, int_height); - glVertex2i(int_width - wi->highlight_width, int_height - wi->highlight_width); - glVertex2i(0, int_height); - glVertex2i(wi->highlight_width, int_height - wi->highlight_width); - glVertex2i(0, 0); - glVertex2i(wi->highlight_width, wi->highlight_width); - glEnd(); - } - if (wi->border_width > 0) { - if (wi->relief != ZN_RELIEF_FLAT) { - 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; - ZnRenderPolygonRelief(wi, wi->relief, wi->relief_grad, - False, p, 5, (ZnReal) wi->border_width); - } - else { - color = ZnGetGradientColor(wi->back_color, 0.0, &alpha); - alpha = ZnComposeAlpha(alpha, 100); - glColor4us(color->red, color->green, color->blue, alpha); - - glBegin(GL_QUAD_STRIP); - glVertex2d(0.0, 0.0); - glVertex2i(wi->highlight_width, wi->highlight_width); - glVertex2i(int_width, 0); - glVertex2i(int_width - wi->highlight_width, wi->highlight_width); - glVertex2i(int_width, int_height); - glVertex2i(int_width - wi->highlight_width, int_height - wi->highlight_width); - glVertex2i(0, int_height); - glVertex2i(wi->highlight_width, int_height - wi->highlight_width); - glVertex2i(0, 0); - glVertex2i(wi->highlight_width, wi->highlight_width); - glEnd(); - } - } - - CLEAR(wi->flags, ZN_CONFIGURE_EVENT); - } - - /* Switch the GL buffers. */ - /* The scissor test might be needed under windows, should be tested. - * Symptom: when moving the window, the buffer switch results in a - * shifted display all around the damaged area. - */ -#ifdef GL_DAMAGE - if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) { - glEnable(GL_SCISSOR_TEST); - } -#endif - ZnGLSwapBuffers(ce, wi); - - /* - * Wait the end of GL update if we need to synchronize - * to monitor perfs. - */ - if (ISSET(wi->flags, ZN_MONITORING)) { - ZnGLWaitGL(); - } - - ZnGLReleaseContext(ce); -#endif - } - else { - XRectangle r, rs[4]; - ZnBBox merge; - - ClampDamageArea(wi); - /* -m * Merge the damaged area with the exposed area. - */ - ZnResetBBox(&merge); - ZnCopyBBox(&wi->damaged_area, &merge); - ZnAddBBoxToBBox(&merge, &wi->exposed_area); - if (!ZnIsEmptyBBox(&merge)) { - - /* Set the whole damaged area as clip rect. */ - wi->damaged_area.orig.x = r.x = ZnNearestInt(wi->damaged_area.orig.x); - wi->damaged_area.orig.y = r.y = ZnNearestInt(wi->damaged_area.orig.y); - wi->damaged_area.corner.x = ZnNearestInt(wi->damaged_area.corner.x); - wi->damaged_area.corner.y = ZnNearestInt(wi->damaged_area.corner.y); - r.width = (unsigned short) (wi->damaged_area.corner.x - wi->damaged_area.orig.x); - r.height = (unsigned short) (wi->damaged_area.corner.y - wi->damaged_area.orig.y); - p[0] = wi->damaged_area.orig; - p[1] = wi->damaged_area.corner; - ZnTriStrip1(&tristrip, p, 2, False); - ZnPushClip(wi, &tristrip, True, True); - - /* Fill the background of the double buffer pixmap. */ - if (wi->tile == ZnUnspecifiedImage) { - values.foreground = ZnGetGradientPixel(wi->back_color, 0.0); - values.fill_style = FillSolid; - XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &values); - } - else { - values.fill_style = FillTiled; - values.tile = ZnImagePixmap(wi->tile, wi->win); - values.ts_x_origin = values.ts_y_origin = 0; - XChangeGC(wi->dpy, wi->gc, - GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin, - &values); - } - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y, r.width, r.height); - - /* Draw the items */ - 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); - ZnBBox2XRect(&merge, &r); - XCopyArea(wi->dpy, - wi->draw_buffer, Tk_WindowId(wi->win), wi->gc, - r.x, r.y, r.width, r.height, r.x, r.y); - } - - /* - * Redraw the borders. - */ - if (wi->border_width > 0) { - Pixmap save; - - save = wi->draw_buffer; - wi->draw_buffer = Tk_WindowId(wi->win); - if (wi->relief_grad != ZN_RELIEF_FLAT) { - r.x = r.y = wi->highlight_width; - r.width = int_width - 2*wi->highlight_width; - r.height = int_height - 2*wi->highlight_width; - ZnDrawRectangleRelief(wi, wi->relief, wi->relief_grad, &r, - (ZnDim) wi->border_width); - } - else { - XSetForeground(wi->dpy, wi->gc, ZnGetGradientPixel(wi->back_color, 0.0)); - XSetFillStyle(wi->dpy, wi->gc, FillSolid); - rs[0].x = rs[0].y = wi->highlight_width; - rs[0].width = int_width - 2*wi->highlight_width; - rs[0].height = wi->border_width; - rs[1].x = int_width - wi->highlight_width - wi->border_width; - rs[1].y = 0; - rs[1].width = wi->border_width; - rs[1].height = int_height - 2*wi->highlight_width; - rs[2].x = 0; - rs[2].y = int_height - wi->highlight_width - wi->border_width; - rs[2].width = rs[0].width; - rs[2].height = wi->border_width; - rs[3].x = rs[3].y = wi->highlight_width; - rs[3].width = wi->border_width; - rs[3].height = rs[1].height; - XFillRectangles(wi->dpy, Tk_WindowId(wi->win), wi->gc, rs, 4); - } - wi->draw_buffer = save; - } - if (wi->highlight_width > 0) { - XSetForeground(wi->dpy, wi->gc, - ZnGetGradientPixel(ISSET(wi->flags, ZN_GOT_FOCUS)?wi->highlight_color: - wi->highlight_bg_color, 0.0)); - XSetFillStyle(wi->dpy, wi->gc, FillSolid); - rs[0].x = rs[0].y = 0; - rs[0].width = int_width; - rs[0].height = wi->highlight_width; - rs[1].x = int_width - wi->highlight_width; - rs[1].y = 0; - rs[1].width = wi->highlight_width; - rs[1].height = int_height; - rs[2].x = 0; - rs[2].y = int_height - wi->highlight_width; - rs[2].width = int_width; - rs[2].height = wi->highlight_width; - rs[3].x = rs[3].y = 0; - rs[3].width = wi->highlight_width; - rs[3].height = int_height; - XFillRectangles(wi->dpy, Tk_WindowId(wi->win), wi->gc, rs, 4); - } - } -} - - -/* - *---------------------------------------------------------------------- - * - * 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. - * - *---------------------------------------------------------------------- - */ - -static void -Redisplay(ClientData client_data) /* Information about the widget. */ -{ - ZnWInfo *wi = (ZnWInfo *) client_data; - - CLEAR(wi->flags, ZN_UPDATE_PENDING); - if (ISCLEAR(wi->flags, ZN_REALIZED) || !Tk_IsMapped(wi->win)) { - return; - } - - if (ISSET(wi->flags, ZN_MONITORING)) { -#ifndef _WIN32 - ZnXStartChrono(wi->total_draw_chrono, wi->dpy, Tk_WindowId(wi->win)); - ZnResetChronos(wi->this_draw_chrono); - ZnXStartChrono(wi->this_draw_chrono, wi->dpy, Tk_WindowId(wi->win)); -#endif - } - - do { - /* - * Update the items. - */ - 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->flags, ZN_INTERNAL_NEED_REPICK)) { - Tk_Window tkwin; - - if (wi->follow_pointer) { - Tcl_Preserve((ClientData) wi); - CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK); - PickCurrentItem(wi, &wi->pick_event); - tkwin = wi->win; - Tcl_Release((ClientData) wi); - if (tkwin == NULL) { - return; - } - } - else if (ISCLEAR(wi->top_group->inv_flags, ZN_COORDS_FLAG) && - ISCLEAR(wi->top_group->inv_flags, ZN_TRANSFO_FLAG)) { - /* Don't repick now but escape the loop if - * the geometry is updated. */ - break; - } - } - } - while (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) || - ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG) || - ISSET(wi->flags, ZN_INTERNAL_NEED_REPICK)); - - /* - * 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. - */ - ZnResetBBox(&wi->exposed_area); - ZnResetBBox(&wi->damaged_area); - - if (ISSET(wi->flags, ZN_MONITORING)) { -#ifndef _WIN32 - ZnXStopChrono(wi->total_draw_chrono, wi->dpy, Tk_WindowId(wi->win)); - ZnXStopChrono(wi->this_draw_chrono, wi->dpy, Tk_WindowId(wi->win)); -#endif - } - - if (ISSET(wi->flags, ZN_UPDATE_SCROLLBARS)) { - UpdateScrollbars(wi); - } -} - -#ifndef _WIN32 -#define CALLBACK -#endif - -static void CALLBACK -ZnTessBegin(GLenum type, - void *data) -{ - ZnPoly *outlines = data; - ZnTriStrip *tristrips = data; - - ZnListEmpty(ZnWorkPoints); - ZnTesselator.type = type; - if (type == GL_LINE_LOOP) { - outlines->num_contours++; - outlines->contours = ZnRealloc(outlines->contours, - outlines->num_contours * sizeof(ZnContour)); - } - else { - tristrips->num_strips++; - tristrips->strips = ZnRealloc(tristrips->strips, - tristrips->num_strips * sizeof(ZnStrip)); - tristrips->strips[tristrips->num_strips-1].fan = (type==GL_TRIANGLE_FAN); - } - //printf("Début de fragment de type: %s\n", - //(type == GL_TRIANGLE_FAN) ? "FAN" : - //(type == GL_TRIANGLE_STRIP) ? "STRIP" : - //(type == GL_TRIANGLES) ? "TRIANGLES" : - //(type == GL_LINE_LOOP) ? "LINE LOOP" : ""); -} - -static void CALLBACK -ZnTessVertex(void *vertex_data, - void *data) -{ - ZnTriStrip *tristrips = data; - ZnPoint p; - int size; - - p.x = ((GLdouble *) vertex_data)[0]; - p.y = ((GLdouble *) vertex_data)[1]; - //printf("Sommet en %g %g\n", p.x, p.y); - size = ZnListSize(ZnWorkPoints); - if ((ZnTesselator.type == GL_TRIANGLES) && (size == 3)) { - tristrips->strips[tristrips->num_strips-1].num_points = size; - tristrips->strips[tristrips->num_strips-1].points = ZnMalloc(size * sizeof(ZnPoint)); - memcpy(tristrips->strips[tristrips->num_strips-1].points, - ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint)); - //printf("Fin de fragment intermediaire %d, num points: %d\n", tristrips->num_strips-1, size); - /* Allocate a new fragment */ - ZnListEmpty(ZnWorkPoints); - tristrips->num_strips++; - tristrips->strips = ZnRealloc(tristrips->strips, - tristrips->num_strips * sizeof(ZnStrip)); - tristrips->strips[tristrips->num_strips-1].fan = False; - } - ZnListAdd(ZnWorkPoints, &p, ZnListTail); -} - -static void CALLBACK -ZnTessEnd(void *data) -{ - ZnPoly *outlines = data; - ZnTriStrip *tristrips = data; - unsigned int size = ZnListSize(ZnWorkPoints); - unsigned int num; - - if (ZnTesselator.type == GL_LINE_LOOP) { - /* Add the last point to close the outline */ - size++; - num = outlines->num_contours; - outlines->contours[num-1].num_points = size; - outlines->contours[num-1].points = ZnMalloc(size * sizeof(ZnPoint)); - memcpy(outlines->contours[num-1].points, - ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint)); - outlines->contours[num-1].points[size-1] = outlines->contours[num-1].points[0]; - outlines->contours[num-1].cw = !ZnTestCCW(outlines->contours[num-1].points, size); - } - else { - num = tristrips->num_strips; - tristrips->strips[num-1].num_points = size; - tristrips->strips[num-1].points = ZnMalloc(size * sizeof(ZnPoint)); - memcpy(tristrips->strips[num-1].points, - ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint)); - } - //printf("Fin de fragment %d, num points: %d\n", num, size); -} - -static void CALLBACK -ZnTessCombine(GLdouble coords[3], - void *vertex_data[4], - GLfloat weight[4], - void **out_data, - void *data) -{ - ZnCombineData *cdata; - - cdata = ZnMalloc(sizeof(ZnCombineData)); - cdata->v[0] = coords[0]; - cdata->v[1] = coords[1]; - cdata->next = ZnTesselator.combine_list; - ZnTesselator.combine_list = cdata; - *out_data = &cdata->v; - ZnTesselator.combine_length++; - //printf("Création d'un nouveau sommet en %g %g\n", - //cdata->v[0], cdata->v[1]); -} - -static void CALLBACK -ZnTessError(GLenum errno, - void *data) -{ - fprintf(stderr, "Tesselation error in curve item: %d\n", errno); -} - - -static void -InitZinc(Tcl_Interp *interp) { - static ZnBool inited = False; - unsigned int i, x, y, bit; - char name[TCL_INTEGER_SPACE + 20]; - - if (inited) { - return; - } - - /* - * Add the specific bitmaps. - */ - for (i = 0; i < sizeof(SYMBOLS_BITS)/(SYMBOL_WIDTH*SYMBOL_HEIGHT/8); i++) { - sprintf(name, "AtcSymbol%d", i+1); - Tk_DefineBitmap(interp, Tk_GetUid(name), - SYMBOLS_BITS[i], SYMBOL_WIDTH, SYMBOL_HEIGHT); - } - - for (i = 0; i < ZN_NUM_ALPHA_STEPS; i++) { - for (y = 0; y < 4; y++) { - bitmaps[i][y][0] = 0; - for (x = 0; x < 4; x++) { - /* - * Use the dither4x4 matrix to determine if this bit is on - */ - bit = (i >= dither4x4[y][x]) ? 1 : 0; - /* - * set the bit in the array used to make the X Bitmap - * mirror the pattern in x & y to make an 8x8 bitmap. - */ - if (bit) { - bitmaps[i][y][0] |= (1 << x); - bitmaps[i][y][0] |= (1 << (4 + x)); - } - } - bitmaps[i][y][1] = bitmaps[i][y][2] = bitmaps[i][y][3] = bitmaps[i][y][0]; - bitmaps[i][y+4][0] = bitmaps[i][y+4][1] = bitmaps[i][y][0]; - bitmaps[i][y+4][2] = bitmaps[i][y+4][3] = bitmaps[i][y][0]; - bitmaps[i][y+8][0] = bitmaps[i][y+8][1] = bitmaps[i][y][0]; - bitmaps[i][y+8][2] = bitmaps[i][y+8][3] = bitmaps[i][y][0]; - bitmaps[i][y+12][0] = bitmaps[i][y+12][1] = bitmaps[i][y][0]; - bitmaps[i][y+12][2] = bitmaps[i][y+12][3] = bitmaps[i][y][0]; - bitmaps[i][y+16][0] = bitmaps[i][y+16][1] = bitmaps[i][y][0]; - bitmaps[i][y+16][2] = bitmaps[i][y+16][3] = bitmaps[i][y][0]; - bitmaps[i][y+20][0] = bitmaps[i][y+20][1] = bitmaps[i][y][0]; - bitmaps[i][y+20][2] = bitmaps[i][y+20][3] = bitmaps[i][y][0]; - bitmaps[i][y+24][0] = bitmaps[i][y+24][1] = bitmaps[i][y][0]; - bitmaps[i][y+24][2] = bitmaps[i][y+24][3] = bitmaps[i][y][0]; - bitmaps[i][y+28][0] = bitmaps[i][y+28][1] = bitmaps[i][y][0]; - bitmaps[i][y+28][2] = bitmaps[i][y+28][3] = bitmaps[i][y][0]; - } - sprintf(name, "AlphaStipple%d", i); - Tk_DefineBitmap(interp, Tk_GetUid(name), (char *) bitmaps[i], 32, 32); - } - - /* - * Initialize the temporary lists. - */ - ZnWorkPoints = ZnListNew(8, sizeof(ZnPoint)); - ZnWorkXPoints = ZnListNew(8, sizeof(XPoint)); - ZnWorkStrings = ZnListNew(8, sizeof(char *)); - - /* - * Allocate a GLU tesselator. - */ - ZnTesselator.tess = gluNewTess(); - ZnTesselator.combine_list = NULL; - ZnTesselator.combine_length = 0; - gluTessCallback(ZnTesselator.tess, GLU_TESS_BEGIN_DATA, ZnTessBegin); - gluTessCallback(ZnTesselator.tess, GLU_TESS_VERTEX_DATA, ZnTessVertex); - gluTessCallback(ZnTesselator.tess, GLU_TESS_END_DATA, ZnTessEnd); - gluTessCallback(ZnTesselator.tess, GLU_TESS_COMBINE_DATA, ZnTessCombine); - gluTessCallback(ZnTesselator.tess, GLU_TESS_ERROR_DATA, ZnTessError); - gluTessNormal(ZnTesselator.tess, 0.0, 0.0, -1.0); - - /* - * Initialize the item module. - */ - ZnItemInit(); - - 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("!"); - dot_uid = Tk_GetUid("."); - star_uid = Tk_GetUid("*"); - - /* - * Initialise Overlap manager library. - */ -#ifdef ATC - OmInit(); -#endif - - inited = True; -} - -#ifdef BUILD_Tkzinc -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLEXPORT -#endif - -/* - *---------------------------------------------------------------------- - * - * Tkzinc_Init -- - * - * This procedure is invoked by Tcl_AppInit in tkAppInit.c to - * initialize the widget. - * - *---------------------------------------------------------------------- - */ -EXTERN int -Tkzinc_Init(Tcl_Interp *interp) /* Used for error reporting. */ -{ -#ifndef PTK - if ( -# ifdef USE_TCL_STUBS - Tcl_InitStubs(interp, "8.4", 0) -# else - Tcl_PkgRequire(interp, "Tcl", "8.4", 0) -# endif - == NULL) { - return TCL_ERROR; - } - - if ( -# ifdef USE_TK_STUBS - Tk_InitStubs(interp, "8.4", 0) -# else - Tcl_PkgRequire(interp, "Tk", "8.4", 0) -# endif - == NULL) { - return TCL_ERROR; - } -#endif - /* - * Create additional commands - */ - Tcl_CreateObjCommand(interp, "zinc", ZincObjCmd, - (ClientData) Tk_MainWindow(interp), - (Tcl_CmdDeleteProc *) NULL); -#ifdef ATC - Tcl_CreateObjCommand(interp, "mapinfo", ZnMapInfoObjCmd, - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); - Tcl_CreateObjCommand(interp, "videomap", ZnVideomapObjCmd, - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); -#endif - -#ifndef PTK - if (Tcl_PkgProvide(interp, "Tkzinc", VERSION) == TCL_ERROR) { - return TCL_ERROR; - } -#endif - - return TCL_OK; -} - -EXTERN int -Tkzinc_debug_Init(Tcl_Interp *interp) /* Used for error reporting. */ -{ - return Tkzinc_Init(interp); -} - -#ifdef _WIN32 -/* - *---------------------------------------------------------------------- - * - * DllEntryPoint -- - * - * This wrapper function is used by Windows to invoke the - * initialization code for the DLL. If we are compiling - * with Visual C++, this routine will be renamed to DllMain. - * routine. - * - * Results: - * Returns TRUE; - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -BOOL APIENTRY -DllEntryPoint(HINSTANCE hInst, /* Library instance handle. */ - DWORD reason, /* Reason this function is being called. */ - LPVOID reserved) /* Not used. */ -{ - return TRUE; -} -#endif -- cgit v1.1