/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tk3d.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tk3d.c

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

projs/trunk/shared_source/c_tk_base_7_5_w_mods/tk3d.c revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tk3d.c revision 98 by dashley, Sun Dec 18 00:57:31 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tk3d.c --   * tk3d.c --
5   *   *
6   *      This module provides procedures to draw borders in   *      This module provides procedures to draw borders in
7   *      the three-dimensional Motif style.   *      the three-dimensional Motif style.
8   *   *
9   * Copyright (c) 1990-1994 The Regents of the University of California.   * Copyright (c) 1990-1994 The Regents of the University of California.
10   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
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: tk3d.c,v 1.1.1.1 2001/06/13 04:53:30 dtashley Exp $   * RCS: @(#) $Id: tk3d.c,v 1.1.1.1 2001/06/13 04:53:30 dtashley Exp $
16   */   */
17    
18  #include "tk3d.h"  #include "tk3d.h"
19    
20  /*  /*
21   * The following table defines the string values for reliefs, which are   * The following table defines the string values for reliefs, which are
22   * used by Tk_GetReliefFromObj.   * used by Tk_GetReliefFromObj.
23   */   */
24    
25  static char *reliefStrings[] = {"flat", "groove", "raised", "ridge", "solid",  static char *reliefStrings[] = {"flat", "groove", "raised", "ridge", "solid",
26          "sunken", (char *) NULL};          "sunken", (char *) NULL};
27    
28  /*  /*
29   * Forward declarations for procedures defined in this file:   * Forward declarations for procedures defined in this file:
30   */   */
31    
32  static void             BorderInit _ANSI_ARGS_((TkDisplay *dispPtr));  static void             BorderInit _ANSI_ARGS_((TkDisplay *dispPtr));
33  static void             DupBorderObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr,  static void             DupBorderObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr,
34                              Tcl_Obj *dupObjPtr));                              Tcl_Obj *dupObjPtr));
35  static void             FreeBorderObjProc _ANSI_ARGS_((Tcl_Obj *objPtr));  static void             FreeBorderObjProc _ANSI_ARGS_((Tcl_Obj *objPtr));
36  static int              Intersect _ANSI_ARGS_((XPoint *a1Ptr, XPoint *a2Ptr,  static int              Intersect _ANSI_ARGS_((XPoint *a1Ptr, XPoint *a2Ptr,
37                              XPoint *b1Ptr, XPoint *b2Ptr, XPoint *iPtr));                              XPoint *b1Ptr, XPoint *b2Ptr, XPoint *iPtr));
38  static void             InitBorderObj _ANSI_ARGS_((Tcl_Obj *objPtr));  static void             InitBorderObj _ANSI_ARGS_((Tcl_Obj *objPtr));
39  static void             ShiftLine _ANSI_ARGS_((XPoint *p1Ptr, XPoint *p2Ptr,  static void             ShiftLine _ANSI_ARGS_((XPoint *p1Ptr, XPoint *p2Ptr,
40                              int distance, XPoint *p3Ptr));                              int distance, XPoint *p3Ptr));
41    
42  /*  /*
43   * The following structure defines the implementation of the "border" Tcl   * The following structure defines the implementation of the "border" Tcl
44   * object, used for drawing. The border object remembers the hash table entry   * object, used for drawing. The border object remembers the hash table entry
45   * associated with a border. The actual allocation and deallocation of the   * associated with a border. The actual allocation and deallocation of the
46   * border should be done by the configuration package when the border option   * border should be done by the configuration package when the border option
47   * is set.   * is set.
48   */   */
49    
50  static Tcl_ObjType borderObjType = {  static Tcl_ObjType borderObjType = {
51      "border",                   /* name */      "border",                   /* name */
52      FreeBorderObjProc,          /* freeIntRepProc */      FreeBorderObjProc,          /* freeIntRepProc */
53      DupBorderObjProc,           /* dupIntRepProc */      DupBorderObjProc,           /* dupIntRepProc */
54      NULL,                       /* updateStringProc */      NULL,                       /* updateStringProc */
55      NULL                        /* setFromAnyProc */      NULL                        /* setFromAnyProc */
56  };  };
57    
58  /*  /*
59   *----------------------------------------------------------------------   *----------------------------------------------------------------------
60   *   *
61   * Tk_Alloc3DBorderFromObj --   * Tk_Alloc3DBorderFromObj --
62   *   *
63   *      Given a Tcl_Obj *, map the value to a corresponding   *      Given a Tcl_Obj *, map the value to a corresponding
64   *      Tk_3DBorder structure based on the tkwin given.   *      Tk_3DBorder structure based on the tkwin given.
65   *   *
66   * Results:   * Results:
67   *      The return value is a token for a data structure describing a   *      The return value is a token for a data structure describing a
68   *      3-D border.  This token may be passed to procedures such as   *      3-D border.  This token may be passed to procedures such as
69   *      Tk_Draw3DRectangle and Tk_Free3DBorder.  If an error prevented   *      Tk_Draw3DRectangle and Tk_Free3DBorder.  If an error prevented
70   *      the border from being created then NULL is returned and an error   *      the border from being created then NULL is returned and an error
71   *      message will be left in the interp's result.   *      message will be left in the interp's result.
72   *   *
73   * Side effects:   * Side effects:
74   *      The border is added to an internal database with a reference   *      The border is added to an internal database with a reference
75   *      count. For each call to this procedure, there should eventually   *      count. For each call to this procedure, there should eventually
76   *      be a call to FreeBorderObjProc so that the database is   *      be a call to FreeBorderObjProc so that the database is
77   *      cleaned up when borders aren't in use anymore.   *      cleaned up when borders aren't in use anymore.
78   *   *
79   *----------------------------------------------------------------------   *----------------------------------------------------------------------
80   */   */
81    
82  Tk_3DBorder  Tk_3DBorder
83  Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr)  Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr)
84      Tcl_Interp *interp;         /* Interp for error results. */      Tcl_Interp *interp;         /* Interp for error results. */
85      Tk_Window tkwin;            /* Need the screen the border is used on.*/      Tk_Window tkwin;            /* Need the screen the border is used on.*/
86      Tcl_Obj *objPtr;            /* Object giving name of color for window      Tcl_Obj *objPtr;            /* Object giving name of color for window
87                                   * background. */                                   * background. */
88  {  {
89      TkBorder *borderPtr;      TkBorder *borderPtr;
90    
91      if (objPtr->typePtr != &borderObjType) {      if (objPtr->typePtr != &borderObjType) {
92          InitBorderObj(objPtr);          InitBorderObj(objPtr);
93      }      }
94      borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;      borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;
95    
96      /*      /*
97       * If the object currently points to a TkBorder, see if it's the       * If the object currently points to a TkBorder, see if it's the
98       * one we want.  If so, increment its reference count and return.       * one we want.  If so, increment its reference count and return.
99       */       */
100    
101      if (borderPtr != NULL) {      if (borderPtr != NULL) {
102          if (borderPtr->resourceRefCount == 0) {          if (borderPtr->resourceRefCount == 0) {
103              /*              /*
104               * This is a stale reference: it refers to a border that's               * This is a stale reference: it refers to a border that's
105               * no longer in use.  Clear the reference.               * no longer in use.  Clear the reference.
106               */               */
107    
108              FreeBorderObjProc(objPtr);              FreeBorderObjProc(objPtr);
109              borderPtr = NULL;              borderPtr = NULL;
110          } else if ((Tk_Screen(tkwin) == borderPtr->screen)          } else if ((Tk_Screen(tkwin) == borderPtr->screen)
111                  && (Tk_Colormap(tkwin) == borderPtr->colormap)) {                  && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
112              borderPtr->resourceRefCount++;              borderPtr->resourceRefCount++;
113              return (Tk_3DBorder) borderPtr;              return (Tk_3DBorder) borderPtr;
114          }          }
115      }      }
116    
117      /*      /*
118       * The object didn't point to the border that we wanted.  Search       * The object didn't point to the border that we wanted.  Search
119       * the list of borders with the same name to see if one of the       * the list of borders with the same name to see if one of the
120       * others is the right one.       * others is the right one.
121       */       */
122    
123      /*      /*
124       * If the cached value is NULL, either the object type was not a       * If the cached value is NULL, either the object type was not a
125       * color going in, or the object is a color type but had       * color going in, or the object is a color type but had
126       * previously been freed.       * previously been freed.
127       *       *
128       * If the value is not NULL, the internal rep is the value       * If the value is not NULL, the internal rep is the value
129       * of the color the last time this object was accessed. Check       * of the color the last time this object was accessed. Check
130       * the screen and colormap of the last access, and if they       * the screen and colormap of the last access, and if they
131       * match, we are done.       * match, we are done.
132       */       */
133    
134      if (borderPtr != NULL) {      if (borderPtr != NULL) {
135          TkBorder *firstBorderPtr =          TkBorder *firstBorderPtr =
136                  (TkBorder *) Tcl_GetHashValue(borderPtr->hashPtr);                  (TkBorder *) Tcl_GetHashValue(borderPtr->hashPtr);
137          FreeBorderObjProc(objPtr);          FreeBorderObjProc(objPtr);
138          for (borderPtr = firstBorderPtr ; borderPtr != NULL;          for (borderPtr = firstBorderPtr ; borderPtr != NULL;
139                  borderPtr = borderPtr->nextPtr) {                  borderPtr = borderPtr->nextPtr) {
140              if ((Tk_Screen(tkwin) == borderPtr->screen)              if ((Tk_Screen(tkwin) == borderPtr->screen)
141                  && (Tk_Colormap(tkwin) == borderPtr->colormap)) {                  && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
142                  borderPtr->resourceRefCount++;                  borderPtr->resourceRefCount++;
143                  borderPtr->objRefCount++;                  borderPtr->objRefCount++;
144                  objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;                  objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;
145                  return (Tk_3DBorder) borderPtr;                  return (Tk_3DBorder) borderPtr;
146              }              }
147          }          }
148      }      }
149    
150      /*      /*
151       * Still no luck.  Call Tk_Get3DBorder to allocate a new border.       * Still no luck.  Call Tk_Get3DBorder to allocate a new border.
152       */       */
153    
154      borderPtr = (TkBorder *) Tk_Get3DBorder(interp, tkwin,      borderPtr = (TkBorder *) Tk_Get3DBorder(interp, tkwin,
155              Tcl_GetString(objPtr));              Tcl_GetString(objPtr));
156      objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;      objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;
157      if (borderPtr != NULL) {      if (borderPtr != NULL) {
158          borderPtr->objRefCount++;          borderPtr->objRefCount++;
159      }      }
160      return (Tk_3DBorder) borderPtr;      return (Tk_3DBorder) borderPtr;
161  }  }
162    
163  /*  /*
164   *--------------------------------------------------------------   *--------------------------------------------------------------
165   *   *
166   * Tk_Get3DBorder --   * Tk_Get3DBorder --
167   *   *
168   *      Create a data structure for displaying a 3-D border.   *      Create a data structure for displaying a 3-D border.
169   *   *
170   * Results:   * Results:
171   *      The return value is a token for a data structure describing a   *      The return value is a token for a data structure describing a
172   *      3-D border.  This token may be passed to procedures such as   *      3-D border.  This token may be passed to procedures such as
173   *      Tk_Draw3DRectangle and Tk_Free3DBorder.  If an error prevented   *      Tk_Draw3DRectangle and Tk_Free3DBorder.  If an error prevented
174   *      the border from being created then NULL is returned and an error   *      the border from being created then NULL is returned and an error
175   *      message will be left in the interp's result.   *      message will be left in the interp's result.
176   *   *
177   * Side effects:   * Side effects:
178   *      Data structures, graphics contexts, etc. are allocated.   *      Data structures, graphics contexts, etc. are allocated.
179   *      It is the caller's responsibility to eventually call   *      It is the caller's responsibility to eventually call
180   *      Tk_Free3DBorder to release the resources.   *      Tk_Free3DBorder to release the resources.
181   *   *
182   *--------------------------------------------------------------   *--------------------------------------------------------------
183   */   */
184    
185  Tk_3DBorder  Tk_3DBorder
186  Tk_Get3DBorder(interp, tkwin, colorName)  Tk_Get3DBorder(interp, tkwin, colorName)
187      Tcl_Interp *interp;         /* Place to store an error message. */      Tcl_Interp *interp;         /* Place to store an error message. */
188      Tk_Window tkwin;            /* Token for window in which border will      Tk_Window tkwin;            /* Token for window in which border will
189                                   * be drawn. */                                   * be drawn. */
190      char *colorName;            /* String giving name of color      char *colorName;            /* String giving name of color
191                                   * for window background. */                                   * for window background. */
192  {  {
193      Tcl_HashEntry *hashPtr;      Tcl_HashEntry *hashPtr;
194      TkBorder *borderPtr, *existingBorderPtr;      TkBorder *borderPtr, *existingBorderPtr;
195      int new;      int new;
196      XGCValues gcValues;      XGCValues gcValues;
197      XColor *bgColorPtr;      XColor *bgColorPtr;
198      TkDisplay *dispPtr;      TkDisplay *dispPtr;
199    
200      dispPtr = ((TkWindow *) tkwin)->dispPtr;      dispPtr = ((TkWindow *) tkwin)->dispPtr;
201    
202      if (!dispPtr->borderInit) {      if (!dispPtr->borderInit) {
203          BorderInit(dispPtr);          BorderInit(dispPtr);
204      }      }
205    
206      hashPtr = Tcl_CreateHashEntry(&dispPtr->borderTable, colorName, &new);      hashPtr = Tcl_CreateHashEntry(&dispPtr->borderTable, colorName, &new);
207      if (!new) {      if (!new) {
208          existingBorderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);          existingBorderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);
209          for (borderPtr = existingBorderPtr; borderPtr != NULL;          for (borderPtr = existingBorderPtr; borderPtr != NULL;
210                  borderPtr = borderPtr->nextPtr) {                  borderPtr = borderPtr->nextPtr) {
211              if ((Tk_Screen(tkwin) == borderPtr->screen)              if ((Tk_Screen(tkwin) == borderPtr->screen)
212                      && (Tk_Colormap(tkwin) == borderPtr->colormap)) {                      && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
213                  borderPtr->resourceRefCount++;                  borderPtr->resourceRefCount++;
214                  return (Tk_3DBorder) borderPtr;                  return (Tk_3DBorder) borderPtr;
215              }              }
216          }          }
217      } else {      } else {
218          existingBorderPtr = NULL;          existingBorderPtr = NULL;
219      }      }
220    
221      /*      /*
222       * No satisfactory border exists yet.  Initialize a new one.       * No satisfactory border exists yet.  Initialize a new one.
223       */       */
224    
225      bgColorPtr = Tk_GetColor(interp, tkwin, colorName);      bgColorPtr = Tk_GetColor(interp, tkwin, colorName);
226      if (bgColorPtr == NULL) {      if (bgColorPtr == NULL) {
227          if (new) {          if (new) {
228              Tcl_DeleteHashEntry(hashPtr);              Tcl_DeleteHashEntry(hashPtr);
229          }          }
230          return NULL;          return NULL;
231      }      }
232    
233      borderPtr = TkpGetBorder();      borderPtr = TkpGetBorder();
234      borderPtr->screen = Tk_Screen(tkwin);      borderPtr->screen = Tk_Screen(tkwin);
235      borderPtr->visual = Tk_Visual(tkwin);      borderPtr->visual = Tk_Visual(tkwin);
236      borderPtr->depth = Tk_Depth(tkwin);      borderPtr->depth = Tk_Depth(tkwin);
237      borderPtr->colormap = Tk_Colormap(tkwin);      borderPtr->colormap = Tk_Colormap(tkwin);
238      borderPtr->resourceRefCount = 1;      borderPtr->resourceRefCount = 1;
239      borderPtr->objRefCount = 0;      borderPtr->objRefCount = 0;
240      borderPtr->bgColorPtr = bgColorPtr;      borderPtr->bgColorPtr = bgColorPtr;
241      borderPtr->darkColorPtr = NULL;      borderPtr->darkColorPtr = NULL;
242      borderPtr->lightColorPtr = NULL;      borderPtr->lightColorPtr = NULL;
243      borderPtr->shadow = None;      borderPtr->shadow = None;
244      borderPtr->bgGC = None;      borderPtr->bgGC = None;
245      borderPtr->darkGC = None;      borderPtr->darkGC = None;
246      borderPtr->lightGC = None;      borderPtr->lightGC = None;
247      borderPtr->hashPtr = hashPtr;      borderPtr->hashPtr = hashPtr;
248      borderPtr->nextPtr = existingBorderPtr;      borderPtr->nextPtr = existingBorderPtr;
249      Tcl_SetHashValue(hashPtr, borderPtr);      Tcl_SetHashValue(hashPtr, borderPtr);
250    
251      /*      /*
252       * Create the information for displaying the background color,       * Create the information for displaying the background color,
253       * but delay the allocation of shadows until they are actually       * but delay the allocation of shadows until they are actually
254       * needed for drawing.       * needed for drawing.
255       */       */
256    
257      gcValues.foreground = borderPtr->bgColorPtr->pixel;      gcValues.foreground = borderPtr->bgColorPtr->pixel;
258      borderPtr->bgGC = Tk_GetGC(tkwin, GCForeground, &gcValues);      borderPtr->bgGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
259      return (Tk_3DBorder) borderPtr;      return (Tk_3DBorder) borderPtr;
260  }  }
261    
262  /*  /*
263   *--------------------------------------------------------------   *--------------------------------------------------------------
264   *   *
265   * Tk_Draw3DRectangle --   * Tk_Draw3DRectangle --
266   *   *
267   *      Draw a 3-D border at a given place in a given window.   *      Draw a 3-D border at a given place in a given window.
268   *   *
269   * Results:   * Results:
270   *      None.   *      None.
271   *   *
272   * Side effects:   * Side effects:
273   *      A 3-D border will be drawn in the indicated drawable.   *      A 3-D border will be drawn in the indicated drawable.
274   *      The outside edges of the border will be determined by x,   *      The outside edges of the border will be determined by x,
275   *      y, width, and height.  The inside edges of the border   *      y, width, and height.  The inside edges of the border
276   *      will be determined by the borderWidth argument.   *      will be determined by the borderWidth argument.
277   *   *
278   *--------------------------------------------------------------   *--------------------------------------------------------------
279   */   */
280    
281  void  void
282  Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width, height,  Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width, height,
283          borderWidth, relief)          borderWidth, relief)
284      Tk_Window tkwin;            /* Window for which border was allocated. */      Tk_Window tkwin;            /* Window for which border was allocated. */
285      Drawable drawable;          /* X window or pixmap in which to draw. */      Drawable drawable;          /* X window or pixmap in which to draw. */
286      Tk_3DBorder border;         /* Token for border to draw. */      Tk_3DBorder border;         /* Token for border to draw. */
287      int x, y, width, height;    /* Outside area of region in      int x, y, width, height;    /* Outside area of region in
288                                   * which border will be drawn. */                                   * which border will be drawn. */
289      int borderWidth;            /* Desired width for border, in      int borderWidth;            /* Desired width for border, in
290                                   * pixels. */                                   * pixels. */
291      int relief;                 /* Type of relief: TK_RELIEF_RAISED,      int relief;                 /* Type of relief: TK_RELIEF_RAISED,
292                                   * TK_RELIEF_SUNKEN, TK_RELIEF_GROOVE, etc. */                                   * TK_RELIEF_SUNKEN, TK_RELIEF_GROOVE, etc. */
293  {  {
294      if (width < 2*borderWidth) {      if (width < 2*borderWidth) {
295          borderWidth = width/2;          borderWidth = width/2;
296      }      }
297      if (height < 2*borderWidth) {      if (height < 2*borderWidth) {
298          borderWidth = height/2;          borderWidth = height/2;
299      }      }
300      Tk_3DVerticalBevel(tkwin, drawable, border, x, y, borderWidth, height,      Tk_3DVerticalBevel(tkwin, drawable, border, x, y, borderWidth, height,
301              1, relief);              1, relief);
302      Tk_3DVerticalBevel(tkwin, drawable, border, x+width-borderWidth, y,      Tk_3DVerticalBevel(tkwin, drawable, border, x+width-borderWidth, y,
303              borderWidth, height, 0, relief);              borderWidth, height, 0, relief);
304      Tk_3DHorizontalBevel(tkwin, drawable, border, x, y, width, borderWidth,      Tk_3DHorizontalBevel(tkwin, drawable, border, x, y, width, borderWidth,
305              1, 1, 1, relief);              1, 1, 1, relief);
306      Tk_3DHorizontalBevel(tkwin, drawable, border, x, y+height-borderWidth,      Tk_3DHorizontalBevel(tkwin, drawable, border, x, y+height-borderWidth,
307              width, borderWidth, 0, 0, 0, relief);              width, borderWidth, 0, 0, 0, relief);
308  }  }
309    
310  /*  /*
311   *--------------------------------------------------------------   *--------------------------------------------------------------
312   *   *
313   * Tk_NameOf3DBorder --   * Tk_NameOf3DBorder --
314   *   *
315   *      Given a border, return a textual string identifying the   *      Given a border, return a textual string identifying the
316   *      border's color.   *      border's color.
317   *   *
318   * Results:   * Results:
319   *      The return value is the string that was used to create   *      The return value is the string that was used to create
320   *      the border.   *      the border.
321   *   *
322   * Side effects:   * Side effects:
323   *      None.   *      None.
324   *   *
325   *--------------------------------------------------------------   *--------------------------------------------------------------
326   */   */
327    
328  char *  char *
329  Tk_NameOf3DBorder(border)  Tk_NameOf3DBorder(border)
330      Tk_3DBorder border;         /* Token for border. */      Tk_3DBorder border;         /* Token for border. */
331  {  {
332      TkBorder *borderPtr = (TkBorder *) border;      TkBorder *borderPtr = (TkBorder *) border;
333    
334      return borderPtr->hashPtr->key.string;      return borderPtr->hashPtr->key.string;
335  }  }
336    
337  /*  /*
338   *--------------------------------------------------------------------   *--------------------------------------------------------------------
339   *   *
340   * Tk_3DBorderColor --   * Tk_3DBorderColor --
341   *   *
342   *      Given a 3D border, return the X color used for the "flat"   *      Given a 3D border, return the X color used for the "flat"
343   *      surfaces.   *      surfaces.
344   *   *
345   * Results:   * Results:
346   *      Returns the color used drawing flat surfaces with the border.   *      Returns the color used drawing flat surfaces with the border.
347   *   *
348   * Side effects:   * Side effects:
349   *      None.   *      None.
350   *   *
351   *--------------------------------------------------------------------   *--------------------------------------------------------------------
352   */   */
353  XColor *  XColor *
354  Tk_3DBorderColor(border)  Tk_3DBorderColor(border)
355      Tk_3DBorder border;         /* Border whose color is wanted. */      Tk_3DBorder border;         /* Border whose color is wanted. */
356  {  {
357      return(((TkBorder *) border)->bgColorPtr);      return(((TkBorder *) border)->bgColorPtr);
358  }  }
359    
360  /*  /*
361   *--------------------------------------------------------------------   *--------------------------------------------------------------------
362   *   *
363   * Tk_3DBorderGC --   * Tk_3DBorderGC --
364   *   *
365   *      Given a 3D border, returns one of the graphics contexts used to   *      Given a 3D border, returns one of the graphics contexts used to
366   *      draw the border.   *      draw the border.
367   *   *
368   * Results:   * Results:
369   *      Returns the graphics context given by the "which" argument.   *      Returns the graphics context given by the "which" argument.
370   *   *
371   * Side effects:   * Side effects:
372   *      None.   *      None.
373   *   *
374   *--------------------------------------------------------------------   *--------------------------------------------------------------------
375   */   */
376  GC  GC
377  Tk_3DBorderGC(tkwin, border, which)  Tk_3DBorderGC(tkwin, border, which)
378      Tk_Window tkwin;            /* Window for which border was allocated. */      Tk_Window tkwin;            /* Window for which border was allocated. */
379      Tk_3DBorder border;         /* Border whose GC is wanted. */      Tk_3DBorder border;         /* Border whose GC is wanted. */
380      int which;                  /* Selects one of the border's 3 GC's:      int which;                  /* Selects one of the border's 3 GC's:
381                                   * TK_3D_FLAT_GC, TK_3D_LIGHT_GC, or                                   * TK_3D_FLAT_GC, TK_3D_LIGHT_GC, or
382                                   * TK_3D_DARK_GC. */                                   * TK_3D_DARK_GC. */
383  {  {
384      TkBorder * borderPtr = (TkBorder *) border;      TkBorder * borderPtr = (TkBorder *) border;
385    
386      if ((borderPtr->lightGC == None) && (which != TK_3D_FLAT_GC)) {      if ((borderPtr->lightGC == None) && (which != TK_3D_FLAT_GC)) {
387          TkpGetShadows(borderPtr, tkwin);          TkpGetShadows(borderPtr, tkwin);
388      }      }
389      if (which == TK_3D_FLAT_GC) {      if (which == TK_3D_FLAT_GC) {
390          return borderPtr->bgGC;          return borderPtr->bgGC;
391      } else if (which == TK_3D_LIGHT_GC) {      } else if (which == TK_3D_LIGHT_GC) {
392          return borderPtr->lightGC;          return borderPtr->lightGC;
393      } else if (which == TK_3D_DARK_GC){      } else if (which == TK_3D_DARK_GC){
394          return borderPtr->darkGC;          return borderPtr->darkGC;
395      }      }
396      panic("bogus \"which\" value in Tk_3DBorderGC");      panic("bogus \"which\" value in Tk_3DBorderGC");
397    
398      /*      /*
399       * The code below will never be executed, but it's needed to       * The code below will never be executed, but it's needed to
400       * keep compilers happy.       * keep compilers happy.
401       */       */
402    
403      return (GC) None;      return (GC) None;
404  }  }
405    
406  /*  /*
407   *--------------------------------------------------------------   *--------------------------------------------------------------
408   *   *
409   * Tk_Free3DBorder --   * Tk_Free3DBorder --
410   *   *
411   *      This procedure is called when a 3D border is no longer   *      This procedure is called when a 3D border is no longer
412   *      needed.  It frees the resources associated with the   *      needed.  It frees the resources associated with the
413   *      border.  After this call, the caller should never again   *      border.  After this call, the caller should never again
414   *      use the "border" token.   *      use the "border" token.
415   *   *
416   * Results:   * Results:
417   *      None.   *      None.
418   *   *
419   * Side effects:   * Side effects:
420   *      Resources are freed.   *      Resources are freed.
421   *   *
422   *--------------------------------------------------------------   *--------------------------------------------------------------
423   */   */
424    
425  void  void
426  Tk_Free3DBorder(border)  Tk_Free3DBorder(border)
427      Tk_3DBorder border;         /* Token for border to be released. */      Tk_3DBorder border;         /* Token for border to be released. */
428  {  {
429      TkBorder *borderPtr = (TkBorder *) border;      TkBorder *borderPtr = (TkBorder *) border;
430      Display *display = DisplayOfScreen(borderPtr->screen);      Display *display = DisplayOfScreen(borderPtr->screen);
431      TkBorder *prevPtr;      TkBorder *prevPtr;
432    
433      borderPtr->resourceRefCount--;      borderPtr->resourceRefCount--;
434      if (borderPtr->resourceRefCount > 0) {      if (borderPtr->resourceRefCount > 0) {
435          return;          return;
436      }      }
437    
438      prevPtr = (TkBorder *) Tcl_GetHashValue(borderPtr->hashPtr);      prevPtr = (TkBorder *) Tcl_GetHashValue(borderPtr->hashPtr);
439      TkpFreeBorder(borderPtr);      TkpFreeBorder(borderPtr);
440      if (borderPtr->bgColorPtr != NULL) {      if (borderPtr->bgColorPtr != NULL) {
441          Tk_FreeColor(borderPtr->bgColorPtr);          Tk_FreeColor(borderPtr->bgColorPtr);
442      }      }
443      if (borderPtr->darkColorPtr != NULL) {      if (borderPtr->darkColorPtr != NULL) {
444          Tk_FreeColor(borderPtr->darkColorPtr);          Tk_FreeColor(borderPtr->darkColorPtr);
445      }      }
446      if (borderPtr->lightColorPtr != NULL) {      if (borderPtr->lightColorPtr != NULL) {
447          Tk_FreeColor(borderPtr->lightColorPtr);          Tk_FreeColor(borderPtr->lightColorPtr);
448      }      }
449      if (borderPtr->shadow != None) {      if (borderPtr->shadow != None) {
450          Tk_FreeBitmap(display, borderPtr->shadow);          Tk_FreeBitmap(display, borderPtr->shadow);
451      }      }
452      if (borderPtr->bgGC != None) {      if (borderPtr->bgGC != None) {
453          Tk_FreeGC(display, borderPtr->bgGC);          Tk_FreeGC(display, borderPtr->bgGC);
454      }      }
455      if (borderPtr->darkGC != None) {      if (borderPtr->darkGC != None) {
456          Tk_FreeGC(display, borderPtr->darkGC);          Tk_FreeGC(display, borderPtr->darkGC);
457      }      }
458      if (borderPtr->lightGC != None) {      if (borderPtr->lightGC != None) {
459          Tk_FreeGC(display, borderPtr->lightGC);          Tk_FreeGC(display, borderPtr->lightGC);
460      }      }
461      if (prevPtr == borderPtr) {      if (prevPtr == borderPtr) {
462          if (borderPtr->nextPtr == NULL) {          if (borderPtr->nextPtr == NULL) {
463              Tcl_DeleteHashEntry(borderPtr->hashPtr);              Tcl_DeleteHashEntry(borderPtr->hashPtr);
464          } else {          } else {
465              Tcl_SetHashValue(borderPtr->hashPtr, borderPtr->nextPtr);              Tcl_SetHashValue(borderPtr->hashPtr, borderPtr->nextPtr);
466          }          }
467      } else {      } else {
468          while (prevPtr->nextPtr != borderPtr) {          while (prevPtr->nextPtr != borderPtr) {
469              prevPtr = prevPtr->nextPtr;              prevPtr = prevPtr->nextPtr;
470          }          }
471          prevPtr->nextPtr = borderPtr->nextPtr;          prevPtr->nextPtr = borderPtr->nextPtr;
472      }      }
473      if (borderPtr->objRefCount == 0) {      if (borderPtr->objRefCount == 0) {
474          ckfree((char *) borderPtr);          ckfree((char *) borderPtr);
475      }      }
476  }  }
477    
478  /*  /*
479   *----------------------------------------------------------------------   *----------------------------------------------------------------------
480   *   *
481   * Tk_Free3DBorderFromObj --   * Tk_Free3DBorderFromObj --
482   *   *
483   *      This procedure is called to release a border allocated by   *      This procedure is called to release a border allocated by
484   *      Tk_Alloc3DBorderFromObj. It does not throw away the Tcl_Obj *;   *      Tk_Alloc3DBorderFromObj. It does not throw away the Tcl_Obj *;
485   *      it only gets rid of the hash table entry for this border   *      it only gets rid of the hash table entry for this border
486   *      and clears the cached value that is normally stored in the object.   *      and clears the cached value that is normally stored in the object.
487   *   *
488   * Results:   * Results:
489   *      None.   *      None.
490   *   *
491   * Side effects:   * Side effects:
492   *      The reference count associated with the border represented by   *      The reference count associated with the border represented by
493   *      objPtr is decremented, and the border's resources are released   *      objPtr is decremented, and the border's resources are released
494   *      to X if there are no remaining uses for it.   *      to X if there are no remaining uses for it.
495   *   *
496   *----------------------------------------------------------------------   *----------------------------------------------------------------------
497   */   */
498    
499  void  void
500  Tk_Free3DBorderFromObj(tkwin, objPtr)  Tk_Free3DBorderFromObj(tkwin, objPtr)
501      Tk_Window tkwin;            /* The window this border lives in. Needed      Tk_Window tkwin;            /* The window this border lives in. Needed
502                                   * for the screen and colormap values. */                                   * for the screen and colormap values. */
503      Tcl_Obj *objPtr;            /* The Tcl_Obj * to be freed. */      Tcl_Obj *objPtr;            /* The Tcl_Obj * to be freed. */
504  {  {
505      Tk_Free3DBorder(Tk_Get3DBorderFromObj(tkwin, objPtr));      Tk_Free3DBorder(Tk_Get3DBorderFromObj(tkwin, objPtr));
506  }  }
507    
508  /*  /*
509   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
510   *   *
511   * FreeBorderObjProc --   * FreeBorderObjProc --
512   *   *
513   *      This proc is called to release an object reference to a border.   *      This proc is called to release an object reference to a border.
514   *      Called when the object's internal rep is released or when   *      Called when the object's internal rep is released or when
515   *      the cached borderPtr needs to be changed.   *      the cached borderPtr needs to be changed.
516   *   *
517   * Results:   * Results:
518   *      None.   *      None.
519   *   *
520   * Side effects:   * Side effects:
521   *      The object reference count is decremented. When both it   *      The object reference count is decremented. When both it
522   *      and the hash ref count go to zero, the border's resources   *      and the hash ref count go to zero, the border's resources
523   *      are released.   *      are released.
524   *   *
525   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
526   */   */
527    
528  static void  static void
529  FreeBorderObjProc(objPtr)  FreeBorderObjProc(objPtr)
530      Tcl_Obj *objPtr;            /* The object we are releasing. */      Tcl_Obj *objPtr;            /* The object we are releasing. */
531  {  {
532      TkBorder *borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;      TkBorder *borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;
533    
534      if (borderPtr != NULL) {      if (borderPtr != NULL) {
535          borderPtr->objRefCount--;          borderPtr->objRefCount--;
536          if ((borderPtr->objRefCount == 0)          if ((borderPtr->objRefCount == 0)
537                  && (borderPtr->resourceRefCount == 0)) {                  && (borderPtr->resourceRefCount == 0)) {
538              ckfree((char *) borderPtr);              ckfree((char *) borderPtr);
539          }          }
540          objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;          objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
541      }      }
542  }  }
543    
544  /*  /*
545   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
546   *   *
547   * DupBorderObjProc --   * DupBorderObjProc --
548   *   *
549   *      When a cached border object is duplicated, this is called to   *      When a cached border object is duplicated, this is called to
550   *      update the internal reps.   *      update the internal reps.
551   *   *
552   * Results:   * Results:
553   *      None.   *      None.
554   *   *
555   * Side effects:   * Side effects:
556   *      The border's objRefCount is incremented and the internal rep   *      The border's objRefCount is incremented and the internal rep
557   *      of the copy is set to point to it.   *      of the copy is set to point to it.
558   *   *
559   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
560   */   */
561    
562  static void  static void
563  DupBorderObjProc(srcObjPtr, dupObjPtr)  DupBorderObjProc(srcObjPtr, dupObjPtr)
564      Tcl_Obj *srcObjPtr;         /* The object we are copying from. */      Tcl_Obj *srcObjPtr;         /* The object we are copying from. */
565      Tcl_Obj *dupObjPtr;         /* The object we are copying to. */      Tcl_Obj *dupObjPtr;         /* The object we are copying to. */
566  {  {
567      TkBorder *borderPtr = (TkBorder *) srcObjPtr->internalRep.twoPtrValue.ptr1;      TkBorder *borderPtr = (TkBorder *) srcObjPtr->internalRep.twoPtrValue.ptr1;
568            
569      dupObjPtr->typePtr = srcObjPtr->typePtr;      dupObjPtr->typePtr = srcObjPtr->typePtr;
570      dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;      dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;
571    
572      if (borderPtr != NULL) {      if (borderPtr != NULL) {
573          borderPtr->objRefCount++;          borderPtr->objRefCount++;
574      }      }
575  }  }
576    
577  /*  /*
578   *----------------------------------------------------------------------   *----------------------------------------------------------------------
579   *   *
580   * Tk_SetBackgroundFromBorder --   * Tk_SetBackgroundFromBorder --
581   *   *
582   *      Change the background of a window to one appropriate for a given   *      Change the background of a window to one appropriate for a given
583   *      3-D border.   *      3-D border.
584   *   *
585   * Results:   * Results:
586   *      None.   *      None.
587   *   *
588   * Side effects:   * Side effects:
589   *      Tkwin's background gets modified.   *      Tkwin's background gets modified.
590   *   *
591   *----------------------------------------------------------------------   *----------------------------------------------------------------------
592   */   */
593    
594  void  void
595  Tk_SetBackgroundFromBorder(tkwin, border)  Tk_SetBackgroundFromBorder(tkwin, border)
596      Tk_Window tkwin;            /* Window whose background is to be set. */      Tk_Window tkwin;            /* Window whose background is to be set. */
597      Tk_3DBorder border;         /* Token for border. */      Tk_3DBorder border;         /* Token for border. */
598  {  {
599      register TkBorder *borderPtr = (TkBorder *) border;      register TkBorder *borderPtr = (TkBorder *) border;
600    
601      Tk_SetWindowBackground(tkwin, borderPtr->bgColorPtr->pixel);      Tk_SetWindowBackground(tkwin, borderPtr->bgColorPtr->pixel);
602  }  }
603    
604  /*  /*
605   *----------------------------------------------------------------------   *----------------------------------------------------------------------
606   *   *
607   * Tk_GetReliefFromObj --   * Tk_GetReliefFromObj --
608   *   *
609   *      Return an integer value based on the value of the objPtr.   *      Return an integer value based on the value of the objPtr.
610   *   *
611   * Results:   * Results:
612   *      The return value is a standard Tcl result. If an error occurs during   *      The return value is a standard Tcl result. If an error occurs during
613   *      conversion, an error message is left in the interpreter's result   *      conversion, an error message is left in the interpreter's result
614   *      unless "interp" is NULL.   *      unless "interp" is NULL.
615   *   *
616   * Side effects:   * Side effects:
617   *      The object gets converted by Tcl_GetIndexFromObj.   *      The object gets converted by Tcl_GetIndexFromObj.
618   *   *
619   *----------------------------------------------------------------------   *----------------------------------------------------------------------
620   */   */
621    
622  int  int
623  Tk_GetReliefFromObj(interp, objPtr, resultPtr)  Tk_GetReliefFromObj(interp, objPtr, resultPtr)
624      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
625      Tcl_Obj *objPtr;            /* The object we are trying to get the      Tcl_Obj *objPtr;            /* The object we are trying to get the
626                                   * value from. */                                   * value from. */
627      int *resultPtr;             /* Where to place the answer. */      int *resultPtr;             /* Where to place the answer. */
628  {  {
629      return Tcl_GetIndexFromObj(interp, objPtr, reliefStrings, "relief", 0,      return Tcl_GetIndexFromObj(interp, objPtr, reliefStrings, "relief", 0,
630              resultPtr);              resultPtr);
631  }  }
632    
633  /*  /*
634   *----------------------------------------------------------------------   *----------------------------------------------------------------------
635   *   *
636   * Tk_GetRelief --   * Tk_GetRelief --
637   *   *
638   *      Parse a relief description and return the corresponding   *      Parse a relief description and return the corresponding
639   *      relief value, or an error.   *      relief value, or an error.
640   *   *
641   * Results:   * Results:
642   *      A standard Tcl return value.  If all goes well then   *      A standard Tcl return value.  If all goes well then
643   *      *reliefPtr is filled in with one of the values   *      *reliefPtr is filled in with one of the values
644   *      TK_RELIEF_RAISED, TK_RELIEF_FLAT, or TK_RELIEF_SUNKEN.   *      TK_RELIEF_RAISED, TK_RELIEF_FLAT, or TK_RELIEF_SUNKEN.
645   *   *
646   * Side effects:   * Side effects:
647   *      None.   *      None.
648   *   *
649   *----------------------------------------------------------------------   *----------------------------------------------------------------------
650   */   */
651    
652  int  int
653  Tk_GetRelief(interp, name, reliefPtr)  Tk_GetRelief(interp, name, reliefPtr)
654      Tcl_Interp *interp;         /* For error messages. */      Tcl_Interp *interp;         /* For error messages. */
655      char *name;                 /* Name of a relief type. */      char *name;                 /* Name of a relief type. */
656      int *reliefPtr;             /* Where to store converted relief. */      int *reliefPtr;             /* Where to store converted relief. */
657  {  {
658      char c;      char c;
659      size_t length;      size_t length;
660    
661      c = name[0];      c = name[0];
662      length = strlen(name);      length = strlen(name);
663      if ((c == 'f') && (strncmp(name, "flat", length) == 0)) {      if ((c == 'f') && (strncmp(name, "flat", length) == 0)) {
664          *reliefPtr = TK_RELIEF_FLAT;          *reliefPtr = TK_RELIEF_FLAT;
665      } else if ((c == 'g') && (strncmp(name, "groove", length) == 0)      } else if ((c == 'g') && (strncmp(name, "groove", length) == 0)
666              && (length >= 2)) {              && (length >= 2)) {
667          *reliefPtr = TK_RELIEF_GROOVE;          *reliefPtr = TK_RELIEF_GROOVE;
668      } else if ((c == 'r') && (strncmp(name, "raised", length) == 0)      } else if ((c == 'r') && (strncmp(name, "raised", length) == 0)
669              && (length >= 2)) {              && (length >= 2)) {
670          *reliefPtr = TK_RELIEF_RAISED;          *reliefPtr = TK_RELIEF_RAISED;
671      } else if ((c == 'r') && (strncmp(name, "ridge", length) == 0)) {      } else if ((c == 'r') && (strncmp(name, "ridge", length) == 0)) {
672          *reliefPtr = TK_RELIEF_RIDGE;          *reliefPtr = TK_RELIEF_RIDGE;
673      } else if ((c == 's') && (strncmp(name, "solid", length) == 0)) {      } else if ((c == 's') && (strncmp(name, "solid", length) == 0)) {
674          *reliefPtr = TK_RELIEF_SOLID;          *reliefPtr = TK_RELIEF_SOLID;
675      } else if ((c == 's') && (strncmp(name, "sunken", length) == 0)) {      } else if ((c == 's') && (strncmp(name, "sunken", length) == 0)) {
676          *reliefPtr = TK_RELIEF_SUNKEN;          *reliefPtr = TK_RELIEF_SUNKEN;
677      } else {      } else {
678          char buf[200];          char buf[200];
679    
680          sprintf(buf, "bad relief type \"%.50s\": must be %s",          sprintf(buf, "bad relief type \"%.50s\": must be %s",
681                  name, "flat, groove, raised, ridge, solid, or sunken");                  name, "flat, groove, raised, ridge, solid, or sunken");
682          Tcl_SetResult(interp, buf, TCL_VOLATILE);          Tcl_SetResult(interp, buf, TCL_VOLATILE);
683          return TCL_ERROR;          return TCL_ERROR;
684      }      }
685      return TCL_OK;      return TCL_OK;
686  }  }
687    
688  /*  /*
689   *--------------------------------------------------------------   *--------------------------------------------------------------
690   *   *
691   * Tk_NameOfRelief --   * Tk_NameOfRelief --
692   *   *
693   *      Given a relief value, produce a string describing that   *      Given a relief value, produce a string describing that
694   *      relief value.   *      relief value.
695   *   *
696   * Results:   * Results:
697   *      The return value is a static string that is equivalent   *      The return value is a static string that is equivalent
698   *      to relief.   *      to relief.
699   *   *
700   * Side effects:   * Side effects:
701   *      None.   *      None.
702   *   *
703   *--------------------------------------------------------------   *--------------------------------------------------------------
704   */   */
705    
706  char *  char *
707  Tk_NameOfRelief(relief)  Tk_NameOfRelief(relief)
708      int relief;         /* One of TK_RELIEF_FLAT, TK_RELIEF_RAISED,      int relief;         /* One of TK_RELIEF_FLAT, TK_RELIEF_RAISED,
709                           * or TK_RELIEF_SUNKEN. */                           * or TK_RELIEF_SUNKEN. */
710  {  {
711      if (relief == TK_RELIEF_FLAT) {      if (relief == TK_RELIEF_FLAT) {
712          return "flat";          return "flat";
713      } else if (relief == TK_RELIEF_SUNKEN) {      } else if (relief == TK_RELIEF_SUNKEN) {
714          return "sunken";          return "sunken";
715      } else if (relief == TK_RELIEF_RAISED) {      } else if (relief == TK_RELIEF_RAISED) {
716          return "raised";          return "raised";
717      } else if (relief == TK_RELIEF_GROOVE) {      } else if (relief == TK_RELIEF_GROOVE) {
718          return "groove";          return "groove";
719      } else if (relief == TK_RELIEF_RIDGE) {      } else if (relief == TK_RELIEF_RIDGE) {
720          return "ridge";          return "ridge";
721      } else if (relief == TK_RELIEF_SOLID) {      } else if (relief == TK_RELIEF_SOLID) {
722          return "solid";          return "solid";
723      } else {      } else {
724          return "unknown relief";          return "unknown relief";
725      }      }
726  }  }
727    
728  /*  /*
729   *--------------------------------------------------------------   *--------------------------------------------------------------
730   *   *
731   * Tk_Draw3DPolygon --   * Tk_Draw3DPolygon --
732   *   *
733   *      Draw a border with 3-D appearance around the edge of a   *      Draw a border with 3-D appearance around the edge of a
734   *      given polygon.   *      given polygon.
735   *   *
736   * Results:   * Results:
737   *      None.   *      None.
738   *   *
739   * Side effects:   * Side effects:
740   *      Information is drawn in "drawable" in the form of a   *      Information is drawn in "drawable" in the form of a
741   *      3-D border borderWidth units width wide on the left   *      3-D border borderWidth units width wide on the left
742   *      of the trajectory given by pointPtr and numPoints (or   *      of the trajectory given by pointPtr and numPoints (or
743   *      -borderWidth units wide on the right side, if borderWidth   *      -borderWidth units wide on the right side, if borderWidth
744   *      is negative).   *      is negative).
745   *   *
746   *--------------------------------------------------------------   *--------------------------------------------------------------
747   */   */
748    
749  void  void
750  Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,  Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
751          borderWidth, leftRelief)          borderWidth, leftRelief)
752      Tk_Window tkwin;            /* Window for which border was allocated. */      Tk_Window tkwin;            /* Window for which border was allocated. */
753      Drawable drawable;          /* X window or pixmap in which to draw. */      Drawable drawable;          /* X window or pixmap in which to draw. */
754      Tk_3DBorder border;         /* Token for border to draw. */      Tk_3DBorder border;         /* Token for border to draw. */
755      XPoint *pointPtr;           /* Array of points describing      XPoint *pointPtr;           /* Array of points describing
756                                   * polygon.  All points must be                                   * polygon.  All points must be
757                                   * absolute (CoordModeOrigin). */                                   * absolute (CoordModeOrigin). */
758      int numPoints;              /* Number of points at *pointPtr. */      int numPoints;              /* Number of points at *pointPtr. */
759      int borderWidth;            /* Width of border, measured in      int borderWidth;            /* Width of border, measured in
760                                   * pixels to the left of the polygon's                                   * pixels to the left of the polygon's
761                                   * trajectory.   May be negative. */                                   * trajectory.   May be negative. */
762      int leftRelief;             /* TK_RELIEF_RAISED or      int leftRelief;             /* TK_RELIEF_RAISED or
763                                   * TK_RELIEF_SUNKEN: indicates how                                   * TK_RELIEF_SUNKEN: indicates how
764                                   * stuff to left of trajectory looks                                   * stuff to left of trajectory looks
765                                   * relative to stuff on right. */                                   * relative to stuff on right. */
766  {  {
767      XPoint poly[4], b1, b2, newB1, newB2;      XPoint poly[4], b1, b2, newB1, newB2;
768      XPoint perp, c, shift1, shift2;     /* Used for handling parallel lines. */      XPoint perp, c, shift1, shift2;     /* Used for handling parallel lines. */
769      register XPoint *p1Ptr, *p2Ptr;      register XPoint *p1Ptr, *p2Ptr;
770      TkBorder *borderPtr = (TkBorder *) border;      TkBorder *borderPtr = (TkBorder *) border;
771      GC gc;      GC gc;
772      int i, lightOnLeft, dx, dy, parallel, pointsSeen;      int i, lightOnLeft, dx, dy, parallel, pointsSeen;
773      Display *display = Tk_Display(tkwin);      Display *display = Tk_Display(tkwin);
774    
775      if (borderPtr->lightGC == None) {      if (borderPtr->lightGC == None) {
776          TkpGetShadows(borderPtr, tkwin);          TkpGetShadows(borderPtr, tkwin);
777      }      }
778    
779      /*      /*
780       * Handle grooves and ridges with recursive calls.       * Handle grooves and ridges with recursive calls.
781       */       */
782    
783      if ((leftRelief == TK_RELIEF_GROOVE) || (leftRelief == TK_RELIEF_RIDGE)) {      if ((leftRelief == TK_RELIEF_GROOVE) || (leftRelief == TK_RELIEF_RIDGE)) {
784          int halfWidth;          int halfWidth;
785    
786          halfWidth = borderWidth/2;          halfWidth = borderWidth/2;
787          Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,          Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
788                  halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_RAISED                  halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_RAISED
789                  : TK_RELIEF_SUNKEN);                  : TK_RELIEF_SUNKEN);
790          Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,          Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
791                  -halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_SUNKEN                  -halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_SUNKEN
792                  : TK_RELIEF_RAISED);                  : TK_RELIEF_RAISED);
793          return;          return;
794      }      }
795    
796      /*      /*
797       * If the polygon is already closed, drop the last point from it       * If the polygon is already closed, drop the last point from it
798       * (we'll close it automatically).       * (we'll close it automatically).
799       */       */
800    
801      p1Ptr = &pointPtr[numPoints-1];      p1Ptr = &pointPtr[numPoints-1];
802      p2Ptr = &pointPtr[0];      p2Ptr = &pointPtr[0];
803      if ((p1Ptr->x == p2Ptr->x) && (p1Ptr->y == p2Ptr->y)) {      if ((p1Ptr->x == p2Ptr->x) && (p1Ptr->y == p2Ptr->y)) {
804          numPoints--;          numPoints--;
805      }      }
806    
807      /*      /*
808       * The loop below is executed once for each vertex in the polgon.       * The loop below is executed once for each vertex in the polgon.
809       * At the beginning of each iteration things look like this:       * At the beginning of each iteration things look like this:
810       *       *
811       *          poly[1]       /       *          poly[1]       /
812       *             *        /       *             *        /
813       *             |      /       *             |      /
814       *             b1   * poly[0] (pointPtr[i-1])       *             b1   * poly[0] (pointPtr[i-1])
815       *             |    |       *             |    |
816       *             |    |       *             |    |
817       *             |    |       *             |    |
818       *             |    |       *             |    |
819       *             |    |       *             |    |
820       *             |    | *p1Ptr            *p2Ptr       *             |    | *p1Ptr            *p2Ptr
821       *             b2   *--------------------*       *             b2   *--------------------*
822       *             |       *             |
823       *             |       *             |
824       *             x-------------------------       *             x-------------------------
825       *       *
826       * The job of this iteration is to do the following:       * The job of this iteration is to do the following:
827       * (a) Compute x (the border corner corresponding to       * (a) Compute x (the border corner corresponding to
828       *     pointPtr[i]) and put it in poly[2].  As part of       *     pointPtr[i]) and put it in poly[2].  As part of
829       *     this, compute a new b1 and b2 value for the next       *     this, compute a new b1 and b2 value for the next
830       *     side of the polygon.       *     side of the polygon.
831       * (b) Put pointPtr[i] into poly[3].       * (b) Put pointPtr[i] into poly[3].
832       * (c) Draw the polygon given by poly[0..3].       * (c) Draw the polygon given by poly[0..3].
833       * (d) Advance poly[0], poly[1], b1, and b2 for the       * (d) Advance poly[0], poly[1], b1, and b2 for the
834       *     next side of the polygon.       *     next side of the polygon.
835       */       */
836    
837      /*      /*
838       * The above situation doesn't first come into existence until       * The above situation doesn't first come into existence until
839       * two points have been processed;  the first two points are       * two points have been processed;  the first two points are
840       * used to "prime the pump", so some parts of the processing       * used to "prime the pump", so some parts of the processing
841       * are ommitted for these points.  The variable "pointsSeen"       * are ommitted for these points.  The variable "pointsSeen"
842       * keeps track of the priming process;  it has to be separate       * keeps track of the priming process;  it has to be separate
843       * from i in order to be able to ignore duplicate points in the       * from i in order to be able to ignore duplicate points in the
844       * polygon.       * polygon.
845       */       */
846    
847      pointsSeen = 0;      pointsSeen = 0;
848      for (i = -2, p1Ptr = &pointPtr[numPoints-2], p2Ptr = p1Ptr+1;      for (i = -2, p1Ptr = &pointPtr[numPoints-2], p2Ptr = p1Ptr+1;
849              i < numPoints; i++, p1Ptr = p2Ptr, p2Ptr++) {              i < numPoints; i++, p1Ptr = p2Ptr, p2Ptr++) {
850          if ((i == -1) || (i == numPoints-1)) {          if ((i == -1) || (i == numPoints-1)) {
851              p2Ptr = pointPtr;              p2Ptr = pointPtr;
852          }          }
853          if ((p2Ptr->x == p1Ptr->x) && (p2Ptr->y == p1Ptr->y)) {          if ((p2Ptr->x == p1Ptr->x) && (p2Ptr->y == p1Ptr->y)) {
854              /*              /*
855               * Ignore duplicate points (they'd cause core dumps in               * Ignore duplicate points (they'd cause core dumps in
856               * ShiftLine calls below).               * ShiftLine calls below).
857               */               */
858              continue;              continue;
859          }          }
860          ShiftLine(p1Ptr, p2Ptr, borderWidth, &newB1);          ShiftLine(p1Ptr, p2Ptr, borderWidth, &newB1);
861          newB2.x = newB1.x + (p2Ptr->x - p1Ptr->x);          newB2.x = newB1.x + (p2Ptr->x - p1Ptr->x);
862          newB2.y = newB1.y + (p2Ptr->y - p1Ptr->y);          newB2.y = newB1.y + (p2Ptr->y - p1Ptr->y);
863          poly[3] = *p1Ptr;          poly[3] = *p1Ptr;
864          parallel = 0;          parallel = 0;
865          if (pointsSeen >= 1) {          if (pointsSeen >= 1) {
866              parallel = Intersect(&newB1, &newB2, &b1, &b2, &poly[2]);              parallel = Intersect(&newB1, &newB2, &b1, &b2, &poly[2]);
867    
868              /*              /*
869               * If two consecutive segments of the polygon are parallel,               * If two consecutive segments of the polygon are parallel,
870               * then things get more complex.  Consider the following               * then things get more complex.  Consider the following
871               * diagram:               * diagram:
872               *               *
873               * poly[1]               * poly[1]
874               *    *----b1-----------b2------a               *    *----b1-----------b2------a
875               *                                \               *                                \
876               *                                  \               *                                  \
877               *         *---------*----------*    b               *         *---------*----------*    b
878               *        poly[0]  *p2Ptr   *p1Ptr  /               *        poly[0]  *p2Ptr   *p1Ptr  /
879               *                                /               *                                /
880               *              --*--------*----c               *              --*--------*----c
881               *              newB1    newB2               *              newB1    newB2
882               *               *
883               * Instead of using x and *p1Ptr for poly[2] and poly[3], as               * Instead of using x and *p1Ptr for poly[2] and poly[3], as
884               * in the original diagram, use a and b as above.  Then instead               * in the original diagram, use a and b as above.  Then instead
885               * of using x and *p1Ptr for the new poly[0] and poly[1], use               * of using x and *p1Ptr for the new poly[0] and poly[1], use
886               * b and c as above.               * b and c as above.
887               *               *
888               * Do the computation in three stages:               * Do the computation in three stages:
889               * 1. Compute a point "perp" such that the line p1Ptr-perp               * 1. Compute a point "perp" such that the line p1Ptr-perp
890               *    is perpendicular to p1Ptr-p2Ptr.               *    is perpendicular to p1Ptr-p2Ptr.
891               * 2. Compute the points a and c by intersecting the lines               * 2. Compute the points a and c by intersecting the lines
892               *    b1-b2 and newB1-newB2 with p1Ptr-perp.               *    b1-b2 and newB1-newB2 with p1Ptr-perp.
893               * 3. Compute b by shifting p1Ptr-perp to the right and               * 3. Compute b by shifting p1Ptr-perp to the right and
894               *    intersecting it with p1Ptr-p2Ptr.               *    intersecting it with p1Ptr-p2Ptr.
895               */               */
896    
897              if (parallel) {              if (parallel) {
898                  perp.x = p1Ptr->x + (p2Ptr->y - p1Ptr->y);                  perp.x = p1Ptr->x + (p2Ptr->y - p1Ptr->y);
899                  perp.y = p1Ptr->y - (p2Ptr->x - p1Ptr->x);                  perp.y = p1Ptr->y - (p2Ptr->x - p1Ptr->x);
900                  (void) Intersect(p1Ptr, &perp, &b1, &b2, &poly[2]);                  (void) Intersect(p1Ptr, &perp, &b1, &b2, &poly[2]);
901                  (void) Intersect(p1Ptr, &perp, &newB1, &newB2, &c);                  (void) Intersect(p1Ptr, &perp, &newB1, &newB2, &c);
902                  ShiftLine(p1Ptr, &perp, borderWidth, &shift1);                  ShiftLine(p1Ptr, &perp, borderWidth, &shift1);
903                  shift2.x = shift1.x + (perp.x - p1Ptr->x);                  shift2.x = shift1.x + (perp.x - p1Ptr->x);
904                  shift2.y = shift1.y + (perp.y - p1Ptr->y);                  shift2.y = shift1.y + (perp.y - p1Ptr->y);
905                  (void) Intersect(p1Ptr, p2Ptr, &shift1, &shift2, &poly[3]);                  (void) Intersect(p1Ptr, p2Ptr, &shift1, &shift2, &poly[3]);
906              }              }
907          }          }
908          if (pointsSeen >= 2) {          if (pointsSeen >= 2) {
909              dx = poly[3].x - poly[0].x;              dx = poly[3].x - poly[0].x;
910              dy = poly[3].y - poly[0].y;              dy = poly[3].y - poly[0].y;
911              if (dx > 0) {              if (dx > 0) {
912                  lightOnLeft = (dy <= dx);                  lightOnLeft = (dy <= dx);
913              } else {              } else {
914                  lightOnLeft = (dy < dx);                  lightOnLeft = (dy < dx);
915              }              }
916              if (lightOnLeft ^ (leftRelief == TK_RELIEF_RAISED)) {              if (lightOnLeft ^ (leftRelief == TK_RELIEF_RAISED)) {
917                  gc = borderPtr->lightGC;                  gc = borderPtr->lightGC;
918              } else {              } else {
919                  gc = borderPtr->darkGC;                  gc = borderPtr->darkGC;
920              }              }
921              XFillPolygon(display, drawable, gc, poly, 4, Convex,              XFillPolygon(display, drawable, gc, poly, 4, Convex,
922                      CoordModeOrigin);                      CoordModeOrigin);
923          }          }
924          b1.x = newB1.x;          b1.x = newB1.x;
925          b1.y = newB1.y;          b1.y = newB1.y;
926          b2.x = newB2.x;          b2.x = newB2.x;
927          b2.y = newB2.y;          b2.y = newB2.y;
928          poly[0].x = poly[3].x;          poly[0].x = poly[3].x;
929          poly[0].y = poly[3].y;          poly[0].y = poly[3].y;
930          if (parallel) {          if (parallel) {
931              poly[1].x = c.x;              poly[1].x = c.x;
932              poly[1].y = c.y;              poly[1].y = c.y;
933          } else if (pointsSeen >= 1) {          } else if (pointsSeen >= 1) {
934              poly[1].x = poly[2].x;              poly[1].x = poly[2].x;
935              poly[1].y = poly[2].y;              poly[1].y = poly[2].y;
936          }          }
937          pointsSeen++;          pointsSeen++;
938      }      }
939  }  }
940    
941  /*  /*
942   *----------------------------------------------------------------------   *----------------------------------------------------------------------
943   *   *
944   * Tk_Fill3DRectangle --   * Tk_Fill3DRectangle --
945   *   *
946   *      Fill a rectangular area, supplying a 3D border if desired.   *      Fill a rectangular area, supplying a 3D border if desired.
947   *   *
948   * Results:   * Results:
949   *      None.   *      None.
950   *   *
951   * Side effects:   * Side effects:
952   *      Information gets drawn on the screen.   *      Information gets drawn on the screen.
953   *   *
954   *----------------------------------------------------------------------   *----------------------------------------------------------------------
955   */   */
956    
957  void  void
958  Tk_Fill3DRectangle(tkwin, drawable, border, x, y, width,  Tk_Fill3DRectangle(tkwin, drawable, border, x, y, width,
959          height, borderWidth, relief)          height, borderWidth, relief)
960      Tk_Window tkwin;            /* Window for which border was allocated. */      Tk_Window tkwin;            /* Window for which border was allocated. */
961      Drawable drawable;          /* X window or pixmap in which to draw. */      Drawable drawable;          /* X window or pixmap in which to draw. */
962      Tk_3DBorder border;         /* Token for border to draw. */      Tk_3DBorder border;         /* Token for border to draw. */
963      int x, y, width, height;    /* Outside area of rectangular region. */      int x, y, width, height;    /* Outside area of rectangular region. */
964      int borderWidth;            /* Desired width for border, in      int borderWidth;            /* Desired width for border, in
965                                   * pixels. Border will be *inside* region. */                                   * pixels. Border will be *inside* region. */
966      int relief;                 /* Indicates 3D effect: TK_RELIEF_FLAT,      int relief;                 /* Indicates 3D effect: TK_RELIEF_FLAT,
967                                   * TK_RELIEF_RAISED, or TK_RELIEF_SUNKEN. */                                   * TK_RELIEF_RAISED, or TK_RELIEF_SUNKEN. */
968  {  {
969      register TkBorder *borderPtr = (TkBorder *) border;      register TkBorder *borderPtr = (TkBorder *) border;
970      int doubleBorder;      int doubleBorder;
971    
972      /*      /*
973       * This code is slightly tricky because it only draws the background       * This code is slightly tricky because it only draws the background
974       * in areas not covered by the 3D border. This avoids flashing       * in areas not covered by the 3D border. This avoids flashing
975       * effects on the screen for the border region.       * effects on the screen for the border region.
976       */       */
977        
978      if (relief == TK_RELIEF_FLAT) {      if (relief == TK_RELIEF_FLAT) {
979          borderWidth = 0;          borderWidth = 0;
980      } else {      } else {
981          /*          /*
982           * We need to make this extra check, otherwise we will leave           * We need to make this extra check, otherwise we will leave
983           * garbage in thin frames [Bug: 3596]           * garbage in thin frames [Bug: 3596]
984           */           */
985          if (width < 2*borderWidth) {          if (width < 2*borderWidth) {
986              borderWidth = width/2;              borderWidth = width/2;
987          }          }
988          if (height < 2*borderWidth) {          if (height < 2*borderWidth) {
989              borderWidth = height/2;              borderWidth = height/2;
990          }          }
991      }      }
992      doubleBorder = 2*borderWidth;      doubleBorder = 2*borderWidth;
993    
994      if ((width > doubleBorder) && (height > doubleBorder)) {      if ((width > doubleBorder) && (height > doubleBorder)) {
995          XFillRectangle(Tk_Display(tkwin), drawable, borderPtr->bgGC,          XFillRectangle(Tk_Display(tkwin), drawable, borderPtr->bgGC,
996                  x + borderWidth, y + borderWidth,                  x + borderWidth, y + borderWidth,
997                  (unsigned int) (width - doubleBorder),                  (unsigned int) (width - doubleBorder),
998                  (unsigned int) (height - doubleBorder));                  (unsigned int) (height - doubleBorder));
999      }      }
1000      if (borderWidth) {      if (borderWidth) {
1001          Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width,          Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width,
1002                  height, borderWidth, relief);                  height, borderWidth, relief);
1003      }      }
1004  }  }
1005    
1006  /*  /*
1007   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1008   *   *
1009   * Tk_Fill3DPolygon --   * Tk_Fill3DPolygon --
1010   *   *
1011   *      Fill a polygonal area, supplying a 3D border if desired.   *      Fill a polygonal area, supplying a 3D border if desired.
1012   *   *
1013   * Results:   * Results:
1014   *      None.   *      None.
1015   *   *
1016   * Side effects:   * Side effects:
1017   *      Information gets drawn on the screen.   *      Information gets drawn on the screen.
1018   *   *
1019   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1020   */   */
1021    
1022  void  void
1023  Tk_Fill3DPolygon(tkwin, drawable, border, pointPtr, numPoints,  Tk_Fill3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
1024          borderWidth, leftRelief)          borderWidth, leftRelief)
1025      Tk_Window tkwin;            /* Window for which border was allocated. */      Tk_Window tkwin;            /* Window for which border was allocated. */
1026      Drawable drawable;          /* X window or pixmap in which to draw. */      Drawable drawable;          /* X window or pixmap in which to draw. */
1027      Tk_3DBorder border;         /* Token for border to draw. */      Tk_3DBorder border;         /* Token for border to draw. */
1028      XPoint *pointPtr;           /* Array of points describing      XPoint *pointPtr;           /* Array of points describing
1029                                   * polygon.  All points must be                                   * polygon.  All points must be
1030                                   * absolute (CoordModeOrigin). */                                   * absolute (CoordModeOrigin). */
1031      int numPoints;              /* Number of points at *pointPtr. */      int numPoints;              /* Number of points at *pointPtr. */
1032      int borderWidth;            /* Width of border, measured in      int borderWidth;            /* Width of border, measured in
1033                                   * pixels to the left of the polygon's                                   * pixels to the left of the polygon's
1034                                   * trajectory.   May be negative. */                                   * trajectory.   May be negative. */
1035      int leftRelief;                     /* Indicates 3D effect of left side of      int leftRelief;                     /* Indicates 3D effect of left side of
1036                                   * trajectory relative to right:                                   * trajectory relative to right:
1037                                   * TK_RELIEF_FLAT, TK_RELIEF_RAISED,                                   * TK_RELIEF_FLAT, TK_RELIEF_RAISED,
1038                                   * or TK_RELIEF_SUNKEN. */                                   * or TK_RELIEF_SUNKEN. */
1039  {  {
1040      register TkBorder *borderPtr = (TkBorder *) border;      register TkBorder *borderPtr = (TkBorder *) border;
1041    
1042      XFillPolygon(Tk_Display(tkwin), drawable, borderPtr->bgGC,      XFillPolygon(Tk_Display(tkwin), drawable, borderPtr->bgGC,
1043              pointPtr, numPoints, Complex, CoordModeOrigin);              pointPtr, numPoints, Complex, CoordModeOrigin);
1044      if (leftRelief != TK_RELIEF_FLAT) {      if (leftRelief != TK_RELIEF_FLAT) {
1045          Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,          Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
1046                  borderWidth, leftRelief);                  borderWidth, leftRelief);
1047      }      }
1048  }  }
1049    
1050  /*  /*
1051   *--------------------------------------------------------------   *--------------------------------------------------------------
1052   *   *
1053   * BorderInit --   * BorderInit --
1054   *   *
1055   *      Initialize the structures used for border management.   *      Initialize the structures used for border management.
1056   *   *
1057   * Results:   * Results:
1058   *      None.   *      None.
1059   *   *
1060   * Side effects:   * Side effects:
1061   *      Read the code.   *      Read the code.
1062   *   *
1063   *-------------------------------------------------------------   *-------------------------------------------------------------
1064   */   */
1065    
1066  static void  static void
1067  BorderInit(dispPtr)  BorderInit(dispPtr)
1068       TkDisplay * dispPtr;     /* Used to access thread-specific data. */       TkDisplay * dispPtr;     /* Used to access thread-specific data. */
1069  {  {
1070      dispPtr->borderInit = 1;      dispPtr->borderInit = 1;
1071      Tcl_InitHashTable(&dispPtr->borderTable, TCL_STRING_KEYS);      Tcl_InitHashTable(&dispPtr->borderTable, TCL_STRING_KEYS);
1072  }  }
1073    
1074  /*  /*
1075   *--------------------------------------------------------------   *--------------------------------------------------------------
1076   *   *
1077   * ShiftLine --   * ShiftLine --
1078   *   *
1079   *      Given two points on a line, compute a point on a   *      Given two points on a line, compute a point on a
1080   *      new line that is parallel to the given line and   *      new line that is parallel to the given line and
1081   *      a given distance away from it.   *      a given distance away from it.
1082   *   *
1083   * Results:   * Results:
1084   *      None.   *      None.
1085   *   *
1086   * Side effects:   * Side effects:
1087   *      None.   *      None.
1088   *   *
1089   *--------------------------------------------------------------   *--------------------------------------------------------------
1090   */   */
1091    
1092  static void  static void
1093  ShiftLine(p1Ptr, p2Ptr, distance, p3Ptr)  ShiftLine(p1Ptr, p2Ptr, distance, p3Ptr)
1094      XPoint *p1Ptr;              /* First point on line. */      XPoint *p1Ptr;              /* First point on line. */
1095      XPoint *p2Ptr;              /* Second point on line. */      XPoint *p2Ptr;              /* Second point on line. */
1096      int distance;               /* New line is to be this many      int distance;               /* New line is to be this many
1097                                   * units to the left of original                                   * units to the left of original
1098                                   * line, when looking from p1 to                                   * line, when looking from p1 to
1099                                   * p2.  May be negative. */                                   * p2.  May be negative. */
1100      XPoint *p3Ptr;              /* Store coords of point on new      XPoint *p3Ptr;              /* Store coords of point on new
1101                                   * line here. */                                   * line here. */
1102  {  {
1103      int dx, dy, dxNeg, dyNeg;      int dx, dy, dxNeg, dyNeg;
1104    
1105      /*      /*
1106       * The table below is used for a quick approximation in       * The table below is used for a quick approximation in
1107       * computing the new point.  An index into the table       * computing the new point.  An index into the table
1108       * is 128 times the slope of the original line (the slope       * is 128 times the slope of the original line (the slope
1109       * must always be between 0 and 1).  The value of the table       * must always be between 0 and 1).  The value of the table
1110       * entry is 128 times the amount to displace the new line       * entry is 128 times the amount to displace the new line
1111       * in y for each unit of perpendicular distance.  In other       * in y for each unit of perpendicular distance.  In other
1112       * words, the table maps from the tangent of an angle to       * words, the table maps from the tangent of an angle to
1113       * the inverse of its cosine.  If the slope of the original       * the inverse of its cosine.  If the slope of the original
1114       * line is greater than 1, then the displacement is done in       * line is greater than 1, then the displacement is done in
1115       * x rather than in y.       * x rather than in y.
1116       */       */
1117    
1118      static int shiftTable[129];      static int shiftTable[129];
1119    
1120      /*      /*
1121       * Initialize the table if this is the first time it is       * Initialize the table if this is the first time it is
1122       * used.       * used.
1123       */       */
1124    
1125      if (shiftTable[0] == 0) {      if (shiftTable[0] == 0) {
1126          int i;          int i;
1127          double tangent, cosine;          double tangent, cosine;
1128    
1129          for (i = 0; i <= 128; i++) {          for (i = 0; i <= 128; i++) {
1130              tangent = i/128.0;              tangent = i/128.0;
1131              cosine = 128/cos(atan(tangent)) + .5;              cosine = 128/cos(atan(tangent)) + .5;
1132              shiftTable[i] = (int) cosine;              shiftTable[i] = (int) cosine;
1133          }          }
1134      }      }
1135    
1136      *p3Ptr = *p1Ptr;      *p3Ptr = *p1Ptr;
1137      dx = p2Ptr->x - p1Ptr->x;      dx = p2Ptr->x - p1Ptr->x;
1138      dy = p2Ptr->y - p1Ptr->y;      dy = p2Ptr->y - p1Ptr->y;
1139      if (dy < 0) {      if (dy < 0) {
1140          dyNeg = 1;          dyNeg = 1;
1141          dy = -dy;          dy = -dy;
1142      } else {      } else {
1143          dyNeg = 0;          dyNeg = 0;
1144      }      }
1145      if (dx < 0) {      if (dx < 0) {
1146          dxNeg = 1;          dxNeg = 1;
1147          dx = -dx;          dx = -dx;
1148      } else {      } else {
1149          dxNeg = 0;          dxNeg = 0;
1150      }      }
1151      if (dy <= dx) {      if (dy <= dx) {
1152          dy = ((distance * shiftTable[(dy<<7)/dx]) + 64) >> 7;          dy = ((distance * shiftTable[(dy<<7)/dx]) + 64) >> 7;
1153          if (!dxNeg) {          if (!dxNeg) {
1154              dy = -dy;              dy = -dy;
1155          }          }
1156          p3Ptr->y += dy;          p3Ptr->y += dy;
1157      } else {      } else {
1158          dx = ((distance * shiftTable[(dx<<7)/dy]) + 64) >> 7;          dx = ((distance * shiftTable[(dx<<7)/dy]) + 64) >> 7;
1159          if (dyNeg) {          if (dyNeg) {
1160              dx = -dx;              dx = -dx;
1161          }          }
1162          p3Ptr->x += dx;          p3Ptr->x += dx;
1163      }      }
1164  }  }
1165    
1166  /*  /*
1167   *--------------------------------------------------------------   *--------------------------------------------------------------
1168   *   *
1169   * Intersect --   * Intersect --
1170   *   *
1171   *      Find the intersection point between two lines.   *      Find the intersection point between two lines.
1172   *   *
1173   * Results:   * Results:
1174   *      Under normal conditions 0 is returned and the point   *      Under normal conditions 0 is returned and the point
1175   *      at *iPtr is filled in with the intersection between   *      at *iPtr is filled in with the intersection between
1176   *      the two lines.  If the two lines are parallel, then   *      the two lines.  If the two lines are parallel, then
1177   *      -1 is returned and *iPtr isn't modified.   *      -1 is returned and *iPtr isn't modified.
1178   *   *
1179   * Side effects:   * Side effects:
1180   *      None.   *      None.
1181   *   *
1182   *--------------------------------------------------------------   *--------------------------------------------------------------
1183   */   */
1184    
1185  static int  static int
1186  Intersect(a1Ptr, a2Ptr, b1Ptr, b2Ptr, iPtr)  Intersect(a1Ptr, a2Ptr, b1Ptr, b2Ptr, iPtr)
1187      XPoint *a1Ptr;              /* First point of first line. */      XPoint *a1Ptr;              /* First point of first line. */
1188      XPoint *a2Ptr;              /* Second point of first line. */      XPoint *a2Ptr;              /* Second point of first line. */
1189      XPoint *b1Ptr;              /* First point of second line. */      XPoint *b1Ptr;              /* First point of second line. */
1190      XPoint *b2Ptr;              /* Second point of second line. */      XPoint *b2Ptr;              /* Second point of second line. */
1191      XPoint *iPtr;               /* Filled in with intersection point. */      XPoint *iPtr;               /* Filled in with intersection point. */
1192  {  {
1193      int dxadyb, dxbdya, dxadxb, dyadyb, p, q;      int dxadyb, dxbdya, dxadxb, dyadyb, p, q;
1194    
1195      /*      /*
1196       * The code below is just a straightforward manipulation of two       * The code below is just a straightforward manipulation of two
1197       * equations of the form y = (x-x1)*(y2-y1)/(x2-x1) + y1 to solve       * equations of the form y = (x-x1)*(y2-y1)/(x2-x1) + y1 to solve
1198       * for the x-coordinate of intersection, then the y-coordinate.       * for the x-coordinate of intersection, then the y-coordinate.
1199       */       */
1200    
1201      dxadyb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->y - b1Ptr->y);      dxadyb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->y - b1Ptr->y);
1202      dxbdya = (b2Ptr->x - b1Ptr->x)*(a2Ptr->y - a1Ptr->y);      dxbdya = (b2Ptr->x - b1Ptr->x)*(a2Ptr->y - a1Ptr->y);
1203      dxadxb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->x - b1Ptr->x);      dxadxb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->x - b1Ptr->x);
1204      dyadyb = (a2Ptr->y - a1Ptr->y)*(b2Ptr->y - b1Ptr->y);      dyadyb = (a2Ptr->y - a1Ptr->y)*(b2Ptr->y - b1Ptr->y);
1205    
1206      if (dxadyb == dxbdya) {      if (dxadyb == dxbdya) {
1207          return -1;          return -1;
1208      }      }
1209      p = (a1Ptr->x*dxbdya - b1Ptr->x*dxadyb + (b1Ptr->y - a1Ptr->y)*dxadxb);      p = (a1Ptr->x*dxbdya - b1Ptr->x*dxadyb + (b1Ptr->y - a1Ptr->y)*dxadxb);
1210      q = dxbdya - dxadyb;      q = dxbdya - dxadyb;
1211      if (q < 0) {      if (q < 0) {
1212          p = -p;          p = -p;
1213          q = -q;          q = -q;
1214      }      }
1215      if (p < 0) {      if (p < 0) {
1216          iPtr->x = - ((-p + q/2)/q);          iPtr->x = - ((-p + q/2)/q);
1217      } else {      } else {
1218          iPtr->x = (p + q/2)/q;          iPtr->x = (p + q/2)/q;
1219      }      }
1220      p = (a1Ptr->y*dxadyb - b1Ptr->y*dxbdya + (b1Ptr->x - a1Ptr->x)*dyadyb);      p = (a1Ptr->y*dxadyb - b1Ptr->y*dxbdya + (b1Ptr->x - a1Ptr->x)*dyadyb);
1221      q = dxadyb - dxbdya;      q = dxadyb - dxbdya;
1222      if (q < 0) {      if (q < 0) {
1223          p = -p;          p = -p;
1224          q = -q;          q = -q;
1225      }      }
1226      if (p < 0) {      if (p < 0) {
1227          iPtr->y = - ((-p + q/2)/q);          iPtr->y = - ((-p + q/2)/q);
1228      } else {      } else {
1229          iPtr->y = (p + q/2)/q;          iPtr->y = (p + q/2)/q;
1230      }      }
1231      return 0;      return 0;
1232  }  }
1233    
1234  /*  /*
1235   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1236   *   *
1237   * Tk_Get3DBorderFromObj --   * Tk_Get3DBorderFromObj --
1238   *   *
1239   *      Returns the border referred to by a Tcl object.  The border must   *      Returns the border referred to by a Tcl object.  The border must
1240   *      already have been allocated via a call to Tk_Alloc3DBorderFromObj   *      already have been allocated via a call to Tk_Alloc3DBorderFromObj
1241   *      or Tk_Get3DBorder.   *      or Tk_Get3DBorder.
1242   *   *
1243   * Results:   * Results:
1244   *      Returns the Tk_3DBorder that matches the tkwin and the string rep   *      Returns the Tk_3DBorder that matches the tkwin and the string rep
1245   *      of the name of the border given in objPtr.   *      of the name of the border given in objPtr.
1246   *   *
1247   * Side effects:   * Side effects:
1248   *      If the object is not already a border, the conversion will free   *      If the object is not already a border, the conversion will free
1249   *      any old internal representation.   *      any old internal representation.
1250   *   *
1251   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1252   */   */
1253    
1254  Tk_3DBorder  Tk_3DBorder
1255  Tk_Get3DBorderFromObj(tkwin, objPtr)  Tk_Get3DBorderFromObj(tkwin, objPtr)
1256      Tk_Window tkwin;      Tk_Window tkwin;
1257      Tcl_Obj *objPtr;            /* The object whose string value selects      Tcl_Obj *objPtr;            /* The object whose string value selects
1258                                   * a border. */                                   * a border. */
1259  {  {
1260      TkBorder *borderPtr = NULL;      TkBorder *borderPtr = NULL;
1261      Tcl_HashEntry *hashPtr;      Tcl_HashEntry *hashPtr;
1262      TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;      TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
1263    
1264      if (objPtr->typePtr != &borderObjType) {      if (objPtr->typePtr != &borderObjType) {
1265          InitBorderObj(objPtr);          InitBorderObj(objPtr);
1266      }      }
1267    
1268      borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;      borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;
1269      if (borderPtr != NULL) {      if (borderPtr != NULL) {
1270          if ((borderPtr->resourceRefCount > 0)          if ((borderPtr->resourceRefCount > 0)
1271                  && (Tk_Screen(tkwin) == borderPtr->screen)                  && (Tk_Screen(tkwin) == borderPtr->screen)
1272                  && (Tk_Colormap(tkwin) == borderPtr->colormap)) {                  && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
1273              /*              /*
1274               * The object already points to the right border structure.               * The object already points to the right border structure.
1275               * Just return it.               * Just return it.
1276               */               */
1277    
1278              return (Tk_3DBorder) borderPtr;              return (Tk_3DBorder) borderPtr;
1279          }          }
1280          hashPtr = borderPtr->hashPtr;          hashPtr = borderPtr->hashPtr;
1281          FreeBorderObjProc(objPtr);          FreeBorderObjProc(objPtr);
1282      } else {      } else {
1283          hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable,          hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable,
1284                  Tcl_GetString(objPtr));                  Tcl_GetString(objPtr));
1285          if (hashPtr == NULL) {          if (hashPtr == NULL) {
1286              goto error;              goto error;
1287          }          }
1288      }      }
1289    
1290      /*      /*
1291       * At this point we've got a hash table entry, off of which hang       * At this point we've got a hash table entry, off of which hang
1292       * one or more  TkBorder structures.  See if any of them will work.       * one or more  TkBorder structures.  See if any of them will work.
1293       */       */
1294    
1295      for (borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);      for (borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);
1296              (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {              (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {
1297          if ((Tk_Screen(tkwin) == borderPtr->screen)          if ((Tk_Screen(tkwin) == borderPtr->screen)
1298                  && (Tk_Colormap(tkwin) == borderPtr->colormap)) {                  && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
1299              objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;              objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;
1300              borderPtr->objRefCount++;              borderPtr->objRefCount++;
1301              return (Tk_3DBorder) borderPtr;              return (Tk_3DBorder) borderPtr;
1302          }          }
1303      }      }
1304    
1305      error:      error:
1306      panic("Tk_Get3DBorderFromObj called with non-existent border!");      panic("Tk_Get3DBorderFromObj called with non-existent border!");
1307      /*      /*
1308       * The following code isn't reached; it's just there to please compilers.       * The following code isn't reached; it's just there to please compilers.
1309       */       */
1310      return NULL;      return NULL;
1311  }  }
1312    
1313  /*  /*
1314   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1315   *   *
1316   * InitBorderObj --   * InitBorderObj --
1317   *   *
1318   *      Attempt to generate a border internal form for the Tcl object   *      Attempt to generate a border internal form for the Tcl object
1319   *      "objPtr".   *      "objPtr".
1320   *   *
1321   * Results:   * Results:
1322   *      The return value is a standard Tcl result. If an error occurs during   *      The return value is a standard Tcl result. If an error occurs during
1323   *      conversion, an error message is left in the interpreter's result   *      conversion, an error message is left in the interpreter's result
1324   *      unless "interp" is NULL.   *      unless "interp" is NULL.
1325   *   *
1326   * Side effects:   * Side effects:
1327   *      If no error occurs, a blank internal format for a border value   *      If no error occurs, a blank internal format for a border value
1328   *      is intialized. The final form cannot be done without a Tk_Window.   *      is intialized. The final form cannot be done without a Tk_Window.
1329   *   *
1330   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1331   */   */
1332    
1333  static void  static void
1334  InitBorderObj(objPtr)  InitBorderObj(objPtr)
1335      Tcl_Obj *objPtr;            /* The object to convert. */      Tcl_Obj *objPtr;            /* The object to convert. */
1336  {  {
1337      Tcl_ObjType *typePtr;      Tcl_ObjType *typePtr;
1338    
1339      /*      /*
1340       * Free the old internalRep before setting the new one.       * Free the old internalRep before setting the new one.
1341       */       */
1342    
1343      Tcl_GetString(objPtr);      Tcl_GetString(objPtr);
1344      typePtr = objPtr->typePtr;      typePtr = objPtr->typePtr;
1345      if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {      if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
1346          (*typePtr->freeIntRepProc)(objPtr);          (*typePtr->freeIntRepProc)(objPtr);
1347      }      }
1348      objPtr->typePtr = &borderObjType;      objPtr->typePtr = &borderObjType;
1349      objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;      objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
1350  }  }
1351    
1352  /*  /*
1353   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1354   *   *
1355   * TkDebugBorder --   * TkDebugBorder --
1356   *   *
1357   *      This procedure returns debugging information about a border.   *      This procedure returns debugging information about a border.
1358   *   *
1359   * Results:   * Results:
1360   *      The return value is a list with one sublist for each TkBorder   *      The return value is a list with one sublist for each TkBorder
1361   *      corresponding to "name".  Each sublist has two elements that   *      corresponding to "name".  Each sublist has two elements that
1362   *      contain the resourceRefCount and objRefCount fields from the   *      contain the resourceRefCount and objRefCount fields from the
1363   *      TkBorder structure.   *      TkBorder structure.
1364   *   *
1365   * Side effects:   * Side effects:
1366   *      None.   *      None.
1367   *   *
1368   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1369   */   */
1370    
1371  Tcl_Obj *  Tcl_Obj *
1372  TkDebugBorder(tkwin, name)  TkDebugBorder(tkwin, name)
1373      Tk_Window tkwin;            /* The window in which the border will be      Tk_Window tkwin;            /* The window in which the border will be
1374                                   * used (not currently used). */                                   * used (not currently used). */
1375      char *name;                 /* Name of the desired color. */      char *name;                 /* Name of the desired color. */
1376  {  {
1377      TkBorder *borderPtr;      TkBorder *borderPtr;
1378      Tcl_HashEntry *hashPtr;      Tcl_HashEntry *hashPtr;
1379      Tcl_Obj *resultPtr, *objPtr;      Tcl_Obj *resultPtr, *objPtr;
1380      TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;      TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
1381    
1382      resultPtr = Tcl_NewObj();      resultPtr = Tcl_NewObj();
1383      hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, name);      hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, name);
1384      if (hashPtr != NULL) {      if (hashPtr != NULL) {
1385          borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);          borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);
1386          if (borderPtr == NULL) {          if (borderPtr == NULL) {
1387              panic("TkDebugBorder found empty hash table entry");              panic("TkDebugBorder found empty hash table entry");
1388          }          }
1389          for ( ; (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {          for ( ; (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {
1390              objPtr = Tcl_NewObj();              objPtr = Tcl_NewObj();
1391              Tcl_ListObjAppendElement(NULL, objPtr,              Tcl_ListObjAppendElement(NULL, objPtr,
1392                      Tcl_NewIntObj(borderPtr->resourceRefCount));                      Tcl_NewIntObj(borderPtr->resourceRefCount));
1393              Tcl_ListObjAppendElement(NULL, objPtr,              Tcl_ListObjAppendElement(NULL, objPtr,
1394                      Tcl_NewIntObj(borderPtr->objRefCount));                      Tcl_NewIntObj(borderPtr->objRefCount));
1395              Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);              Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
1396          }          }
1397      }      }
1398      return resultPtr;      return resultPtr;
1399  }  }
1400    
1401  /* End of tk3d.c */  /* End of tk3d.c */

Legend:
Removed from v.69  
changed lines
  Added in v.98

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25