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

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

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

projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkcanvtext.c revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkcanvtext.c revision 220 by dashley, Sun Jul 22 15:58:07 2018 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkCanvText.c --   * tkCanvText.c --
5   *   *
6   *      This file implements text items for canvas widgets.   *      This file implements text items for canvas widgets.
7   *   *
8   * Copyright (c) 1991-1994 The Regents of the University of California.   * Copyright (c) 1991-1994 The Regents of the University of California.
9   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
10   *   *
11   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
12   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13   *   *
14   * RCS: @(#) $Id: tkcanvtext.c,v 1.1.1.1 2001/06/13 04:57:44 dtashley Exp $   * RCS: @(#) $Id: tkcanvtext.c,v 1.1.1.1 2001/06/13 04:57:44 dtashley Exp $
15   */   */
16    
17  #include <stdio.h>  #include <stdio.h>
18  #include "tkInt.h"  #include "tkInt.h"
19  #include "tkCanvas.h"  #include "tkCanvas.h"
20  #include "tkPort.h"  #include "tkPort.h"
21  #include "default.h"  #include "default.h"
22    
23  /*  /*
24   * The structure below defines the record for each text item.   * The structure below defines the record for each text item.
25   */   */
26    
27  typedef struct TextItem  {  typedef struct TextItem  {
28      Tk_Item header;             /* Generic stuff that's the same for all      Tk_Item header;             /* Generic stuff that's the same for all
29                                   * types.  MUST BE FIRST IN STRUCTURE. */                                   * types.  MUST BE FIRST IN STRUCTURE. */
30      Tk_CanvasTextInfo *textInfoPtr;      Tk_CanvasTextInfo *textInfoPtr;
31                                  /* Pointer to a structure containing                                  /* Pointer to a structure containing
32                                   * information about the selection and                                   * information about the selection and
33                                   * insertion cursor.  The structure is owned                                   * insertion cursor.  The structure is owned
34                                   * by (and shared with) the generic canvas                                   * by (and shared with) the generic canvas
35                                   * code. */                                   * code. */
36      /*      /*
37       * Fields that are set by widget commands other than "configure".       * Fields that are set by widget commands other than "configure".
38       */       */
39            
40      double x, y;                /* Positioning point for text. */      double x, y;                /* Positioning point for text. */
41      int insertPos;              /* Character index of character just before      int insertPos;              /* Character index of character just before
42                                   * which the insertion cursor is displayed. */                                   * which the insertion cursor is displayed. */
43    
44      /*      /*
45       * Configuration settings that are updated by Tk_ConfigureWidget.       * Configuration settings that are updated by Tk_ConfigureWidget.
46       */       */
47    
48      Tk_Anchor anchor;           /* Where to anchor text relative to (x,y). */      Tk_Anchor anchor;           /* Where to anchor text relative to (x,y). */
49      Tk_TSOffset tsoffset;      Tk_TSOffset tsoffset;
50      XColor *color;              /* Color for text. */      XColor *color;              /* Color for text. */
51      XColor *activeColor;        /* Color for text. */      XColor *activeColor;        /* Color for text. */
52      XColor *disabledColor;      /* Color for text. */      XColor *disabledColor;      /* Color for text. */
53      Tk_Font tkfont;             /* Font for drawing text. */      Tk_Font tkfont;             /* Font for drawing text. */
54      Tk_Justify justify;         /* Justification mode for text. */      Tk_Justify justify;         /* Justification mode for text. */
55      Pixmap stipple;             /* Stipple bitmap for text, or None. */      Pixmap stipple;             /* Stipple bitmap for text, or None. */
56      Pixmap activeStipple;       /* Stipple bitmap for text, or None. */      Pixmap activeStipple;       /* Stipple bitmap for text, or None. */
57      Pixmap disabledStipple;     /* Stipple bitmap for text, or None. */      Pixmap disabledStipple;     /* Stipple bitmap for text, or None. */
58      char *text;                 /* Text for item (malloc-ed). */      char *text;                 /* Text for item (malloc-ed). */
59      int width;                  /* Width of lines for word-wrap, pixels.      int width;                  /* Width of lines for word-wrap, pixels.
60                                   * Zero means no word-wrap. */                                   * Zero means no word-wrap. */
61    
62      /*      /*
63       * Fields whose values are derived from the current values of the       * Fields whose values are derived from the current values of the
64       * configuration settings above.       * configuration settings above.
65       */       */
66    
67      int numChars;               /* Length of text in characters. */      int numChars;               /* Length of text in characters. */
68      int numBytes;               /* Length of text in bytes. */      int numBytes;               /* Length of text in bytes. */
69      Tk_TextLayout textLayout;   /* Cached text layout information. */      Tk_TextLayout textLayout;   /* Cached text layout information. */
70      int leftEdge;               /* Pixel location of the left edge of the      int leftEdge;               /* Pixel location of the left edge of the
71                                   * text item; where the left border of the                                   * text item; where the left border of the
72                                   * text layout is drawn. */                                   * text layout is drawn. */
73      int rightEdge;              /* Pixel just to right of right edge of      int rightEdge;              /* Pixel just to right of right edge of
74                                   * area of text item.  Used for selecting up                                   * area of text item.  Used for selecting up
75                                   * to end of line. */                                   * to end of line. */
76      GC gc;                      /* Graphics context for drawing text. */      GC gc;                      /* Graphics context for drawing text. */
77      GC selTextGC;               /* Graphics context for selected text. */      GC selTextGC;               /* Graphics context for selected text. */
78      GC cursorOffGC;             /* If not None, this gives a graphics context      GC cursorOffGC;             /* If not None, this gives a graphics context
79                                   * to use to draw the insertion cursor when                                   * to use to draw the insertion cursor when
80                                   * it's off.  Used if the selection and                                   * it's off.  Used if the selection and
81                                   * insertion cursor colors are the same.  */                                   * insertion cursor colors are the same.  */
82  } TextItem;  } TextItem;
83    
84  /*  /*
85   * Information used for parsing configuration specs:   * Information used for parsing configuration specs:
86   */   */
87    
88  static Tk_CustomOption stateOption = {  static Tk_CustomOption stateOption = {
89      (Tk_OptionParseProc *) TkStateParseProc,      (Tk_OptionParseProc *) TkStateParseProc,
90      TkStatePrintProc, (ClientData) 2      TkStatePrintProc, (ClientData) 2
91  };  };
92  static Tk_CustomOption tagsOption = {  static Tk_CustomOption tagsOption = {
93      (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,      (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
94      Tk_CanvasTagsPrintProc, (ClientData) NULL      Tk_CanvasTagsPrintProc, (ClientData) NULL
95  };  };
96  static Tk_CustomOption offsetOption = {  static Tk_CustomOption offsetOption = {
97      (Tk_OptionParseProc *) TkOffsetParseProc,      (Tk_OptionParseProc *) TkOffsetParseProc,
98      TkOffsetPrintProc, (ClientData) (TK_OFFSET_RELATIVE)      TkOffsetPrintProc, (ClientData) (TK_OFFSET_RELATIVE)
99  };  };
100    
101  static Tk_ConfigSpec configSpecs[] = {  static Tk_ConfigSpec configSpecs[] = {
102      {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,      {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
103          (char *) NULL, Tk_Offset(TextItem, activeColor), TK_CONFIG_NULL_OK},          (char *) NULL, Tk_Offset(TextItem, activeColor), TK_CONFIG_NULL_OK},
104      {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,      {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
105          (char *) NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK},          (char *) NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK},
106      {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,      {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
107          "center", Tk_Offset(TextItem, anchor),          "center", Tk_Offset(TextItem, anchor),
108          TK_CONFIG_DONT_SET_DEFAULT},          TK_CONFIG_DONT_SET_DEFAULT},
109      {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,      {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
110          (char *) NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK},          (char *) NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK},
111      {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,      {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
112          (char *) NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK},          (char *) NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK},
113      {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,      {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
114          "black", Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK},          "black", Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK},
115      {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,      {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
116          DEF_CANVTEXT_FONT, Tk_Offset(TextItem, tkfont), 0},          DEF_CANVTEXT_FONT, Tk_Offset(TextItem, tkfont), 0},
117      {TK_CONFIG_JUSTIFY, "-justify", (char *) NULL, (char *) NULL,      {TK_CONFIG_JUSTIFY, "-justify", (char *) NULL, (char *) NULL,
118          "left", Tk_Offset(TextItem, justify),          "left", Tk_Offset(TextItem, justify),
119          TK_CONFIG_DONT_SET_DEFAULT},          TK_CONFIG_DONT_SET_DEFAULT},
120      {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
121          "0,0", Tk_Offset(TextItem, tsoffset),          "0,0", Tk_Offset(TextItem, tsoffset),
122          TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},          TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
123      {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
124          (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,          (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
125          &stateOption},          &stateOption},
126      {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,      {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
127          (char *) NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK},          (char *) NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK},
128      {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
129          (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},          (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
130      {TK_CONFIG_STRING, "-text", (char *) NULL, (char *) NULL,      {TK_CONFIG_STRING, "-text", (char *) NULL, (char *) NULL,
131          "", Tk_Offset(TextItem, text), 0},          "", Tk_Offset(TextItem, text), 0},
132      {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,      {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
133          "0", Tk_Offset(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT},          "0", Tk_Offset(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT},
134      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
135          (char *) NULL, 0, 0}          (char *) NULL, 0, 0}
136  };  };
137    
138  /*  /*
139   * Prototypes for procedures defined in this file:   * Prototypes for procedures defined in this file:
140   */   */
141    
142  static void             ComputeTextBbox _ANSI_ARGS_((Tk_Canvas canvas,  static void             ComputeTextBbox _ANSI_ARGS_((Tk_Canvas canvas,
143                              TextItem *textPtr));                              TextItem *textPtr));
144  static int              ConfigureText _ANSI_ARGS_((Tcl_Interp *interp,  static int              ConfigureText _ANSI_ARGS_((Tcl_Interp *interp,
145                              Tk_Canvas canvas, Tk_Item *itemPtr, int argc,                              Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
146                              Tcl_Obj *CONST argv[], int flags));                              Tcl_Obj *CONST argv[], int flags));
147  static int              CreateText _ANSI_ARGS_((Tcl_Interp *interp,  static int              CreateText _ANSI_ARGS_((Tcl_Interp *interp,
148                              Tk_Canvas canvas, struct Tk_Item *itemPtr,                              Tk_Canvas canvas, struct Tk_Item *itemPtr,
149                              int argc, Tcl_Obj *CONST argv[]));                              int argc, Tcl_Obj *CONST argv[]));
150  static void             DeleteText _ANSI_ARGS_((Tk_Canvas canvas,  static void             DeleteText _ANSI_ARGS_((Tk_Canvas canvas,
151                              Tk_Item *itemPtr, Display *display));                              Tk_Item *itemPtr, Display *display));
152  static void             DisplayCanvText _ANSI_ARGS_((Tk_Canvas canvas,  static void             DisplayCanvText _ANSI_ARGS_((Tk_Canvas canvas,
153                              Tk_Item *itemPtr, Display *display, Drawable dst,                              Tk_Item *itemPtr, Display *display, Drawable dst,
154                              int x, int y, int width, int height));                              int x, int y, int width, int height));
155  static int              GetSelText _ANSI_ARGS_((Tk_Canvas canvas,  static int              GetSelText _ANSI_ARGS_((Tk_Canvas canvas,
156                              Tk_Item *itemPtr, int offset, char *buffer,                              Tk_Item *itemPtr, int offset, char *buffer,
157                              int maxBytes));                              int maxBytes));
158  static int              GetTextIndex _ANSI_ARGS_((Tcl_Interp *interp,  static int              GetTextIndex _ANSI_ARGS_((Tcl_Interp *interp,
159                              Tk_Canvas canvas, Tk_Item *itemPtr,                              Tk_Canvas canvas, Tk_Item *itemPtr,
160                              Tcl_Obj *obj, int *indexPtr));                              Tcl_Obj *obj, int *indexPtr));
161  static void             ScaleText _ANSI_ARGS_((Tk_Canvas canvas,  static void             ScaleText _ANSI_ARGS_((Tk_Canvas canvas,
162                              Tk_Item *itemPtr, double originX, double originY,                              Tk_Item *itemPtr, double originX, double originY,
163                              double scaleX, double scaleY));                              double scaleX, double scaleY));
164  static void             SetTextCursor _ANSI_ARGS_((Tk_Canvas canvas,  static void             SetTextCursor _ANSI_ARGS_((Tk_Canvas canvas,
165                              Tk_Item *itemPtr, int index));                              Tk_Item *itemPtr, int index));
166  static int              TextCoords _ANSI_ARGS_((Tcl_Interp *interp,  static int              TextCoords _ANSI_ARGS_((Tcl_Interp *interp,
167                              Tk_Canvas canvas, Tk_Item *itemPtr,                              Tk_Canvas canvas, Tk_Item *itemPtr,
168                              int argc, Tcl_Obj *CONST argv[]));                              int argc, Tcl_Obj *CONST argv[]));
169  static void             TextDeleteChars _ANSI_ARGS_((Tk_Canvas canvas,  static void             TextDeleteChars _ANSI_ARGS_((Tk_Canvas canvas,
170                              Tk_Item *itemPtr, int first, int last));                              Tk_Item *itemPtr, int first, int last));
171  static void             TextInsert _ANSI_ARGS_((Tk_Canvas canvas,  static void             TextInsert _ANSI_ARGS_((Tk_Canvas canvas,
172                              Tk_Item *itemPtr, int beforeThis, char *string));                              Tk_Item *itemPtr, int beforeThis, char *string));
173  static int              TextToArea _ANSI_ARGS_((Tk_Canvas canvas,  static int              TextToArea _ANSI_ARGS_((Tk_Canvas canvas,
174                              Tk_Item *itemPtr, double *rectPtr));                              Tk_Item *itemPtr, double *rectPtr));
175  static double           TextToPoint _ANSI_ARGS_((Tk_Canvas canvas,  static double           TextToPoint _ANSI_ARGS_((Tk_Canvas canvas,
176                              Tk_Item *itemPtr, double *pointPtr));                              Tk_Item *itemPtr, double *pointPtr));
177  static int              TextToPostscript _ANSI_ARGS_((Tcl_Interp *interp,  static int              TextToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
178                              Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));                              Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
179  static void             TranslateText _ANSI_ARGS_((Tk_Canvas canvas,  static void             TranslateText _ANSI_ARGS_((Tk_Canvas canvas,
180                              Tk_Item *itemPtr, double deltaX, double deltaY));                              Tk_Item *itemPtr, double deltaX, double deltaY));
181    
182  /*  /*
183   * The structures below defines the rectangle and oval item types   * The structures below defines the rectangle and oval item types
184   * by means of procedures that can be invoked by generic item code.   * by means of procedures that can be invoked by generic item code.
185   */   */
186    
187  Tk_ItemType tkTextType = {  Tk_ItemType tkTextType = {
188      "text",                     /* name */      "text",                     /* name */
189      sizeof(TextItem),           /* itemSize */      sizeof(TextItem),           /* itemSize */
190      CreateText,                 /* createProc */      CreateText,                 /* createProc */
191      configSpecs,                /* configSpecs */      configSpecs,                /* configSpecs */
192      ConfigureText,              /* configureProc */      ConfigureText,              /* configureProc */
193      TextCoords,                 /* coordProc */      TextCoords,                 /* coordProc */
194      DeleteText,                 /* deleteProc */      DeleteText,                 /* deleteProc */
195      DisplayCanvText,            /* displayProc */      DisplayCanvText,            /* displayProc */
196      TK_CONFIG_OBJS,             /* flags */      TK_CONFIG_OBJS,             /* flags */
197      TextToPoint,                /* pointProc */      TextToPoint,                /* pointProc */
198      TextToArea,                 /* areaProc */      TextToArea,                 /* areaProc */
199      TextToPostscript,           /* postscriptProc */      TextToPostscript,           /* postscriptProc */
200      ScaleText,                  /* scaleProc */      ScaleText,                  /* scaleProc */
201      TranslateText,              /* translateProc */      TranslateText,              /* translateProc */
202      (Tk_ItemIndexProc *) GetTextIndex,/* indexProc */      (Tk_ItemIndexProc *) GetTextIndex,/* indexProc */
203      SetTextCursor,              /* icursorProc */      SetTextCursor,              /* icursorProc */
204      GetSelText,                 /* selectionProc */      GetSelText,                 /* selectionProc */
205      TextInsert,                 /* insertProc */      TextInsert,                 /* insertProc */
206      TextDeleteChars,            /* dTextProc */      TextDeleteChars,            /* dTextProc */
207      (Tk_ItemType *) NULL,       /* nextPtr */      (Tk_ItemType *) NULL,       /* nextPtr */
208  };  };
209    
210  /*  /*
211   *--------------------------------------------------------------   *--------------------------------------------------------------
212   *   *
213   * CreateText --   * CreateText --
214   *   *
215   *      This procedure is invoked to create a new text item   *      This procedure is invoked to create a new text item
216   *      in a canvas.   *      in a canvas.
217   *   *
218   * Results:   * Results:
219   *      A standard Tcl return value.  If an error occurred in   *      A standard Tcl return value.  If an error occurred in
220   *      creating the item then an error message is left in   *      creating the item then an error message is left in
221   *      the interp's result;  in this case itemPtr is left uninitialized   *      the interp's result;  in this case itemPtr is left uninitialized
222   *      so it can be safely freed by the caller.   *      so it can be safely freed by the caller.
223   *   *
224   * Side effects:   * Side effects:
225   *      A new text item is created.   *      A new text item is created.
226   *   *
227   *--------------------------------------------------------------   *--------------------------------------------------------------
228   */   */
229    
230  static int  static int
231  CreateText(interp, canvas, itemPtr, argc, argv)  CreateText(interp, canvas, itemPtr, argc, argv)
232      Tcl_Interp *interp;         /* Interpreter for error reporting. */      Tcl_Interp *interp;         /* Interpreter for error reporting. */
233      Tk_Canvas canvas;           /* Canvas to hold new item. */      Tk_Canvas canvas;           /* Canvas to hold new item. */
234      Tk_Item *itemPtr;           /* Record to hold new item; header has been      Tk_Item *itemPtr;           /* Record to hold new item; header has been
235                                   * initialized by caller. */                                   * initialized by caller. */
236      int argc;                   /* Number of arguments in argv. */      int argc;                   /* Number of arguments in argv. */
237      Tcl_Obj *CONST argv[];      /* Arguments describing rectangle. */      Tcl_Obj *CONST argv[];      /* Arguments describing rectangle. */
238  {  {
239      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
240      int i;      int i;
241    
242      if (argc==1) {      if (argc==1) {
243          i = 1;          i = 1;
244      } else {      } else {
245          char *arg = Tcl_GetStringFromObj(argv[1], NULL);          char *arg = Tcl_GetStringFromObj(argv[1], NULL);
246          if ((argc>1) && (arg[0] == '-')          if ((argc>1) && (arg[0] == '-')
247                  && (arg[1] >= 'a') && (arg[1] <= 'z')) {                  && (arg[1] >= 'a') && (arg[1] <= 'z')) {
248              i = 1;              i = 1;
249          } else {          } else {
250              i = 2;              i = 2;
251          }          }
252      }      }
253    
254      if (argc < i) {      if (argc < i) {
255          Tcl_AppendResult(interp, "wrong # args: should be \"",          Tcl_AppendResult(interp, "wrong # args: should be \"",
256                  Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",                  Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
257                  itemPtr->typePtr->name, " x y ?options?\"", (char *) NULL);                  itemPtr->typePtr->name, " x y ?options?\"", (char *) NULL);
258          return TCL_ERROR;          return TCL_ERROR;
259      }      }
260    
261      /*      /*
262       * Carry out initialization that is needed in order to clean up after       * Carry out initialization that is needed in order to clean up after
263       * errors during the the remainder of this procedure.       * errors during the the remainder of this procedure.
264       */       */
265    
266      textPtr->textInfoPtr = Tk_CanvasGetTextInfo(canvas);      textPtr->textInfoPtr = Tk_CanvasGetTextInfo(canvas);
267    
268      textPtr->insertPos  = 0;      textPtr->insertPos  = 0;
269    
270      textPtr->anchor     = TK_ANCHOR_CENTER;      textPtr->anchor     = TK_ANCHOR_CENTER;
271      textPtr->tsoffset.flags = 0;      textPtr->tsoffset.flags = 0;
272      textPtr->tsoffset.xoffset = 0;      textPtr->tsoffset.xoffset = 0;
273      textPtr->tsoffset.yoffset = 0;      textPtr->tsoffset.yoffset = 0;
274      textPtr->color      = NULL;      textPtr->color      = NULL;
275      textPtr->activeColor = NULL;      textPtr->activeColor = NULL;
276      textPtr->disabledColor = NULL;      textPtr->disabledColor = NULL;
277      textPtr->tkfont     = NULL;      textPtr->tkfont     = NULL;
278      textPtr->justify    = TK_JUSTIFY_LEFT;      textPtr->justify    = TK_JUSTIFY_LEFT;
279      textPtr->stipple    = None;      textPtr->stipple    = None;
280      textPtr->activeStipple = None;      textPtr->activeStipple = None;
281      textPtr->disabledStipple = None;      textPtr->disabledStipple = None;
282      textPtr->text       = NULL;      textPtr->text       = NULL;
283      textPtr->width      = 0;      textPtr->width      = 0;
284    
285      textPtr->numChars   = 0;      textPtr->numChars   = 0;
286      textPtr->numBytes   = 0;      textPtr->numBytes   = 0;
287      textPtr->textLayout = NULL;      textPtr->textLayout = NULL;
288      textPtr->leftEdge   = 0;      textPtr->leftEdge   = 0;
289      textPtr->rightEdge  = 0;      textPtr->rightEdge  = 0;
290      textPtr->gc         = None;      textPtr->gc         = None;
291      textPtr->selTextGC  = None;      textPtr->selTextGC  = None;
292      textPtr->cursorOffGC = None;      textPtr->cursorOffGC = None;
293    
294      /*      /*
295       * Process the arguments to fill in the item record.       * Process the arguments to fill in the item record.
296       */       */
297    
298      if ((TextCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {      if ((TextCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
299          goto error;          goto error;
300      }      }
301      if (ConfigureText(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {      if (ConfigureText(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
302          return TCL_OK;          return TCL_OK;
303      }      }
304    
305      error:      error:
306      DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));      DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
307      return TCL_ERROR;      return TCL_ERROR;
308  }  }
309    
310  /*  /*
311   *--------------------------------------------------------------   *--------------------------------------------------------------
312   *   *
313   * TextCoords --   * TextCoords --
314   *   *
315   *      This procedure is invoked to process the "coords" widget   *      This procedure is invoked to process the "coords" widget
316   *      command on text items.  See the user documentation for   *      command on text items.  See the user documentation for
317   *      details on what it does.   *      details on what it does.
318   *   *
319   * Results:   * Results:
320   *      Returns TCL_OK or TCL_ERROR, and sets the interp's result.   *      Returns TCL_OK or TCL_ERROR, and sets the interp's result.
321   *   *
322   * Side effects:   * Side effects:
323   *      The coordinates for the given item may be changed.   *      The coordinates for the given item may be changed.
324   *   *
325   *--------------------------------------------------------------   *--------------------------------------------------------------
326   */   */
327    
328  static int  static int
329  TextCoords(interp, canvas, itemPtr, argc, argv)  TextCoords(interp, canvas, itemPtr, argc, argv)
330      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
331      Tk_Canvas canvas;           /* Canvas containing item. */      Tk_Canvas canvas;           /* Canvas containing item. */
332      Tk_Item *itemPtr;           /* Item whose coordinates are to be read or      Tk_Item *itemPtr;           /* Item whose coordinates are to be read or
333                                   * modified. */                                   * modified. */
334      int argc;                   /* Number of coordinates supplied in argv. */      int argc;                   /* Number of coordinates supplied in argv. */
335      Tcl_Obj *CONST argv[];      /* Array of coordinates: x1, y1, x2, y2, ... */      Tcl_Obj *CONST argv[];      /* Array of coordinates: x1, y1, x2, y2, ... */
336  {  {
337      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
338    
339      if (argc == 0) {      if (argc == 0) {
340          Tcl_Obj *obj = Tcl_NewObj();          Tcl_Obj *obj = Tcl_NewObj();
341          Tcl_Obj *subobj = Tcl_NewDoubleObj(textPtr->x);          Tcl_Obj *subobj = Tcl_NewDoubleObj(textPtr->x);
342          Tcl_ListObjAppendElement(interp, obj, subobj);          Tcl_ListObjAppendElement(interp, obj, subobj);
343          subobj = Tcl_NewDoubleObj(textPtr->y);          subobj = Tcl_NewDoubleObj(textPtr->y);
344          Tcl_ListObjAppendElement(interp, obj, subobj);          Tcl_ListObjAppendElement(interp, obj, subobj);
345          Tcl_SetObjResult(interp, obj);          Tcl_SetObjResult(interp, obj);
346      } else if (argc < 3) {      } else if (argc < 3) {
347          if (argc==1) {          if (argc==1) {
348              if (Tcl_ListObjGetElements(interp, argv[0], &argc,              if (Tcl_ListObjGetElements(interp, argv[0], &argc,
349                      (Tcl_Obj ***) &argv) != TCL_OK) {                      (Tcl_Obj ***) &argv) != TCL_OK) {
350                  return TCL_ERROR;                  return TCL_ERROR;
351              } else if (argc != 2) {              } else if (argc != 2) {
352                  char buf[64 + TCL_INTEGER_SPACE];                  char buf[64 + TCL_INTEGER_SPACE];
353    
354                  sprintf(buf, "wrong # coordinates: expected 2, got %d", argc);                  sprintf(buf, "wrong # coordinates: expected 2, got %d", argc);
355                  Tcl_SetResult(interp, buf, TCL_VOLATILE);                  Tcl_SetResult(interp, buf, TCL_VOLATILE);
356                  return TCL_ERROR;                  return TCL_ERROR;
357              }              }
358          }          }
359          if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &textPtr->x) != TCL_OK)          if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &textPtr->x) != TCL_OK)
360                  || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],                  || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
361                      &textPtr->y) != TCL_OK)) {                      &textPtr->y) != TCL_OK)) {
362              return TCL_ERROR;              return TCL_ERROR;
363          }          }
364          ComputeTextBbox(canvas, textPtr);          ComputeTextBbox(canvas, textPtr);
365      } else {      } else {
366          char buf[64 + TCL_INTEGER_SPACE];          char buf[64 + TCL_INTEGER_SPACE];
367                    
368          sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc);          sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc);
369          Tcl_SetResult(interp, buf, TCL_VOLATILE);          Tcl_SetResult(interp, buf, TCL_VOLATILE);
370          return TCL_ERROR;          return TCL_ERROR;
371      }      }
372      return TCL_OK;      return TCL_OK;
373  }  }
374    
375  /*  /*
376   *--------------------------------------------------------------   *--------------------------------------------------------------
377   *   *
378   * ConfigureText --   * ConfigureText --
379   *   *
380   *      This procedure is invoked to configure various aspects   *      This procedure is invoked to configure various aspects
381   *      of a text item, such as its border and background colors.   *      of a text item, such as its border and background colors.
382   *   *
383   * Results:   * Results:
384   *      A standard Tcl result code.  If an error occurs, then   *      A standard Tcl result code.  If an error occurs, then
385   *      an error message is left in the interp's result.   *      an error message is left in the interp's result.
386   *   *
387   * Side effects:   * Side effects:
388   *      Configuration information, such as colors and stipple   *      Configuration information, such as colors and stipple
389   *      patterns, may be set for itemPtr.   *      patterns, may be set for itemPtr.
390   *   *
391   *--------------------------------------------------------------   *--------------------------------------------------------------
392   */   */
393    
394  static int  static int
395  ConfigureText(interp, canvas, itemPtr, argc, argv, flags)  ConfigureText(interp, canvas, itemPtr, argc, argv, flags)
396      Tcl_Interp *interp;         /* Interpreter for error reporting. */      Tcl_Interp *interp;         /* Interpreter for error reporting. */
397      Tk_Canvas canvas;           /* Canvas containing itemPtr. */      Tk_Canvas canvas;           /* Canvas containing itemPtr. */
398      Tk_Item *itemPtr;           /* Rectangle item to reconfigure. */      Tk_Item *itemPtr;           /* Rectangle item to reconfigure. */
399      int argc;                   /* Number of elements in argv.  */      int argc;                   /* Number of elements in argv.  */
400      Tcl_Obj *CONST argv[];      /* Arguments describing things to configure. */      Tcl_Obj *CONST argv[];      /* Arguments describing things to configure. */
401      int flags;                  /* Flags to pass to Tk_ConfigureWidget. */      int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
402  {  {
403      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
404      XGCValues gcValues;      XGCValues gcValues;
405      GC newGC, newSelGC;      GC newGC, newSelGC;
406      unsigned long mask;      unsigned long mask;
407      Tk_Window tkwin;      Tk_Window tkwin;
408      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
409      XColor *selBgColorPtr;      XColor *selBgColorPtr;
410      XColor *color;      XColor *color;
411      Pixmap stipple;      Pixmap stipple;
412      Tk_State state;      Tk_State state;
413    
414      tkwin = Tk_CanvasTkwin(canvas);      tkwin = Tk_CanvasTkwin(canvas);
415      if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,      if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
416              (char *) textPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {              (char *) textPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
417          return TCL_ERROR;          return TCL_ERROR;
418      }      }
419    
420      /*      /*
421       * A few of the options require additional processing, such as       * A few of the options require additional processing, such as
422       * graphics contexts.       * graphics contexts.
423       */       */
424    
425      state = itemPtr->state;      state = itemPtr->state;
426    
427      if (textPtr->activeColor != NULL ||      if (textPtr->activeColor != NULL ||
428              textPtr->activeStipple != None) {              textPtr->activeStipple != None) {
429          itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;          itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
430      } else {      } else {
431          itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;          itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
432      }      }
433    
434      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
435          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
436      }      }
437    
438      color = textPtr->color;      color = textPtr->color;
439      stipple = textPtr->stipple;      stipple = textPtr->stipple;
440      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
441          if (textPtr->activeColor!=NULL) {          if (textPtr->activeColor!=NULL) {
442              color = textPtr->activeColor;              color = textPtr->activeColor;
443          }          }
444          if (textPtr->activeStipple!=None) {          if (textPtr->activeStipple!=None) {
445              stipple = textPtr->activeStipple;              stipple = textPtr->activeStipple;
446          }          }
447      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
448          if (textPtr->disabledColor!=NULL) {          if (textPtr->disabledColor!=NULL) {
449              color = textPtr->disabledColor;              color = textPtr->disabledColor;
450          }          }
451          if (textPtr->disabledStipple!=None) {          if (textPtr->disabledStipple!=None) {
452              stipple = textPtr->disabledStipple;              stipple = textPtr->disabledStipple;
453          }          }
454      }      }
455    
456      newGC = newSelGC = None;      newGC = newSelGC = None;
457      if (textPtr->tkfont != NULL) {      if (textPtr->tkfont != NULL) {
458          gcValues.font = Tk_FontId(textPtr->tkfont);          gcValues.font = Tk_FontId(textPtr->tkfont);
459          mask = GCFont;          mask = GCFont;
460          if (color != NULL) {          if (color != NULL) {
461              gcValues.foreground = color->pixel;              gcValues.foreground = color->pixel;
462              mask |= GCForeground;              mask |= GCForeground;
463              if (stipple != None) {              if (stipple != None) {
464                  gcValues.stipple = stipple;                  gcValues.stipple = stipple;
465                  gcValues.fill_style = FillStippled;                  gcValues.fill_style = FillStippled;
466                  mask |= GCStipple|GCFillStyle;                  mask |= GCStipple|GCFillStyle;
467              }              }
468              newGC = Tk_GetGC(tkwin, mask, &gcValues);              newGC = Tk_GetGC(tkwin, mask, &gcValues);
469          }          }
470          mask &= ~(GCTile|GCFillStyle|GCStipple);          mask &= ~(GCTile|GCFillStyle|GCStipple);
471          if (stipple != None) {          if (stipple != None) {
472              gcValues.stipple = stipple;              gcValues.stipple = stipple;
473              gcValues.fill_style = FillStippled;              gcValues.fill_style = FillStippled;
474              mask |= GCStipple|GCFillStyle;              mask |= GCStipple|GCFillStyle;
475          }          }
476          gcValues.foreground = textInfoPtr->selFgColorPtr->pixel;          gcValues.foreground = textInfoPtr->selFgColorPtr->pixel;
477          newSelGC = Tk_GetGC(tkwin, mask|GCForeground, &gcValues);          newSelGC = Tk_GetGC(tkwin, mask|GCForeground, &gcValues);
478      }      }
479      if (textPtr->gc != None) {      if (textPtr->gc != None) {
480          Tk_FreeGC(Tk_Display(tkwin), textPtr->gc);          Tk_FreeGC(Tk_Display(tkwin), textPtr->gc);
481      }      }
482      textPtr->gc = newGC;      textPtr->gc = newGC;
483      if (textPtr->selTextGC != None) {      if (textPtr->selTextGC != None) {
484          Tk_FreeGC(Tk_Display(tkwin), textPtr->selTextGC);          Tk_FreeGC(Tk_Display(tkwin), textPtr->selTextGC);
485      }      }
486      textPtr->selTextGC = newSelGC;      textPtr->selTextGC = newSelGC;
487    
488      selBgColorPtr = Tk_3DBorderColor(textInfoPtr->selBorder);      selBgColorPtr = Tk_3DBorderColor(textInfoPtr->selBorder);
489      if (Tk_3DBorderColor(textInfoPtr->insertBorder)->pixel      if (Tk_3DBorderColor(textInfoPtr->insertBorder)->pixel
490              == selBgColorPtr->pixel) {              == selBgColorPtr->pixel) {
491          if (selBgColorPtr->pixel == BlackPixelOfScreen(Tk_Screen(tkwin))) {          if (selBgColorPtr->pixel == BlackPixelOfScreen(Tk_Screen(tkwin))) {
492              gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));              gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
493          } else {          } else {
494              gcValues.foreground = BlackPixelOfScreen(Tk_Screen(tkwin));              gcValues.foreground = BlackPixelOfScreen(Tk_Screen(tkwin));
495          }          }
496          newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);          newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
497      } else {      } else {
498          newGC = None;          newGC = None;
499      }      }
500      if (textPtr->cursorOffGC != None) {      if (textPtr->cursorOffGC != None) {
501          Tk_FreeGC(Tk_Display(tkwin), textPtr->cursorOffGC);          Tk_FreeGC(Tk_Display(tkwin), textPtr->cursorOffGC);
502      }      }
503      textPtr->cursorOffGC = newGC;      textPtr->cursorOffGC = newGC;
504    
505    
506      /*      /*
507       * If the text was changed, move the selection and insertion indices       * If the text was changed, move the selection and insertion indices
508       * to keep them inside the item.       * to keep them inside the item.
509       */       */
510    
511      textPtr->numBytes = strlen(textPtr->text);      textPtr->numBytes = strlen(textPtr->text);
512      textPtr->numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes);      textPtr->numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes);
513      if (textInfoPtr->selItemPtr == itemPtr) {      if (textInfoPtr->selItemPtr == itemPtr) {
514                    
515          if (textInfoPtr->selectFirst >= textPtr->numChars) {          if (textInfoPtr->selectFirst >= textPtr->numChars) {
516              textInfoPtr->selItemPtr = NULL;              textInfoPtr->selItemPtr = NULL;
517          } else {          } else {
518              if (textInfoPtr->selectLast >= textPtr->numChars) {              if (textInfoPtr->selectLast >= textPtr->numChars) {
519                  textInfoPtr->selectLast = textPtr->numChars - 1;                  textInfoPtr->selectLast = textPtr->numChars - 1;
520              }              }
521              if ((textInfoPtr->anchorItemPtr == itemPtr)              if ((textInfoPtr->anchorItemPtr == itemPtr)
522                      && (textInfoPtr->selectAnchor >= textPtr->numChars)) {                      && (textInfoPtr->selectAnchor >= textPtr->numChars)) {
523                  textInfoPtr->selectAnchor = textPtr->numChars - 1;                  textInfoPtr->selectAnchor = textPtr->numChars - 1;
524              }              }
525          }          }
526      }      }
527      if (textPtr->insertPos >= textPtr->numChars) {      if (textPtr->insertPos >= textPtr->numChars) {
528          textPtr->insertPos = textPtr->numChars;          textPtr->insertPos = textPtr->numChars;
529      }      }
530    
531      ComputeTextBbox(canvas, textPtr);      ComputeTextBbox(canvas, textPtr);
532      return TCL_OK;      return TCL_OK;
533  }  }
534    
535  /*  /*
536   *--------------------------------------------------------------   *--------------------------------------------------------------
537   *   *
538   * DeleteText --   * DeleteText --
539   *   *
540   *      This procedure is called to clean up the data structure   *      This procedure is called to clean up the data structure
541   *      associated with a text item.   *      associated with a text item.
542   *   *
543   * Results:   * Results:
544   *      None.   *      None.
545   *   *
546   * Side effects:   * Side effects:
547   *      Resources associated with itemPtr are released.   *      Resources associated with itemPtr are released.
548   *   *
549   *--------------------------------------------------------------   *--------------------------------------------------------------
550   */   */
551    
552  static void  static void
553  DeleteText(canvas, itemPtr, display)  DeleteText(canvas, itemPtr, display)
554      Tk_Canvas canvas;           /* Info about overall canvas widget. */      Tk_Canvas canvas;           /* Info about overall canvas widget. */
555      Tk_Item *itemPtr;           /* Item that is being deleted. */      Tk_Item *itemPtr;           /* Item that is being deleted. */
556      Display *display;           /* Display containing window for canvas. */      Display *display;           /* Display containing window for canvas. */
557  {  {
558      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
559    
560      if (textPtr->color != NULL) {      if (textPtr->color != NULL) {
561          Tk_FreeColor(textPtr->color);          Tk_FreeColor(textPtr->color);
562      }      }
563      if (textPtr->activeColor != NULL) {      if (textPtr->activeColor != NULL) {
564          Tk_FreeColor(textPtr->activeColor);          Tk_FreeColor(textPtr->activeColor);
565      }      }
566      if (textPtr->disabledColor != NULL) {      if (textPtr->disabledColor != NULL) {
567          Tk_FreeColor(textPtr->disabledColor);          Tk_FreeColor(textPtr->disabledColor);
568      }      }
569      Tk_FreeFont(textPtr->tkfont);      Tk_FreeFont(textPtr->tkfont);
570      if (textPtr->stipple != None) {      if (textPtr->stipple != None) {
571          Tk_FreeBitmap(display, textPtr->stipple);          Tk_FreeBitmap(display, textPtr->stipple);
572      }      }
573      if (textPtr->activeStipple != None) {      if (textPtr->activeStipple != None) {
574          Tk_FreeBitmap(display, textPtr->activeStipple);          Tk_FreeBitmap(display, textPtr->activeStipple);
575      }      }
576      if (textPtr->disabledStipple != None) {      if (textPtr->disabledStipple != None) {
577          Tk_FreeBitmap(display, textPtr->disabledStipple);          Tk_FreeBitmap(display, textPtr->disabledStipple);
578      }      }
579      if (textPtr->text != NULL) {      if (textPtr->text != NULL) {
580          ckfree(textPtr->text);          ckfree(textPtr->text);
581      }      }
582    
583      Tk_FreeTextLayout(textPtr->textLayout);      Tk_FreeTextLayout(textPtr->textLayout);
584      if (textPtr->gc != None) {      if (textPtr->gc != None) {
585          Tk_FreeGC(display, textPtr->gc);          Tk_FreeGC(display, textPtr->gc);
586      }      }
587      if (textPtr->selTextGC != None) {      if (textPtr->selTextGC != None) {
588          Tk_FreeGC(display, textPtr->selTextGC);          Tk_FreeGC(display, textPtr->selTextGC);
589      }      }
590      if (textPtr->cursorOffGC != None) {      if (textPtr->cursorOffGC != None) {
591          Tk_FreeGC(display, textPtr->cursorOffGC);          Tk_FreeGC(display, textPtr->cursorOffGC);
592      }      }
593  }  }
594    
595  /*  /*
596   *--------------------------------------------------------------   *--------------------------------------------------------------
597   *   *
598   * ComputeTextBbox --   * ComputeTextBbox --
599   *   *
600   *      This procedure is invoked to compute the bounding box of   *      This procedure is invoked to compute the bounding box of
601   *      all the pixels that may be drawn as part of a text item.   *      all the pixels that may be drawn as part of a text item.
602   *      In addition, it recomputes all of the geometry information   *      In addition, it recomputes all of the geometry information
603   *      used to display a text item or check for mouse hits.   *      used to display a text item or check for mouse hits.
604   *   *
605   * Results:   * Results:
606   *      None.   *      None.
607   *   *
608   * Side effects:   * Side effects:
609   *      The fields x1, y1, x2, and y2 are updated in the header   *      The fields x1, y1, x2, and y2 are updated in the header
610   *      for itemPtr, and the linePtr structure is regenerated   *      for itemPtr, and the linePtr structure is regenerated
611   *      for itemPtr.   *      for itemPtr.
612   *   *
613   *--------------------------------------------------------------   *--------------------------------------------------------------
614   */   */
615    
616  static void  static void
617  ComputeTextBbox(canvas, textPtr)  ComputeTextBbox(canvas, textPtr)
618      Tk_Canvas canvas;           /* Canvas that contains item. */      Tk_Canvas canvas;           /* Canvas that contains item. */
619      TextItem *textPtr;          /* Item whose bbox is to be recomputed. */      TextItem *textPtr;          /* Item whose bbox is to be recomputed. */
620  {  {
621      Tk_CanvasTextInfo *textInfoPtr;      Tk_CanvasTextInfo *textInfoPtr;
622      int leftX, topY, width, height, fudge;      int leftX, topY, width, height, fudge;
623      Tk_State state = textPtr->header.state;      Tk_State state = textPtr->header.state;
624    
625      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
626          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
627      }      }
628    
629      Tk_FreeTextLayout(textPtr->textLayout);      Tk_FreeTextLayout(textPtr->textLayout);
630      textPtr->textLayout = Tk_ComputeTextLayout(textPtr->tkfont,      textPtr->textLayout = Tk_ComputeTextLayout(textPtr->tkfont,
631              textPtr->text, textPtr->numChars, textPtr->width,              textPtr->text, textPtr->numChars, textPtr->width,
632              textPtr->justify, 0, &width, &height);              textPtr->justify, 0, &width, &height);
633    
634      if (state == TK_STATE_HIDDEN || textPtr->color == NULL) {      if (state == TK_STATE_HIDDEN || textPtr->color == NULL) {
635          width = height = 0;          width = height = 0;
636      }      }
637    
638      /*      /*
639       * Use overall geometry information to compute the top-left corner       * Use overall geometry information to compute the top-left corner
640       * of the bounding box for the text item.       * of the bounding box for the text item.
641       */       */
642    
643      leftX = (int) (textPtr->x + 0.5);      leftX = (int) (textPtr->x + 0.5);
644      topY = (int) (textPtr->y + 0.5);      topY = (int) (textPtr->y + 0.5);
645      switch (textPtr->anchor) {      switch (textPtr->anchor) {
646          case TK_ANCHOR_NW:          case TK_ANCHOR_NW:
647          case TK_ANCHOR_N:          case TK_ANCHOR_N:
648          case TK_ANCHOR_NE:          case TK_ANCHOR_NE:
649              break;              break;
650    
651          case TK_ANCHOR_W:          case TK_ANCHOR_W:
652          case TK_ANCHOR_CENTER:          case TK_ANCHOR_CENTER:
653          case TK_ANCHOR_E:          case TK_ANCHOR_E:
654              topY -= height / 2;              topY -= height / 2;
655              break;              break;
656    
657          case TK_ANCHOR_SW:          case TK_ANCHOR_SW:
658          case TK_ANCHOR_S:          case TK_ANCHOR_S:
659          case TK_ANCHOR_SE:          case TK_ANCHOR_SE:
660              topY -= height;              topY -= height;
661              break;              break;
662      }      }
663      switch (textPtr->anchor) {      switch (textPtr->anchor) {
664          case TK_ANCHOR_NW:          case TK_ANCHOR_NW:
665          case TK_ANCHOR_W:          case TK_ANCHOR_W:
666          case TK_ANCHOR_SW:          case TK_ANCHOR_SW:
667              break;              break;
668    
669          case TK_ANCHOR_N:          case TK_ANCHOR_N:
670          case TK_ANCHOR_CENTER:          case TK_ANCHOR_CENTER:
671          case TK_ANCHOR_S:          case TK_ANCHOR_S:
672              leftX -= width / 2;              leftX -= width / 2;
673              break;              break;
674    
675          case TK_ANCHOR_NE:          case TK_ANCHOR_NE:
676          case TK_ANCHOR_E:          case TK_ANCHOR_E:
677          case TK_ANCHOR_SE:          case TK_ANCHOR_SE:
678              leftX -= width;              leftX -= width;
679              break;              break;
680      }      }
681    
682      textPtr->leftEdge  = leftX;      textPtr->leftEdge  = leftX;
683      textPtr->rightEdge = leftX + width;      textPtr->rightEdge = leftX + width;
684    
685      /*      /*
686       * Last of all, update the bounding box for the item.  The item's       * Last of all, update the bounding box for the item.  The item's
687       * bounding box includes the bounding box of all its lines, plus       * bounding box includes the bounding box of all its lines, plus
688       * an extra fudge factor for the cursor border (which could       * an extra fudge factor for the cursor border (which could
689       * potentially be quite large).       * potentially be quite large).
690       */       */
691    
692      textInfoPtr = textPtr->textInfoPtr;      textInfoPtr = textPtr->textInfoPtr;
693      fudge = (textInfoPtr->insertWidth + 1) / 2;      fudge = (textInfoPtr->insertWidth + 1) / 2;
694      if (textInfoPtr->selBorderWidth > fudge) {      if (textInfoPtr->selBorderWidth > fudge) {
695          fudge = textInfoPtr->selBorderWidth;          fudge = textInfoPtr->selBorderWidth;
696      }      }
697      textPtr->header.x1 = leftX - fudge;      textPtr->header.x1 = leftX - fudge;
698      textPtr->header.y1 = topY;      textPtr->header.y1 = topY;
699      textPtr->header.x2 = leftX + width + fudge;      textPtr->header.x2 = leftX + width + fudge;
700      textPtr->header.y2 = topY + height;      textPtr->header.y2 = topY + height;
701  }  }
702    
703  /*  /*
704   *--------------------------------------------------------------   *--------------------------------------------------------------
705   *   *
706   * DisplayCanvText --   * DisplayCanvText --
707   *   *
708   *      This procedure is invoked to draw a text item in a given   *      This procedure is invoked to draw a text item in a given
709   *      drawable.   *      drawable.
710   *   *
711   * Results:   * Results:
712   *      None.   *      None.
713   *   *
714   * Side effects:   * Side effects:
715   *      ItemPtr is drawn in drawable using the transformation   *      ItemPtr is drawn in drawable using the transformation
716   *      information in canvas.   *      information in canvas.
717   *   *
718   *--------------------------------------------------------------   *--------------------------------------------------------------
719   */   */
720    
721  static void  static void
722  DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)  DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
723      Tk_Canvas canvas;           /* Canvas that contains item. */      Tk_Canvas canvas;           /* Canvas that contains item. */
724      Tk_Item *itemPtr;           /* Item to be displayed. */      Tk_Item *itemPtr;           /* Item to be displayed. */
725      Display *display;           /* Display on which to draw item. */      Display *display;           /* Display on which to draw item. */
726      Drawable drawable;          /* Pixmap or window in which to draw item. */      Drawable drawable;          /* Pixmap or window in which to draw item. */
727      int x, y, width, height;    /* Describes region of canvas that must be      int x, y, width, height;    /* Describes region of canvas that must be
728                                   * redisplayed (not used). */                                   * redisplayed (not used). */
729  {  {
730      TextItem *textPtr;      TextItem *textPtr;
731      Tk_CanvasTextInfo *textInfoPtr;      Tk_CanvasTextInfo *textInfoPtr;
732      int selFirstChar, selLastChar;      int selFirstChar, selLastChar;
733      short drawableX, drawableY;      short drawableX, drawableY;
734      Pixmap stipple;      Pixmap stipple;
735      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
736    
737      textPtr = (TextItem *) itemPtr;      textPtr = (TextItem *) itemPtr;
738      textInfoPtr = textPtr->textInfoPtr;      textInfoPtr = textPtr->textInfoPtr;
739    
740      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
741          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
742      }      }
743      stipple = textPtr->stipple;      stipple = textPtr->stipple;
744      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {      if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
745          if (textPtr->activeStipple!=None) {          if (textPtr->activeStipple!=None) {
746              stipple = textPtr->activeStipple;              stipple = textPtr->activeStipple;
747          }          }
748      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
749          if (textPtr->disabledStipple!=None) {          if (textPtr->disabledStipple!=None) {
750              stipple = textPtr->disabledStipple;              stipple = textPtr->disabledStipple;
751          }          }
752      }      }
753    
754      if (textPtr->gc == None) {      if (textPtr->gc == None) {
755          return;          return;
756      }      }
757    
758      /*      /*
759       * If we're stippling, then modify the stipple offset in the GC.  Be       * If we're stippling, then modify the stipple offset in the GC.  Be
760       * sure to reset the offset when done, since the GC is supposed to be       * sure to reset the offset when done, since the GC is supposed to be
761       * read-only.       * read-only.
762       */       */
763    
764      if (stipple != None) {      if (stipple != None) {
765          Tk_CanvasSetOffset(canvas, textPtr->gc, &textPtr->tsoffset);          Tk_CanvasSetOffset(canvas, textPtr->gc, &textPtr->tsoffset);
766      }      }
767    
768      selFirstChar = -1;      selFirstChar = -1;
769      selLastChar = 0;            /* lint. */      selLastChar = 0;            /* lint. */
770    
771      if (textInfoPtr->selItemPtr == itemPtr) {      if (textInfoPtr->selItemPtr == itemPtr) {
772          selFirstChar = textInfoPtr->selectFirst;          selFirstChar = textInfoPtr->selectFirst;
773          selLastChar = textInfoPtr->selectLast;          selLastChar = textInfoPtr->selectLast;
774          if (selLastChar > textPtr->numChars) {          if (selLastChar > textPtr->numChars) {
775              selLastChar = textPtr->numChars - 1;              selLastChar = textPtr->numChars - 1;
776          }          }
777          if ((selFirstChar >= 0) && (selFirstChar <= selLastChar)) {          if ((selFirstChar >= 0) && (selFirstChar <= selLastChar)) {
778              int xFirst, yFirst, hFirst;              int xFirst, yFirst, hFirst;
779              int xLast, yLast;              int xLast, yLast;
780    
781              /*              /*
782               * Draw a special background under the selection.               * Draw a special background under the selection.
783               */               */
784    
785              Tk_CharBbox(textPtr->textLayout, selFirstChar, &xFirst, &yFirst,              Tk_CharBbox(textPtr->textLayout, selFirstChar, &xFirst, &yFirst,
786                      NULL, &hFirst);                      NULL, &hFirst);
787              Tk_CharBbox(textPtr->textLayout, selLastChar, &xLast, &yLast,              Tk_CharBbox(textPtr->textLayout, selLastChar, &xLast, &yLast,
788                      NULL, NULL);                      NULL, NULL);
789    
790              /*              /*
791               * If the selection spans the end of this line, then display               * If the selection spans the end of this line, then display
792               * selection background all the way to the end of the line.               * selection background all the way to the end of the line.
793               * However, for the last line we only want to display up to the               * However, for the last line we only want to display up to the
794               * last character, not the end of the line.               * last character, not the end of the line.
795               */               */
796    
797              x = xFirst;              x = xFirst;
798              height = hFirst;              height = hFirst;
799              for (y = yFirst ; y <= yLast; y += height) {              for (y = yFirst ; y <= yLast; y += height) {
800                  if (y == yLast) {                  if (y == yLast) {
801                      width = xLast - x;                      width = xLast - x;
802                  } else {                              } else {            
803                      width = textPtr->rightEdge - textPtr->leftEdge - x;                      width = textPtr->rightEdge - textPtr->leftEdge - x;
804                  }                  }
805                  Tk_CanvasDrawableCoords(canvas,                  Tk_CanvasDrawableCoords(canvas,
806                          (double) (textPtr->leftEdge + x                          (double) (textPtr->leftEdge + x
807                                  - textInfoPtr->selBorderWidth),                                  - textInfoPtr->selBorderWidth),
808                          (double) (textPtr->header.y1 + y),                          (double) (textPtr->header.y1 + y),
809                          &drawableX, &drawableY);                          &drawableX, &drawableY);
810                  Tk_Fill3DRectangle(Tk_CanvasTkwin(canvas), drawable,                  Tk_Fill3DRectangle(Tk_CanvasTkwin(canvas), drawable,
811                          textInfoPtr->selBorder, drawableX, drawableY,                          textInfoPtr->selBorder, drawableX, drawableY,
812                          width + 2 * textInfoPtr->selBorderWidth,                          width + 2 * textInfoPtr->selBorderWidth,
813                          height, textInfoPtr->selBorderWidth, TK_RELIEF_RAISED);                          height, textInfoPtr->selBorderWidth, TK_RELIEF_RAISED);
814                  x = 0;                  x = 0;
815              }              }
816          }          }
817      }      }
818    
819      /*      /*
820       * If the insertion point should be displayed, then draw a special       * If the insertion point should be displayed, then draw a special
821       * background for the cursor before drawing the text.  Note:  if       * background for the cursor before drawing the text.  Note:  if
822       * we're the cursor item but the cursor is turned off, then redraw       * we're the cursor item but the cursor is turned off, then redraw
823       * background over the area of the cursor.  This guarantees that       * background over the area of the cursor.  This guarantees that
824       * the selection won't make the cursor invisible on mono displays,       * the selection won't make the cursor invisible on mono displays,
825       * where both are drawn in the same color.       * where both are drawn in the same color.
826       */       */
827    
828      if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) {      if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) {
829          if (Tk_CharBbox(textPtr->textLayout, textPtr->insertPos,          if (Tk_CharBbox(textPtr->textLayout, textPtr->insertPos,
830                  &x, &y, NULL, &height)) {                  &x, &y, NULL, &height)) {
831              Tk_CanvasDrawableCoords(canvas,              Tk_CanvasDrawableCoords(canvas,
832                      (double) (textPtr->leftEdge + x                      (double) (textPtr->leftEdge + x
833                              - (textInfoPtr->insertWidth / 2)),                              - (textInfoPtr->insertWidth / 2)),
834                      (double) (textPtr->header.y1 + y),                      (double) (textPtr->header.y1 + y),
835                      &drawableX, &drawableY);                      &drawableX, &drawableY);
836              if (textInfoPtr->cursorOn) {              if (textInfoPtr->cursorOn) {
837                  Tk_Fill3DRectangle(Tk_CanvasTkwin(canvas), drawable,                  Tk_Fill3DRectangle(Tk_CanvasTkwin(canvas), drawable,
838                          textInfoPtr->insertBorder,                          textInfoPtr->insertBorder,
839                          drawableX, drawableY,                          drawableX, drawableY,
840                          textInfoPtr->insertWidth, height,                          textInfoPtr->insertWidth, height,
841                          textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED);                          textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED);
842              } else if (textPtr->cursorOffGC != None) {              } else if (textPtr->cursorOffGC != None) {
843                  /*                  /*
844                   * Redraw the background over the area of the cursor,                   * Redraw the background over the area of the cursor,
845                   * even though the cursor is turned off.  This                   * even though the cursor is turned off.  This
846                   * guarantees that the selection won't make the cursor                   * guarantees that the selection won't make the cursor
847                   * invisible on mono displays, where both may be drawn                   * invisible on mono displays, where both may be drawn
848                   * in the same color.                   * in the same color.
849                   */                   */
850    
851                  XFillRectangle(display, drawable, textPtr->cursorOffGC,                  XFillRectangle(display, drawable, textPtr->cursorOffGC,
852                          drawableX, drawableY,                          drawableX, drawableY,
853                          (unsigned) textInfoPtr->insertWidth,                          (unsigned) textInfoPtr->insertWidth,
854                          (unsigned) height);                          (unsigned) height);
855              }              }
856          }          }
857      }      }
858    
859    
860      /*      /*
861       * Display the text in two pieces: draw the entire text item, then       * Display the text in two pieces: draw the entire text item, then
862       * draw the selected text on top of it.  The selected text then       * draw the selected text on top of it.  The selected text then
863       * will only need to be drawn if it has different attributes (such       * will only need to be drawn if it has different attributes (such
864       * as foreground color) than regular text.       * as foreground color) than regular text.
865       */       */
866    
867      Tk_CanvasDrawableCoords(canvas, (double) textPtr->leftEdge,      Tk_CanvasDrawableCoords(canvas, (double) textPtr->leftEdge,
868              (double) textPtr->header.y1, &drawableX, &drawableY);              (double) textPtr->header.y1, &drawableX, &drawableY);
869      Tk_DrawTextLayout(display, drawable, textPtr->gc, textPtr->textLayout,      Tk_DrawTextLayout(display, drawable, textPtr->gc, textPtr->textLayout,
870              drawableX, drawableY, 0, -1);              drawableX, drawableY, 0, -1);
871    
872      if ((selFirstChar >= 0) && (textPtr->selTextGC != textPtr->gc)) {      if ((selFirstChar >= 0) && (textPtr->selTextGC != textPtr->gc)) {
873          Tk_DrawTextLayout(display, drawable, textPtr->selTextGC,          Tk_DrawTextLayout(display, drawable, textPtr->selTextGC,
874              textPtr->textLayout, drawableX, drawableY, selFirstChar,              textPtr->textLayout, drawableX, drawableY, selFirstChar,
875              selLastChar + 1);              selLastChar + 1);
876      }      }
877    
878      if (stipple != None) {      if (stipple != None) {
879          XSetTSOrigin(display, textPtr->gc, 0, 0);          XSetTSOrigin(display, textPtr->gc, 0, 0);
880      }      }
881  }  }
882    
883  /*  /*
884   *--------------------------------------------------------------   *--------------------------------------------------------------
885   *   *
886   * TextInsert --   * TextInsert --
887   *   *
888   *      Insert characters into a text item at a given position.   *      Insert characters into a text item at a given position.
889   *   *
890   * Results:   * Results:
891   *      None.   *      None.
892   *   *
893   * Side effects:   * Side effects:
894   *      The text in the given item is modified.  The cursor and   *      The text in the given item is modified.  The cursor and
895   *      selection positions are also modified to reflect the   *      selection positions are also modified to reflect the
896   *      insertion.   *      insertion.
897   *   *
898   *--------------------------------------------------------------   *--------------------------------------------------------------
899   */   */
900    
901  static void  static void
902  TextInsert(canvas, itemPtr, index, string)  TextInsert(canvas, itemPtr, index, string)
903      Tk_Canvas canvas;           /* Canvas containing text item. */      Tk_Canvas canvas;           /* Canvas containing text item. */
904      Tk_Item *itemPtr;           /* Text item to be modified. */      Tk_Item *itemPtr;           /* Text item to be modified. */
905      int index;                  /* Character index before which string is      int index;                  /* Character index before which string is
906                                   * to be inserted. */                                   * to be inserted. */
907      char *string;               /* New characters to be inserted. */      char *string;               /* New characters to be inserted. */
908  {  {
909      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
910      int byteIndex, byteCount, charsAdded;      int byteIndex, byteCount, charsAdded;
911      char *new, *text;      char *new, *text;
912      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
913    
914      string = Tcl_GetStringFromObj((Tcl_Obj *) string, &byteCount);      string = Tcl_GetStringFromObj((Tcl_Obj *) string, &byteCount);
915    
916      text = textPtr->text;      text = textPtr->text;
917    
918      if (index < 0) {      if (index < 0) {
919          index = 0;          index = 0;
920      }      }
921      if (index > textPtr->numChars) {      if (index > textPtr->numChars) {
922          index = textPtr->numChars;          index = textPtr->numChars;
923      }      }
924      byteIndex = Tcl_UtfAtIndex(text, index) - text;      byteIndex = Tcl_UtfAtIndex(text, index) - text;
925      byteCount = strlen(string);      byteCount = strlen(string);
926      if (byteCount == 0) {      if (byteCount == 0) {
927          return;          return;
928      }      }
929    
930      new = (char *) ckalloc((unsigned) textPtr->numBytes + byteCount + 1);      new = (char *) ckalloc((unsigned) textPtr->numBytes + byteCount + 1);
931      memcpy(new, text, (size_t) byteIndex);      memcpy(new, text, (size_t) byteIndex);
932      strcpy(new + byteIndex, string);      strcpy(new + byteIndex, string);
933      strcpy(new + byteIndex + byteCount, text + byteIndex);      strcpy(new + byteIndex + byteCount, text + byteIndex);
934    
935      ckfree(text);      ckfree(text);
936      textPtr->text = new;      textPtr->text = new;
937      charsAdded = Tcl_NumUtfChars(string, byteCount);      charsAdded = Tcl_NumUtfChars(string, byteCount);
938      textPtr->numChars += charsAdded;      textPtr->numChars += charsAdded;
939      textPtr->numBytes += byteCount;      textPtr->numBytes += byteCount;
940    
941      /*      /*
942       * Inserting characters invalidates indices such as those for the       * Inserting characters invalidates indices such as those for the
943       * selection and cursor.  Update the indices appropriately.       * selection and cursor.  Update the indices appropriately.
944       */       */
945    
946      if (textInfoPtr->selItemPtr == itemPtr) {      if (textInfoPtr->selItemPtr == itemPtr) {
947          if (textInfoPtr->selectFirst >= index) {          if (textInfoPtr->selectFirst >= index) {
948              textInfoPtr->selectFirst += charsAdded;              textInfoPtr->selectFirst += charsAdded;
949          }          }
950          if (textInfoPtr->selectLast >= index) {          if (textInfoPtr->selectLast >= index) {
951              textInfoPtr->selectLast += charsAdded;              textInfoPtr->selectLast += charsAdded;
952          }          }
953          if ((textInfoPtr->anchorItemPtr == itemPtr)          if ((textInfoPtr->anchorItemPtr == itemPtr)
954                  && (textInfoPtr->selectAnchor >= index)) {                  && (textInfoPtr->selectAnchor >= index)) {
955              textInfoPtr->selectAnchor += charsAdded;              textInfoPtr->selectAnchor += charsAdded;
956          }          }
957      }      }
958      if (textPtr->insertPos >= index) {      if (textPtr->insertPos >= index) {
959          textPtr->insertPos += charsAdded;          textPtr->insertPos += charsAdded;
960      }      }
961      ComputeTextBbox(canvas, textPtr);      ComputeTextBbox(canvas, textPtr);
962  }  }
963    
964  /*  /*
965   *--------------------------------------------------------------   *--------------------------------------------------------------
966   *   *
967   * TextDeleteChars --   * TextDeleteChars --
968   *   *
969   *      Delete one or more characters from a text item.   *      Delete one or more characters from a text item.
970   *   *
971   * Results:   * Results:
972   *      None.   *      None.
973   *   *
974   * Side effects:   * Side effects:
975   *      Characters between "first" and "last", inclusive, get   *      Characters between "first" and "last", inclusive, get
976   *      deleted from itemPtr, and things like the selection   *      deleted from itemPtr, and things like the selection
977   *      position get updated.   *      position get updated.
978   *   *
979   *--------------------------------------------------------------   *--------------------------------------------------------------
980   */   */
981    
982  static void  static void
983  TextDeleteChars(canvas, itemPtr, first, last)  TextDeleteChars(canvas, itemPtr, first, last)
984      Tk_Canvas canvas;           /* Canvas containing itemPtr. */      Tk_Canvas canvas;           /* Canvas containing itemPtr. */
985      Tk_Item *itemPtr;           /* Item in which to delete characters. */      Tk_Item *itemPtr;           /* Item in which to delete characters. */
986      int first;                  /* Character index of first character to      int first;                  /* Character index of first character to
987                                   * delete. */                                   * delete. */
988      int last;                   /* Character index of last character to      int last;                   /* Character index of last character to
989                                   * delete (inclusive). */                                   * delete (inclusive). */
990  {  {
991      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
992      int byteIndex, byteCount, charsRemoved;      int byteIndex, byteCount, charsRemoved;
993      char *new, *text;      char *new, *text;
994      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
995    
996      text = textPtr->text;      text = textPtr->text;
997      if (first < 0) {      if (first < 0) {
998          first = 0;          first = 0;
999      }      }
1000      if (last >= textPtr->numChars) {      if (last >= textPtr->numChars) {
1001          last = textPtr->numChars - 1;          last = textPtr->numChars - 1;
1002      }      }
1003      if (first > last) {      if (first > last) {
1004          return;          return;
1005      }      }
1006      charsRemoved = last + 1 - first;      charsRemoved = last + 1 - first;
1007    
1008      byteIndex = Tcl_UtfAtIndex(text, first) - text;      byteIndex = Tcl_UtfAtIndex(text, first) - text;
1009      byteCount = Tcl_UtfAtIndex(text + byteIndex, charsRemoved)      byteCount = Tcl_UtfAtIndex(text + byteIndex, charsRemoved)
1010          - (text + byteIndex);          - (text + byteIndex);
1011            
1012      new = (char *) ckalloc((unsigned) (textPtr->numBytes + 1 - byteCount));      new = (char *) ckalloc((unsigned) (textPtr->numBytes + 1 - byteCount));
1013      memcpy(new, text, (size_t) byteIndex);      memcpy(new, text, (size_t) byteIndex);
1014      strcpy(new + byteIndex, text + byteIndex + byteCount);      strcpy(new + byteIndex, text + byteIndex + byteCount);
1015    
1016      ckfree(text);      ckfree(text);
1017      textPtr->text = new;      textPtr->text = new;
1018      textPtr->numChars -= charsRemoved;      textPtr->numChars -= charsRemoved;
1019      textPtr->numBytes -= byteCount;      textPtr->numBytes -= byteCount;
1020    
1021      /*      /*
1022       * Update indexes for the selection and cursor to reflect the       * Update indexes for the selection and cursor to reflect the
1023       * renumbering of the remaining characters.       * renumbering of the remaining characters.
1024       */       */
1025    
1026      if (textInfoPtr->selItemPtr == itemPtr) {      if (textInfoPtr->selItemPtr == itemPtr) {
1027          if (textInfoPtr->selectFirst > first) {          if (textInfoPtr->selectFirst > first) {
1028              textInfoPtr->selectFirst -= charsRemoved;              textInfoPtr->selectFirst -= charsRemoved;
1029              if (textInfoPtr->selectFirst < first) {              if (textInfoPtr->selectFirst < first) {
1030                  textInfoPtr->selectFirst = first;                  textInfoPtr->selectFirst = first;
1031              }              }
1032          }          }
1033          if (textInfoPtr->selectLast >= first) {          if (textInfoPtr->selectLast >= first) {
1034              textInfoPtr->selectLast -= charsRemoved;              textInfoPtr->selectLast -= charsRemoved;
1035              if (textInfoPtr->selectLast < first - 1) {              if (textInfoPtr->selectLast < first - 1) {
1036                  textInfoPtr->selectLast = first - 1;                  textInfoPtr->selectLast = first - 1;
1037              }              }
1038          }          }
1039          if (textInfoPtr->selectFirst > textInfoPtr->selectLast) {          if (textInfoPtr->selectFirst > textInfoPtr->selectLast) {
1040              textInfoPtr->selItemPtr = NULL;              textInfoPtr->selItemPtr = NULL;
1041          }          }
1042          if ((textInfoPtr->anchorItemPtr == itemPtr)          if ((textInfoPtr->anchorItemPtr == itemPtr)
1043                  && (textInfoPtr->selectAnchor > first)) {                  && (textInfoPtr->selectAnchor > first)) {
1044              textInfoPtr->selectAnchor -= charsRemoved;              textInfoPtr->selectAnchor -= charsRemoved;
1045              if (textInfoPtr->selectAnchor < first) {              if (textInfoPtr->selectAnchor < first) {
1046                  textInfoPtr->selectAnchor = first;                  textInfoPtr->selectAnchor = first;
1047              }              }
1048          }          }
1049      }      }
1050      if (textPtr->insertPos > first) {      if (textPtr->insertPos > first) {
1051          textPtr->insertPos -= charsRemoved;          textPtr->insertPos -= charsRemoved;
1052          if (textPtr->insertPos < first) {          if (textPtr->insertPos < first) {
1053              textPtr->insertPos = first;              textPtr->insertPos = first;
1054          }          }
1055      }      }
1056      ComputeTextBbox(canvas, textPtr);      ComputeTextBbox(canvas, textPtr);
1057      return;      return;
1058  }  }
1059    
1060  /*  /*
1061   *--------------------------------------------------------------   *--------------------------------------------------------------
1062   *   *
1063   * TextToPoint --   * TextToPoint --
1064   *   *
1065   *      Computes the distance from a given point to a given   *      Computes the distance from a given point to a given
1066   *      text item, in canvas units.   *      text item, in canvas units.
1067   *   *
1068   * Results:   * Results:
1069   *      The return value is 0 if the point whose x and y coordinates   *      The return value is 0 if the point whose x and y coordinates
1070   *      are pointPtr[0] and pointPtr[1] is inside the text item.  If   *      are pointPtr[0] and pointPtr[1] is inside the text item.  If
1071   *      the point isn't inside the text item then the return value   *      the point isn't inside the text item then the return value
1072   *      is the distance from the point to the text item.   *      is the distance from the point to the text item.
1073   *   *
1074   * Side effects:   * Side effects:
1075   *      None.   *      None.
1076   *   *
1077   *--------------------------------------------------------------   *--------------------------------------------------------------
1078   */   */
1079    
1080  static double  static double
1081  TextToPoint(canvas, itemPtr, pointPtr)  TextToPoint(canvas, itemPtr, pointPtr)
1082      Tk_Canvas canvas;           /* Canvas containing itemPtr. */      Tk_Canvas canvas;           /* Canvas containing itemPtr. */
1083      Tk_Item *itemPtr;           /* Item to check against point. */      Tk_Item *itemPtr;           /* Item to check against point. */
1084      double *pointPtr;           /* Pointer to x and y coordinates. */      double *pointPtr;           /* Pointer to x and y coordinates. */
1085  {  {
1086      TextItem *textPtr;      TextItem *textPtr;
1087      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
1088      double value;      double value;
1089    
1090      if (state == TK_STATE_NULL) {      if (state == TK_STATE_NULL) {
1091          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
1092      }      }
1093      textPtr = (TextItem *) itemPtr;      textPtr = (TextItem *) itemPtr;
1094      value =  (double) Tk_DistanceToTextLayout(textPtr->textLayout,      value =  (double) Tk_DistanceToTextLayout(textPtr->textLayout,
1095              (int) pointPtr[0] - textPtr->leftEdge,              (int) pointPtr[0] - textPtr->leftEdge,
1096              (int) pointPtr[1] - textPtr->header.y1);              (int) pointPtr[1] - textPtr->header.y1);
1097    
1098      if ((state == TK_STATE_HIDDEN) || (textPtr->color == NULL) ||      if ((state == TK_STATE_HIDDEN) || (textPtr->color == NULL) ||
1099              (textPtr->text == NULL) || (*textPtr->text == 0)) {              (textPtr->text == NULL) || (*textPtr->text == 0)) {
1100          value = 1.0e36;          value = 1.0e36;
1101      }      }
1102      return value;      return value;
1103  }  }
1104    
1105  /*  /*
1106   *--------------------------------------------------------------   *--------------------------------------------------------------
1107   *   *
1108   * TextToArea --   * TextToArea --
1109   *   *
1110   *      This procedure is called to determine whether an item   *      This procedure is called to determine whether an item
1111   *      lies entirely inside, entirely outside, or overlapping   *      lies entirely inside, entirely outside, or overlapping
1112   *      a given rectangle.   *      a given rectangle.
1113   *   *
1114   * Results:   * Results:
1115   *      -1 is returned if the item is entirely outside the area   *      -1 is returned if the item is entirely outside the area
1116   *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely   *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely
1117   *      inside the given area.   *      inside the given area.
1118   *   *
1119   * Side effects:   * Side effects:
1120   *      None.   *      None.
1121   *   *
1122   *--------------------------------------------------------------   *--------------------------------------------------------------
1123   */   */
1124    
1125  static int  static int
1126  TextToArea(canvas, itemPtr, rectPtr)  TextToArea(canvas, itemPtr, rectPtr)
1127      Tk_Canvas canvas;           /* Canvas containing itemPtr. */      Tk_Canvas canvas;           /* Canvas containing itemPtr. */
1128      Tk_Item *itemPtr;           /* Item to check against rectangle. */      Tk_Item *itemPtr;           /* Item to check against rectangle. */
1129      double *rectPtr;            /* Pointer to array of four coordinates      double *rectPtr;            /* Pointer to array of four coordinates
1130                                   * (x1, y1, x2, y2) describing rectangular                                   * (x1, y1, x2, y2) describing rectangular
1131                                   * area.  */                                   * area.  */
1132  {  {
1133      TextItem *textPtr;      TextItem *textPtr;
1134      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
1135    
1136      if (state == TK_STATE_NULL) {      if (state == TK_STATE_NULL) {
1137          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
1138      }      }
1139    
1140      textPtr = (TextItem *) itemPtr;      textPtr = (TextItem *) itemPtr;
1141      return Tk_IntersectTextLayout(textPtr->textLayout,      return Tk_IntersectTextLayout(textPtr->textLayout,
1142              (int) (rectPtr[0] + 0.5) - textPtr->leftEdge,              (int) (rectPtr[0] + 0.5) - textPtr->leftEdge,
1143              (int) (rectPtr[1] + 0.5) - textPtr->header.y1,              (int) (rectPtr[1] + 0.5) - textPtr->header.y1,
1144              (int) (rectPtr[2] - rectPtr[0] + 0.5),              (int) (rectPtr[2] - rectPtr[0] + 0.5),
1145              (int) (rectPtr[3] - rectPtr[1] + 0.5));              (int) (rectPtr[3] - rectPtr[1] + 0.5));
1146  }  }
1147    
1148  /*  /*
1149   *--------------------------------------------------------------   *--------------------------------------------------------------
1150   *   *
1151   * ScaleText --   * ScaleText --
1152   *   *
1153   *      This procedure is invoked to rescale a text item.   *      This procedure is invoked to rescale a text item.
1154   *   *
1155   * Results:   * Results:
1156   *      None.   *      None.
1157   *   *
1158   * Side effects:   * Side effects:
1159   *      Scales the position of the text, but not the size   *      Scales the position of the text, but not the size
1160   *      of the font for the text.   *      of the font for the text.
1161   *   *
1162   *--------------------------------------------------------------   *--------------------------------------------------------------
1163   */   */
1164    
1165          /* ARGSUSED */          /* ARGSUSED */
1166  static void  static void
1167  ScaleText(canvas, itemPtr, originX, originY, scaleX, scaleY)  ScaleText(canvas, itemPtr, originX, originY, scaleX, scaleY)
1168      Tk_Canvas canvas;           /* Canvas containing rectangle. */      Tk_Canvas canvas;           /* Canvas containing rectangle. */
1169      Tk_Item *itemPtr;           /* Rectangle to be scaled. */      Tk_Item *itemPtr;           /* Rectangle to be scaled. */
1170      double originX, originY;    /* Origin about which to scale rect. */      double originX, originY;    /* Origin about which to scale rect. */
1171      double scaleX;              /* Amount to scale in X direction. */      double scaleX;              /* Amount to scale in X direction. */
1172      double scaleY;              /* Amount to scale in Y direction. */      double scaleY;              /* Amount to scale in Y direction. */
1173  {  {
1174      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
1175    
1176      textPtr->x = originX + scaleX*(textPtr->x - originX);      textPtr->x = originX + scaleX*(textPtr->x - originX);
1177      textPtr->y = originY + scaleY*(textPtr->y - originY);      textPtr->y = originY + scaleY*(textPtr->y - originY);
1178      ComputeTextBbox(canvas, textPtr);      ComputeTextBbox(canvas, textPtr);
1179      return;      return;
1180  }  }
1181    
1182  /*  /*
1183   *--------------------------------------------------------------   *--------------------------------------------------------------
1184   *   *
1185   * TranslateText --   * TranslateText --
1186   *   *
1187   *      This procedure is called to move a text item by a   *      This procedure is called to move a text item by a
1188   *      given amount.   *      given amount.
1189   *   *
1190   * Results:   * Results:
1191   *      None.   *      None.
1192   *   *
1193   * Side effects:   * Side effects:
1194   *      The position of the text item is offset by (xDelta, yDelta),   *      The position of the text item is offset by (xDelta, yDelta),
1195   *      and the bounding box is updated in the generic part of the   *      and the bounding box is updated in the generic part of the
1196   *      item structure.   *      item structure.
1197   *   *
1198   *--------------------------------------------------------------   *--------------------------------------------------------------
1199   */   */
1200    
1201  static void  static void
1202  TranslateText(canvas, itemPtr, deltaX, deltaY)  TranslateText(canvas, itemPtr, deltaX, deltaY)
1203      Tk_Canvas canvas;           /* Canvas containing item. */      Tk_Canvas canvas;           /* Canvas containing item. */
1204      Tk_Item *itemPtr;           /* Item that is being moved. */      Tk_Item *itemPtr;           /* Item that is being moved. */
1205      double deltaX, deltaY;      /* Amount by which item is to be moved. */      double deltaX, deltaY;      /* Amount by which item is to be moved. */
1206  {  {
1207      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
1208    
1209      textPtr->x += deltaX;      textPtr->x += deltaX;
1210      textPtr->y += deltaY;      textPtr->y += deltaY;
1211      ComputeTextBbox(canvas, textPtr);      ComputeTextBbox(canvas, textPtr);
1212  }  }
1213    
1214  /*  /*
1215   *--------------------------------------------------------------   *--------------------------------------------------------------
1216   *   *
1217   * GetTextIndex --   * GetTextIndex --
1218   *   *
1219   *      Parse an index into a text item and return either its value   *      Parse an index into a text item and return either its value
1220   *      or an error.   *      or an error.
1221   *   *
1222   * Results:   * Results:
1223   *      A standard Tcl result.  If all went well, then *indexPtr is   *      A standard Tcl result.  If all went well, then *indexPtr is
1224   *      filled in with the index (into itemPtr) corresponding to   *      filled in with the index (into itemPtr) corresponding to
1225   *      string.  Otherwise an error message is left in   *      string.  Otherwise an error message is left in
1226   *      the interp's result.   *      the interp's result.
1227   *   *
1228   * Side effects:   * Side effects:
1229   *      None.   *      None.
1230   *   *
1231   *--------------------------------------------------------------   *--------------------------------------------------------------
1232   */   */
1233    
1234  static int  static int
1235  GetTextIndex(interp, canvas, itemPtr, obj, indexPtr)  GetTextIndex(interp, canvas, itemPtr, obj, indexPtr)
1236      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
1237      Tk_Canvas canvas;           /* Canvas containing item. */      Tk_Canvas canvas;           /* Canvas containing item. */
1238      Tk_Item *itemPtr;           /* Item for which the index is being      Tk_Item *itemPtr;           /* Item for which the index is being
1239                                   * specified. */                                   * specified. */
1240      Tcl_Obj *obj;               /* Specification of a particular character      Tcl_Obj *obj;               /* Specification of a particular character
1241                                   * in itemPtr's text. */                                   * in itemPtr's text. */
1242      int *indexPtr;              /* Where to store converted character      int *indexPtr;              /* Where to store converted character
1243                                   * index. */                                   * index. */
1244  {  {
1245      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
1246      size_t length;      size_t length;
1247      int c;      int c;
1248      TkCanvas *canvasPtr = (TkCanvas *) canvas;      TkCanvas *canvasPtr = (TkCanvas *) canvas;
1249      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
1250      char *string = Tcl_GetStringFromObj(obj, (int *) &length);      char *string = Tcl_GetStringFromObj(obj, (int *) &length);
1251    
1252      c = string[0];      c = string[0];
1253      length = strlen(string);      length = strlen(string);
1254    
1255      if ((c == 'e') && (strncmp(string, "end", length) == 0)) {      if ((c == 'e') && (strncmp(string, "end", length) == 0)) {
1256          *indexPtr = textPtr->numChars;          *indexPtr = textPtr->numChars;
1257      } else if ((c == 'i') && (strncmp(string, "insert", length) == 0)) {      } else if ((c == 'i') && (strncmp(string, "insert", length) == 0)) {
1258          *indexPtr = textPtr->insertPos;          *indexPtr = textPtr->insertPos;
1259      } else if ((c == 's') && (strncmp(string, "sel.first", length) == 0)      } else if ((c == 's') && (strncmp(string, "sel.first", length) == 0)
1260              && (length >= 5)) {              && (length >= 5)) {
1261          if (textInfoPtr->selItemPtr != itemPtr) {          if (textInfoPtr->selItemPtr != itemPtr) {
1262              Tcl_SetResult(interp, "selection isn't in item", TCL_STATIC);              Tcl_SetResult(interp, "selection isn't in item", TCL_STATIC);
1263              return TCL_ERROR;              return TCL_ERROR;
1264          }          }
1265          *indexPtr = textInfoPtr->selectFirst;          *indexPtr = textInfoPtr->selectFirst;
1266      } else if ((c == 's') && (strncmp(string, "sel.last", length) == 0)      } else if ((c == 's') && (strncmp(string, "sel.last", length) == 0)
1267              && (length >= 5)) {              && (length >= 5)) {
1268          if (textInfoPtr->selItemPtr != itemPtr) {          if (textInfoPtr->selItemPtr != itemPtr) {
1269              Tcl_SetResult(interp, "selection isn't in item", TCL_STATIC);              Tcl_SetResult(interp, "selection isn't in item", TCL_STATIC);
1270              return TCL_ERROR;              return TCL_ERROR;
1271          }          }
1272          *indexPtr = textInfoPtr->selectLast;          *indexPtr = textInfoPtr->selectLast;
1273      } else if (c == '@') {      } else if (c == '@') {
1274          int x, y;          int x, y;
1275          double tmp;          double tmp;
1276          char *end, *p;          char *end, *p;
1277    
1278          p = string+1;          p = string+1;
1279          tmp = strtod(p, &end);          tmp = strtod(p, &end);
1280          if ((end == p) || (*end != ',')) {          if ((end == p) || (*end != ',')) {
1281              goto badIndex;              goto badIndex;
1282          }          }
1283          x = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);          x = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
1284          p = end+1;          p = end+1;
1285          tmp = strtod(p, &end);          tmp = strtod(p, &end);
1286          if ((end == p) || (*end != 0)) {          if ((end == p) || (*end != 0)) {
1287              goto badIndex;              goto badIndex;
1288          }          }
1289          y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);          y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
1290          *indexPtr = Tk_PointToChar(textPtr->textLayout,          *indexPtr = Tk_PointToChar(textPtr->textLayout,
1291                  x + canvasPtr->scrollX1 - textPtr->leftEdge,                  x + canvasPtr->scrollX1 - textPtr->leftEdge,
1292                  y + canvasPtr->scrollY1 - textPtr->header.y1);                  y + canvasPtr->scrollY1 - textPtr->header.y1);
1293      } else if (Tcl_GetIntFromObj((Tcl_Interp *)NULL, obj, indexPtr) == TCL_OK) {      } else if (Tcl_GetIntFromObj((Tcl_Interp *)NULL, obj, indexPtr) == TCL_OK) {
1294          if (*indexPtr < 0){          if (*indexPtr < 0){
1295              *indexPtr = 0;              *indexPtr = 0;
1296          } else if (*indexPtr > textPtr->numChars) {          } else if (*indexPtr > textPtr->numChars) {
1297              *indexPtr = textPtr->numChars;              *indexPtr = textPtr->numChars;
1298          }          }
1299      } else {      } else {
1300          /*          /*
1301           * Some of the paths here leave messages in the interp's result,           * Some of the paths here leave messages in the interp's result,
1302           * so we have to clear it out before storing our own message.           * so we have to clear it out before storing our own message.
1303           */           */
1304    
1305          badIndex:          badIndex:
1306          Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);          Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
1307          Tcl_AppendResult(interp, "bad index \"", string, "\"",          Tcl_AppendResult(interp, "bad index \"", string, "\"",
1308                  (char *) NULL);                  (char *) NULL);
1309          return TCL_ERROR;          return TCL_ERROR;
1310      }      }
1311      return TCL_OK;      return TCL_OK;
1312  }  }
1313    
1314  /*  /*
1315   *--------------------------------------------------------------   *--------------------------------------------------------------
1316   *   *
1317   * SetTextCursor --   * SetTextCursor --
1318   *   *
1319   *      Set the position of the insertion cursor in this item.   *      Set the position of the insertion cursor in this item.
1320   *   *
1321   * Results:   * Results:
1322   *      None.   *      None.
1323   *   *
1324   * Side effects:   * Side effects:
1325   *      The cursor position will change.   *      The cursor position will change.
1326   *   *
1327   *--------------------------------------------------------------   *--------------------------------------------------------------
1328   */   */
1329    
1330          /* ARGSUSED */          /* ARGSUSED */
1331  static void  static void
1332  SetTextCursor(canvas, itemPtr, index)  SetTextCursor(canvas, itemPtr, index)
1333      Tk_Canvas canvas;           /* Record describing canvas widget. */      Tk_Canvas canvas;           /* Record describing canvas widget. */
1334      Tk_Item *itemPtr;           /* Text item in which cursor position is to      Tk_Item *itemPtr;           /* Text item in which cursor position is to
1335                                   * be set. */                                   * be set. */
1336      int index;                  /* Character index of character just before      int index;                  /* Character index of character just before
1337                                   * which cursor is to be positioned. */                                   * which cursor is to be positioned. */
1338  {  {
1339      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
1340    
1341      if (index < 0) {      if (index < 0) {
1342          textPtr->insertPos = 0;          textPtr->insertPos = 0;
1343      } else  if (index > textPtr->numChars) {      } else  if (index > textPtr->numChars) {
1344          textPtr->insertPos = textPtr->numChars;          textPtr->insertPos = textPtr->numChars;
1345      } else {      } else {
1346          textPtr->insertPos = index;          textPtr->insertPos = index;
1347      }      }
1348  }  }
1349    
1350  /*  /*
1351   *--------------------------------------------------------------   *--------------------------------------------------------------
1352   *   *
1353   * GetSelText --   * GetSelText --
1354   *   *
1355   *      This procedure is invoked to return the selected portion   *      This procedure is invoked to return the selected portion
1356   *      of a text item.  It is only called when this item has   *      of a text item.  It is only called when this item has
1357   *      the selection.   *      the selection.
1358   *   *
1359   * Results:   * Results:
1360   *      The return value is the number of non-NULL bytes stored   *      The return value is the number of non-NULL bytes stored
1361   *      at buffer.  Buffer is filled (or partially filled) with a   *      at buffer.  Buffer is filled (or partially filled) with a
1362   *      NULL-terminated string containing part or all of the selection,   *      NULL-terminated string containing part or all of the selection,
1363   *      as given by offset and maxBytes.   *      as given by offset and maxBytes.
1364   *   *
1365   * Side effects:   * Side effects:
1366   *      None.   *      None.
1367   *   *
1368   *--------------------------------------------------------------   *--------------------------------------------------------------
1369   */   */
1370    
1371  static int  static int
1372  GetSelText(canvas, itemPtr, offset, buffer, maxBytes)  GetSelText(canvas, itemPtr, offset, buffer, maxBytes)
1373      Tk_Canvas canvas;           /* Canvas containing selection. */      Tk_Canvas canvas;           /* Canvas containing selection. */
1374      Tk_Item *itemPtr;           /* Text item containing selection. */      Tk_Item *itemPtr;           /* Text item containing selection. */
1375      int offset;                 /* Byte offset within selection of first      int offset;                 /* Byte offset within selection of first
1376                                   * character to be returned. */                                   * character to be returned. */
1377      char *buffer;               /* Location in which to place selection. */      char *buffer;               /* Location in which to place selection. */
1378      int maxBytes;               /* Maximum number of bytes to place at      int maxBytes;               /* Maximum number of bytes to place at
1379                                   * buffer, not including terminating NULL                                   * buffer, not including terminating NULL
1380                                   * character. */                                   * character. */
1381  {  {
1382      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
1383      int byteCount;      int byteCount;
1384      char *text, *selStart, *selEnd;      char *text, *selStart, *selEnd;
1385      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;      Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
1386    
1387      if ((textInfoPtr->selectFirst < 0) ||      if ((textInfoPtr->selectFirst < 0) ||
1388              (textInfoPtr->selectFirst > textInfoPtr->selectLast)) {              (textInfoPtr->selectFirst > textInfoPtr->selectLast)) {
1389          return 0;          return 0;
1390      }      }
1391      text = textPtr->text;      text = textPtr->text;
1392      selStart = Tcl_UtfAtIndex(text, textInfoPtr->selectFirst);      selStart = Tcl_UtfAtIndex(text, textInfoPtr->selectFirst);
1393      selEnd = Tcl_UtfAtIndex(selStart,      selEnd = Tcl_UtfAtIndex(selStart,
1394              textInfoPtr->selectLast + 1 - textInfoPtr->selectFirst);              textInfoPtr->selectLast + 1 - textInfoPtr->selectFirst);
1395      byteCount = selEnd - selStart - offset;      byteCount = selEnd - selStart - offset;
1396      if (byteCount > maxBytes) {      if (byteCount > maxBytes) {
1397          byteCount = maxBytes;          byteCount = maxBytes;
1398      }      }
1399      if (byteCount <= 0) {      if (byteCount <= 0) {
1400          return 0;          return 0;
1401      }      }
1402      memcpy(buffer, selStart + offset, (size_t) byteCount);      memcpy(buffer, selStart + offset, (size_t) byteCount);
1403      buffer[byteCount] = '\0';      buffer[byteCount] = '\0';
1404      return byteCount;      return byteCount;
1405  }  }
1406    
1407  /*  /*
1408   *--------------------------------------------------------------   *--------------------------------------------------------------
1409   *   *
1410   * TextToPostscript --   * TextToPostscript --
1411   *   *
1412   *      This procedure is called to generate Postscript for   *      This procedure is called to generate Postscript for
1413   *      text items.   *      text items.
1414   *   *
1415   * Results:   * Results:
1416   *      The return value is a standard Tcl result.  If an error   *      The return value is a standard Tcl result.  If an error
1417   *      occurs in generating Postscript then an error message is   *      occurs in generating Postscript then an error message is
1418   *      left in the interp's result, replacing whatever used   *      left in the interp's result, replacing whatever used
1419   *      to be there.  If no error occurs, then Postscript for the   *      to be there.  If no error occurs, then Postscript for the
1420   *      item is appended to the result.   *      item is appended to the result.
1421   *   *
1422   * Side effects:   * Side effects:
1423   *      None.   *      None.
1424   *   *
1425   *--------------------------------------------------------------   *--------------------------------------------------------------
1426   */   */
1427    
1428  static int  static int
1429  TextToPostscript(interp, canvas, itemPtr, prepass)  TextToPostscript(interp, canvas, itemPtr, prepass)
1430      Tcl_Interp *interp;         /* Leave Postscript or error message here. */      Tcl_Interp *interp;         /* Leave Postscript or error message here. */
1431      Tk_Canvas canvas;           /* Information about overall canvas. */      Tk_Canvas canvas;           /* Information about overall canvas. */
1432      Tk_Item *itemPtr;           /* Item for which Postscript is wanted. */      Tk_Item *itemPtr;           /* Item for which Postscript is wanted. */
1433      int prepass;                /* 1 means this is a prepass to collect      int prepass;                /* 1 means this is a prepass to collect
1434                                   * font information; 0 means final Postscript                                   * font information; 0 means final Postscript
1435                                   * is being created. */                                   * is being created. */
1436  {  {
1437      TextItem *textPtr = (TextItem *) itemPtr;      TextItem *textPtr = (TextItem *) itemPtr;
1438      int x, y;      int x, y;
1439      Tk_FontMetrics fm;      Tk_FontMetrics fm;
1440      char *justify;      char *justify;
1441      char buffer[500];      char buffer[500];
1442      XColor *color;      XColor *color;
1443      Pixmap stipple;      Pixmap stipple;
1444      Tk_State state = itemPtr->state;      Tk_State state = itemPtr->state;
1445    
1446      if(state == TK_STATE_NULL) {      if(state == TK_STATE_NULL) {
1447          state = ((TkCanvas *)canvas)->canvas_state;          state = ((TkCanvas *)canvas)->canvas_state;
1448      }      }
1449      color = textPtr->color;      color = textPtr->color;
1450      stipple = textPtr->stipple;      stipple = textPtr->stipple;
1451      if (state == TK_STATE_HIDDEN || textPtr->color == NULL ||      if (state == TK_STATE_HIDDEN || textPtr->color == NULL ||
1452              textPtr->text == NULL || *textPtr->text == 0) {              textPtr->text == NULL || *textPtr->text == 0) {
1453          return TCL_OK;          return TCL_OK;
1454      } else if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {      } else if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1455          if (textPtr->activeColor!=NULL) {          if (textPtr->activeColor!=NULL) {
1456              color = textPtr->activeColor;              color = textPtr->activeColor;
1457          }          }
1458          if (textPtr->activeStipple!=None) {          if (textPtr->activeStipple!=None) {
1459              stipple = textPtr->activeStipple;              stipple = textPtr->activeStipple;
1460          }          }
1461      } else if (state==TK_STATE_DISABLED) {      } else if (state==TK_STATE_DISABLED) {
1462          if (textPtr->disabledColor!=NULL) {          if (textPtr->disabledColor!=NULL) {
1463              color = textPtr->disabledColor;              color = textPtr->disabledColor;
1464          }          }
1465          if (textPtr->disabledStipple!=None) {          if (textPtr->disabledStipple!=None) {
1466              stipple = textPtr->disabledStipple;              stipple = textPtr->disabledStipple;
1467          }          }
1468      }      }
1469    
1470      if (Tk_CanvasPsFont(interp, canvas, textPtr->tkfont) != TCL_OK) {      if (Tk_CanvasPsFont(interp, canvas, textPtr->tkfont) != TCL_OK) {
1471          return TCL_ERROR;          return TCL_ERROR;
1472      }      }
1473      if (prepass != 0) {      if (prepass != 0) {
1474          return TCL_OK;          return TCL_OK;
1475      }      }
1476      if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {      if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
1477          return TCL_ERROR;          return TCL_ERROR;
1478      }      }
1479      if (stipple != None) {      if (stipple != None) {
1480          Tcl_AppendResult(interp, "/StippleText {\n    ",          Tcl_AppendResult(interp, "/StippleText {\n    ",
1481                  (char *) NULL);                  (char *) NULL);
1482          Tk_CanvasPsStipple(interp, canvas, stipple);          Tk_CanvasPsStipple(interp, canvas, stipple);
1483          Tcl_AppendResult(interp, "} bind def\n", (char *) NULL);          Tcl_AppendResult(interp, "} bind def\n", (char *) NULL);
1484      }      }
1485    
1486      sprintf(buffer, "%.15g %.15g [\n", textPtr->x,      sprintf(buffer, "%.15g %.15g [\n", textPtr->x,
1487              Tk_CanvasPsY(canvas, textPtr->y));              Tk_CanvasPsY(canvas, textPtr->y));
1488      Tcl_AppendResult(interp, buffer, (char *) NULL);      Tcl_AppendResult(interp, buffer, (char *) NULL);
1489    
1490      Tk_TextLayoutToPostscript(interp, textPtr->textLayout);      Tk_TextLayoutToPostscript(interp, textPtr->textLayout);
1491    
1492      x = 0;  y = 0;  justify = NULL;     /* lint. */      x = 0;  y = 0;  justify = NULL;     /* lint. */
1493      switch (textPtr->anchor) {      switch (textPtr->anchor) {
1494          case TK_ANCHOR_NW:      x = 0; y = 0;   break;          case TK_ANCHOR_NW:      x = 0; y = 0;   break;
1495          case TK_ANCHOR_N:       x = 1; y = 0;   break;          case TK_ANCHOR_N:       x = 1; y = 0;   break;
1496          case TK_ANCHOR_NE:      x = 2; y = 0;   break;          case TK_ANCHOR_NE:      x = 2; y = 0;   break;
1497          case TK_ANCHOR_E:       x = 2; y = 1;   break;          case TK_ANCHOR_E:       x = 2; y = 1;   break;
1498          case TK_ANCHOR_SE:      x = 2; y = 2;   break;          case TK_ANCHOR_SE:      x = 2; y = 2;   break;
1499          case TK_ANCHOR_S:       x = 1; y = 2;   break;          case TK_ANCHOR_S:       x = 1; y = 2;   break;
1500          case TK_ANCHOR_SW:      x = 0; y = 2;   break;          case TK_ANCHOR_SW:      x = 0; y = 2;   break;
1501          case TK_ANCHOR_W:       x = 0; y = 1;   break;          case TK_ANCHOR_W:       x = 0; y = 1;   break;
1502          case TK_ANCHOR_CENTER:  x = 1; y = 1;   break;          case TK_ANCHOR_CENTER:  x = 1; y = 1;   break;
1503      }      }
1504      switch (textPtr->justify) {      switch (textPtr->justify) {
1505          case TK_JUSTIFY_LEFT:   justify = "0";  break;          case TK_JUSTIFY_LEFT:   justify = "0";  break;
1506          case TK_JUSTIFY_CENTER: justify = "0.5";break;          case TK_JUSTIFY_CENTER: justify = "0.5";break;
1507          case TK_JUSTIFY_RIGHT:  justify = "1";  break;          case TK_JUSTIFY_RIGHT:  justify = "1";  break;
1508      }      }
1509    
1510      Tk_GetFontMetrics(textPtr->tkfont, &fm);      Tk_GetFontMetrics(textPtr->tkfont, &fm);
1511      sprintf(buffer, "] %d %g %g %s %s DrawText\n",      sprintf(buffer, "] %d %g %g %s %s DrawText\n",
1512              fm.linespace, x / -2.0, y / 2.0, justify,              fm.linespace, x / -2.0, y / 2.0, justify,
1513              ((stipple == None) ? "false" : "true"));              ((stipple == None) ? "false" : "true"));
1514      Tcl_AppendResult(interp, buffer, (char *) NULL);      Tcl_AppendResult(interp, buffer, (char *) NULL);
1515    
1516      return TCL_OK;      return TCL_OK;
1517  }  }
1518  /* $Header$ */  /* $Header$ */
1519    
1520  /* End of tkcanvtext.c */  /* End of tkcanvtext.c */

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25