/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkcanvline.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkcanvline.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 70 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkCanvLine.c --   * tkCanvLine.c --
5   *   *
6   *      This file implements line items for canvas widgets.   *      This file implements line items for canvas widgets.
7   *   *
8   * Copyright (c) 1991-1994 The Regents of the University of California.   * Copyright (c) 1991-1994 The Regents of the University of California.
9   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
10   * Copyright (c) 1998-1999 by Scriptics Corporation.   * Copyright (c) 1998-1999 by Scriptics Corporation.
11   *   *
12   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
13   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14   *   *
15   * RCS: @(#) $Id: tkcanvline.c,v 1.1.1.1 2001/06/13 04:56:46 dtashley Exp $   * RCS: @(#) $Id: tkcanvline.c,v 1.1.1.1 2001/06/13 04:56:46 dtashley Exp $
16   */   */
17    
18  #include <stdio.h>  #include <stdio.h>
19  #include "tkInt.h"  #include "tkInt.h"
20  #include "tkPort.h"  #include "tkPort.h"
21  #include "tkCanvas.h"  #include "tkCanvas.h"
22    
23  /*  /*
24   * The structure below defines the record for each line item.   * The structure below defines the record for each line item.
25   */   */
26    
27  typedef enum {  typedef enum {
28      ARROWS_NONE, ARROWS_FIRST, ARROWS_LAST, ARROWS_BOTH      ARROWS_NONE, ARROWS_FIRST, ARROWS_LAST, ARROWS_BOTH
29  } Arrows;  } Arrows;
30    
31  typedef struct LineItem  {  typedef struct LineItem  {
32      Tk_Item header;             /* Generic stuff that's the same for all      Tk_Item header;             /* Generic stuff that's the same for all
33                                   * types.  MUST BE FIRST IN STRUCTURE. */                                   * types.  MUST BE FIRST IN STRUCTURE. */
34      Tk_Outline outline;         /* Outline structure */      Tk_Outline outline;         /* Outline structure */
35      Tk_Canvas canvas;           /* Canvas containing item.  Needed for      Tk_Canvas canvas;           /* Canvas containing item.  Needed for
36                                   * parsing arrow shapes. */                                   * parsing arrow shapes. */
37      int numPoints;              /* Number of points in line (always >= 0). */      int numPoints;              /* Number of points in line (always >= 0). */
38      double *coordPtr;           /* Pointer to malloc-ed array containing      double *coordPtr;           /* Pointer to malloc-ed array containing
39                                   * x- and y-coords of all points in line.                                   * x- and y-coords of all points in line.
40                                   * X-coords are even-valued indices, y-coords                                   * X-coords are even-valued indices, y-coords
41                                   * are corresponding odd-valued indices. If                                   * are corresponding odd-valued indices. If
42                                   * the line has arrowheads then the first                                   * the line has arrowheads then the first
43                                   * and last points have been adjusted to refer                                   * and last points have been adjusted to refer
44                                   * to the necks of the arrowheads rather than                                   * to the necks of the arrowheads rather than
45                                   * their tips.  The actual endpoints are                                   * their tips.  The actual endpoints are
46                                   * stored in the *firstArrowPtr and                                   * stored in the *firstArrowPtr and
47                                   * *lastArrowPtr, if they exist. */                                   * *lastArrowPtr, if they exist. */
48      int capStyle;               /* Cap style for line. */      int capStyle;               /* Cap style for line. */
49      int joinStyle;              /* Join style for line. */      int joinStyle;              /* Join style for line. */
50      GC arrowGC;                 /* Graphics context for drawing arrowheads. */      GC arrowGC;                 /* Graphics context for drawing arrowheads. */
51      Arrows arrow;               /* Indicates whether or not to draw arrowheads:      Arrows arrow;               /* Indicates whether or not to draw arrowheads:
52                                   * "none", "first", "last", or "both". */                                   * "none", "first", "last", or "both". */
53      float arrowShapeA;          /* Distance from tip of arrowhead to center. */      float arrowShapeA;          /* Distance from tip of arrowhead to center. */
54      float arrowShapeB;          /* Distance from tip of arrowhead to trailing      float arrowShapeB;          /* Distance from tip of arrowhead to trailing
55                                   * point, measured along shaft. */                                   * point, measured along shaft. */
56      float arrowShapeC;          /* Distance of trailing points from outside      float arrowShapeC;          /* Distance of trailing points from outside
57                                   * edge of shaft. */                                   * edge of shaft. */
58      double *firstArrowPtr;      /* Points to array of PTS_IN_ARROW points      double *firstArrowPtr;      /* Points to array of PTS_IN_ARROW points
59                                   * describing polygon for arrowhead at first                                   * describing polygon for arrowhead at first
60                                   * point in line.  First point of arrowhead                                   * point in line.  First point of arrowhead
61                                   * is tip.  Malloc'ed.  NULL means no arrowhead                                   * is tip.  Malloc'ed.  NULL means no arrowhead
62                                   * at first point. */                                   * at first point. */
63      double *lastArrowPtr;       /* Points to polygon for arrowhead at last      double *lastArrowPtr;       /* Points to polygon for arrowhead at last
64                                   * point in line (PTS_IN_ARROW points, first                                   * point in line (PTS_IN_ARROW points, first
65                                   * of which is tip).  Malloc'ed.  NULL means                                   * of which is tip).  Malloc'ed.  NULL means
66                                   * no arrowhead at last point. */                                   * no arrowhead at last point. */
67      Tk_SmoothMethod *smooth;    /* Non-zero means draw line smoothed (i.e.      Tk_SmoothMethod *smooth;    /* Non-zero means draw line smoothed (i.e.
68                                   * with Bezier splines). */                                   * with Bezier splines). */
69      int splineSteps;            /* Number of steps in each spline segment. */      int splineSteps;            /* Number of steps in each spline segment. */
70  } LineItem;  } LineItem;
71    
72  /*  /*
73   * Number of points in an arrowHead:   * Number of points in an arrowHead:
74   */   */
75    
76  #define PTS_IN_ARROW 6  #define PTS_IN_ARROW 6
77    
78  /*  /*
79   * Prototypes for procedures defined in this file:   * Prototypes for procedures defined in this file:
80   */   */
81    
82  static int              ArrowheadPostscript _ANSI_ARGS_((Tcl_Interp *interp,  static int              ArrowheadPostscript _ANSI_ARGS_((Tcl_Interp *interp,
83                              Tk_Canvas canvas, LineItem *linePtr,                              Tk_Canvas canvas, LineItem *linePtr,
84                              double *arrowPtr));                              double *arrowPtr));
85  static void             ComputeLineBbox _ANSI_ARGS_((Tk_Canvas canvas,  static void             ComputeLineBbox _ANSI_ARGS_((Tk_Canvas canvas,
86                              LineItem *linePtr));                              LineItem *linePtr));
87  static int              ConfigureLine _ANSI_ARGS_((Tcl_Interp *interp,  static int              ConfigureLine _ANSI_ARGS_((Tcl_Interp *interp,
88                              Tk_Canvas canvas, Tk_Item *itemPtr, int argc,                              Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
89                              Tcl_Obj *CONST argv[], int flags));                              Tcl_Obj *CONST argv[], int flags));
90  static int              ConfigureArrows _ANSI_ARGS_((Tk_Canvas canvas,  static int              ConfigureArrows _ANSI_ARGS_((Tk_Canvas canvas,
91                              LineItem *linePtr));                              LineItem *linePtr));
92  static int              CreateLine _ANSI_ARGS_((Tcl_Interp *interp,  static int              CreateLine _ANSI_ARGS_((Tcl_Interp *interp,
93                              Tk_Canvas canvas, struct Tk_Item *itemPtr,                              Tk_Canvas canvas, struct Tk_Item *itemPtr,
94                              int argc, Tcl_Obj *CONST argv[]));                              int argc, Tcl_Obj *CONST argv[]));
95  static void             DeleteLine _ANSI_ARGS_((Tk_Canvas canvas,  static void             DeleteLine _ANSI_ARGS_((Tk_Canvas canvas,
96                              Tk_Item *itemPtr, Display *display));                              Tk_Item *itemPtr, Display *display));
97  static void             DisplayLine _ANSI_ARGS_((Tk_Canvas canvas,  static void             DisplayLine _ANSI_ARGS_((Tk_Canvas canvas,
98                              Tk_Item *itemPtr, Display *display, Drawable dst,                              Tk_Item *itemPtr, Display *display, Drawable dst,
99                              int x, int y, int width, int height));                              int x, int y, int width, int height));
100  static int              GetLineIndex _ANSI_ARGS_((Tcl_Interp *interp,  static int              GetLineIndex _ANSI_ARGS_((Tcl_Interp *interp,
101                              Tk_Canvas canvas, Tk_Item *itemPtr,                              Tk_Canvas canvas, Tk_Item *itemPtr,
102                              Tcl_Obj *obj, int *indexPtr));                              Tcl_Obj *obj, int *indexPtr));
103  static int              LineCoords _ANSI_ARGS_((Tcl_Interp *interp,  static int              LineCoords _ANSI_ARGS_((Tcl_Interp *interp,
104                              Tk_Canvas canvas, Tk_Item *itemPtr,                              Tk_Canvas canvas, Tk_Item *itemPtr,
105                              int argc, Tcl_Obj *CONST argv[]));                              int argc, Tcl_Obj *CONST argv[]));
106  static void             LineDeleteCoords _ANSI_ARGS_((Tk_Canvas canvas,  static void             LineDeleteCoords _ANSI_ARGS_((Tk_Canvas canvas,
107                              Tk_Item *itemPtr, int first, int last));                              Tk_Item *itemPtr, int first, int last));
108  static void             LineInsert _ANSI_ARGS_((Tk_Canvas canvas,  static void             LineInsert _ANSI_ARGS_((Tk_Canvas canvas,
109                              Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj));                              Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj));
110  static int              LineToArea _ANSI_ARGS_((Tk_Canvas canvas,  static int              LineToArea _ANSI_ARGS_((Tk_Canvas canvas,
111                              Tk_Item *itemPtr, double *rectPtr));                              Tk_Item *itemPtr, double *rectPtr));
112  static double           LineToPoint _ANSI_ARGS_((Tk_Canvas canvas,  static double           LineToPoint _ANSI_ARGS_((Tk_Canvas canvas,
113                              Tk_Item *itemPtr, double *coordPtr));                              Tk_Item *itemPtr, double *coordPtr));
114  static int              LineToPostscript _ANSI_ARGS_((Tcl_Interp *interp,  static int              LineToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
115                              Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));                              Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
116  static int              ArrowParseProc _ANSI_ARGS_((ClientData clientData,  static int              ArrowParseProc _ANSI_ARGS_((ClientData clientData,
117                              Tcl_Interp *interp, Tk_Window tkwin,                              Tcl_Interp *interp, Tk_Window tkwin,
118                              CONST char *value, char *recordPtr, int offset));                              CONST char *value, char *recordPtr, int offset));
119  static char *           ArrowPrintProc _ANSI_ARGS_((ClientData clientData,  static char *           ArrowPrintProc _ANSI_ARGS_((ClientData clientData,
120                              Tk_Window tkwin, char *recordPtr, int offset,                              Tk_Window tkwin, char *recordPtr, int offset,
121                              Tcl_FreeProc **freeProcPtr));                              Tcl_FreeProc **freeProcPtr));
122  static int              ParseArrowShape _ANSI_ARGS_((ClientData clientData,  static int              ParseArrowShape _ANSI_ARGS_((ClientData clientData,
123                              Tcl_Interp *interp, Tk_Window tkwin,                              Tcl_Interp *interp, Tk_Window tkwin,
124                              CONST char *value, char *recordPtr, int offset));                              CONST char *value, char *recordPtr, int offset));
125  static char *           PrintArrowShape _ANSI_ARGS_((ClientData clientData,  static char *           PrintArrowShape _ANSI_ARGS_((ClientData clientData,
126                              Tk_Window tkwin, char *recordPtr, int offset,                              Tk_Window tkwin, char *recordPtr, int offset,
127                              Tcl_FreeProc **freeProcPtr));                              Tcl_FreeProc **freeProcPtr));
128  static void             ScaleLine _ANSI_ARGS_((Tk_Canvas canvas,  static void             ScaleLine _ANSI_ARGS_((Tk_Canvas canvas,
129                              Tk_Item *itemPtr, double originX, double originY,                              Tk_Item *itemPtr, double originX, double originY,
130                              double scaleX, double scaleY));                              double scaleX, double scaleY));
131  static void             TranslateLine _ANSI_ARGS_((Tk_Canvas canvas,  static void             TranslateLine _ANSI_ARGS_((Tk_Canvas canvas,
132                              Tk_Item *itemPtr, double deltaX, double deltaY));                              Tk_Item *itemPtr, double deltaX, double deltaY));
133    
134  /*  /*
135   * Information used for parsing configuration specs.  If you change any   * Information used for parsing configuration specs.  If you change any
136   * of the default strings, be sure to change the corresponding default   * of the default strings, be sure to change the corresponding default
137   * values in CreateLine.   * values in CreateLine.
138   */   */
139    
140  static Tk_CustomOption arrowShapeOption = {  static Tk_CustomOption arrowShapeOption = {
141      (Tk_OptionParseProc *) ParseArrowShape,      (Tk_OptionParseProc *) ParseArrowShape,
142      PrintArrowShape, (ClientData) NULL      PrintArrowShape, (ClientData) NULL
143  };  };
144  static Tk_CustomOption arrowOption = {  static Tk_CustomOption arrowOption = {
145      (Tk_OptionParseProc *) ArrowParseProc,      (Tk_OptionParseProc *) ArrowParseProc,
146      ArrowPrintProc, (ClientData) NULL      ArrowPrintProc, (ClientData) NULL
147  };  };
148  static Tk_CustomOption smoothOption = {  static Tk_CustomOption smoothOption = {
149      (Tk_OptionParseProc *) TkSmoothParseProc,      (Tk_OptionParseProc *) TkSmoothParseProc,
150      TkSmoothPrintProc, (ClientData) NULL      TkSmoothPrintProc, (ClientData) NULL
151  };  };
152  static Tk_CustomOption stateOption = {  static Tk_CustomOption stateOption = {
153      (Tk_OptionParseProc *) TkStateParseProc,      (Tk_OptionParseProc *) TkStateParseProc,
154      TkStatePrintProc, (ClientData) 2      TkStatePrintProc, (ClientData) 2
155  };  };
156  static Tk_CustomOption tagsOption = {  static Tk_CustomOption tagsOption = {
157      (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,      (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
158      Tk_CanvasTagsPrintProc, (ClientData) NULL      Tk_CanvasTagsPrintProc, (ClientData) NULL
159  };  };
160  static Tk_CustomOption dashOption = {  static Tk_CustomOption dashOption = {
161      (Tk_OptionParseProc *) TkCanvasDashParseProc,      (Tk_OptionParseProc *) TkCanvasDashParseProc,
162      TkCanvasDashPrintProc, (ClientData) NULL      TkCanvasDashPrintProc, (ClientData) NULL
163  };  };
164  static Tk_CustomOption offsetOption = {  static Tk_CustomOption offsetOption = {
165      (Tk_OptionParseProc *) TkOffsetParseProc,      (Tk_OptionParseProc *) TkOffsetParseProc,
166      TkOffsetPrintProc,      TkOffsetPrintProc,
167      (ClientData) (TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)      (ClientData) (TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
168  };  };
169  static Tk_CustomOption pixelOption = {  static Tk_CustomOption pixelOption = {
170      (Tk_OptionParseProc *) TkPixelParseProc,      (Tk_OptionParseProc *) TkPixelParseProc,
171      TkPixelPrintProc, (ClientData) NULL      TkPixelPrintProc, (ClientData) NULL
172  };  };
173    
174  static Tk_ConfigSpec configSpecs[] = {  static Tk_ConfigSpec configSpecs[] = {
175      {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
176          (char *) NULL, Tk_Offset(LineItem, outline.activeDash),          (char *) NULL, Tk_Offset(LineItem, outline.activeDash),
177          TK_CONFIG_NULL_OK, &dashOption},          TK_CONFIG_NULL_OK, &dashOption},
178      {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,      {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
179          (char *) NULL, Tk_Offset(LineItem, outline.activeColor),          (char *) NULL, Tk_Offset(LineItem, outline.activeColor),
180          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
181      {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,      {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
182          (char *) NULL, Tk_Offset(LineItem, outline.activeStipple),          (char *) NULL, Tk_Offset(LineItem, outline.activeStipple),
183          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
184      {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
185          "0.0", Tk_Offset(LineItem, outline.activeWidth),          "0.0", Tk_Offset(LineItem, outline.activeWidth),
186          TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},          TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
187      {TK_CONFIG_CUSTOM, "-arrow", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-arrow", (char *) NULL, (char *) NULL,
188          "none", Tk_Offset(LineItem, arrow), TK_CONFIG_DONT_SET_DEFAULT, &arrowOption},          "none", Tk_Offset(LineItem, arrow), TK_CONFIG_DONT_SET_DEFAULT, &arrowOption},
189      {TK_CONFIG_CUSTOM, "-arrowshape", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-arrowshape", (char *) NULL, (char *) NULL,
190          "8 10 3", Tk_Offset(LineItem, arrowShapeA),          "8 10 3", Tk_Offset(LineItem, arrowShapeA),
191          TK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption},          TK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption},
192      {TK_CONFIG_CAP_STYLE, "-capstyle", (char *) NULL, (char *) NULL,      {TK_CONFIG_CAP_STYLE, "-capstyle", (char *) NULL, (char *) NULL,
193          "butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT},          "butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT},
194      {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,      {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
195          "black", Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK},          "black", Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK},
196      {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
197          (char *) NULL, Tk_Offset(LineItem, outline.dash),          (char *) NULL, Tk_Offset(LineItem, outline.dash),
198          TK_CONFIG_NULL_OK, &dashOption},          TK_CONFIG_NULL_OK, &dashOption},
199      {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,      {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
200          "0", Tk_Offset(LineItem, outline.offset),          "0", Tk_Offset(LineItem, outline.offset),
201          TK_CONFIG_DONT_SET_DEFAULT},          TK_CONFIG_DONT_SET_DEFAULT},
202      {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
203          (char *) NULL, Tk_Offset(LineItem, outline.disabledDash),          (char *) NULL, Tk_Offset(LineItem, outline.disabledDash),
204          TK_CONFIG_NULL_OK, &dashOption},          TK_CONFIG_NULL_OK, &dashOption},
205      {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,      {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
206          (char *) NULL, Tk_Offset(LineItem, outline.disabledColor),          (char *) NULL, Tk_Offset(LineItem, outline.disabledColor),
207          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
208      {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,      {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
209          (char *) NULL, Tk_Offset(LineItem, outline.disabledStipple),          (char *) NULL, Tk_Offset(LineItem, outline.disabledStipple),
210          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
211      {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL,
212          "0.0", Tk_Offset(LineItem, outline.disabledWidth),          "0.0", Tk_Offset(LineItem, outline.disabledWidth),
213          TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},          TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
214      {TK_CONFIG_JOIN_STYLE, "-joinstyle", (char *) NULL, (char *) NULL,      {TK_CONFIG_JOIN_STYLE, "-joinstyle", (char *) NULL, (char *) NULL,
215          "round", Tk_Offset(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT},          "round", Tk_Offset(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT},
216      {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
217          "0,0", Tk_Offset(LineItem, outline.tsoffset),          "0,0", Tk_Offset(LineItem, outline.tsoffset),
218          TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},          TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
219      {TK_CONFIG_CUSTOM, "-smooth", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-smooth", (char *) NULL, (char *) NULL,
220          "0", Tk_Offset(LineItem, smooth),          "0", Tk_Offset(LineItem, smooth),
221          TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},          TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
222      {TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL,      {TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL,
223          "12", Tk_Offset(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT},          "12", Tk_Offset(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT},
224      {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
225          (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,          (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
226          &stateOption},          &stateOption},
227      {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,      {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
228          (char *) NULL, Tk_Offset(LineItem, outline.stipple),          (char *) NULL, Tk_Offset(LineItem, outline.stipple),
229          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
230      {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
231          (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},          (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
232      {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
233          "1.0", Tk_Offset(LineItem, outline.width),          "1.0", Tk_Offset(LineItem, outline.width),
234          TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},          TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
235      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
236          (char *) NULL, 0, 0}          (char *) NULL, 0, 0}
237  };  };
238    
239  /*  /*
240   * The structures below defines the line item type by means   * The structures below defines the line item type by means
241   * of procedures that can be invoked by generic item code.   * of procedures that can be invoked by generic item code.
242   */   */
243    
244  Tk_ItemType tkLineType = {  Tk_ItemType tkLineType = {
245      "line",                             /* name */      "line",                             /* name */
246      sizeof(LineItem),                   /* itemSize */      sizeof(LineItem),                   /* itemSize */
247      CreateLine,                         /* createProc */      CreateLine,                         /* createProc */
248      configSpecs,                        /* configSpecs */      configSpecs,                        /* configSpecs */
249      ConfigureLine,                      /* configureProc */      ConfigureLine,                      /* configureProc */
250      LineCoords,                         /* coordProc */      LineCoords,                         /* coordProc */
251      DeleteLine,                         /* deleteProc */      DeleteLine,                         /* deleteProc */
252      DisplayLine,                        /* displayProc */      DisplayLine,                        /* displayProc */
253      TK_CONFIG_OBJS,                     /* flags */      TK_CONFIG_OBJS,                     /* flags */
254      LineToPoint,                        /* pointProc */      LineToPoint,                        /* pointProc */
255      LineToArea,                         /* areaProc */      LineToArea,                         /* areaProc */
256      LineToPostscript,                   /* postscriptProc */      LineToPostscript,                   /* postscriptProc */
257      ScaleLine,                          /* scaleProc */      ScaleLine,                          /* scaleProc */
258      TranslateLine,                      /* translateProc */      TranslateLine,                      /* translateProc */
259      (Tk_ItemIndexProc *) GetLineIndex,  /* indexProc */      (Tk_ItemIndexProc *) GetLineIndex,  /* indexProc */
260      (Tk_ItemCursorProc *) NULL,         /* icursorProc */      (Tk_ItemCursorProc *) NULL,         /* icursorProc */
261      (Tk_ItemSelectionProc *) NULL,      /* selectionProc */      (Tk_ItemSelectionProc *) NULL,      /* selectionProc */
262      (Tk_ItemInsertProc *) LineInsert,   /* insertProc */      (Tk_ItemInsertProc *) LineInsert,   /* insertProc */
263      LineDeleteCoords,                   /* dTextProc */      LineDeleteCoords,                   /* dTextProc */
264      (Tk_ItemType *) NULL,               /* nextPtr */      (Tk_ItemType *) NULL,               /* nextPtr */
265  };  };
266    
267  /*  /*
268   * The definition below determines how large are static arrays   * The definition below determines how large are static arrays
269   * used to hold spline points (splines larger than this have to   * used to hold spline points (splines larger than this have to
270   * have their arrays malloc-ed).   * have their arrays malloc-ed).
271   */   */
272    
273  #define MAX_STATIC_POINTS 200  #define MAX_STATIC_POINTS 200
274    
275  /*  /*
276   *--------------------------------------------------------------   *--------------------------------------------------------------
277   *   *
278   * CreateLine --   * CreateLine --
279   *   *
280   *      This procedure is invoked to create a new line item in   *      This procedure is invoked to create a new line item in
281   *      a canvas.   *      a canvas.
282   *   *
283   * Results:   * Results:
284   *      A standard Tcl return value.  If an error occurred in   *      A standard Tcl return value.  If an error occurred in
285   *      creating the item, then an error message is left in   *      creating the item, then an error message is left in
286   *      the interp's result;  in this case itemPtr is left uninitialized,   *      the interp's result;  in this case itemPtr is left uninitialized,
287   *      so it can be safely freed by the caller.   *      so it can be safely freed by the caller.
288   *   *
289   * Side effects:   * Side effects:
290   *      A new line item is created.   *      A new line item is created.
291   *   *
292   *--------------------------------------------------------------   *--------------------------------------------------------------
293   */   */
294    
295  static int  static int
296  CreateLine(interp, canvas, itemPtr, argc, argv)  CreateLine(interp, canvas, itemPtr, argc, argv)
297      Tcl_Interp *interp;                 /* Interpreter for error reporting. */      Tcl_Interp *interp;                 /* Interpreter for error reporting. */
298      Tk_Canvas canvas;                   /* Canvas to hold new item. */      Tk_Canvas canvas;                   /* Canvas to hold new item. */
299      Tk_Item *itemPtr;                   /* Record to hold new item;  header      Tk_Item *itemPtr;                   /* Record to hold new item;  header
300                                           * has been initialized by caller. */                                           * has been initialized by caller. */
301      int argc;                           /* Number of arguments in argv. */      int argc;                           /* Number of arguments in argv. */
302      Tcl_Obj *CONST argv[];              /* Arguments describing line. */      Tcl_Obj *CONST argv[];              /* Arguments describing line. */
303  {  {
304      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
305      int i;      int i;
306    
307      /*      /*
308       * Carry out initialization that is needed to set defaults and to       * Carry out initialization that is needed to set defaults and to
309       * allow proper cleanup after errors during the the remainder of       * allow proper cleanup after errors during the the remainder of
310       * this procedure.       * this procedure.
311       */       */
312    
313      Tk_CreateOutline(&(linePtr->outline));      Tk_CreateOutline(&(linePtr->outline));
314      linePtr->canvas = canvas;      linePtr->canvas = canvas;
315      linePtr->numPoints = 0;      linePtr->numPoints = 0;
316      linePtr->coordPtr = NULL;      linePtr->coordPtr = NULL;
317      linePtr->capStyle = CapButt;      linePtr->capStyle = CapButt;
318      linePtr->joinStyle = JoinRound;      linePtr->joinStyle = JoinRound;
319      linePtr->arrowGC = None;      linePtr->arrowGC = None;
320      linePtr->arrow = ARROWS_NONE;      linePtr->arrow = ARROWS_NONE;
321      linePtr->arrowShapeA = (float)8.0;      linePtr->arrowShapeA = (float)8.0;
322      linePtr->arrowShapeB = (float)10.0;      linePtr->arrowShapeB = (float)10.0;
323      linePtr->arrowShapeC = (float)3.0;      linePtr->arrowShapeC = (float)3.0;
324      linePtr->firstArrowPtr = NULL;      linePtr->firstArrowPtr = NULL;
325      linePtr->lastArrowPtr = NULL;      linePtr->lastArrowPtr = NULL;
326      linePtr->smooth = (Tk_SmoothMethod *) NULL;      linePtr->smooth = (Tk_SmoothMethod *) NULL;
327      linePtr->splineSteps = 12;      linePtr->splineSteps = 12;
328    
329      /*      /*
330       * Count the number of points and then parse them into a point       * Count the number of points and then parse them into a point
331       * array.  Leading arguments are assumed to be points if they       * array.  Leading arguments are assumed to be points if they
332       * start with a digit or a minus sign followed by a digit.       * start with a digit or a minus sign followed by a digit.
333       */       */
334    
335      for (i = 0; i < argc; i++) {      for (i = 0; i < argc; i++) {
336          char *arg = Tcl_GetStringFromObj(argv[i], NULL);          char *arg = Tcl_GetStringFromObj(argv[i], NULL);
337          if ((arg[0] == '-') && (arg[1] >= 'a')          if ((arg[0] == '-') && (arg[1] >= 'a')
338                  && (arg[1] <= 'z')) {                  && (arg[1] <= 'z')) {
339              break;              break;
340          }          }
341      }      }
342      if (i && (LineCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {      if (i && (LineCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
343          goto error;          goto error;
344      }      }
345      if (ConfigureLine(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {      if (ConfigureLine(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
346          return TCL_OK;          return TCL_OK;
347      }      }
348    
349      error:      error:
350      DeleteLine(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));      DeleteLine(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
351      return TCL_ERROR;      return TCL_ERROR;
352  }  }
353    
354  /*  /*
355   *--------------------------------------------------------------   *--------------------------------------------------------------
356   *   *
357   * LineCoords --   * LineCoords --
358   *   *
359   *      This procedure is invoked to process the "coords" widget   *      This procedure is invoked to process the "coords" widget
360   *      command on lines.  See the user documentation for details   *      command on lines.  See the user documentation for details
361   *      on what it does.   *      on what it does.
362   *   *
363   * Results:   * Results:
364   *      Returns TCL_OK or TCL_ERROR, and sets the interp's result.   *      Returns TCL_OK or TCL_ERROR, and sets the interp's result.
365   *   *
366   * Side effects:   * Side effects:
367   *      The coordinates for the given item may be changed.   *      The coordinates for the given item may be changed.
368   *   *
369   *--------------------------------------------------------------   *--------------------------------------------------------------
370   */   */
371    
372  static int  static int
373  LineCoords(interp, canvas, itemPtr, argc, argv)  LineCoords(interp, canvas, itemPtr, argc, argv)
374      Tcl_Interp *interp;                 /* Used for error reporting. */      Tcl_Interp *interp;                 /* Used for error reporting. */
375      Tk_Canvas canvas;                   /* Canvas containing item. */      Tk_Canvas canvas;                   /* Canvas containing item. */
376      Tk_Item *itemPtr;                   /* Item whose coordinates are to be      Tk_Item *itemPtr;                   /* Item whose coordinates are to be
377                                           * read or modified. */                                           * read or modified. */
378      int argc;                           /* Number of coordinates supplied in      int argc;                           /* Number of coordinates supplied in
379                                           * argv. */                                           * argv. */
380      Tcl_Obj *CONST argv[];              /* Array of coordinates: x1, y1,      Tcl_Obj *CONST argv[];              /* Array of coordinates: x1, y1,
381                                           * x2, y2, ... */                                           * x2, y2, ... */
382  {  {
383      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
384      int i, numPoints;      int i, numPoints;
385      double *coordPtr;      double *coordPtr;
386    
387      if (argc == 0) {      if (argc == 0) {
388          int numCoords;          int numCoords;
389          Tcl_Obj *subobj, *obj = Tcl_NewObj();          Tcl_Obj *subobj, *obj = Tcl_NewObj();
390    
391          numCoords = 2*linePtr->numPoints;          numCoords = 2*linePtr->numPoints;
392          if (linePtr->firstArrowPtr != NULL) {          if (linePtr->firstArrowPtr != NULL) {
393              coordPtr = linePtr->firstArrowPtr;              coordPtr = linePtr->firstArrowPtr;
394          } else {          } else {
395              coordPtr = linePtr->coordPtr;              coordPtr = linePtr->coordPtr;
396          }          }
397          for (i = 0; i < numCoords; i++, coordPtr++) {          for (i = 0; i < numCoords; i++, coordPtr++) {
398              if (i == 2) {              if (i == 2) {
399                  coordPtr = linePtr->coordPtr+2;                  coordPtr = linePtr->coordPtr+2;
400              }              }
401              if ((linePtr->lastArrowPtr != NULL) && (i == (numCoords-2))) {              if ((linePtr->lastArrowPtr != NULL) && (i == (numCoords-2))) {
402                  coordPtr = linePtr->lastArrowPtr;                  coordPtr = linePtr->lastArrowPtr;
403              }              }
404              subobj = Tcl_NewDoubleObj(*coordPtr);              subobj = Tcl_NewDoubleObj(*coordPtr);
405              Tcl_ListObjAppendElement(interp, obj, subobj);              Tcl_ListObjAppendElement(interp, obj, subobj);
406          }          }
407          Tcl_SetObjResult(interp, obj);          Tcl_SetObjResult(interp, obj);
408          return TCL_OK;          return TCL_OK;
409      }      }
410      if (argc == 1) {      if (argc == 1) {
411          if (Tcl_ListObjGetElements(interp, argv[0], &argc,          if (Tcl_ListObjGetElements(interp, argv[0], &argc,
412                  (Tcl_Obj ***) &argv) != TCL_OK) {                  (Tcl_Obj ***) &argv) != TCL_OK) {
413              return TCL_ERROR;              return TCL_ERROR;
414          }          }
415      }      }
416      if (argc & 1) {      if (argc & 1) {
417          Tcl_AppendResult(interp,          Tcl_AppendResult(interp,
418                  "odd number of coordinates specified for line",                  "odd number of coordinates specified for line",
419                  (char *) NULL);                  (char *) NULL);
420          return TCL_ERROR;          return TCL_ERROR;
421      } else if (argc < 4) {      } else if (argc < 4) {
422          Tcl_AppendResult(interp,          Tcl_AppendResult(interp,
423                  "too few coordinates specified for line",                  "too few coordinates specified for line",
424                  (char *) NULL);                  (char *) NULL);
425          return TCL_ERROR;          return TCL_ERROR;
426      } else {      } else {
427          numPoints = argc/2;          numPoints = argc/2;
428          if (linePtr->numPoints != numPoints) {          if (linePtr->numPoints != numPoints) {
429              coordPtr = (double *) ckalloc((unsigned)              coordPtr = (double *) ckalloc((unsigned)
430                      (sizeof(double) * argc));                      (sizeof(double) * argc));
431              if (linePtr->coordPtr != NULL) {              if (linePtr->coordPtr != NULL) {
432                  ckfree((char *) linePtr->coordPtr);                  ckfree((char *) linePtr->coordPtr);
433              }              }
434              linePtr->coordPtr = coordPtr;              linePtr->coordPtr = coordPtr;
435              linePtr->numPoints = numPoints;              linePtr->numPoints = numPoints;
436          }          }
437          coordPtr = linePtr->coordPtr;          coordPtr = linePtr->coordPtr;
438          for (i = 0; i <argc; i++) {          for (i = 0; i <argc; i++) {
439              if (Tk_CanvasGetCoordFromObj(interp, canvas, argv[i],              if (Tk_CanvasGetCoordFromObj(interp, canvas, argv[i],
440                      coordPtr++) != TCL_OK) {                      coordPtr++) != TCL_OK) {
441                  return TCL_ERROR;                  return TCL_ERROR;
442              }              }
443          }          }
444    
445          /*          /*
446           * Update arrowheads by throwing away any existing arrow-head           * Update arrowheads by throwing away any existing arrow-head
447           * information and calling ConfigureArrows to recompute it.           * information and calling ConfigureArrows to recompute it.
448           */           */
449    
450          if (linePtr->firstArrowPtr != NULL) {          if (linePtr->firstArrowPtr != NULL) {
451              ckfree((char *) linePtr->firstArrowPtr);              ckfree((char *) linePtr->firstArrowPtr);
452              linePtr->firstArrowPtr = NULL;              linePtr->firstArrowPtr = NULL;
453          }          }
454          if (linePtr->lastArrowPtr != NULL) {          if (linePtr->lastArrowPtr != NULL) {
455              ckfree((char *) linePtr->lastArrowPtr);              ckfree((char *) linePtr->lastArrowPtr);
456              linePtr->lastArrowPtr = NULL;              linePtr->lastArrowPtr = NULL;
457          }          }
458          if (linePtr->arrow != ARROWS_NONE) {          if (linePtr->arrow != ARROWS_NONE) {
459              ConfigureArrows(canvas, linePtr);              ConfigureArrows(canvas, linePtr);
460          }          }
461          ComputeLineBbox(canvas, linePtr);          ComputeLineBbox(canvas, linePtr);
462      }      }
463      return TCL_OK;      return TCL_OK;
464  }  }
465    
466  /*  /*
467   *--------------------------------------------------------------   *--------------------------------------------------------------
468   *   *
469   * ConfigureLine --   * ConfigureLine --
470   *   *
471   *      This procedure is invoked to configure various aspects   *      This procedure is invoked to configure various aspects
472   *      of a line item such as its background color.   *      of a line item such as its background color.
473   *   *
474   * Results:   * Results:
475   *      A standard Tcl result code.  If an error occurs, then   *      A standard Tcl result code.  If an error occurs, then
476   *      an error message is left in the interp's result.   *      an error message is left in the interp's result.
477   *   *
478   * Side effects:   * Side effects:
479   *      Configuration information, such as colors and stipple   *      Configuration information, such as colors and stipple
480   *      patterns, may be set for itemPtr.   *      patterns, may be set for itemPtr.
481   *   *
482   *--------------------------------------------------------------   *--------------------------------------------------------------
483   */   */
484    
485  static int  static int
486  ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)  ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
487      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
488      Tk_Canvas canvas;           /* Canvas containing itemPtr. */      Tk_Canvas canvas;           /* Canvas containing itemPtr. */
489      Tk_Item *itemPtr;           /* Line item to reconfigure. */      Tk_Item *itemPtr;           /* Line item to reconfigure. */
490      int argc;                   /* Number of elements in argv.  */      int argc;                   /* Number of elements in argv.  */
491      Tcl_Obj *CONST argv[];      /* Arguments describing things to configure. */      Tcl_Obj *CONST argv[];      /* Arguments describing things to configure. */
492      int flags;                  /* Flags to pass to Tk_ConfigureWidget. */      int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
493  {  {
494      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
495      XGCValues gcValues;      XGCValues gcValues;
496      GC newGC, arrowGC;      GC newGC, arrowGC;
497      unsigned long mask;      unsigned long mask;
498      Tk_Window tkwin;      Tk_Window tkwin;
499      Tk_State state;      Tk_State state;
500    
501      tkwin = Tk_CanvasTkwin(canvas);      tkwin = Tk_CanvasTkwin(canvas);
502      if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,      if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
503              (char *) linePtr, flags|TK_CONFIG_OBJS) != TCL_OK) {              (char *) linePtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
504          return TCL_ERROR;          return TCL_ERROR;
505      }      }
506    
507      /*      /*
508       * A few of the options require additional processing, such as       * A few of the options require additional processing, such as
509       * graphics contexts.       * graphics contexts.
510       */       */
511    
512      state = itemPtr->state;      state = itemPtr->state;
513    
514      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
515          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
516      }      }
517    
518      if (linePtr->outline.activeWidth > linePtr->outline.width ||      if (linePtr->outline.activeWidth > linePtr->outline.width ||
519              linePtr->outline.activeDash.number != 0 ||              linePtr->outline.activeDash.number != 0 ||
520              linePtr->outline.activeColor != NULL ||              linePtr->outline.activeColor != NULL ||
521              linePtr->outline.activeStipple != None) {              linePtr->outline.activeStipple != None) {
522          itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;          itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
523      } else {      } else {
524          itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;          itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
525      }      }
526      mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,      mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
527              &(linePtr->outline));              &(linePtr->outline));
528      if (mask) {      if (mask) {
529          if (linePtr->arrow == ARROWS_NONE) {          if (linePtr->arrow == ARROWS_NONE) {
530              gcValues.cap_style = linePtr->capStyle;              gcValues.cap_style = linePtr->capStyle;
531              mask |= GCCapStyle;              mask |= GCCapStyle;
532          }          }
533          gcValues.join_style = linePtr->joinStyle;          gcValues.join_style = linePtr->joinStyle;
534          mask |= GCJoinStyle;          mask |= GCJoinStyle;
535          newGC = Tk_GetGC(tkwin, mask, &gcValues);          newGC = Tk_GetGC(tkwin, mask, &gcValues);
536          gcValues.line_width = 0;          gcValues.line_width = 0;
537          arrowGC = Tk_GetGC(tkwin, mask, &gcValues);          arrowGC = Tk_GetGC(tkwin, mask, &gcValues);
538      } else {      } else {
539          newGC = arrowGC = None;          newGC = arrowGC = None;
540      }      }
541      if (linePtr->outline.gc != None) {      if (linePtr->outline.gc != None) {
542          Tk_FreeGC(Tk_Display(tkwin), linePtr->outline.gc);          Tk_FreeGC(Tk_Display(tkwin), linePtr->outline.gc);
543      }      }
544      if (linePtr->arrowGC != None) {      if (linePtr->arrowGC != None) {
545          Tk_FreeGC(Tk_Display(tkwin), linePtr->arrowGC);          Tk_FreeGC(Tk_Display(tkwin), linePtr->arrowGC);
546      }      }
547      linePtr->outline.gc = newGC;      linePtr->outline.gc = newGC;
548      linePtr->arrowGC = arrowGC;      linePtr->arrowGC = arrowGC;
549    
550      /*      /*
551       * Keep spline parameters within reasonable limits.       * Keep spline parameters within reasonable limits.
552       */       */
553    
554      if (linePtr->splineSteps < 1) {      if (linePtr->splineSteps < 1) {
555          linePtr->splineSteps = 1;          linePtr->splineSteps = 1;
556      } else if (linePtr->splineSteps > 100) {      } else if (linePtr->splineSteps > 100) {
557          linePtr->splineSteps = 100;          linePtr->splineSteps = 100;
558      }      }
559    
560      if ((!linePtr->numPoints) || (state==TK_STATE_HIDDEN)) {      if ((!linePtr->numPoints) || (state==TK_STATE_HIDDEN)) {
561          ComputeLineBbox(canvas, linePtr);          ComputeLineBbox(canvas, linePtr);
562          return TCL_OK;          return TCL_OK;
563      }      }
564    
565      /*      /*
566       * Setup arrowheads, if needed.  If arrowheads are turned off,       * Setup arrowheads, if needed.  If arrowheads are turned off,
567       * restore the line's endpoints (they were shortened when the       * restore the line's endpoints (they were shortened when the
568       * arrowheads were added).       * arrowheads were added).
569       */       */
570    
571      if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != ARROWS_FIRST)      if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != ARROWS_FIRST)
572              && (linePtr->arrow != ARROWS_BOTH)) {              && (linePtr->arrow != ARROWS_BOTH)) {
573          linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];          linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
574          linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];          linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
575          ckfree((char *) linePtr->firstArrowPtr);          ckfree((char *) linePtr->firstArrowPtr);
576          linePtr->firstArrowPtr = NULL;          linePtr->firstArrowPtr = NULL;
577      }      }
578      if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != ARROWS_LAST)      if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != ARROWS_LAST)
579              && (linePtr->arrow != ARROWS_BOTH)) {              && (linePtr->arrow != ARROWS_BOTH)) {
580          int i;          int i;
581    
582          i = 2*(linePtr->numPoints-1);          i = 2*(linePtr->numPoints-1);
583          linePtr->coordPtr[i] = linePtr->lastArrowPtr[0];          linePtr->coordPtr[i] = linePtr->lastArrowPtr[0];
584          linePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];          linePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];
585          ckfree((char *) linePtr->lastArrowPtr);          ckfree((char *) linePtr->lastArrowPtr);
586          linePtr->lastArrowPtr = NULL;          linePtr->lastArrowPtr = NULL;
587      }      }
588      if (linePtr->arrow != ARROWS_NONE) {      if (linePtr->arrow != ARROWS_NONE) {
589          ConfigureArrows(canvas, linePtr);          ConfigureArrows(canvas, linePtr);
590      }      }
591    
592      /*      /*
593       * Recompute bounding box for line.       * Recompute bounding box for line.
594       */       */
595    
596      ComputeLineBbox(canvas, linePtr);      ComputeLineBbox(canvas, linePtr);
597    
598      return TCL_OK;      return TCL_OK;
599  }  }
600    
601  /*  /*
602   *--------------------------------------------------------------   *--------------------------------------------------------------
603   *   *
604   * DeleteLine --   * DeleteLine --
605   *   *
606   *      This procedure is called to clean up the data structure   *      This procedure is called to clean up the data structure
607   *      associated with a line item.   *      associated with a line item.
608   *   *
609   * Results:   * Results:
610   *      None.   *      None.
611   *   *
612   * Side effects:   * Side effects:
613   *      Resources associated with itemPtr are released.   *      Resources associated with itemPtr are released.
614   *   *
615   *--------------------------------------------------------------   *--------------------------------------------------------------
616   */   */
617    
618  static void  static void
619  DeleteLine(canvas, itemPtr, display)  DeleteLine(canvas, itemPtr, display)
620      Tk_Canvas canvas;                   /* Info about overall canvas widget. */      Tk_Canvas canvas;                   /* Info about overall canvas widget. */
621      Tk_Item *itemPtr;                   /* Item that is being deleted. */      Tk_Item *itemPtr;                   /* Item that is being deleted. */
622      Display *display;                   /* Display containing window for      Display *display;                   /* Display containing window for
623                                           * canvas. */                                           * canvas. */
624  {  {
625      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
626    
627      Tk_DeleteOutline(display, &(linePtr->outline));      Tk_DeleteOutline(display, &(linePtr->outline));
628      if (linePtr->coordPtr != NULL) {      if (linePtr->coordPtr != NULL) {
629          ckfree((char *) linePtr->coordPtr);          ckfree((char *) linePtr->coordPtr);
630      }      }
631      if (linePtr->arrowGC != None) {      if (linePtr->arrowGC != None) {
632          Tk_FreeGC(display, linePtr->arrowGC);          Tk_FreeGC(display, linePtr->arrowGC);
633      }      }
634      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
635          ckfree((char *) linePtr->firstArrowPtr);          ckfree((char *) linePtr->firstArrowPtr);
636      }      }
637      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
638          ckfree((char *) linePtr->lastArrowPtr);          ckfree((char *) linePtr->lastArrowPtr);
639      }      }
640  }  }
641    
642  /*  /*
643   *--------------------------------------------------------------   *--------------------------------------------------------------
644   *   *
645   * ComputeLineBbox --   * ComputeLineBbox --
646   *   *
647   *      This procedure is invoked to compute the bounding box of   *      This procedure is invoked to compute the bounding box of
648   *      all the pixels that may be drawn as part of a line.   *      all the pixels that may be drawn as part of a line.
649   *   *
650   * Results:   * Results:
651   *      None.   *      None.
652   *   *
653   * Side effects:   * Side effects:
654   *      The fields x1, y1, x2, and y2 are updated in the header   *      The fields x1, y1, x2, and y2 are updated in the header
655   *      for itemPtr.   *      for itemPtr.
656   *   *
657   *--------------------------------------------------------------   *--------------------------------------------------------------
658   */   */
659    
660  static void  static void
661  ComputeLineBbox(canvas, linePtr)  ComputeLineBbox(canvas, linePtr)
662      Tk_Canvas canvas;                   /* Canvas that contains item. */      Tk_Canvas canvas;                   /* Canvas that contains item. */
663      LineItem *linePtr;                  /* Item whose bbos is to be      LineItem *linePtr;                  /* Item whose bbos is to be
664                                           * recomputed. */                                           * recomputed. */
665  {  {
666      double *coordPtr;      double *coordPtr;
667      int i, intWidth;      int i, intWidth;
668      double width;      double width;
669      Tk_State state = linePtr->header.state;      Tk_State state = linePtr->header.state;
670      Tk_TSOffset *tsoffset;      Tk_TSOffset *tsoffset;
671    
672      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
673          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
674      }      }
675    
676      if (!(linePtr->numPoints) || (state==TK_STATE_HIDDEN)) {      if (!(linePtr->numPoints) || (state==TK_STATE_HIDDEN)) {
677          linePtr->header.x1 = -1;          linePtr->header.x1 = -1;
678          linePtr->header.x2 = -1;          linePtr->header.x2 = -1;
679          linePtr->header.y1 = -1;          linePtr->header.y1 = -1;
680          linePtr->header.y2 = -1;          linePtr->header.y2 = -1;
681          return;          return;
682      }      }
683    
684      width = linePtr->outline.width;      width = linePtr->outline.width;
685      if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {      if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
686          if (linePtr->outline.activeWidth>width) {          if (linePtr->outline.activeWidth>width) {
687              width = linePtr->outline.activeWidth;              width = linePtr->outline.activeWidth;
688          }          }
689      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
690          if (linePtr->outline.disabledWidth>0) {          if (linePtr->outline.disabledWidth>0) {
691              width = linePtr->outline.disabledWidth;              width = linePtr->outline.disabledWidth;
692          }          }
693      }      }
694    
695      coordPtr = linePtr->coordPtr;      coordPtr = linePtr->coordPtr;
696      linePtr->header.x1 = linePtr->header.x2 = (int) *coordPtr;      linePtr->header.x1 = linePtr->header.x2 = (int) *coordPtr;
697      linePtr->header.y1 = linePtr->header.y2 = (int) coordPtr[1];      linePtr->header.y1 = linePtr->header.y2 = (int) coordPtr[1];
698    
699      /*      /*
700       * Compute the bounding box of all the points in the line,       * Compute the bounding box of all the points in the line,
701       * then expand in all directions by the line's width to take       * then expand in all directions by the line's width to take
702       * care of butting or rounded corners and projecting or       * care of butting or rounded corners and projecting or
703       * rounded caps.  This expansion is an overestimate (worst-case       * rounded caps.  This expansion is an overestimate (worst-case
704       * is square root of two over two) but it's simple.  Don't do       * is square root of two over two) but it's simple.  Don't do
705       * anything special for curves.  This causes an additional       * anything special for curves.  This causes an additional
706       * overestimate in the bounding box, but is faster.       * overestimate in the bounding box, but is faster.
707       */       */
708    
709      for (i = 1, coordPtr = linePtr->coordPtr+2; i < linePtr->numPoints;      for (i = 1, coordPtr = linePtr->coordPtr+2; i < linePtr->numPoints;
710              i++, coordPtr += 2) {              i++, coordPtr += 2) {
711          TkIncludePoint((Tk_Item *) linePtr, coordPtr);          TkIncludePoint((Tk_Item *) linePtr, coordPtr);
712      }      }
713      width = linePtr->outline.width;      width = linePtr->outline.width;
714      if (width < 1.0) {      if (width < 1.0) {
715          width = 1.0;          width = 1.0;
716      }      }
717      if (linePtr->arrow != ARROWS_NONE) {      if (linePtr->arrow != ARROWS_NONE) {
718          if (linePtr->arrow != ARROWS_LAST) {          if (linePtr->arrow != ARROWS_LAST) {
719              TkIncludePoint((Tk_Item *) linePtr, linePtr->firstArrowPtr);              TkIncludePoint((Tk_Item *) linePtr, linePtr->firstArrowPtr);
720          }          }
721          if (linePtr->arrow != ARROWS_FIRST) {          if (linePtr->arrow != ARROWS_FIRST) {
722              TkIncludePoint((Tk_Item *) linePtr, linePtr->lastArrowPtr);              TkIncludePoint((Tk_Item *) linePtr, linePtr->lastArrowPtr);
723          }          }
724      }      }
725    
726      tsoffset = &linePtr->outline.tsoffset;      tsoffset = &linePtr->outline.tsoffset;
727      if (tsoffset->flags & TK_OFFSET_INDEX) {      if (tsoffset->flags & TK_OFFSET_INDEX) {
728          double *coordPtr = linePtr->coordPtr + (tsoffset->flags & ~TK_OFFSET_INDEX);          double *coordPtr = linePtr->coordPtr + (tsoffset->flags & ~TK_OFFSET_INDEX);
729          if (tsoffset->flags <= 0) {          if (tsoffset->flags <= 0) {
730              coordPtr = linePtr->coordPtr;              coordPtr = linePtr->coordPtr;
731              if ((linePtr->arrow == ARROWS_FIRST) || (linePtr->arrow == ARROWS_BOTH)) {              if ((linePtr->arrow == ARROWS_FIRST) || (linePtr->arrow == ARROWS_BOTH)) {
732                  coordPtr = linePtr->firstArrowPtr;                  coordPtr = linePtr->firstArrowPtr;
733              }              }
734          }          }
735          if (tsoffset->flags > (linePtr->numPoints * 2)) {          if (tsoffset->flags > (linePtr->numPoints * 2)) {
736              coordPtr = linePtr->coordPtr + (linePtr->numPoints * 2);              coordPtr = linePtr->coordPtr + (linePtr->numPoints * 2);
737              if ((linePtr->arrow == ARROWS_LAST) || (linePtr->arrow == ARROWS_BOTH)) {              if ((linePtr->arrow == ARROWS_LAST) || (linePtr->arrow == ARROWS_BOTH)) {
738                  coordPtr = linePtr->lastArrowPtr;                  coordPtr = linePtr->lastArrowPtr;
739              }              }
740          }          }
741          tsoffset->xoffset = (int) (coordPtr[0] + 0.5);          tsoffset->xoffset = (int) (coordPtr[0] + 0.5);
742          tsoffset->yoffset = (int) (coordPtr[1] + 0.5);          tsoffset->yoffset = (int) (coordPtr[1] + 0.5);
743      } else {      } else {
744          if (tsoffset->flags & TK_OFFSET_LEFT) {          if (tsoffset->flags & TK_OFFSET_LEFT) {
745              tsoffset->xoffset = linePtr->header.x1;              tsoffset->xoffset = linePtr->header.x1;
746          } else if (tsoffset->flags & TK_OFFSET_CENTER) {          } else if (tsoffset->flags & TK_OFFSET_CENTER) {
747              tsoffset->xoffset = (linePtr->header.x1 + linePtr->header.x2)/2;              tsoffset->xoffset = (linePtr->header.x1 + linePtr->header.x2)/2;
748          } else if (tsoffset->flags & TK_OFFSET_RIGHT) {          } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
749              tsoffset->xoffset = linePtr->header.x2;              tsoffset->xoffset = linePtr->header.x2;
750          }          }
751          if (tsoffset->flags & TK_OFFSET_TOP) {          if (tsoffset->flags & TK_OFFSET_TOP) {
752              tsoffset->yoffset = linePtr->header.y1;              tsoffset->yoffset = linePtr->header.y1;
753          } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {          } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
754              tsoffset->yoffset = (linePtr->header.y1 + linePtr->header.y2)/2;              tsoffset->yoffset = (linePtr->header.y1 + linePtr->header.y2)/2;
755          } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {          } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
756              tsoffset->yoffset = linePtr->header.y2;              tsoffset->yoffset = linePtr->header.y2;
757          }          }
758      }      }
759    
760      intWidth = (int) (width + 0.5);      intWidth = (int) (width + 0.5);
761      linePtr->header.x1 -= intWidth;      linePtr->header.x1 -= intWidth;
762      linePtr->header.x2 += intWidth;      linePtr->header.x2 += intWidth;
763      linePtr->header.y1 -= intWidth;      linePtr->header.y1 -= intWidth;
764      linePtr->header.y2 += intWidth;      linePtr->header.y2 += intWidth;
765    
766      if (linePtr->numPoints==1) {      if (linePtr->numPoints==1) {
767          linePtr->header.x1 -= 1;          linePtr->header.x1 -= 1;
768          linePtr->header.x2 += 1;          linePtr->header.x2 += 1;
769          linePtr->header.y1 -= 1;          linePtr->header.y1 -= 1;
770          linePtr->header.y2 += 1;          linePtr->header.y2 += 1;
771          return;          return;
772      }      }
773    
774      /*      /*
775       * For mitered lines, make a second pass through all the points.       * For mitered lines, make a second pass through all the points.
776       * Compute the locations of the two miter vertex points and add       * Compute the locations of the two miter vertex points and add
777       * those into the bounding box.       * those into the bounding box.
778       */       */
779    
780      if (linePtr->joinStyle == JoinMiter) {      if (linePtr->joinStyle == JoinMiter) {
781          for (i = linePtr->numPoints, coordPtr = linePtr->coordPtr; i >= 3;          for (i = linePtr->numPoints, coordPtr = linePtr->coordPtr; i >= 3;
782                  i--, coordPtr += 2) {                  i--, coordPtr += 2) {
783              double miter[4];              double miter[4];
784              int j;              int j;
785            
786              if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,              if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
787                      width, miter, miter+2)) {                      width, miter, miter+2)) {
788                  for (j = 0; j < 4; j += 2) {                  for (j = 0; j < 4; j += 2) {
789                      TkIncludePoint((Tk_Item *) linePtr, miter+j);                      TkIncludePoint((Tk_Item *) linePtr, miter+j);
790                  }                  }
791              }              }
792          }          }
793      }      }
794    
795      /*      /*
796       * Add in the sizes of arrowheads, if any.       * Add in the sizes of arrowheads, if any.
797       */       */
798    
799      if (linePtr->arrow != ARROWS_NONE) {      if (linePtr->arrow != ARROWS_NONE) {
800          if (linePtr->arrow != ARROWS_LAST) {          if (linePtr->arrow != ARROWS_LAST) {
801              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
802                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
803                  TkIncludePoint((Tk_Item *) linePtr, coordPtr);                  TkIncludePoint((Tk_Item *) linePtr, coordPtr);
804              }              }
805          }          }
806          if (linePtr->arrow != ARROWS_FIRST) {          if (linePtr->arrow != ARROWS_FIRST) {
807              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
808                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
809                  TkIncludePoint((Tk_Item *) linePtr, coordPtr);                  TkIncludePoint((Tk_Item *) linePtr, coordPtr);
810              }              }
811          }          }
812      }      }
813    
814      /*      /*
815       * Add one more pixel of fudge factor just to be safe (e.g.       * Add one more pixel of fudge factor just to be safe (e.g.
816       * X may round differently than we do).       * X may round differently than we do).
817       */       */
818    
819      linePtr->header.x1 -= 1;      linePtr->header.x1 -= 1;
820      linePtr->header.x2 += 1;      linePtr->header.x2 += 1;
821      linePtr->header.y1 -= 1;      linePtr->header.y1 -= 1;
822      linePtr->header.y2 += 1;      linePtr->header.y2 += 1;
823  }  }
824    
825  /*  /*
826   *--------------------------------------------------------------   *--------------------------------------------------------------
827   *   *
828   * DisplayLine --   * DisplayLine --
829   *   *
830   *      This procedure is invoked to draw a line item in a given   *      This procedure is invoked to draw a line item in a given
831   *      drawable.   *      drawable.
832   *   *
833   * Results:   * Results:
834   *      None.   *      None.
835   *   *
836   * Side effects:   * Side effects:
837   *      ItemPtr is drawn in drawable using the transformation   *      ItemPtr is drawn in drawable using the transformation
838   *      information in canvas.   *      information in canvas.
839   *   *
840   *--------------------------------------------------------------   *--------------------------------------------------------------
841   */   */
842    
843  static void  static void
844  DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)  DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
845      Tk_Canvas canvas;                   /* Canvas that contains item. */      Tk_Canvas canvas;                   /* Canvas that contains item. */
846      Tk_Item *itemPtr;                   /* Item to be displayed. */      Tk_Item *itemPtr;                   /* Item to be displayed. */
847      Display *display;                   /* Display on which to draw item. */      Display *display;                   /* Display on which to draw item. */
848      Drawable drawable;                  /* Pixmap or window in which to draw      Drawable drawable;                  /* Pixmap or window in which to draw
849                                           * item. */                                           * item. */
850      int x, y, width, height;            /* Describes region of canvas that      int x, y, width, height;            /* Describes region of canvas that
851                                           * must be redisplayed (not used). */                                           * must be redisplayed (not used). */
852  {  {
853      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
854      XPoint staticPoints[MAX_STATIC_POINTS];      XPoint staticPoints[MAX_STATIC_POINTS];
855      XPoint *pointPtr;      XPoint *pointPtr;
856      XPoint *pPtr;      XPoint *pPtr;
857      double *coordPtr, linewidth;      double *coordPtr, linewidth;
858      int i, numPoints;      int i, numPoints;
859      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
860      Pixmap stipple = linePtr->outline.stipple;      Pixmap stipple = linePtr->outline.stipple;
861    
862      if ((!linePtr->numPoints)||(linePtr->outline.gc==None)) {      if ((!linePtr->numPoints)||(linePtr->outline.gc==None)) {
863          return;          return;
864      }      }
865    
866      if (state == TK_STATE_NULL) {      if (state == TK_STATE_NULL) {
867              state = ((TkCanvas *)canvas)->canvas_state;              state = ((TkCanvas *)canvas)->canvas_state;
868      }      }
869      linewidth = linePtr->outline.width;      linewidth = linePtr->outline.width;
870      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
871          if (linePtr->outline.activeStipple!=None) {          if (linePtr->outline.activeStipple!=None) {
872              stipple = linePtr->outline.activeStipple;              stipple = linePtr->outline.activeStipple;
873          }          }
874          if (linePtr->outline.activeWidth>linewidth) {          if (linePtr->outline.activeWidth>linewidth) {
875              linewidth = linePtr->outline.activeWidth;              linewidth = linePtr->outline.activeWidth;
876          }          }
877      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
878          if (linePtr->outline.disabledStipple!=None) {          if (linePtr->outline.disabledStipple!=None) {
879              stipple = linePtr->outline.disabledStipple;              stipple = linePtr->outline.disabledStipple;
880          }          }
881          if (linePtr->outline.disabledWidth>linewidth) {          if (linePtr->outline.disabledWidth>linewidth) {
882              linewidth = linePtr->outline.activeWidth;              linewidth = linePtr->outline.activeWidth;
883          }          }
884      }      }
885      /*      /*
886       * Build up an array of points in screen coordinates.  Use a       * Build up an array of points in screen coordinates.  Use a
887       * static array unless the line has an enormous number of points;       * static array unless the line has an enormous number of points;
888       * in this case, dynamically allocate an array.  For smoothed lines,       * in this case, dynamically allocate an array.  For smoothed lines,
889       * generate the curve points on each redisplay.       * generate the curve points on each redisplay.
890       */       */
891    
892      if ((linePtr->smooth) && (linePtr->numPoints > 2)) {      if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
893          numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,          numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
894                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
895                  (double *) NULL);                  (double *) NULL);
896      } else {      } else {
897          numPoints = linePtr->numPoints;          numPoints = linePtr->numPoints;
898      }      }
899    
900      if (numPoints <= MAX_STATIC_POINTS) {      if (numPoints <= MAX_STATIC_POINTS) {
901          pointPtr = staticPoints;          pointPtr = staticPoints;
902      } else {      } else {
903          pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint)));          pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint)));
904      }      }
905    
906      if ((linePtr->smooth) && (linePtr->numPoints > 2)) {      if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
907          numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,          numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
908                  linePtr->numPoints, linePtr->splineSteps, pointPtr,                  linePtr->numPoints, linePtr->splineSteps, pointPtr,
909                  (double *) NULL);                  (double *) NULL);
910      } else {      } else {
911          for (i = 0, coordPtr = linePtr->coordPtr, pPtr = pointPtr;          for (i = 0, coordPtr = linePtr->coordPtr, pPtr = pointPtr;
912                  i < linePtr->numPoints;  i += 1, coordPtr += 2, pPtr++) {                  i < linePtr->numPoints;  i += 1, coordPtr += 2, pPtr++) {
913              Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1],              Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1],
914                      &pPtr->x, &pPtr->y);                      &pPtr->x, &pPtr->y);
915          }          }
916      }      }
917    
918      /*      /*
919       * Display line, the free up line storage if it was dynamically       * Display line, the free up line storage if it was dynamically
920       * allocated.  If we're stippling, then modify the stipple offset       * allocated.  If we're stippling, then modify the stipple offset
921       * in the GC.  Be sure to reset the offset when done, since the       * in the GC.  Be sure to reset the offset when done, since the
922       * GC is supposed to be read-only.       * GC is supposed to be read-only.
923       */       */
924    
925      if (Tk_ChangeOutlineGC(canvas, itemPtr, &(linePtr->outline))) {      if (Tk_ChangeOutlineGC(canvas, itemPtr, &(linePtr->outline))) {
926          Tk_CanvasSetOffset(canvas, linePtr->arrowGC, &linePtr->outline.tsoffset);          Tk_CanvasSetOffset(canvas, linePtr->arrowGC, &linePtr->outline.tsoffset);
927      }      }
928      if (numPoints>1) {      if (numPoints>1) {
929          XDrawLines(display, drawable, linePtr->outline.gc, pointPtr, numPoints,          XDrawLines(display, drawable, linePtr->outline.gc, pointPtr, numPoints,
930              CoordModeOrigin);              CoordModeOrigin);
931      } else {      } else {
932          int intwidth = (int) (linewidth + 0.5);          int intwidth = (int) (linewidth + 0.5);
933          if (intwidth<1) {          if (intwidth<1) {
934              intwidth=1;              intwidth=1;
935          }          }
936          XFillArc(display, drawable, linePtr->outline.gc,          XFillArc(display, drawable, linePtr->outline.gc,
937                  pointPtr->x - intwidth/2, pointPtr->y - intwidth/2,                  pointPtr->x - intwidth/2, pointPtr->y - intwidth/2,
938                  (unsigned int)intwidth+1, (unsigned int)intwidth+1, 0, 64*360);                  (unsigned int)intwidth+1, (unsigned int)intwidth+1, 0, 64*360);
939      }      }
940      if (pointPtr != staticPoints) {      if (pointPtr != staticPoints) {
941          ckfree((char *) pointPtr);          ckfree((char *) pointPtr);
942      }      }
943    
944      /*      /*
945       * Display arrowheads, if they are wanted.       * Display arrowheads, if they are wanted.
946       */       */
947    
948      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
949          TkFillPolygon(canvas, linePtr->firstArrowPtr, PTS_IN_ARROW,          TkFillPolygon(canvas, linePtr->firstArrowPtr, PTS_IN_ARROW,
950                  display, drawable, linePtr->arrowGC, NULL);                  display, drawable, linePtr->arrowGC, NULL);
951      }      }
952      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
953          TkFillPolygon(canvas, linePtr->lastArrowPtr, PTS_IN_ARROW,          TkFillPolygon(canvas, linePtr->lastArrowPtr, PTS_IN_ARROW,
954                  display, drawable, linePtr->arrowGC, NULL);                  display, drawable, linePtr->arrowGC, NULL);
955      }      }
956      if (Tk_ResetOutlineGC(canvas, itemPtr, &(linePtr->outline))) {      if (Tk_ResetOutlineGC(canvas, itemPtr, &(linePtr->outline))) {
957          XSetTSOrigin(display, linePtr->arrowGC, 0, 0);          XSetTSOrigin(display, linePtr->arrowGC, 0, 0);
958      }      }
959  }  }
960    
961  /*  /*
962   *--------------------------------------------------------------   *--------------------------------------------------------------
963   *   *
964   * LineInsert --   * LineInsert --
965   *   *
966   *      Insert coords into a line item at a given index.   *      Insert coords into a line item at a given index.
967   *   *
968   * Results:   * Results:
969   *      None.   *      None.
970   *   *
971   * Side effects:   * Side effects:
972   *      The coords in the given item is modified.   *      The coords in the given item is modified.
973   *   *
974   *--------------------------------------------------------------   *--------------------------------------------------------------
975   */   */
976    
977  static void  static void
978  LineInsert(canvas, itemPtr, beforeThis, obj)  LineInsert(canvas, itemPtr, beforeThis, obj)
979      Tk_Canvas canvas;           /* Canvas containing text item. */      Tk_Canvas canvas;           /* Canvas containing text item. */
980      Tk_Item *itemPtr;           /* Line item to be modified. */      Tk_Item *itemPtr;           /* Line item to be modified. */
981      int beforeThis;             /* Index before which new coordinates      int beforeThis;             /* Index before which new coordinates
982                                   * are to be inserted. */                                   * are to be inserted. */
983      Tcl_Obj *obj;               /* New coordinates to be inserted. */      Tcl_Obj *obj;               /* New coordinates to be inserted. */
984  {  {
985      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
986      int length, argc, i;      int length, argc, i;
987      double *new, *coordPtr;      double *new, *coordPtr;
988      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
989      Tcl_Obj **objv;      Tcl_Obj **objv;
990    
991      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
992          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
993      }      }
994    
995      if (!obj || (Tcl_ListObjGetElements((Tcl_Interp *) NULL, obj, &argc, &objv) != TCL_OK)      if (!obj || (Tcl_ListObjGetElements((Tcl_Interp *) NULL, obj, &argc, &objv) != TCL_OK)
996              || !argc || argc&1) {              || !argc || argc&1) {
997          return;          return;
998      }      }
999      length = 2*linePtr->numPoints;      length = 2*linePtr->numPoints;
1000      if (beforeThis < 0) {      if (beforeThis < 0) {
1001          beforeThis = 0;          beforeThis = 0;
1002      }      }
1003      if (beforeThis > length) {      if (beforeThis > length) {
1004          beforeThis = length;          beforeThis = length;
1005      }      }
1006      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
1007          linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];          linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
1008          linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];          linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
1009      }      }
1010      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
1011          linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];          linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
1012          linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];          linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
1013      }      }
1014      new = (double *) ckalloc((unsigned)(sizeof(double) * (length + argc)));      new = (double *) ckalloc((unsigned)(sizeof(double) * (length + argc)));
1015      for(i=0; i<beforeThis; i++) {      for(i=0; i<beforeThis; i++) {
1016          new[i] = linePtr->coordPtr[i];          new[i] = linePtr->coordPtr[i];
1017      }      }
1018      for(i=0; i<argc; i++) {      for(i=0; i<argc; i++) {
1019          if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,objv[i],          if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,objv[i],
1020                  new+(i+beforeThis))!=TCL_OK) {                  new+(i+beforeThis))!=TCL_OK) {
1021              Tcl_ResetResult(((TkCanvas *)canvas)->interp);              Tcl_ResetResult(((TkCanvas *)canvas)->interp);
1022              ckfree((char *) new);              ckfree((char *) new);
1023              return;              return;
1024          }          }
1025      }      }
1026    
1027      for(i=beforeThis; i<length; i++) {      for(i=beforeThis; i<length; i++) {
1028          new[i+argc] = linePtr->coordPtr[i];          new[i+argc] = linePtr->coordPtr[i];
1029      }      }
1030      if(linePtr->coordPtr) ckfree((char *)linePtr->coordPtr);      if(linePtr->coordPtr) ckfree((char *)linePtr->coordPtr);
1031      linePtr->coordPtr = new;      linePtr->coordPtr = new;
1032      linePtr->numPoints = (length + argc)/2;      linePtr->numPoints = (length + argc)/2;
1033    
1034      if ((length>3) && (state != TK_STATE_HIDDEN)) {      if ((length>3) && (state != TK_STATE_HIDDEN)) {
1035          /*          /*
1036           * This is some optimizing code that will result that only the part           * This is some optimizing code that will result that only the part
1037           * of the polygon that changed (and the objects that are overlapping           * of the polygon that changed (and the objects that are overlapping
1038           * with that part) need to be redrawn. A special flag is set that           * with that part) need to be redrawn. A special flag is set that
1039           * instructs the general canvas code not to redraw the whole           * instructs the general canvas code not to redraw the whole
1040           * object. If this flag is not set, the canvas will do the redrawing,           * object. If this flag is not set, the canvas will do the redrawing,
1041           * otherwise I have to do it here.           * otherwise I have to do it here.
1042           */           */
1043          itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;          itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
1044    
1045          if (beforeThis>0) {beforeThis -= 2; argc+=2; }          if (beforeThis>0) {beforeThis -= 2; argc+=2; }
1046          if ((beforeThis+argc)<length) argc+=2;          if ((beforeThis+argc)<length) argc+=2;
1047          if (linePtr->smooth) {          if (linePtr->smooth) {
1048              if(beforeThis>0) {              if(beforeThis>0) {
1049                  beforeThis-=2; argc+=2;                  beforeThis-=2; argc+=2;
1050              }              }
1051              if((beforeThis+argc+2)<length) {              if((beforeThis+argc+2)<length) {
1052                  argc+=2;                  argc+=2;
1053              }              }
1054          }          }
1055          itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis];          itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis];
1056          itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1];          itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1];
1057          if ((linePtr->firstArrowPtr != NULL) && (beforeThis<1)) {          if ((linePtr->firstArrowPtr != NULL) && (beforeThis<1)) {
1058              /* include old first arrow */              /* include old first arrow */
1059              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
1060                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
1061                  TkIncludePoint(itemPtr, coordPtr);                  TkIncludePoint(itemPtr, coordPtr);
1062              }              }
1063          }          }
1064          if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+argc)>=length)) {          if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+argc)>=length)) {
1065                  /* include old last arrow */                  /* include old last arrow */
1066              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
1067                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
1068                  TkIncludePoint(itemPtr, coordPtr);                  TkIncludePoint(itemPtr, coordPtr);
1069              }              }
1070          }          }
1071          coordPtr = linePtr->coordPtr+beforeThis+2;          coordPtr = linePtr->coordPtr+beforeThis+2;
1072          for(i=2; i<argc; i+=2) {          for(i=2; i<argc; i+=2) {
1073              TkIncludePoint(itemPtr, coordPtr);              TkIncludePoint(itemPtr, coordPtr);
1074                  coordPtr+=2;                  coordPtr+=2;
1075          }          }
1076      }      }
1077      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
1078          ckfree((char *) linePtr->firstArrowPtr);          ckfree((char *) linePtr->firstArrowPtr);
1079          linePtr->firstArrowPtr = NULL;          linePtr->firstArrowPtr = NULL;
1080      }      }
1081      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
1082          ckfree((char *) linePtr->lastArrowPtr);          ckfree((char *) linePtr->lastArrowPtr);
1083          linePtr->lastArrowPtr = NULL;          linePtr->lastArrowPtr = NULL;
1084      }      }
1085      if (linePtr->arrow != ARROWS_NONE) {      if (linePtr->arrow != ARROWS_NONE) {
1086              ConfigureArrows(canvas, linePtr);              ConfigureArrows(canvas, linePtr);
1087      }      }
1088    
1089      if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {      if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
1090          double width;          double width;
1091          int intWidth;          int intWidth;
1092          if ((linePtr->firstArrowPtr != NULL) && (beforeThis>2)) {          if ((linePtr->firstArrowPtr != NULL) && (beforeThis>2)) {
1093              /* include new first arrow */              /* include new first arrow */
1094              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
1095                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
1096                  TkIncludePoint(itemPtr, coordPtr);                  TkIncludePoint(itemPtr, coordPtr);
1097              }              }
1098          }          }
1099          if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+argc)<(length-2))) {          if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+argc)<(length-2))) {
1100              /* include new right arrow */              /* include new right arrow */
1101              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
1102                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
1103                  TkIncludePoint(itemPtr, coordPtr);                  TkIncludePoint(itemPtr, coordPtr);
1104              }              }
1105          }          }
1106          width = linePtr->outline.width;          width = linePtr->outline.width;
1107          if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {          if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1108                  if (linePtr->outline.activeWidth>width) {                  if (linePtr->outline.activeWidth>width) {
1109                      width = linePtr->outline.activeWidth;                      width = linePtr->outline.activeWidth;
1110                  }                  }
1111          } else if (state==TK_STATE_DISABLED) {          } else if (state==TK_STATE_DISABLED) {
1112                  if (linePtr->outline.disabledWidth>0) {                  if (linePtr->outline.disabledWidth>0) {
1113                      width = linePtr->outline.disabledWidth;                      width = linePtr->outline.disabledWidth;
1114                  }                  }
1115          }          }
1116          intWidth = (int) (width + 0.5);          intWidth = (int) (width + 0.5);
1117          if (intWidth < 1) {          if (intWidth < 1) {
1118              intWidth = 1;              intWidth = 1;
1119          }          }
1120          itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth;          itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth;
1121          itemPtr->x2 += intWidth; itemPtr->y2 += intWidth;          itemPtr->x2 += intWidth; itemPtr->y2 += intWidth;
1122          Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,          Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,
1123                  itemPtr->x2, itemPtr->y2);                  itemPtr->x2, itemPtr->y2);
1124      }      }
1125    
1126      ComputeLineBbox(canvas, linePtr);      ComputeLineBbox(canvas, linePtr);
1127  }  }
1128    
1129  /*  /*
1130   *--------------------------------------------------------------   *--------------------------------------------------------------
1131   *   *
1132   * LineDeleteCoords --   * LineDeleteCoords --
1133   *   *
1134   *      Delete one or more coordinates from a line item.   *      Delete one or more coordinates from a line item.
1135   *   *
1136   * Results:   * Results:
1137   *      None.   *      None.
1138   *   *
1139   * Side effects:   * Side effects:
1140   *      Characters between "first" and "last", inclusive, get   *      Characters between "first" and "last", inclusive, get
1141   *      deleted from itemPtr.   *      deleted from itemPtr.
1142   *   *
1143   *--------------------------------------------------------------   *--------------------------------------------------------------
1144   */   */
1145    
1146  static void  static void
1147  LineDeleteCoords(canvas, itemPtr, first, last)  LineDeleteCoords(canvas, itemPtr, first, last)
1148      Tk_Canvas canvas;           /* Canvas containing itemPtr. */      Tk_Canvas canvas;           /* Canvas containing itemPtr. */
1149      Tk_Item *itemPtr;           /* Item in which to delete characters. */      Tk_Item *itemPtr;           /* Item in which to delete characters. */
1150      int first;                  /* Index of first character to delete. */      int first;                  /* Index of first character to delete. */
1151      int last;                   /* Index of last character to delete. */      int last;                   /* Index of last character to delete. */
1152  {  {
1153      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
1154      int count, i, first1, last1;      int count, i, first1, last1;
1155      int length = 2*linePtr->numPoints;      int length = 2*linePtr->numPoints;
1156      double *coordPtr;      double *coordPtr;
1157      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
1158    
1159      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
1160          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
1161      }      }
1162    
1163      first &= -2;      first &= -2;
1164      last &= -2;      last &= -2;
1165    
1166      if (first < 0) {      if (first < 0) {
1167          first = 0;          first = 0;
1168      }      }
1169      if (last >= length) {      if (last >= length) {
1170          last = length-2;          last = length-2;
1171      }      }
1172      if (first > last) {      if (first > last) {
1173          return;          return;
1174      }      }
1175      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
1176          linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];          linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
1177          linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];          linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
1178      }      }
1179      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
1180          linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];          linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
1181          linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];          linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
1182      }      }
1183      first1 = first; last1 = last;      first1 = first; last1 = last;
1184      if(first1>0) first1 -= 2;      if(first1>0) first1 -= 2;
1185      if(last1<length-2) last1 += 2;      if(last1<length-2) last1 += 2;
1186      if (linePtr->smooth) {      if (linePtr->smooth) {
1187          if(first1>0) first1 -= 2;          if(first1>0) first1 -= 2;
1188          if(last1<length-2) last1 += 2;          if(last1<length-2) last1 += 2;
1189      }      }
1190    
1191      if((first1<2) && (last1 >= length-2)) {      if((first1<2) && (last1 >= length-2)) {
1192          /*          /*
1193           * This is some optimizing code that will result that only the part           * This is some optimizing code that will result that only the part
1194           * of the line that changed (and the objects that are overlapping           * of the line that changed (and the objects that are overlapping
1195           * with that part) need to be redrawn. A special flag is set that           * with that part) need to be redrawn. A special flag is set that
1196           * instructs the general canvas code not to redraw the whole           * instructs the general canvas code not to redraw the whole
1197           * object. If this flag is set, the redrawing has to be done here,           * object. If this flag is set, the redrawing has to be done here,
1198           * otherwise the general Canvas code will take care of it.           * otherwise the general Canvas code will take care of it.
1199           */           */
1200    
1201          itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;          itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
1202          itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[first1];          itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[first1];
1203          itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[first1+1];          itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[first1+1];
1204          if ((linePtr->firstArrowPtr != NULL) && (first1<2)) {          if ((linePtr->firstArrowPtr != NULL) && (first1<2)) {
1205              /* include old first arrow */              /* include old first arrow */
1206              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
1207                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
1208                  TkIncludePoint(itemPtr, coordPtr);                  TkIncludePoint(itemPtr, coordPtr);
1209              }              }
1210          }          }
1211          if ((linePtr->lastArrowPtr != NULL) && (last1>=length-2)) {          if ((linePtr->lastArrowPtr != NULL) && (last1>=length-2)) {
1212                  /* include old last arrow */                  /* include old last arrow */
1213              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
1214                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
1215                  TkIncludePoint(itemPtr, coordPtr);                  TkIncludePoint(itemPtr, coordPtr);
1216              }              }
1217          }          }
1218          coordPtr = linePtr->coordPtr+first1+2;          coordPtr = linePtr->coordPtr+first1+2;
1219          for (i=first1+2; i<=last1; i+=2) {          for (i=first1+2; i<=last1; i+=2) {
1220              TkIncludePoint(itemPtr, coordPtr);              TkIncludePoint(itemPtr, coordPtr);
1221              coordPtr+=2;              coordPtr+=2;
1222          }          }
1223      }      }
1224    
1225      count = last + 2 - first;      count = last + 2 - first;
1226      for (i=last+2; i<length; i++) {      for (i=last+2; i<length; i++) {
1227          linePtr->coordPtr[i-count] = linePtr->coordPtr[i];          linePtr->coordPtr[i-count] = linePtr->coordPtr[i];
1228      }      }
1229      linePtr->numPoints -= count/2;      linePtr->numPoints -= count/2;
1230      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
1231          ckfree((char *) linePtr->firstArrowPtr);          ckfree((char *) linePtr->firstArrowPtr);
1232          linePtr->firstArrowPtr = NULL;          linePtr->firstArrowPtr = NULL;
1233      }      }
1234      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
1235          ckfree((char *) linePtr->lastArrowPtr);          ckfree((char *) linePtr->lastArrowPtr);
1236          linePtr->lastArrowPtr = NULL;          linePtr->lastArrowPtr = NULL;
1237      }      }
1238      if (linePtr->arrow != ARROWS_NONE) {      if (linePtr->arrow != ARROWS_NONE) {
1239              ConfigureArrows(canvas, linePtr);              ConfigureArrows(canvas, linePtr);
1240      }      }
1241      if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {      if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
1242          double width;          double width;
1243          int intWidth;          int intWidth;
1244          if ((linePtr->firstArrowPtr != NULL) && (first1<4)) {          if ((linePtr->firstArrowPtr != NULL) && (first1<4)) {
1245              /* include new first arrow */              /* include new first arrow */
1246              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
1247                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
1248                  TkIncludePoint(itemPtr, coordPtr);                  TkIncludePoint(itemPtr, coordPtr);
1249              }              }
1250          }          }
1251          if ((linePtr->lastArrowPtr != NULL) && (last1>(length-4))) {          if ((linePtr->lastArrowPtr != NULL) && (last1>(length-4))) {
1252              /* include new right arrow */              /* include new right arrow */
1253              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;              for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
1254                      i++, coordPtr += 2) {                      i++, coordPtr += 2) {
1255                  TkIncludePoint(itemPtr, coordPtr);                  TkIncludePoint(itemPtr, coordPtr);
1256              }              }
1257          }          }
1258          width = linePtr->outline.width;          width = linePtr->outline.width;
1259          if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {          if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1260                  if (linePtr->outline.activeWidth>width) {                  if (linePtr->outline.activeWidth>width) {
1261                      width = linePtr->outline.activeWidth;                      width = linePtr->outline.activeWidth;
1262                  }                  }
1263          } else if (state==TK_STATE_DISABLED) {          } else if (state==TK_STATE_DISABLED) {
1264                  if (linePtr->outline.disabledWidth>0) {                  if (linePtr->outline.disabledWidth>0) {
1265                      width = linePtr->outline.disabledWidth;                      width = linePtr->outline.disabledWidth;
1266                  }                  }
1267          }          }
1268          intWidth = (int) (width + 0.5);          intWidth = (int) (width + 0.5);
1269          if (intWidth < 1) {          if (intWidth < 1) {
1270              intWidth = 1;              intWidth = 1;
1271          }          }
1272          itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth;          itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth;
1273          itemPtr->x2 += intWidth; itemPtr->y2 += intWidth;          itemPtr->x2 += intWidth; itemPtr->y2 += intWidth;
1274          Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,          Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,
1275                  itemPtr->x2, itemPtr->y2);                  itemPtr->x2, itemPtr->y2);
1276      }      }
1277      ComputeLineBbox(canvas, linePtr);      ComputeLineBbox(canvas, linePtr);
1278  }  }
1279    
1280  /*  /*
1281   *--------------------------------------------------------------   *--------------------------------------------------------------
1282   *   *
1283   * LineToPoint --   * LineToPoint --
1284   *   *
1285   *      Computes the distance from a given point to a given   *      Computes the distance from a given point to a given
1286   *      line, in canvas units.   *      line, in canvas units.
1287   *   *
1288   * Results:   * Results:
1289   *      The return value is 0 if the point whose x and y coordinates   *      The return value is 0 if the point whose x and y coordinates
1290   *      are pointPtr[0] and pointPtr[1] is inside the line.  If the   *      are pointPtr[0] and pointPtr[1] is inside the line.  If the
1291   *      point isn't inside the line then the return value is the   *      point isn't inside the line then the return value is the
1292   *      distance from the point to the line.   *      distance from the point to the line.
1293   *   *
1294   * Side effects:   * Side effects:
1295   *      None.   *      None.
1296   *   *
1297   *--------------------------------------------------------------   *--------------------------------------------------------------
1298   */   */
1299    
1300          /* ARGSUSED */          /* ARGSUSED */
1301  static double  static double
1302  LineToPoint(canvas, itemPtr, pointPtr)  LineToPoint(canvas, itemPtr, pointPtr)
1303      Tk_Canvas canvas;           /* Canvas containing item. */      Tk_Canvas canvas;           /* Canvas containing item. */
1304      Tk_Item *itemPtr;           /* Item to check against point. */      Tk_Item *itemPtr;           /* Item to check against point. */
1305      double *pointPtr;           /* Pointer to x and y coordinates. */      double *pointPtr;           /* Pointer to x and y coordinates. */
1306  {  {
1307      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
1308      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
1309      double *coordPtr, *linePoints;      double *coordPtr, *linePoints;
1310      double staticSpace[2*MAX_STATIC_POINTS];      double staticSpace[2*MAX_STATIC_POINTS];
1311      double poly[10];      double poly[10];
1312      double bestDist, dist, width;      double bestDist, dist, width;
1313      int numPoints, count;      int numPoints, count;
1314      int changedMiterToBevel;    /* Non-zero means that a mitered corner      int changedMiterToBevel;    /* Non-zero means that a mitered corner
1315                                   * had to be treated as beveled after all                                   * had to be treated as beveled after all
1316                                   * because the angle was < 11 degrees. */                                   * because the angle was < 11 degrees. */
1317    
1318      bestDist = 1.0e36;      bestDist = 1.0e36;
1319    
1320      /*      /*
1321       * Handle smoothed lines by generating an expanded set of points       * Handle smoothed lines by generating an expanded set of points
1322       * against which to do the check.       * against which to do the check.
1323       */       */
1324    
1325      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
1326          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
1327      }      }
1328    
1329      width = linePtr->outline.width;      width = linePtr->outline.width;
1330      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1331          if (linePtr->outline.activeWidth>width) {          if (linePtr->outline.activeWidth>width) {
1332              width = linePtr->outline.activeWidth;              width = linePtr->outline.activeWidth;
1333          }          }
1334      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
1335          if (linePtr->outline.disabledWidth>0) {          if (linePtr->outline.disabledWidth>0) {
1336              width = linePtr->outline.disabledWidth;              width = linePtr->outline.disabledWidth;
1337          }          }
1338      }      }
1339    
1340      if ((linePtr->smooth) && (linePtr->numPoints > 2)) {      if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
1341          numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,          numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
1342                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
1343                  (double *) NULL);                  (double *) NULL);
1344          if (numPoints <= MAX_STATIC_POINTS) {          if (numPoints <= MAX_STATIC_POINTS) {
1345              linePoints = staticSpace;              linePoints = staticSpace;
1346          } else {          } else {
1347              linePoints = (double *) ckalloc((unsigned)              linePoints = (double *) ckalloc((unsigned)
1348                      (2*numPoints*sizeof(double)));                      (2*numPoints*sizeof(double)));
1349          }          }
1350          numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,          numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
1351                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
1352                  linePoints);                  linePoints);
1353      } else {      } else {
1354          numPoints = linePtr->numPoints;          numPoints = linePtr->numPoints;
1355          linePoints = linePtr->coordPtr;          linePoints = linePtr->coordPtr;
1356      }      }
1357    
1358      if (width < 1.0) {      if (width < 1.0) {
1359          width = 1.0;          width = 1.0;
1360      }      }
1361    
1362      if (!numPoints || itemPtr->state==TK_STATE_HIDDEN) {      if (!numPoints || itemPtr->state==TK_STATE_HIDDEN) {
1363          return bestDist;          return bestDist;
1364      } else if (numPoints == 1) {      } else if (numPoints == 1) {
1365          bestDist = hypot(linePoints[0] - pointPtr[0], linePoints[1] - pointPtr[1])          bestDist = hypot(linePoints[0] - pointPtr[0], linePoints[1] - pointPtr[1])
1366                      - width/2.0;                      - width/2.0;
1367          if (bestDist < 0) bestDist = 0;          if (bestDist < 0) bestDist = 0;
1368          return bestDist;          return bestDist;
1369      }      }
1370    
1371      /*      /*
1372       * The overall idea is to iterate through all of the edges of       * The overall idea is to iterate through all of the edges of
1373       * the line, computing a polygon for each edge and testing the       * the line, computing a polygon for each edge and testing the
1374       * point against that polygon.  In addition, there are additional       * point against that polygon.  In addition, there are additional
1375       * tests to deal with rounded joints and caps.       * tests to deal with rounded joints and caps.
1376       */       */
1377    
1378      changedMiterToBevel = 0;      changedMiterToBevel = 0;
1379      for (count = numPoints, coordPtr = linePoints; count >= 2;      for (count = numPoints, coordPtr = linePoints; count >= 2;
1380              count--, coordPtr += 2) {              count--, coordPtr += 2) {
1381    
1382          /*          /*
1383           * If rounding is done around the first point then compute           * If rounding is done around the first point then compute
1384           * the distance between the point and the point.           * the distance between the point and the point.
1385           */           */
1386    
1387          if (((linePtr->capStyle == CapRound) && (count == numPoints))          if (((linePtr->capStyle == CapRound) && (count == numPoints))
1388                  || ((linePtr->joinStyle == JoinRound)                  || ((linePtr->joinStyle == JoinRound)
1389                          && (count != numPoints))) {                          && (count != numPoints))) {
1390              dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])              dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
1391                      - width/2.0;                      - width/2.0;
1392              if (dist <= 0.0) {              if (dist <= 0.0) {
1393                  bestDist = 0.0;                  bestDist = 0.0;
1394                  goto done;                  goto done;
1395              } else if (dist < bestDist) {              } else if (dist < bestDist) {
1396                  bestDist = dist;                  bestDist = dist;
1397              }              }
1398          }          }
1399    
1400          /*          /*
1401           * Compute the polygonal shape corresponding to this edge,           * Compute the polygonal shape corresponding to this edge,
1402           * consisting of two points for the first point of the edge           * consisting of two points for the first point of the edge
1403           * and two points for the last point of the edge.           * and two points for the last point of the edge.
1404           */           */
1405    
1406          if (count == numPoints) {          if (count == numPoints) {
1407              TkGetButtPoints(coordPtr+2, coordPtr, width,              TkGetButtPoints(coordPtr+2, coordPtr, width,
1408                      linePtr->capStyle == CapProjecting, poly, poly+2);                      linePtr->capStyle == CapProjecting, poly, poly+2);
1409          } else if ((linePtr->joinStyle == JoinMiter) && !changedMiterToBevel) {          } else if ((linePtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
1410              poly[0] = poly[6];              poly[0] = poly[6];
1411              poly[1] = poly[7];              poly[1] = poly[7];
1412              poly[2] = poly[4];              poly[2] = poly[4];
1413              poly[3] = poly[5];              poly[3] = poly[5];
1414          } else {          } else {
1415              TkGetButtPoints(coordPtr+2, coordPtr, width, 0,              TkGetButtPoints(coordPtr+2, coordPtr, width, 0,
1416                      poly, poly+2);                      poly, poly+2);
1417    
1418              /*              /*
1419               * If this line uses beveled joints, then check the distance               * If this line uses beveled joints, then check the distance
1420               * to a polygon comprising the last two points of the previous               * to a polygon comprising the last two points of the previous
1421               * polygon and the first two from this polygon;  this checks               * polygon and the first two from this polygon;  this checks
1422               * the wedges that fill the mitered joint.               * the wedges that fill the mitered joint.
1423               */               */
1424    
1425              if ((linePtr->joinStyle == JoinBevel) || changedMiterToBevel) {              if ((linePtr->joinStyle == JoinBevel) || changedMiterToBevel) {
1426                  poly[8] = poly[0];                  poly[8] = poly[0];
1427                  poly[9] = poly[1];                  poly[9] = poly[1];
1428                  dist = TkPolygonToPoint(poly, 5, pointPtr);                  dist = TkPolygonToPoint(poly, 5, pointPtr);
1429                  if (dist <= 0.0) {                  if (dist <= 0.0) {
1430                      bestDist = 0.0;                      bestDist = 0.0;
1431                      goto done;                      goto done;
1432                  } else if (dist < bestDist) {                  } else if (dist < bestDist) {
1433                      bestDist = dist;                      bestDist = dist;
1434                  }                  }
1435                  changedMiterToBevel = 0;                  changedMiterToBevel = 0;
1436              }              }
1437          }          }
1438          if (count == 2) {          if (count == 2) {
1439              TkGetButtPoints(coordPtr, coordPtr+2, width,              TkGetButtPoints(coordPtr, coordPtr+2, width,
1440                      linePtr->capStyle == CapProjecting, poly+4, poly+6);                      linePtr->capStyle == CapProjecting, poly+4, poly+6);
1441          } else if (linePtr->joinStyle == JoinMiter) {          } else if (linePtr->joinStyle == JoinMiter) {
1442              if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,              if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
1443                      width, poly+4, poly+6) == 0) {                      width, poly+4, poly+6) == 0) {
1444                  changedMiterToBevel = 1;                  changedMiterToBevel = 1;
1445                  TkGetButtPoints(coordPtr, coordPtr+2, width,                  TkGetButtPoints(coordPtr, coordPtr+2, width,
1446                          0, poly+4, poly+6);                          0, poly+4, poly+6);
1447              }              }
1448          } else {          } else {
1449              TkGetButtPoints(coordPtr, coordPtr+2, width, 0,              TkGetButtPoints(coordPtr, coordPtr+2, width, 0,
1450                      poly+4, poly+6);                      poly+4, poly+6);
1451          }          }
1452          poly[8] = poly[0];          poly[8] = poly[0];
1453          poly[9] = poly[1];          poly[9] = poly[1];
1454          dist = TkPolygonToPoint(poly, 5, pointPtr);          dist = TkPolygonToPoint(poly, 5, pointPtr);
1455          if (dist <= 0.0) {          if (dist <= 0.0) {
1456              bestDist = 0.0;              bestDist = 0.0;
1457              goto done;              goto done;
1458          } else if (dist < bestDist) {          } else if (dist < bestDist) {
1459              bestDist = dist;              bestDist = dist;
1460          }          }
1461      }      }
1462    
1463      /*      /*
1464       * If caps are rounded, check the distance to the cap around the       * If caps are rounded, check the distance to the cap around the
1465       * final end point of the line.       * final end point of the line.
1466       */       */
1467    
1468      if (linePtr->capStyle == CapRound) {      if (linePtr->capStyle == CapRound) {
1469          dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])          dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
1470                  - width/2.0;                  - width/2.0;
1471          if (dist <= 0.0) {          if (dist <= 0.0) {
1472              bestDist = 0.0;              bestDist = 0.0;
1473              goto done;              goto done;
1474          } else if (dist < bestDist) {          } else if (dist < bestDist) {
1475              bestDist = dist;              bestDist = dist;
1476          }          }
1477      }      }
1478    
1479      /*      /*
1480       * If there are arrowheads, check the distance to the arrowheads.       * If there are arrowheads, check the distance to the arrowheads.
1481       */       */
1482    
1483      if (linePtr->arrow != ARROWS_NONE) {      if (linePtr->arrow != ARROWS_NONE) {
1484          if (linePtr->arrow != ARROWS_LAST) {          if (linePtr->arrow != ARROWS_LAST) {
1485              dist = TkPolygonToPoint(linePtr->firstArrowPtr, PTS_IN_ARROW,              dist = TkPolygonToPoint(linePtr->firstArrowPtr, PTS_IN_ARROW,
1486                      pointPtr);                      pointPtr);
1487              if (dist <= 0.0) {              if (dist <= 0.0) {
1488                  bestDist = 0.0;                  bestDist = 0.0;
1489                  goto done;                  goto done;
1490              } else if (dist < bestDist) {              } else if (dist < bestDist) {
1491                  bestDist = dist;                  bestDist = dist;
1492              }              }
1493          }          }
1494          if (linePtr->arrow != ARROWS_FIRST) {          if (linePtr->arrow != ARROWS_FIRST) {
1495              dist = TkPolygonToPoint(linePtr->lastArrowPtr, PTS_IN_ARROW,              dist = TkPolygonToPoint(linePtr->lastArrowPtr, PTS_IN_ARROW,
1496                      pointPtr);                      pointPtr);
1497              if (dist <= 0.0) {              if (dist <= 0.0) {
1498                  bestDist = 0.0;                  bestDist = 0.0;
1499                  goto done;                  goto done;
1500              } else if (dist < bestDist) {              } else if (dist < bestDist) {
1501                  bestDist = dist;                  bestDist = dist;
1502              }              }
1503          }          }
1504      }      }
1505    
1506      done:      done:
1507      if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {      if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {
1508          ckfree((char *) linePoints);          ckfree((char *) linePoints);
1509      }      }
1510      return bestDist;      return bestDist;
1511  }  }
1512    
1513  /*  /*
1514   *--------------------------------------------------------------   *--------------------------------------------------------------
1515   *   *
1516   * LineToArea --   * LineToArea --
1517   *   *
1518   *      This procedure is called to determine whether an item   *      This procedure is called to determine whether an item
1519   *      lies entirely inside, entirely outside, or overlapping   *      lies entirely inside, entirely outside, or overlapping
1520   *      a given rectangular area.   *      a given rectangular area.
1521   *   *
1522   * Results:   * Results:
1523   *      -1 is returned if the item is entirely outside the   *      -1 is returned if the item is entirely outside the
1524   *      area, 0 if it overlaps, and 1 if it is entirely   *      area, 0 if it overlaps, and 1 if it is entirely
1525   *      inside the given area.   *      inside the given area.
1526   *   *
1527   * Side effects:   * Side effects:
1528   *      None.   *      None.
1529   *   *
1530   *--------------------------------------------------------------   *--------------------------------------------------------------
1531   */   */
1532    
1533          /* ARGSUSED */          /* ARGSUSED */
1534  static int  static int
1535  LineToArea(canvas, itemPtr, rectPtr)  LineToArea(canvas, itemPtr, rectPtr)
1536      Tk_Canvas canvas;           /* Canvas containing item. */      Tk_Canvas canvas;           /* Canvas containing item. */
1537      Tk_Item *itemPtr;           /* Item to check against line. */      Tk_Item *itemPtr;           /* Item to check against line. */
1538      double *rectPtr;      double *rectPtr;
1539  {  {
1540      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
1541      double staticSpace[2*MAX_STATIC_POINTS];      double staticSpace[2*MAX_STATIC_POINTS];
1542      double *linePoints;      double *linePoints;
1543      int numPoints, result;      int numPoints, result;
1544      double radius, width;      double radius, width;
1545      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
1546    
1547      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
1548          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
1549      }      }
1550      width = linePtr->outline.width;      width = linePtr->outline.width;
1551      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1552          if (linePtr->outline.activeWidth>width) {          if (linePtr->outline.activeWidth>width) {
1553              width = linePtr->outline.activeWidth;              width = linePtr->outline.activeWidth;
1554          }          }
1555      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
1556          if (linePtr->outline.disabledWidth>0) {          if (linePtr->outline.disabledWidth>0) {
1557              width = linePtr->outline.disabledWidth;              width = linePtr->outline.disabledWidth;
1558          }          }
1559      }      }
1560    
1561      radius = (width+1.0)/2.0;      radius = (width+1.0)/2.0;
1562    
1563      if ((state==TK_STATE_HIDDEN) || !linePtr->numPoints) {      if ((state==TK_STATE_HIDDEN) || !linePtr->numPoints) {
1564          return -1;          return -1;
1565      } else if (linePtr->numPoints == 1) {      } else if (linePtr->numPoints == 1) {
1566          double oval[4];          double oval[4];
1567          oval[0] = linePtr->coordPtr[0]-radius;          oval[0] = linePtr->coordPtr[0]-radius;
1568          oval[1] = linePtr->coordPtr[1]-radius;          oval[1] = linePtr->coordPtr[1]-radius;
1569          oval[2] = linePtr->coordPtr[0]+radius;          oval[2] = linePtr->coordPtr[0]+radius;
1570          oval[3] = linePtr->coordPtr[1]+radius;          oval[3] = linePtr->coordPtr[1]+radius;
1571          return TkOvalToArea(oval, rectPtr);          return TkOvalToArea(oval, rectPtr);
1572      }      }
1573    
1574      /*      /*
1575       * Handle smoothed lines by generating an expanded set of points       * Handle smoothed lines by generating an expanded set of points
1576       * against which to do the check.       * against which to do the check.
1577       */       */
1578    
1579      if ((linePtr->smooth) && (linePtr->numPoints > 2)) {      if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
1580          numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,          numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
1581                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
1582                  (double *) NULL);                  (double *) NULL);
1583          if (numPoints <= MAX_STATIC_POINTS) {          if (numPoints <= MAX_STATIC_POINTS) {
1584              linePoints = staticSpace;              linePoints = staticSpace;
1585          } else {          } else {
1586              linePoints = (double *) ckalloc((unsigned)              linePoints = (double *) ckalloc((unsigned)
1587                      (2*numPoints*sizeof(double)));                      (2*numPoints*sizeof(double)));
1588          }          }
1589          numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,          numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
1590                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,                  linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
1591                  linePoints);                  linePoints);
1592      } else {      } else {
1593          numPoints = linePtr->numPoints;          numPoints = linePtr->numPoints;
1594          linePoints = linePtr->coordPtr;          linePoints = linePtr->coordPtr;
1595      }      }
1596    
1597      /*      /*
1598       * Check the segments of the line.       * Check the segments of the line.
1599       */       */
1600    
1601       if (width < 1.0) {       if (width < 1.0) {
1602          width = 1.0;          width = 1.0;
1603      }      }
1604    
1605      result = TkThickPolyLineToArea(linePoints, numPoints,      result = TkThickPolyLineToArea(linePoints, numPoints,
1606              width, linePtr->capStyle, linePtr->joinStyle,              width, linePtr->capStyle, linePtr->joinStyle,
1607              rectPtr);              rectPtr);
1608      if (result == 0) {      if (result == 0) {
1609          goto done;          goto done;
1610      }      }
1611    
1612      /*      /*
1613       * Check arrowheads, if any.       * Check arrowheads, if any.
1614       */       */
1615    
1616      if (linePtr->arrow != ARROWS_NONE) {      if (linePtr->arrow != ARROWS_NONE) {
1617          if (linePtr->arrow != ARROWS_LAST) {          if (linePtr->arrow != ARROWS_LAST) {
1618              if (TkPolygonToArea(linePtr->firstArrowPtr, PTS_IN_ARROW,              if (TkPolygonToArea(linePtr->firstArrowPtr, PTS_IN_ARROW,
1619                      rectPtr) != result) {                      rectPtr) != result) {
1620                  result = 0;                  result = 0;
1621                  goto done;                  goto done;
1622              }              }
1623          }          }
1624          if (linePtr->arrow != ARROWS_FIRST) {          if (linePtr->arrow != ARROWS_FIRST) {
1625              if (TkPolygonToArea(linePtr->lastArrowPtr, PTS_IN_ARROW,              if (TkPolygonToArea(linePtr->lastArrowPtr, PTS_IN_ARROW,
1626                      rectPtr) != result) {                      rectPtr) != result) {
1627                  result = 0;                  result = 0;
1628                  goto done;                  goto done;
1629              }              }
1630          }          }
1631      }      }
1632    
1633      done:      done:
1634      if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {      if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {
1635          ckfree((char *) linePoints);          ckfree((char *) linePoints);
1636      }      }
1637      return result;      return result;
1638  }  }
1639    
1640  /*  /*
1641   *--------------------------------------------------------------   *--------------------------------------------------------------
1642   *   *
1643   * ScaleLine --   * ScaleLine --
1644   *   *
1645   *      This procedure is invoked to rescale a line item.   *      This procedure is invoked to rescale a line item.
1646   *   *
1647   * Results:   * Results:
1648   *      None.   *      None.
1649   *   *
1650   * Side effects:   * Side effects:
1651   *      The line referred to by itemPtr is rescaled so that the   *      The line referred to by itemPtr is rescaled so that the
1652   *      following transformation is applied to all point   *      following transformation is applied to all point
1653   *      coordinates:   *      coordinates:
1654   *              x' = originX + scaleX*(x-originX)   *              x' = originX + scaleX*(x-originX)
1655   *              y' = originY + scaleY*(y-originY)   *              y' = originY + scaleY*(y-originY)
1656   *   *
1657   *--------------------------------------------------------------   *--------------------------------------------------------------
1658   */   */
1659    
1660  static void  static void
1661  ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY)  ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY)
1662      Tk_Canvas canvas;                   /* Canvas containing line. */      Tk_Canvas canvas;                   /* Canvas containing line. */
1663      Tk_Item *itemPtr;                   /* Line to be scaled. */      Tk_Item *itemPtr;                   /* Line to be scaled. */
1664      double originX, originY;            /* Origin about which to scale rect. */      double originX, originY;            /* Origin about which to scale rect. */
1665      double scaleX;                      /* Amount to scale in X direction. */      double scaleX;                      /* Amount to scale in X direction. */
1666      double scaleY;                      /* Amount to scale in Y direction. */      double scaleY;                      /* Amount to scale in Y direction. */
1667  {  {
1668      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
1669      double *coordPtr;      double *coordPtr;
1670      int i;      int i;
1671    
1672      /*      /*
1673       * Delete any arrowheads before scaling all the points (so that       * Delete any arrowheads before scaling all the points (so that
1674       * the end-points of the line get restored).       * the end-points of the line get restored).
1675       */       */
1676    
1677      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
1678          linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];          linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
1679          linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];          linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
1680          ckfree((char *) linePtr->firstArrowPtr);          ckfree((char *) linePtr->firstArrowPtr);
1681          linePtr->firstArrowPtr = NULL;          linePtr->firstArrowPtr = NULL;
1682      }      }
1683      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
1684          int i;          int i;
1685    
1686          i = 2*(linePtr->numPoints-1);          i = 2*(linePtr->numPoints-1);
1687          linePtr->coordPtr[i] = linePtr->lastArrowPtr[0];          linePtr->coordPtr[i] = linePtr->lastArrowPtr[0];
1688          linePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];          linePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];
1689          ckfree((char *) linePtr->lastArrowPtr);          ckfree((char *) linePtr->lastArrowPtr);
1690          linePtr->lastArrowPtr = NULL;          linePtr->lastArrowPtr = NULL;
1691      }      }
1692      for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;      for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;
1693              i++, coordPtr += 2) {              i++, coordPtr += 2) {
1694          coordPtr[0] = originX + scaleX*(*coordPtr - originX);          coordPtr[0] = originX + scaleX*(*coordPtr - originX);
1695          coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);          coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
1696      }      }
1697      if (linePtr->arrow != ARROWS_NONE) {      if (linePtr->arrow != ARROWS_NONE) {
1698          ConfigureArrows(canvas, linePtr);          ConfigureArrows(canvas, linePtr);
1699      }      }
1700      ComputeLineBbox(canvas, linePtr);      ComputeLineBbox(canvas, linePtr);
1701  }  }
1702    
1703  /*  /*
1704   *--------------------------------------------------------------   *--------------------------------------------------------------
1705   *   *
1706   * GetLineIndex --   * GetLineIndex --
1707   *   *
1708   *      Parse an index into a line item and return either its value   *      Parse an index into a line item and return either its value
1709   *      or an error.   *      or an error.
1710   *   *
1711   * Results:   * Results:
1712   *      A standard Tcl result.  If all went well, then *indexPtr is   *      A standard Tcl result.  If all went well, then *indexPtr is
1713   *      filled in with the index (into itemPtr) corresponding to   *      filled in with the index (into itemPtr) corresponding to
1714   *      string.  Otherwise an error message is left in   *      string.  Otherwise an error message is left in
1715   *      interp->result.   *      interp->result.
1716   *   *
1717   * Side effects:   * Side effects:
1718   *      None.   *      None.
1719   *   *
1720   *--------------------------------------------------------------   *--------------------------------------------------------------
1721   */   */
1722    
1723  static int  static int
1724  GetLineIndex(interp, canvas, itemPtr, obj, indexPtr)  GetLineIndex(interp, canvas, itemPtr, obj, indexPtr)
1725      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
1726      Tk_Canvas canvas;           /* Canvas containing item. */      Tk_Canvas canvas;           /* Canvas containing item. */
1727      Tk_Item *itemPtr;           /* Item for which the index is being      Tk_Item *itemPtr;           /* Item for which the index is being
1728                                   * specified. */                                   * specified. */
1729      Tcl_Obj *obj;               /* Specification of a particular coord      Tcl_Obj *obj;               /* Specification of a particular coord
1730                                   * in itemPtr's line. */                                   * in itemPtr's line. */
1731      int *indexPtr;              /* Where to store converted index. */      int *indexPtr;              /* Where to store converted index. */
1732  {  {
1733      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
1734      size_t length;      size_t length;
1735      char *string = Tcl_GetStringFromObj(obj, (int *) &length);      char *string = Tcl_GetStringFromObj(obj, (int *) &length);
1736    
1737      if (string[0] == 'e') {      if (string[0] == 'e') {
1738          if (strncmp(string, "end", length) == 0) {          if (strncmp(string, "end", length) == 0) {
1739              *indexPtr = 2*linePtr->numPoints;              *indexPtr = 2*linePtr->numPoints;
1740          } else {          } else {
1741              badIndex:              badIndex:
1742    
1743              /*              /*
1744               * Some of the paths here leave messages in interp->result,               * Some of the paths here leave messages in interp->result,
1745               * so we have to clear it out before storing our own message.               * so we have to clear it out before storing our own message.
1746               */               */
1747    
1748              Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);              Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
1749              Tcl_AppendResult(interp, "bad index \"", string, "\"",              Tcl_AppendResult(interp, "bad index \"", string, "\"",
1750                      (char *) NULL);                      (char *) NULL);
1751              return TCL_ERROR;              return TCL_ERROR;
1752          }          }
1753      } else if (string[0] == '@') {      } else if (string[0] == '@') {
1754          int i;          int i;
1755          double x ,y, bestDist, dist, *coordPtr;          double x ,y, bestDist, dist, *coordPtr;
1756          char *end, *p;          char *end, *p;
1757    
1758          p = string+1;          p = string+1;
1759          x = strtod(p, &end);          x = strtod(p, &end);
1760          if ((end == p) || (*end != ',')) {          if ((end == p) || (*end != ',')) {
1761              goto badIndex;              goto badIndex;
1762          }          }
1763          p = end+1;          p = end+1;
1764          y = strtod(p, &end);          y = strtod(p, &end);
1765          if ((end == p) || (*end != 0)) {          if ((end == p) || (*end != 0)) {
1766              goto badIndex;              goto badIndex;
1767          }          }
1768          bestDist = 1.0e36;          bestDist = 1.0e36;
1769          coordPtr = linePtr->coordPtr;          coordPtr = linePtr->coordPtr;
1770          *indexPtr = 0;          *indexPtr = 0;
1771          for(i=0; i<linePtr->numPoints; i++) {          for(i=0; i<linePtr->numPoints; i++) {
1772              dist = hypot(coordPtr[0] - x, coordPtr[1] - y);              dist = hypot(coordPtr[0] - x, coordPtr[1] - y);
1773              if (dist<bestDist) {              if (dist<bestDist) {
1774                  bestDist = dist;                  bestDist = dist;
1775                  *indexPtr = 2*i;                  *indexPtr = 2*i;
1776              }              }
1777              coordPtr += 2;              coordPtr += 2;
1778          }          }
1779      } else {      } else {
1780          if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {          if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
1781              goto badIndex;              goto badIndex;
1782          }          }
1783          *indexPtr &= -2; /* if index is odd, make it even */          *indexPtr &= -2; /* if index is odd, make it even */
1784          if (*indexPtr < 0){          if (*indexPtr < 0){
1785              *indexPtr = 0;              *indexPtr = 0;
1786          } else if (*indexPtr > (2*linePtr->numPoints)) {          } else if (*indexPtr > (2*linePtr->numPoints)) {
1787              *indexPtr = (2*linePtr->numPoints);              *indexPtr = (2*linePtr->numPoints);
1788          }          }
1789      }      }
1790      return TCL_OK;      return TCL_OK;
1791  }  }
1792    
1793  /*  /*
1794   *--------------------------------------------------------------   *--------------------------------------------------------------
1795   *   *
1796   * TranslateLine --   * TranslateLine --
1797   *   *
1798   *      This procedure is called to move a line by a given amount.   *      This procedure is called to move a line by a given amount.
1799   *   *
1800   * Results:   * Results:
1801   *      None.   *      None.
1802   *   *
1803   * Side effects:   * Side effects:
1804   *      The position of the line is offset by (xDelta, yDelta), and   *      The position of the line is offset by (xDelta, yDelta), and
1805   *      the bounding box is updated in the generic part of the item   *      the bounding box is updated in the generic part of the item
1806   *      structure.   *      structure.
1807   *   *
1808   *--------------------------------------------------------------   *--------------------------------------------------------------
1809   */   */
1810    
1811  static void  static void
1812  TranslateLine(canvas, itemPtr, deltaX, deltaY)  TranslateLine(canvas, itemPtr, deltaX, deltaY)
1813      Tk_Canvas canvas;                   /* Canvas containing item. */      Tk_Canvas canvas;                   /* Canvas containing item. */
1814      Tk_Item *itemPtr;                   /* Item that is being moved. */      Tk_Item *itemPtr;                   /* Item that is being moved. */
1815      double deltaX, deltaY;              /* Amount by which item is to be      double deltaX, deltaY;              /* Amount by which item is to be
1816                                           * moved. */                                           * moved. */
1817  {  {
1818      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
1819      double *coordPtr;      double *coordPtr;
1820      int i;      int i;
1821    
1822      for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;      for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;
1823              i++, coordPtr += 2) {              i++, coordPtr += 2) {
1824          coordPtr[0] += deltaX;          coordPtr[0] += deltaX;
1825          coordPtr[1] += deltaY;          coordPtr[1] += deltaY;
1826      }      }
1827      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
1828          for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;          for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
1829                  i++, coordPtr += 2) {                  i++, coordPtr += 2) {
1830              coordPtr[0] += deltaX;              coordPtr[0] += deltaX;
1831              coordPtr[1] += deltaY;              coordPtr[1] += deltaY;
1832          }          }
1833      }      }
1834      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
1835          for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;          for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
1836                  i++, coordPtr += 2) {                  i++, coordPtr += 2) {
1837              coordPtr[0] += deltaX;              coordPtr[0] += deltaX;
1838              coordPtr[1] += deltaY;              coordPtr[1] += deltaY;
1839          }          }
1840      }      }
1841      ComputeLineBbox(canvas, linePtr);      ComputeLineBbox(canvas, linePtr);
1842  }  }
1843    
1844  /*  /*
1845   *--------------------------------------------------------------   *--------------------------------------------------------------
1846   *   *
1847   * ParseArrowShape --   * ParseArrowShape --
1848   *   *
1849   *      This procedure is called back during option parsing to   *      This procedure is called back during option parsing to
1850   *      parse arrow shape information.   *      parse arrow shape information.
1851   *   *
1852   * Results:   * Results:
1853   *      The return value is a standard Tcl result:  TCL_OK means   *      The return value is a standard Tcl result:  TCL_OK means
1854   *      that the arrow shape information was parsed ok, and   *      that the arrow shape information was parsed ok, and
1855   *      TCL_ERROR means it couldn't be parsed.   *      TCL_ERROR means it couldn't be parsed.
1856   *   *
1857   * Side effects:   * Side effects:
1858   *      Arrow information in recordPtr is updated.   *      Arrow information in recordPtr is updated.
1859   *   *
1860   *--------------------------------------------------------------   *--------------------------------------------------------------
1861   */   */
1862    
1863          /* ARGSUSED */          /* ARGSUSED */
1864  static int  static int
1865  ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset)  ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset)
1866      ClientData clientData;      /* Not used. */      ClientData clientData;      /* Not used. */
1867      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
1868      Tk_Window tkwin;            /* Not used. */      Tk_Window tkwin;            /* Not used. */
1869      CONST char *value;          /* Textual specification of arrow shape. */      CONST char *value;          /* Textual specification of arrow shape. */
1870      char *recordPtr;            /* Pointer to item record in which to      char *recordPtr;            /* Pointer to item record in which to
1871                                   * store arrow information. */                                   * store arrow information. */
1872      int offset;                 /* Offset of shape information in widget      int offset;                 /* Offset of shape information in widget
1873                                   * record. */                                   * record. */
1874  {  {
1875      LineItem *linePtr = (LineItem *) recordPtr;      LineItem *linePtr = (LineItem *) recordPtr;
1876      double a, b, c;      double a, b, c;
1877      int argc;      int argc;
1878      char **argv = NULL;      char **argv = NULL;
1879    
1880      if (offset != Tk_Offset(LineItem, arrowShapeA)) {      if (offset != Tk_Offset(LineItem, arrowShapeA)) {
1881          panic("ParseArrowShape received bogus offset");          panic("ParseArrowShape received bogus offset");
1882      }      }
1883    
1884      if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {      if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
1885          syntaxError:          syntaxError:
1886          Tcl_ResetResult(interp);          Tcl_ResetResult(interp);
1887          Tcl_AppendResult(interp, "bad arrow shape \"", value,          Tcl_AppendResult(interp, "bad arrow shape \"", value,
1888                  "\": must be list with three numbers", (char *) NULL);                  "\": must be list with three numbers", (char *) NULL);
1889          if (argv != NULL) {          if (argv != NULL) {
1890              ckfree((char *) argv);              ckfree((char *) argv);
1891          }          }
1892          return TCL_ERROR;          return TCL_ERROR;
1893      }      }
1894      if (argc != 3) {      if (argc != 3) {
1895          goto syntaxError;          goto syntaxError;
1896      }      }
1897      if ((Tk_CanvasGetCoord(interp, linePtr->canvas, argv[0], &a) != TCL_OK)      if ((Tk_CanvasGetCoord(interp, linePtr->canvas, argv[0], &a) != TCL_OK)
1898              || (Tk_CanvasGetCoord(interp, linePtr->canvas, argv[1], &b)              || (Tk_CanvasGetCoord(interp, linePtr->canvas, argv[1], &b)
1899                  != TCL_OK)                  != TCL_OK)
1900              || (Tk_CanvasGetCoord(interp, linePtr->canvas, argv[2], &c)              || (Tk_CanvasGetCoord(interp, linePtr->canvas, argv[2], &c)
1901                  != TCL_OK)) {                  != TCL_OK)) {
1902          goto syntaxError;          goto syntaxError;
1903      }      }
1904      linePtr->arrowShapeA = (float)a;      linePtr->arrowShapeA = (float)a;
1905      linePtr->arrowShapeB = (float)b;      linePtr->arrowShapeB = (float)b;
1906      linePtr->arrowShapeC = (float)c;      linePtr->arrowShapeC = (float)c;
1907      ckfree((char *) argv);      ckfree((char *) argv);
1908      return TCL_OK;      return TCL_OK;
1909  }  }
1910    
1911  /*  /*
1912   *--------------------------------------------------------------   *--------------------------------------------------------------
1913   *   *
1914   * PrintArrowShape --   * PrintArrowShape --
1915   *   *
1916   *      This procedure is a callback invoked by the configuration   *      This procedure is a callback invoked by the configuration
1917   *      code to return a printable value describing an arrow shape.   *      code to return a printable value describing an arrow shape.
1918   *   *
1919   * Results:   * Results:
1920   *      None.   *      None.
1921   *   *
1922   * Side effects:   * Side effects:
1923   *      None.   *      None.
1924   *   *
1925   *--------------------------------------------------------------   *--------------------------------------------------------------
1926   */   */
1927    
1928      /* ARGSUSED */      /* ARGSUSED */
1929  static char *  static char *
1930  PrintArrowShape(clientData, tkwin, recordPtr, offset, freeProcPtr)  PrintArrowShape(clientData, tkwin, recordPtr, offset, freeProcPtr)
1931      ClientData clientData;      /* Not used. */      ClientData clientData;      /* Not used. */
1932      Tk_Window tkwin;            /* Window associated with linePtr's widget. */      Tk_Window tkwin;            /* Window associated with linePtr's widget. */
1933      char *recordPtr;            /* Pointer to item record containing current      char *recordPtr;            /* Pointer to item record containing current
1934                                   * shape information. */                                   * shape information. */
1935      int offset;                 /* Offset of arrow information in record. */      int offset;                 /* Offset of arrow information in record. */
1936      Tcl_FreeProc **freeProcPtr; /* Store address of procedure to call to      Tcl_FreeProc **freeProcPtr; /* Store address of procedure to call to
1937                                   * free string here. */                                   * free string here. */
1938  {  {
1939      LineItem *linePtr = (LineItem *) recordPtr;      LineItem *linePtr = (LineItem *) recordPtr;
1940      char *buffer;      char *buffer;
1941    
1942      buffer = (char *) ckalloc(120);      buffer = (char *) ckalloc(120);
1943      sprintf(buffer, "%.5g %.5g %.5g", linePtr->arrowShapeA,      sprintf(buffer, "%.5g %.5g %.5g", linePtr->arrowShapeA,
1944              linePtr->arrowShapeB, linePtr->arrowShapeC);              linePtr->arrowShapeB, linePtr->arrowShapeC);
1945      *freeProcPtr = TCL_DYNAMIC;      *freeProcPtr = TCL_DYNAMIC;
1946      return buffer;      return buffer;
1947  }  }
1948    
1949    
1950  /*  /*
1951   *--------------------------------------------------------------   *--------------------------------------------------------------
1952   *   *
1953   * ArrowParseProc --   * ArrowParseProc --
1954   *   *
1955   *      This procedure is invoked during option processing to handle   *      This procedure is invoked during option processing to handle
1956   *      the "-arrow" option.   *      the "-arrow" option.
1957   *   *
1958   * Results:   * Results:
1959   *      A standard Tcl return value.   *      A standard Tcl return value.
1960   *   *
1961   * Side effects:   * Side effects:
1962   *      The arrow for a given item gets replaced by the arrow   *      The arrow for a given item gets replaced by the arrow
1963   *      indicated in the value argument.   *      indicated in the value argument.
1964   *   *
1965   *--------------------------------------------------------------   *--------------------------------------------------------------
1966   */   */
1967    
1968  static int  static int
1969  ArrowParseProc(clientData, interp, tkwin, value, widgRec, offset)  ArrowParseProc(clientData, interp, tkwin, value, widgRec, offset)
1970      ClientData clientData;              /* some flags.*/      ClientData clientData;              /* some flags.*/
1971      Tcl_Interp *interp;                 /* Used for reporting errors. */      Tcl_Interp *interp;                 /* Used for reporting errors. */
1972      Tk_Window tkwin;                    /* Window containing canvas widget. */      Tk_Window tkwin;                    /* Window containing canvas widget. */
1973      CONST char *value;                  /* Value of option. */      CONST char *value;                  /* Value of option. */
1974      char *widgRec;                      /* Pointer to record for item. */      char *widgRec;                      /* Pointer to record for item. */
1975      int offset;                         /* Offset into item. */      int offset;                         /* Offset into item. */
1976  {  {
1977      int c;      int c;
1978      size_t length;      size_t length;
1979    
1980      register Arrows *arrowPtr = (Arrows *) (widgRec + offset);      register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
1981    
1982      if(value == NULL || *value == 0) {      if(value == NULL || *value == 0) {
1983          *arrowPtr = ARROWS_NONE;          *arrowPtr = ARROWS_NONE;
1984          return TCL_OK;          return TCL_OK;
1985      }      }
1986    
1987      c = value[0];      c = value[0];
1988      length = strlen(value);      length = strlen(value);
1989    
1990      if ((c == 'n') && (strncmp(value, "none", length) == 0)) {      if ((c == 'n') && (strncmp(value, "none", length) == 0)) {
1991          *arrowPtr = ARROWS_NONE;          *arrowPtr = ARROWS_NONE;
1992          return TCL_OK;          return TCL_OK;
1993      }      }
1994      if ((c == 'f') && (strncmp(value, "first", length) == 0)) {      if ((c == 'f') && (strncmp(value, "first", length) == 0)) {
1995          *arrowPtr = ARROWS_FIRST;          *arrowPtr = ARROWS_FIRST;
1996          return TCL_OK;          return TCL_OK;
1997      }      }
1998      if ((c == 'l') && (strncmp(value, "last", length) == 0)) {      if ((c == 'l') && (strncmp(value, "last", length) == 0)) {
1999          *arrowPtr = ARROWS_LAST;          *arrowPtr = ARROWS_LAST;
2000          return TCL_OK;          return TCL_OK;
2001      }      }
2002      if ((c == 'b') && (strncmp(value, "both", length) == 0)) {      if ((c == 'b') && (strncmp(value, "both", length) == 0)) {
2003          *arrowPtr = ARROWS_BOTH;          *arrowPtr = ARROWS_BOTH;
2004          return TCL_OK;          return TCL_OK;
2005      }      }
2006    
2007      Tcl_AppendResult(interp, "bad arrow spec \"", value,      Tcl_AppendResult(interp, "bad arrow spec \"", value,
2008              "\": must be none, first, last, or both",              "\": must be none, first, last, or both",
2009              (char *) NULL);              (char *) NULL);
2010      *arrowPtr = ARROWS_NONE;      *arrowPtr = ARROWS_NONE;
2011      return TCL_ERROR;      return TCL_ERROR;
2012  }  }
2013    
2014  /*  /*
2015   *--------------------------------------------------------------   *--------------------------------------------------------------
2016   *   *
2017   * ArrowPrintProc --   * ArrowPrintProc --
2018   *   *
2019   *      This procedure is invoked by the Tk configuration code   *      This procedure is invoked by the Tk configuration code
2020   *      to produce a printable string for the "-arrow"   *      to produce a printable string for the "-arrow"
2021   *      configuration option.   *      configuration option.
2022   *   *
2023   * Results:   * Results:
2024   *      The return value is a string describing the arrows for   *      The return value is a string describing the arrows for
2025   *      the item referred to by "widgRec".  In addition, *freeProcPtr   *      the item referred to by "widgRec".  In addition, *freeProcPtr
2026   *      is filled in with the address of a procedure to call to free   *      is filled in with the address of a procedure to call to free
2027   *      the result string when it's no longer needed (or NULL to   *      the result string when it's no longer needed (or NULL to
2028   *      indicate that the string doesn't need to be freed).   *      indicate that the string doesn't need to be freed).
2029   *   *
2030   * Side effects:   * Side effects:
2031   *      None.   *      None.
2032   *   *
2033   *--------------------------------------------------------------   *--------------------------------------------------------------
2034   */   */
2035    
2036  static char *  static char *
2037  ArrowPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)  ArrowPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
2038      ClientData clientData;              /* Ignored. */      ClientData clientData;              /* Ignored. */
2039      Tk_Window tkwin;                    /* Window containing canvas widget. */      Tk_Window tkwin;                    /* Window containing canvas widget. */
2040      char *widgRec;                      /* Pointer to record for item. */      char *widgRec;                      /* Pointer to record for item. */
2041      int offset;                         /* Offset into item. */      int offset;                         /* Offset into item. */
2042      Tcl_FreeProc **freeProcPtr;         /* Pointer to variable to fill in with      Tcl_FreeProc **freeProcPtr;         /* Pointer to variable to fill in with
2043                                           * information about how to reclaim                                           * information about how to reclaim
2044                                           * storage for return string. */                                           * storage for return string. */
2045  {  {
2046      register Arrows *arrowPtr = (Arrows *) (widgRec + offset);      register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
2047    
2048      switch (*arrowPtr) {      switch (*arrowPtr) {
2049        case ARROWS_FIRST:        case ARROWS_FIRST:
2050          return "first";          return "first";
2051        case ARROWS_LAST:        case ARROWS_LAST:
2052          return "last";          return "last";
2053        case ARROWS_BOTH:        case ARROWS_BOTH:
2054          return "both";          return "both";
2055        default:        default:
2056          return "none";          return "none";
2057      }      }
2058  }  }
2059    
2060  /*  /*
2061   *--------------------------------------------------------------   *--------------------------------------------------------------
2062   *   *
2063   * ConfigureArrows --   * ConfigureArrows --
2064   *   *
2065   *      If arrowheads have been requested for a line, this   *      If arrowheads have been requested for a line, this
2066   *      procedure makes arrangements for the arrowheads.   *      procedure makes arrangements for the arrowheads.
2067   *   *
2068   * Results:   * Results:
2069   *      Always returns TCL_OK.   *      Always returns TCL_OK.
2070   *   *
2071   * Side effects:   * Side effects:
2072   *      Information in linePtr is set up for one or two arrowheads.   *      Information in linePtr is set up for one or two arrowheads.
2073   *      the firstArrowPtr and lastArrowPtr polygons are allocated   *      the firstArrowPtr and lastArrowPtr polygons are allocated
2074   *      and initialized, if need be, and the end points of the line   *      and initialized, if need be, and the end points of the line
2075   *      are adjusted so that a thick line doesn't stick out past   *      are adjusted so that a thick line doesn't stick out past
2076   *      the arrowheads.   *      the arrowheads.
2077   *   *
2078   *--------------------------------------------------------------   *--------------------------------------------------------------
2079   */   */
2080    
2081          /* ARGSUSED */          /* ARGSUSED */
2082  static int  static int
2083  ConfigureArrows(canvas, linePtr)  ConfigureArrows(canvas, linePtr)
2084      Tk_Canvas canvas;                   /* Canvas in which arrows will be      Tk_Canvas canvas;                   /* Canvas in which arrows will be
2085                                           * displayed (interp and tkwin                                           * displayed (interp and tkwin
2086                                           * fields are needed). */                                           * fields are needed). */
2087      LineItem *linePtr;                  /* Item to configure for arrows. */      LineItem *linePtr;                  /* Item to configure for arrows. */
2088  {  {
2089      double *poly, *coordPtr;      double *poly, *coordPtr;
2090      double dx, dy, length, sinTheta, cosTheta, temp;      double dx, dy, length, sinTheta, cosTheta, temp;
2091      double fracHeight;                  /* Line width as fraction of      double fracHeight;                  /* Line width as fraction of
2092                                           * arrowhead width. */                                           * arrowhead width. */
2093      double backup;                      /* Distance to backup end points      double backup;                      /* Distance to backup end points
2094                                           * so the line ends in the middle                                           * so the line ends in the middle
2095                                           * of the arrowhead. */                                           * of the arrowhead. */
2096      double vertX, vertY;                /* Position of arrowhead vertex. */      double vertX, vertY;                /* Position of arrowhead vertex. */
2097      double shapeA, shapeB, shapeC;      /* Adjusted coordinates (see      double shapeA, shapeB, shapeC;      /* Adjusted coordinates (see
2098                                           * explanation below). */                                           * explanation below). */
2099      double width;      double width;
2100      Tk_State state = linePtr->header.state;      Tk_State state = linePtr->header.state;
2101    
2102      if (linePtr->numPoints <2) {      if (linePtr->numPoints <2) {
2103          return TCL_OK;          return TCL_OK;
2104      }      }
2105    
2106      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
2107          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
2108      }      }
2109    
2110      width = linePtr->outline.width;      width = linePtr->outline.width;
2111      if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {      if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
2112          if (linePtr->outline.activeWidth>width) {          if (linePtr->outline.activeWidth>width) {
2113              width = linePtr->outline.activeWidth;              width = linePtr->outline.activeWidth;
2114          }          }
2115      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
2116          if (linePtr->outline.disabledWidth>0) {          if (linePtr->outline.disabledWidth>0) {
2117              width = linePtr->outline.disabledWidth;              width = linePtr->outline.disabledWidth;
2118          }          }
2119      }      }
2120    
2121      /*      /*
2122       * The code below makes a tiny increase in the shape parameters       * The code below makes a tiny increase in the shape parameters
2123       * for the line.  This is a bit of a hack, but it seems to result       * for the line.  This is a bit of a hack, but it seems to result
2124       * in displays that more closely approximate the specified parameters.       * in displays that more closely approximate the specified parameters.
2125       * Without the adjustment, the arrows come out smaller than expected.       * Without the adjustment, the arrows come out smaller than expected.
2126       */       */
2127    
2128      shapeA = linePtr->arrowShapeA + 0.001;      shapeA = linePtr->arrowShapeA + 0.001;
2129      shapeB = linePtr->arrowShapeB + 0.001;      shapeB = linePtr->arrowShapeB + 0.001;
2130      shapeC = linePtr->arrowShapeC + width/2.0 + 0.001;      shapeC = linePtr->arrowShapeC + width/2.0 + 0.001;
2131    
2132      /*      /*
2133       * If there's an arrowhead on the first point of the line, compute       * If there's an arrowhead on the first point of the line, compute
2134       * its polygon and adjust the first point of the line so that the       * its polygon and adjust the first point of the line so that the
2135       * line doesn't stick out past the leading edge of the arrowhead.       * line doesn't stick out past the leading edge of the arrowhead.
2136       */       */
2137    
2138      fracHeight = (width/2.0)/shapeC;      fracHeight = (width/2.0)/shapeC;
2139      backup = fracHeight*shapeB + shapeA*(1.0 - fracHeight)/2.0;      backup = fracHeight*shapeB + shapeA*(1.0 - fracHeight)/2.0;
2140      if (linePtr->arrow != ARROWS_LAST) {      if (linePtr->arrow != ARROWS_LAST) {
2141          poly = linePtr->firstArrowPtr;          poly = linePtr->firstArrowPtr;
2142          if (poly == NULL) {          if (poly == NULL) {
2143              poly = (double *) ckalloc((unsigned)              poly = (double *) ckalloc((unsigned)
2144                      (2*PTS_IN_ARROW*sizeof(double)));                      (2*PTS_IN_ARROW*sizeof(double)));
2145              poly[0] = poly[10] = linePtr->coordPtr[0];              poly[0] = poly[10] = linePtr->coordPtr[0];
2146              poly[1] = poly[11] = linePtr->coordPtr[1];              poly[1] = poly[11] = linePtr->coordPtr[1];
2147              linePtr->firstArrowPtr = poly;              linePtr->firstArrowPtr = poly;
2148          }          }
2149          dx = poly[0] - linePtr->coordPtr[2];          dx = poly[0] - linePtr->coordPtr[2];
2150          dy = poly[1] - linePtr->coordPtr[3];          dy = poly[1] - linePtr->coordPtr[3];
2151          length = hypot(dx, dy);          length = hypot(dx, dy);
2152          if (length == 0) {          if (length == 0) {
2153              sinTheta = cosTheta = 0.0;              sinTheta = cosTheta = 0.0;
2154          } else {          } else {
2155              sinTheta = dy/length;              sinTheta = dy/length;
2156              cosTheta = dx/length;              cosTheta = dx/length;
2157          }          }
2158          vertX = poly[0] - shapeA*cosTheta;          vertX = poly[0] - shapeA*cosTheta;
2159          vertY = poly[1] - shapeA*sinTheta;          vertY = poly[1] - shapeA*sinTheta;
2160          temp = shapeC*sinTheta;          temp = shapeC*sinTheta;
2161          poly[2] = poly[0] - shapeB*cosTheta + temp;          poly[2] = poly[0] - shapeB*cosTheta + temp;
2162          poly[8] = poly[2] - 2*temp;          poly[8] = poly[2] - 2*temp;
2163          temp = shapeC*cosTheta;          temp = shapeC*cosTheta;
2164          poly[3] = poly[1] - shapeB*sinTheta - temp;          poly[3] = poly[1] - shapeB*sinTheta - temp;
2165          poly[9] = poly[3] + 2*temp;          poly[9] = poly[3] + 2*temp;
2166          poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);          poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);
2167          poly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight);          poly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight);
2168          poly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight);          poly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight);
2169          poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight);          poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight);
2170    
2171          /*          /*
2172           * Polygon done.  Now move the first point towards the second so           * Polygon done.  Now move the first point towards the second so
2173           * that the corners at the end of the line are inside the           * that the corners at the end of the line are inside the
2174           * arrowhead.           * arrowhead.
2175           */           */
2176    
2177          linePtr->coordPtr[0] = poly[0] - backup*cosTheta;          linePtr->coordPtr[0] = poly[0] - backup*cosTheta;
2178          linePtr->coordPtr[1] = poly[1] - backup*sinTheta;          linePtr->coordPtr[1] = poly[1] - backup*sinTheta;
2179      }      }
2180    
2181      /*      /*
2182       * Similar arrowhead calculation for the last point of the line.       * Similar arrowhead calculation for the last point of the line.
2183       */       */
2184    
2185      if (linePtr->arrow != ARROWS_FIRST) {      if (linePtr->arrow != ARROWS_FIRST) {
2186          coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2);          coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2);
2187          poly = linePtr->lastArrowPtr;          poly = linePtr->lastArrowPtr;
2188          if (poly == NULL) {          if (poly == NULL) {
2189              poly = (double *) ckalloc((unsigned)              poly = (double *) ckalloc((unsigned)
2190                      (2*PTS_IN_ARROW*sizeof(double)));                      (2*PTS_IN_ARROW*sizeof(double)));
2191              poly[0] = poly[10] = coordPtr[2];              poly[0] = poly[10] = coordPtr[2];
2192              poly[1] = poly[11] = coordPtr[3];              poly[1] = poly[11] = coordPtr[3];
2193              linePtr->lastArrowPtr = poly;              linePtr->lastArrowPtr = poly;
2194          }          }
2195          dx = poly[0] - coordPtr[0];          dx = poly[0] - coordPtr[0];
2196          dy = poly[1] - coordPtr[1];          dy = poly[1] - coordPtr[1];
2197          length = hypot(dx, dy);          length = hypot(dx, dy);
2198          if (length == 0) {          if (length == 0) {
2199              sinTheta = cosTheta = 0.0;              sinTheta = cosTheta = 0.0;
2200          } else {          } else {
2201              sinTheta = dy/length;              sinTheta = dy/length;
2202              cosTheta = dx/length;              cosTheta = dx/length;
2203          }          }
2204          vertX = poly[0] - shapeA*cosTheta;          vertX = poly[0] - shapeA*cosTheta;
2205          vertY = poly[1] - shapeA*sinTheta;          vertY = poly[1] - shapeA*sinTheta;
2206          temp = shapeC*sinTheta;          temp = shapeC*sinTheta;
2207          poly[2] = poly[0] - shapeB*cosTheta + temp;          poly[2] = poly[0] - shapeB*cosTheta + temp;
2208          poly[8] = poly[2] - 2*temp;          poly[8] = poly[2] - 2*temp;
2209          temp = shapeC*cosTheta;          temp = shapeC*cosTheta;
2210          poly[3] = poly[1] - shapeB*sinTheta - temp;          poly[3] = poly[1] - shapeB*sinTheta - temp;
2211          poly[9] = poly[3] + 2*temp;          poly[9] = poly[3] + 2*temp;
2212          poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);          poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);
2213          poly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight);          poly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight);
2214          poly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight);          poly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight);
2215          poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight);          poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight);
2216          coordPtr[2] = poly[0] - backup*cosTheta;          coordPtr[2] = poly[0] - backup*cosTheta;
2217          coordPtr[3] = poly[1] - backup*sinTheta;          coordPtr[3] = poly[1] - backup*sinTheta;
2218      }      }
2219    
2220      return TCL_OK;      return TCL_OK;
2221  }  }
2222    
2223  /*  /*
2224   *--------------------------------------------------------------   *--------------------------------------------------------------
2225   *   *
2226   * LineToPostscript --   * LineToPostscript --
2227   *   *
2228   *      This procedure is called to generate Postscript for   *      This procedure is called to generate Postscript for
2229   *      line items.   *      line items.
2230   *   *
2231   * Results:   * Results:
2232   *      The return value is a standard Tcl result.  If an error   *      The return value is a standard Tcl result.  If an error
2233   *      occurs in generating Postscript then an error message is   *      occurs in generating Postscript then an error message is
2234   *      left in the interp's result, replacing whatever used   *      left in the interp's result, replacing whatever used
2235   *      to be there.  If no error occurs, then Postscript for the   *      to be there.  If no error occurs, then Postscript for the
2236   *      item is appended to the result.   *      item is appended to the result.
2237   *   *
2238   * Side effects:   * Side effects:
2239   *      None.   *      None.
2240   *   *
2241   *--------------------------------------------------------------   *--------------------------------------------------------------
2242   */   */
2243    
2244  static int  static int
2245  LineToPostscript(interp, canvas, itemPtr, prepass)  LineToPostscript(interp, canvas, itemPtr, prepass)
2246      Tcl_Interp *interp;                 /* Leave Postscript or error message      Tcl_Interp *interp;                 /* Leave Postscript or error message
2247                                           * here. */                                           * here. */
2248      Tk_Canvas canvas;                   /* Information about overall canvas. */      Tk_Canvas canvas;                   /* Information about overall canvas. */
2249      Tk_Item *itemPtr;                   /* Item for which Postscript is      Tk_Item *itemPtr;                   /* Item for which Postscript is
2250                                           * wanted. */                                           * wanted. */
2251      int prepass;                        /* 1 means this is a prepass to      int prepass;                        /* 1 means this is a prepass to
2252                                           * collect font information;  0 means                                           * collect font information;  0 means
2253                                           * final Postscript is being created. */                                           * final Postscript is being created. */
2254  {  {
2255      LineItem *linePtr = (LineItem *) itemPtr;      LineItem *linePtr = (LineItem *) itemPtr;
2256      char buffer[64 + TCL_INTEGER_SPACE];      char buffer[64 + TCL_INTEGER_SPACE];
2257      char *style;      char *style;
2258    
2259      double width;      double width;
2260      XColor *color;      XColor *color;
2261      Pixmap stipple;      Pixmap stipple;
2262      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
2263    
2264      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
2265          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
2266      }      }
2267    
2268      width = linePtr->outline.width;      width = linePtr->outline.width;
2269      color = linePtr->outline.color;      color = linePtr->outline.color;
2270      stipple = linePtr->outline.stipple;      stipple = linePtr->outline.stipple;
2271      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
2272          if (linePtr->outline.activeWidth>width) {          if (linePtr->outline.activeWidth>width) {
2273              width = linePtr->outline.activeWidth;              width = linePtr->outline.activeWidth;
2274          }          }
2275          if (linePtr->outline.activeColor!=NULL) {          if (linePtr->outline.activeColor!=NULL) {
2276              color = linePtr->outline.activeColor;              color = linePtr->outline.activeColor;
2277          }          }
2278          if (linePtr->outline.activeStipple!=None) {          if (linePtr->outline.activeStipple!=None) {
2279              stipple = linePtr->outline.activeStipple;              stipple = linePtr->outline.activeStipple;
2280          }          }
2281      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
2282          if (linePtr->outline.disabledWidth>0) {          if (linePtr->outline.disabledWidth>0) {
2283              width = linePtr->outline.disabledWidth;              width = linePtr->outline.disabledWidth;
2284          }          }
2285          if (linePtr->outline.disabledColor!=NULL) {          if (linePtr->outline.disabledColor!=NULL) {
2286              color = linePtr->outline.disabledColor;              color = linePtr->outline.disabledColor;
2287          }          }
2288          if (linePtr->outline.disabledStipple!=None) {          if (linePtr->outline.disabledStipple!=None) {
2289              stipple = linePtr->outline.disabledStipple;              stipple = linePtr->outline.disabledStipple;
2290          }          }
2291      }      }
2292    
2293      if (color == NULL || linePtr->numPoints<1 || linePtr->coordPtr==NULL) {      if (color == NULL || linePtr->numPoints<1 || linePtr->coordPtr==NULL) {
2294          return TCL_OK;          return TCL_OK;
2295      }      }
2296    
2297      if (linePtr->numPoints==1) {      if (linePtr->numPoints==1) {
2298          sprintf(buffer, "%.15g %.15g translate %.15g %.15g",          sprintf(buffer, "%.15g %.15g translate %.15g %.15g",
2299                  linePtr->coordPtr[0], Tk_CanvasPsY(canvas, linePtr->coordPtr[1]),                  linePtr->coordPtr[0], Tk_CanvasPsY(canvas, linePtr->coordPtr[1]),
2300                  width/2.0, width/2.0);                  width/2.0, width/2.0);
2301          Tcl_AppendResult(interp, "matrix currentmatrix\n",buffer,          Tcl_AppendResult(interp, "matrix currentmatrix\n",buffer,
2302                  " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", (char *) NULL);                  " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", (char *) NULL);
2303          if (Tk_CanvasPsColor(interp, canvas, color)          if (Tk_CanvasPsColor(interp, canvas, color)
2304                  != TCL_OK) {                  != TCL_OK) {
2305              return TCL_ERROR;              return TCL_ERROR;
2306          }          }
2307          if (stipple != None) {          if (stipple != None) {
2308              Tcl_AppendResult(interp, "clip ", (char *) NULL);              Tcl_AppendResult(interp, "clip ", (char *) NULL);
2309              if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {              if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
2310                  return TCL_ERROR;                  return TCL_ERROR;
2311              }              }
2312          } else {          } else {
2313              Tcl_AppendResult(interp, "fill\n", (char *) NULL);              Tcl_AppendResult(interp, "fill\n", (char *) NULL);
2314          }          }
2315          return TCL_OK;          return TCL_OK;
2316      }      }
2317      /*      /*
2318       * Generate a path for the line's center-line (do this differently       * Generate a path for the line's center-line (do this differently
2319       * for straight lines and smoothed lines).       * for straight lines and smoothed lines).
2320       */       */
2321    
2322      if ((!linePtr->smooth) || (linePtr->numPoints < 3)) {      if ((!linePtr->smooth) || (linePtr->numPoints < 3)) {
2323          Tk_CanvasPsPath(interp, canvas, linePtr->coordPtr, linePtr->numPoints);          Tk_CanvasPsPath(interp, canvas, linePtr->coordPtr, linePtr->numPoints);
2324      } else {      } else {
2325          if ((stipple == None) && linePtr->smooth->postscriptProc) {          if ((stipple == None) && linePtr->smooth->postscriptProc) {
2326              linePtr->smooth->postscriptProc(interp, canvas,              linePtr->smooth->postscriptProc(interp, canvas,
2327                      linePtr->coordPtr, linePtr->numPoints, linePtr->splineSteps);                      linePtr->coordPtr, linePtr->numPoints, linePtr->splineSteps);
2328          } else {          } else {
2329              /*              /*
2330               * Special hack: Postscript printers don't appear to be able               * Special hack: Postscript printers don't appear to be able
2331               * to turn a path drawn with "curveto"s into a clipping path               * to turn a path drawn with "curveto"s into a clipping path
2332               * without exceeding resource limits, so TkMakeBezierPostscript               * without exceeding resource limits, so TkMakeBezierPostscript
2333               * won't work for stippled curves.  Instead, generate all of               * won't work for stippled curves.  Instead, generate all of
2334               * the intermediate points here and output them into the               * the intermediate points here and output them into the
2335               * Postscript file with "lineto"s instead.               * Postscript file with "lineto"s instead.
2336               */               */
2337    
2338              double staticPoints[2*MAX_STATIC_POINTS];              double staticPoints[2*MAX_STATIC_POINTS];
2339              double *pointPtr;              double *pointPtr;
2340              int numPoints;              int numPoints;
2341    
2342              numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,              numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
2343                      linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,                      linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
2344                      (double *) NULL);                      (double *) NULL);
2345              pointPtr = staticPoints;              pointPtr = staticPoints;
2346              if (numPoints > MAX_STATIC_POINTS) {              if (numPoints > MAX_STATIC_POINTS) {
2347                  pointPtr = (double *) ckalloc((unsigned)                  pointPtr = (double *) ckalloc((unsigned)
2348                          (numPoints * 2 * sizeof(double)));                          (numPoints * 2 * sizeof(double)));
2349              }              }
2350              numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,              numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
2351                      linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,                      linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
2352                      pointPtr);                      pointPtr);
2353              Tk_CanvasPsPath(interp, canvas, pointPtr, numPoints);              Tk_CanvasPsPath(interp, canvas, pointPtr, numPoints);
2354              if (pointPtr != staticPoints) {              if (pointPtr != staticPoints) {
2355                  ckfree((char *) pointPtr);                  ckfree((char *) pointPtr);
2356              }              }
2357          }          }
2358      }      }
2359    
2360      /*      /*
2361       * Set other line-drawing parameters and stroke out the line.       * Set other line-drawing parameters and stroke out the line.
2362       */       */
2363    
2364      style = "0 setlinecap\n";      style = "0 setlinecap\n";
2365      if (linePtr->capStyle == CapRound) {      if (linePtr->capStyle == CapRound) {
2366          style = "1 setlinecap\n";          style = "1 setlinecap\n";
2367      } else if (linePtr->capStyle == CapProjecting) {      } else if (linePtr->capStyle == CapProjecting) {
2368          style = "2 setlinecap\n";          style = "2 setlinecap\n";
2369      }      }
2370      Tcl_AppendResult(interp, style, (char *) NULL);      Tcl_AppendResult(interp, style, (char *) NULL);
2371      style = "0 setlinejoin\n";      style = "0 setlinejoin\n";
2372      if (linePtr->joinStyle == JoinRound) {      if (linePtr->joinStyle == JoinRound) {
2373          style = "1 setlinejoin\n";          style = "1 setlinejoin\n";
2374      } else if (linePtr->joinStyle == JoinBevel) {      } else if (linePtr->joinStyle == JoinBevel) {
2375          style = "2 setlinejoin\n";          style = "2 setlinejoin\n";
2376      }      }
2377      Tcl_AppendResult(interp, style, (char *) NULL);      Tcl_AppendResult(interp, style, (char *) NULL);
2378    
2379      if (Tk_CanvasPsOutline(canvas, itemPtr,      if (Tk_CanvasPsOutline(canvas, itemPtr,
2380              &(linePtr->outline)) != TCL_OK) {              &(linePtr->outline)) != TCL_OK) {
2381          return TCL_ERROR;          return TCL_ERROR;
2382      }      }
2383    
2384      /*      /*
2385       * Output polygons for the arrowheads, if there are any.       * Output polygons for the arrowheads, if there are any.
2386       */       */
2387    
2388      if (linePtr->firstArrowPtr != NULL) {      if (linePtr->firstArrowPtr != NULL) {
2389          if (stipple != None) {          if (stipple != None) {
2390              Tcl_AppendResult(interp, "grestore gsave\n",              Tcl_AppendResult(interp, "grestore gsave\n",
2391                      (char *) NULL);                      (char *) NULL);
2392          }          }
2393          if (ArrowheadPostscript(interp, canvas, linePtr,          if (ArrowheadPostscript(interp, canvas, linePtr,
2394                  linePtr->firstArrowPtr) != TCL_OK) {                  linePtr->firstArrowPtr) != TCL_OK) {
2395              return TCL_ERROR;              return TCL_ERROR;
2396          }          }
2397      }      }
2398      if (linePtr->lastArrowPtr != NULL) {      if (linePtr->lastArrowPtr != NULL) {
2399          if (stipple != None) {          if (stipple != None) {
2400              Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);              Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
2401          }          }
2402          if (ArrowheadPostscript(interp, canvas, linePtr,          if (ArrowheadPostscript(interp, canvas, linePtr,
2403                  linePtr->lastArrowPtr) != TCL_OK) {                  linePtr->lastArrowPtr) != TCL_OK) {
2404              return TCL_ERROR;              return TCL_ERROR;
2405          }          }
2406      }      }
2407      return TCL_OK;      return TCL_OK;
2408  }  }
2409    
2410  /*  /*
2411   *--------------------------------------------------------------   *--------------------------------------------------------------
2412   *   *
2413   * ArrowheadPostscript --   * ArrowheadPostscript --
2414   *   *
2415   *      This procedure is called to generate Postscript for   *      This procedure is called to generate Postscript for
2416   *      an arrowhead for a line item.   *      an arrowhead for a line item.
2417   *   *
2418   * Results:   * Results:
2419   *      The return value is a standard Tcl result.  If an error   *      The return value is a standard Tcl result.  If an error
2420   *      occurs in generating Postscript then an error message is   *      occurs in generating Postscript then an error message is
2421   *      left in the interp's result, replacing whatever used   *      left in the interp's result, replacing whatever used
2422   *      to be there.  If no error occurs, then Postscript for the   *      to be there.  If no error occurs, then Postscript for the
2423   *      arrowhead is appended to the result.   *      arrowhead is appended to the result.
2424   *   *
2425   * Side effects:   * Side effects:
2426   *      None.   *      None.
2427   *   *
2428   *--------------------------------------------------------------   *--------------------------------------------------------------
2429   */   */
2430    
2431  static int  static int
2432  ArrowheadPostscript(interp, canvas, linePtr, arrowPtr)  ArrowheadPostscript(interp, canvas, linePtr, arrowPtr)
2433      Tcl_Interp *interp;                 /* Leave Postscript or error message      Tcl_Interp *interp;                 /* Leave Postscript or error message
2434                                           * here. */                                           * here. */
2435      Tk_Canvas canvas;                   /* Information about overall canvas. */      Tk_Canvas canvas;                   /* Information about overall canvas. */
2436      LineItem *linePtr;                  /* Line item for which Postscript is      LineItem *linePtr;                  /* Line item for which Postscript is
2437                                           * being generated. */                                           * being generated. */
2438      double *arrowPtr;                   /* Pointer to first of five points      double *arrowPtr;                   /* Pointer to first of five points
2439                                           * describing arrowhead polygon. */                                           * describing arrowhead polygon. */
2440  {  {
2441      Pixmap stipple;      Pixmap stipple;
2442      Tk_State state = linePtr->header.state;      Tk_State state = linePtr->header.state;
2443    
2444      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
2445          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
2446      }      }
2447    
2448      stipple = linePtr->outline.stipple;      stipple = linePtr->outline.stipple;
2449      if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {      if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
2450          if (linePtr->outline.activeStipple!=None) {          if (linePtr->outline.activeStipple!=None) {
2451              stipple = linePtr->outline.activeStipple;              stipple = linePtr->outline.activeStipple;
2452          }          }
2453      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
2454          if (linePtr->outline.activeStipple!=None) {          if (linePtr->outline.activeStipple!=None) {
2455              stipple = linePtr->outline.disabledStipple;              stipple = linePtr->outline.disabledStipple;
2456          }          }
2457      }      }
2458    
2459      Tk_CanvasPsPath(interp, canvas, arrowPtr, PTS_IN_ARROW);      Tk_CanvasPsPath(interp, canvas, arrowPtr, PTS_IN_ARROW);
2460      if (stipple != None) {      if (stipple != None) {
2461          Tcl_AppendResult(interp, "clip ", (char *) NULL);          Tcl_AppendResult(interp, "clip ", (char *) NULL);
2462          if (Tk_CanvasPsStipple(interp, canvas, stipple)          if (Tk_CanvasPsStipple(interp, canvas, stipple)
2463                  != TCL_OK) {                  != TCL_OK) {
2464              return TCL_ERROR;              return TCL_ERROR;
2465          }          }
2466      } else {      } else {
2467          Tcl_AppendResult(interp, "fill\n", (char *) NULL);          Tcl_AppendResult(interp, "fill\n", (char *) NULL);
2468      }      }
2469      return TCL_OK;      return TCL_OK;
2470  }  }
2471    
2472  /* End of tkcanvline.c */  /* End of tkcanvline.c */

Legend:
Removed from v.70  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25