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

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

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

projs/trunk/shared_source/c_tk_base_7_5_w_mods/tktextimage.c revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tktextimage.c revision 98 by dashley, Sun Dec 18 00:57:31 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkImage.c --   * tkImage.c --
5   *   *
6   *      This file contains code that allows images to be   *      This file contains code that allows images to be
7   *      nested inside text widgets.  It also implements the "image"   *      nested inside text widgets.  It also implements the "image"
8   *      widget command for texts.   *      widget command for texts.
9   *   *
10   * Copyright (c) 1997 Sun Microsystems, Inc.   * Copyright (c) 1997 Sun Microsystems, Inc.
11   *   *
12   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
13   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14   *   *
15   * RCS: @(#) $Id: tktextimage.c,v 1.1.1.1 2001/06/13 05:10:24 dtashley Exp $   * RCS: @(#) $Id: tktextimage.c,v 1.1.1.1 2001/06/13 05:10:24 dtashley Exp $
16   */   */
17    
18  #include "tk.h"  #include "tk.h"
19  #include "tkText.h"  #include "tkText.h"
20  #include "tkPort.h"  #include "tkPort.h"
21    
22  /*  /*
23   * Definitions for alignment values:   * Definitions for alignment values:
24   */   */
25    
26  #define ALIGN_BOTTOM            0  #define ALIGN_BOTTOM            0
27  #define ALIGN_CENTER            1  #define ALIGN_CENTER            1
28  #define ALIGN_TOP               2  #define ALIGN_TOP               2
29  #define ALIGN_BASELINE          3  #define ALIGN_BASELINE          3
30    
31  /*  /*
32   * Macro that determines the size of an embedded image segment:   * Macro that determines the size of an embedded image segment:
33   */   */
34    
35  #define EI_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \  #define EI_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
36          + sizeof(TkTextEmbImage)))          + sizeof(TkTextEmbImage)))
37    
38  /*  /*
39   * Prototypes for procedures defined in this file:   * Prototypes for procedures defined in this file:
40   */   */
41    
42  static int              AlignParseProc _ANSI_ARGS_((ClientData clientData,  static int              AlignParseProc _ANSI_ARGS_((ClientData clientData,
43                              Tcl_Interp *interp, Tk_Window tkwin, char *value,                              Tcl_Interp *interp, Tk_Window tkwin, char *value,
44                              char *widgRec, int offset));                              char *widgRec, int offset));
45  static char *           AlignPrintProc _ANSI_ARGS_((ClientData clientData,  static char *           AlignPrintProc _ANSI_ARGS_((ClientData clientData,
46                              Tk_Window tkwin, char *widgRec, int offset,                              Tk_Window tkwin, char *widgRec, int offset,
47                              Tcl_FreeProc **freeProcPtr));                              Tcl_FreeProc **freeProcPtr));
48  static TkTextSegment *  EmbImageCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr,  static TkTextSegment *  EmbImageCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr,
49                              TkTextLine *linePtr));                              TkTextLine *linePtr));
50  static void             EmbImageCheckProc _ANSI_ARGS_((TkTextSegment *segPtr,  static void             EmbImageCheckProc _ANSI_ARGS_((TkTextSegment *segPtr,
51                              TkTextLine *linePtr));                              TkTextLine *linePtr));
52  static void             EmbImageBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,  static void             EmbImageBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,
53                              int index, int y, int lineHeight, int baseline,                              int index, int y, int lineHeight, int baseline,
54                              int *xPtr, int *yPtr, int *widthPtr,                              int *xPtr, int *yPtr, int *widthPtr,
55                              int *heightPtr));                              int *heightPtr));
56  static int              EmbImageConfigure _ANSI_ARGS_((TkText *textPtr,  static int              EmbImageConfigure _ANSI_ARGS_((TkText *textPtr,
57                              TkTextSegment *eiPtr, int argc, char **argv));                              TkTextSegment *eiPtr, int argc, char **argv));
58  static int              EmbImageDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr,  static int              EmbImageDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr,
59                              TkTextLine *linePtr, int treeGone));                              TkTextLine *linePtr, int treeGone));
60  static void             EmbImageDisplayProc _ANSI_ARGS_((  static void             EmbImageDisplayProc _ANSI_ARGS_((
61                              TkTextDispChunk *chunkPtr, int x, int y,                              TkTextDispChunk *chunkPtr, int x, int y,
62                              int lineHeight, int baseline, Display *display,                              int lineHeight, int baseline, Display *display,
63                              Drawable dst, int screenY));                              Drawable dst, int screenY));
64  static int              EmbImageLayoutProc _ANSI_ARGS_((TkText *textPtr,  static int              EmbImageLayoutProc _ANSI_ARGS_((TkText *textPtr,
65                              TkTextIndex *indexPtr, TkTextSegment *segPtr,                              TkTextIndex *indexPtr, TkTextSegment *segPtr,
66                              int offset, int maxX, int maxChars,                              int offset, int maxX, int maxChars,
67                              int noCharsYet, TkWrapMode wrapMode,                              int noCharsYet, TkWrapMode wrapMode,
68                              TkTextDispChunk *chunkPtr));                              TkTextDispChunk *chunkPtr));
69  static void             EmbImageProc _ANSI_ARGS_((ClientData clientData,  static void             EmbImageProc _ANSI_ARGS_((ClientData clientData,
70                              int x, int y, int width, int height,                              int x, int y, int width, int height,
71                              int imageWidth, int imageHeight));                              int imageWidth, int imageHeight));
72    
73  /*  /*
74   * The following structure declares the "embedded image" segment type.   * The following structure declares the "embedded image" segment type.
75   */   */
76    
77  static Tk_SegType tkTextEmbImageType = {  static Tk_SegType tkTextEmbImageType = {
78      "image",                                    /* name */      "image",                                    /* name */
79      0,                                          /* leftGravity */      0,                                          /* leftGravity */
80      (Tk_SegSplitProc *) NULL,                   /* splitProc */      (Tk_SegSplitProc *) NULL,                   /* splitProc */
81      EmbImageDeleteProc,                         /* deleteProc */      EmbImageDeleteProc,                         /* deleteProc */
82      EmbImageCleanupProc,                        /* cleanupProc */      EmbImageCleanupProc,                        /* cleanupProc */
83      (Tk_SegLineChangeProc *) NULL,              /* lineChangeProc */      (Tk_SegLineChangeProc *) NULL,              /* lineChangeProc */
84      EmbImageLayoutProc,                         /* layoutProc */      EmbImageLayoutProc,                         /* layoutProc */
85      EmbImageCheckProc                           /* checkProc */      EmbImageCheckProc                           /* checkProc */
86  };  };
87    
88  /*  /*
89   * Information used for parsing image configuration options:   * Information used for parsing image configuration options:
90   */   */
91    
92  static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc,  static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc,
93          (ClientData) NULL};          (ClientData) NULL};
94    
95  static Tk_ConfigSpec configSpecs[] = {  static Tk_ConfigSpec configSpecs[] = {
96      {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL,
97          "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption},          "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption},
98      {TK_CONFIG_PIXELS, "-padx", (char *) NULL, (char *) NULL,      {TK_CONFIG_PIXELS, "-padx", (char *) NULL, (char *) NULL,
99          "0", Tk_Offset(TkTextEmbImage, padX),          "0", Tk_Offset(TkTextEmbImage, padX),
100          TK_CONFIG_DONT_SET_DEFAULT},          TK_CONFIG_DONT_SET_DEFAULT},
101      {TK_CONFIG_PIXELS, "-pady", (char *) NULL, (char *) NULL,      {TK_CONFIG_PIXELS, "-pady", (char *) NULL, (char *) NULL,
102          "0", Tk_Offset(TkTextEmbImage, padY),          "0", Tk_Offset(TkTextEmbImage, padY),
103          TK_CONFIG_DONT_SET_DEFAULT},          TK_CONFIG_DONT_SET_DEFAULT},
104      {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,      {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,
105          (char *) NULL, Tk_Offset(TkTextEmbImage, imageString),          (char *) NULL, Tk_Offset(TkTextEmbImage, imageString),
106          TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},          TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
107      {TK_CONFIG_STRING, "-name", (char *) NULL, (char *) NULL,      {TK_CONFIG_STRING, "-name", (char *) NULL, (char *) NULL,
108          (char *) NULL, Tk_Offset(TkTextEmbImage, imageName),          (char *) NULL, Tk_Offset(TkTextEmbImage, imageName),
109          TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},          TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
110      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
111          (char *) NULL, 0, 0}          (char *) NULL, 0, 0}
112  };  };
113    
114  /*  /*
115   *--------------------------------------------------------------   *--------------------------------------------------------------
116   *   *
117   * TkTextImageCmd --   * TkTextImageCmd --
118   *   *
119   *      This procedure implements the "image" widget command   *      This procedure implements the "image" widget command
120   *      for text widgets.  See the user documentation for details   *      for text widgets.  See the user documentation for details
121   *      on what it does.   *      on what it does.
122   *   *
123   * Results:   * Results:
124   *      A standard Tcl result or error.   *      A standard Tcl result or error.
125   *   *
126   * Side effects:   * Side effects:
127   *      See the user documentation.   *      See the user documentation.
128   *   *
129   *--------------------------------------------------------------   *--------------------------------------------------------------
130   */   */
131    
132  int  int
133  TkTextImageCmd(textPtr, interp, argc, argv)  TkTextImageCmd(textPtr, interp, argc, argv)
134      register TkText *textPtr;   /* Information about text widget. */      register TkText *textPtr;   /* Information about text widget. */
135      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
136      int argc;                   /* Number of arguments. */      int argc;                   /* Number of arguments. */
137      char **argv;                /* Argument strings.  Someone else has already      char **argv;                /* Argument strings.  Someone else has already
138                                   * parsed this command enough to know that                                   * parsed this command enough to know that
139                                   * argv[1] is "image". */                                   * argv[1] is "image". */
140  {  {
141      size_t length;      size_t length;
142      register TkTextSegment *eiPtr;      register TkTextSegment *eiPtr;
143    
144      if (argc < 3) {      if (argc < 3) {
145          Tcl_AppendResult(interp, "wrong # args: should be \"",          Tcl_AppendResult(interp, "wrong # args: should be \"",
146                  argv[0], " image option ?arg arg ...?\"", (char *) NULL);                  argv[0], " image option ?arg arg ...?\"", (char *) NULL);
147          return TCL_ERROR;          return TCL_ERROR;
148      }      }
149      length = strlen(argv[2]);      length = strlen(argv[2]);
150      if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {      if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {
151          TkTextIndex index;          TkTextIndex index;
152          TkTextSegment *eiPtr;          TkTextSegment *eiPtr;
153    
154          if (argc != 5) {          if (argc != 5) {
155              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
156                      argv[0], " image cget index option\"",                      argv[0], " image cget index option\"",
157                      (char *) NULL);                      (char *) NULL);
158              return TCL_ERROR;              return TCL_ERROR;
159          }          }
160          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
161              return TCL_ERROR;              return TCL_ERROR;
162          }          }
163          eiPtr = TkTextIndexToSeg(&index, (int *) NULL);          eiPtr = TkTextIndexToSeg(&index, (int *) NULL);
164          if (eiPtr->typePtr != &tkTextEmbImageType) {          if (eiPtr->typePtr != &tkTextEmbImageType) {
165              Tcl_AppendResult(interp, "no embedded image at index \"",              Tcl_AppendResult(interp, "no embedded image at index \"",
166                      argv[3], "\"", (char *) NULL);                      argv[3], "\"", (char *) NULL);
167              return TCL_ERROR;              return TCL_ERROR;
168          }          }
169          return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs,          return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs,
170                  (char *) &eiPtr->body.ei, argv[4], 0);                  (char *) &eiPtr->body.ei, argv[4], 0);
171      } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {      } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {
172          TkTextIndex index;          TkTextIndex index;
173          TkTextSegment *eiPtr;          TkTextSegment *eiPtr;
174    
175          if (argc < 4) {          if (argc < 4) {
176              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
177                      argv[0], " image configure index ?option value ...?\"",                      argv[0], " image configure index ?option value ...?\"",
178                      (char *) NULL);                      (char *) NULL);
179              return TCL_ERROR;              return TCL_ERROR;
180          }          }
181          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
182              return TCL_ERROR;              return TCL_ERROR;
183          }          }
184          eiPtr = TkTextIndexToSeg(&index, (int *) NULL);          eiPtr = TkTextIndexToSeg(&index, (int *) NULL);
185          if (eiPtr->typePtr != &tkTextEmbImageType) {          if (eiPtr->typePtr != &tkTextEmbImageType) {
186              Tcl_AppendResult(interp, "no embedded image at index \"",              Tcl_AppendResult(interp, "no embedded image at index \"",
187                      argv[3], "\"", (char *) NULL);                      argv[3], "\"", (char *) NULL);
188              return TCL_ERROR;              return TCL_ERROR;
189          }          }
190          if (argc == 4) {          if (argc == 4) {
191              return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,              return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
192                      (char *) &eiPtr->body.ei, (char *) NULL, 0);                      (char *) &eiPtr->body.ei, (char *) NULL, 0);
193          } else if (argc == 5) {          } else if (argc == 5) {
194              return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,              return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
195                      (char *) &eiPtr->body.ei, argv[4], 0);                      (char *) &eiPtr->body.ei, argv[4], 0);
196          } else {          } else {
197              TkTextChanged(textPtr, &index, &index);              TkTextChanged(textPtr, &index, &index);
198              return EmbImageConfigure(textPtr, eiPtr, argc-4, argv+4);              return EmbImageConfigure(textPtr, eiPtr, argc-4, argv+4);
199          }          }
200      } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {      } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {
201          TkTextIndex index;          TkTextIndex index;
202          int lineIndex;          int lineIndex;
203    
204          /*          /*
205           * Add a new image.  Find where to put the new image, and           * Add a new image.  Find where to put the new image, and
206           * mark that position for redisplay.           * mark that position for redisplay.
207           */           */
208    
209          if (argc < 4) {          if (argc < 4) {
210              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
211                      argv[0], " image create index ?option value ...?\"",                      argv[0], " image create index ?option value ...?\"",
212                      (char *) NULL);                      (char *) NULL);
213              return TCL_ERROR;              return TCL_ERROR;
214          }          }
215          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
216              return TCL_ERROR;              return TCL_ERROR;
217          }          }
218    
219          /*          /*
220           * Don't allow insertions on the last (dummy) line of the text.           * Don't allow insertions on the last (dummy) line of the text.
221           */           */
222            
223          lineIndex = TkBTreeLineIndex(index.linePtr);          lineIndex = TkBTreeLineIndex(index.linePtr);
224          if (lineIndex == TkBTreeNumLines(textPtr->tree)) {          if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
225              lineIndex--;              lineIndex--;
226              TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);              TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);
227          }          }
228    
229          /*          /*
230           * Create the new image segment and initialize it.           * Create the new image segment and initialize it.
231           */           */
232    
233          eiPtr = (TkTextSegment *) ckalloc(EI_SEG_SIZE);          eiPtr = (TkTextSegment *) ckalloc(EI_SEG_SIZE);
234          eiPtr->typePtr = &tkTextEmbImageType;          eiPtr->typePtr = &tkTextEmbImageType;
235          eiPtr->size = 1;          eiPtr->size = 1;
236          eiPtr->body.ei.textPtr = textPtr;          eiPtr->body.ei.textPtr = textPtr;
237          eiPtr->body.ei.linePtr = NULL;          eiPtr->body.ei.linePtr = NULL;
238          eiPtr->body.ei.imageName = NULL;          eiPtr->body.ei.imageName = NULL;
239          eiPtr->body.ei.imageString = NULL;          eiPtr->body.ei.imageString = NULL;
240          eiPtr->body.ei.name = NULL;          eiPtr->body.ei.name = NULL;
241          eiPtr->body.ei.image = NULL;          eiPtr->body.ei.image = NULL;
242          eiPtr->body.ei.align = ALIGN_CENTER;          eiPtr->body.ei.align = ALIGN_CENTER;
243          eiPtr->body.ei.padX = eiPtr->body.ei.padY = 0;          eiPtr->body.ei.padX = eiPtr->body.ei.padY = 0;
244          eiPtr->body.ei.chunkCount = 0;          eiPtr->body.ei.chunkCount = 0;
245    
246          /*          /*
247           * Link the segment into the text widget, then configure it (delete           * Link the segment into the text widget, then configure it (delete
248           * it again if the configuration fails).           * it again if the configuration fails).
249           */           */
250    
251          TkTextChanged(textPtr, &index, &index);          TkTextChanged(textPtr, &index, &index);
252          TkBTreeLinkSegment(eiPtr, &index);          TkBTreeLinkSegment(eiPtr, &index);
253          if (EmbImageConfigure(textPtr, eiPtr, argc-4, argv+4) != TCL_OK) {          if (EmbImageConfigure(textPtr, eiPtr, argc-4, argv+4) != TCL_OK) {
254              TkTextIndex index2;              TkTextIndex index2;
255    
256              TkTextIndexForwChars(&index, 1, &index2);              TkTextIndexForwChars(&index, 1, &index2);
257              TkBTreeDeleteChars(&index, &index2);              TkBTreeDeleteChars(&index, &index2);
258              return TCL_ERROR;              return TCL_ERROR;
259          }          }
260      } else if (strncmp(argv[2], "names", length) == 0) {      } else if (strncmp(argv[2], "names", length) == 0) {
261          Tcl_HashSearch search;          Tcl_HashSearch search;
262          Tcl_HashEntry *hPtr;          Tcl_HashEntry *hPtr;
263    
264          if (argc != 3) {          if (argc != 3) {
265              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
266                      argv[0], " image names\"", (char *) NULL);                      argv[0], " image names\"", (char *) NULL);
267              return TCL_ERROR;              return TCL_ERROR;
268          }          }
269          for (hPtr = Tcl_FirstHashEntry(&textPtr->imageTable, &search);          for (hPtr = Tcl_FirstHashEntry(&textPtr->imageTable, &search);
270                  hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {                  hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
271              Tcl_AppendElement(interp,              Tcl_AppendElement(interp,
272                      Tcl_GetHashKey(&textPtr->markTable, hPtr));                      Tcl_GetHashKey(&textPtr->markTable, hPtr));
273          }          }
274      } else {      } else {
275          Tcl_AppendResult(interp, "bad image option \"", argv[2],          Tcl_AppendResult(interp, "bad image option \"", argv[2],
276                  "\": must be cget, configure, create, or names",                  "\": must be cget, configure, create, or names",
277                  (char *) NULL);                  (char *) NULL);
278          return TCL_ERROR;          return TCL_ERROR;
279      }      }
280      return TCL_OK;      return TCL_OK;
281  }  }
282    
283  /*  /*
284   *--------------------------------------------------------------   *--------------------------------------------------------------
285   *   *
286   * EmbImageConfigure --   * EmbImageConfigure --
287   *   *
288   *      This procedure is called to handle configuration options   *      This procedure is called to handle configuration options
289   *      for an embedded image, using an argc/argv list.   *      for an embedded image, using an argc/argv list.
290   *   *
291   * Results:   * Results:
292   *      The return value is a standard Tcl result.  If TCL_ERROR is   *      The return value is a standard Tcl result.  If TCL_ERROR is
293   *      returned, then the interp's result contains an error message..   *      returned, then the interp's result contains an error message..
294   *   *
295   * Side effects:   * Side effects:
296   *      Configuration information for the embedded image changes,   *      Configuration information for the embedded image changes,
297   *      such as alignment, or name of the image.   *      such as alignment, or name of the image.
298   *   *
299   *--------------------------------------------------------------   *--------------------------------------------------------------
300   */   */
301    
302  static int  static int
303  EmbImageConfigure(textPtr, eiPtr, argc, argv)  EmbImageConfigure(textPtr, eiPtr, argc, argv)
304      TkText *textPtr;            /* Information about text widget that      TkText *textPtr;            /* Information about text widget that
305                                   * contains embedded image. */                                   * contains embedded image. */
306      TkTextSegment *eiPtr;       /* Embedded image to be configured. */      TkTextSegment *eiPtr;       /* Embedded image to be configured. */
307      int argc;                   /* Number of strings in argv. */      int argc;                   /* Number of strings in argv. */
308      char **argv;                /* Array of strings describing configuration      char **argv;                /* Array of strings describing configuration
309                                   * options. */                                   * options. */
310  {  {
311      Tk_Image image;      Tk_Image image;
312      Tcl_DString newName;      Tcl_DString newName;
313      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
314      Tcl_HashSearch search;      Tcl_HashSearch search;
315      int new;      int new;
316      char *name;      char *name;
317      int count = 0;              /* The counter for picking a unique name */      int count = 0;              /* The counter for picking a unique name */
318      int conflict = 0;           /* True if we have a name conflict */      int conflict = 0;           /* True if we have a name conflict */
319      unsigned int len;           /* length of image name */      unsigned int len;           /* length of image name */
320    
321      if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs,      if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs,
322              argc, argv, (char *) &eiPtr->body.ei,TK_CONFIG_ARGV_ONLY)              argc, argv, (char *) &eiPtr->body.ei,TK_CONFIG_ARGV_ONLY)
323              != TCL_OK) {              != TCL_OK) {
324          return TCL_ERROR;          return TCL_ERROR;
325      }      }
326    
327      /*      /*
328       * Create the image.  Save the old image around and don't free it       * Create the image.  Save the old image around and don't free it
329       * until after the new one is allocated.  This keeps the reference       * until after the new one is allocated.  This keeps the reference
330       * count from going to zero so the image doesn't have to be recreated       * count from going to zero so the image doesn't have to be recreated
331       * if it hasn't changed.       * if it hasn't changed.
332       */       */
333    
334      if (eiPtr->body.ei.imageString != NULL) {      if (eiPtr->body.ei.imageString != NULL) {
335          image = Tk_GetImage(textPtr->interp, textPtr->tkwin, eiPtr->body.ei.imageString,          image = Tk_GetImage(textPtr->interp, textPtr->tkwin, eiPtr->body.ei.imageString,
336                  EmbImageProc, (ClientData) eiPtr);                  EmbImageProc, (ClientData) eiPtr);
337          if (image == NULL) {          if (image == NULL) {
338              return TCL_ERROR;              return TCL_ERROR;
339          }          }
340      } else {      } else {
341          image = NULL;          image = NULL;
342      }      }
343      if (eiPtr->body.ei.image != NULL) {      if (eiPtr->body.ei.image != NULL) {
344          Tk_FreeImage(eiPtr->body.ei.image);          Tk_FreeImage(eiPtr->body.ei.image);
345      }      }
346      eiPtr->body.ei.image = image;      eiPtr->body.ei.image = image;
347    
348      if (eiPtr->body.ei.name != NULL) {      if (eiPtr->body.ei.name != NULL) {
349          return TCL_OK;          return TCL_OK;
350      }      }
351    
352      /*      /*
353       * Find a unique name for this image.  Use imageName (or imageString)       * Find a unique name for this image.  Use imageName (or imageString)
354       * if available, otherwise tack on a #nn and use it.  If a name is already       * if available, otherwise tack on a #nn and use it.  If a name is already
355       * associated with this image, delete the name.       * associated with this image, delete the name.
356       */       */
357    
358      name = eiPtr->body.ei.imageName;      name = eiPtr->body.ei.imageName;
359      if (name == NULL) {      if (name == NULL) {
360          name = eiPtr->body.ei.imageString;          name = eiPtr->body.ei.imageString;
361      }      }
362      if (name == NULL) {      if (name == NULL) {
363          Tcl_AppendResult(textPtr->interp,"Either a \"-name\" ",          Tcl_AppendResult(textPtr->interp,"Either a \"-name\" ",
364                  "or a \"-image\" argument must be provided ",                  "or a \"-image\" argument must be provided ",
365                  "to the \"image create\" subcommand.",                  "to the \"image create\" subcommand.",
366                  (char *) NULL);                  (char *) NULL);
367          return TCL_ERROR;          return TCL_ERROR;
368      }      }
369      len = strlen(name);      len = strlen(name);
370      for (hPtr = Tcl_FirstHashEntry(&textPtr->imageTable, &search);      for (hPtr = Tcl_FirstHashEntry(&textPtr->imageTable, &search);
371              hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {              hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
372          char *haveName = Tcl_GetHashKey(&textPtr->imageTable, hPtr);          char *haveName = Tcl_GetHashKey(&textPtr->imageTable, hPtr);
373          if (strncmp(name, haveName, len) == 0) {          if (strncmp(name, haveName, len) == 0) {
374              new = 0;              new = 0;
375              sscanf(haveName+len,"#%d",&new);              sscanf(haveName+len,"#%d",&new);
376              if (new > count) {              if (new > count) {
377                  count = new;                  count = new;
378              }              }
379              if (len == (int) strlen(haveName)) {              if (len == (int) strlen(haveName)) {
380                  conflict = 1;                  conflict = 1;
381              }              }
382          }          }
383      }      }
384    
385      Tcl_DStringInit(&newName);      Tcl_DStringInit(&newName);
386      Tcl_DStringAppend(&newName,name, -1);      Tcl_DStringAppend(&newName,name, -1);
387    
388      if (conflict) {      if (conflict) {
389          char buf[4 + TCL_INTEGER_SPACE];          char buf[4 + TCL_INTEGER_SPACE];
390          sprintf(buf, "#%d",count+1);          sprintf(buf, "#%d",count+1);
391          Tcl_DStringAppend(&newName,buf, -1);          Tcl_DStringAppend(&newName,buf, -1);
392      }      }
393      name = Tcl_DStringValue(&newName);      name = Tcl_DStringValue(&newName);
394      hPtr = Tcl_CreateHashEntry(&textPtr->imageTable, name, &new);      hPtr = Tcl_CreateHashEntry(&textPtr->imageTable, name, &new);
395      Tcl_SetHashValue(hPtr, eiPtr);      Tcl_SetHashValue(hPtr, eiPtr);
396      Tcl_AppendResult(textPtr->interp, name , (char *) NULL);      Tcl_AppendResult(textPtr->interp, name , (char *) NULL);
397      eiPtr->body.ei.name = ckalloc((unsigned) Tcl_DStringLength(&newName)+1);      eiPtr->body.ei.name = ckalloc((unsigned) Tcl_DStringLength(&newName)+1);
398      strcpy(eiPtr->body.ei.name,name);      strcpy(eiPtr->body.ei.name,name);
399      Tcl_DStringFree(&newName);      Tcl_DStringFree(&newName);
400    
401      return TCL_OK;      return TCL_OK;
402  }  }
403    
404  /*  /*
405   *--------------------------------------------------------------   *--------------------------------------------------------------
406   *   *
407   * AlignParseProc --   * AlignParseProc --
408   *   *
409   *      This procedure is invoked by Tk_ConfigureWidget during   *      This procedure is invoked by Tk_ConfigureWidget during
410   *      option processing to handle "-align" options for embedded   *      option processing to handle "-align" options for embedded
411   *      images.   *      images.
412   *   *
413   * Results:   * Results:
414   *      A standard Tcl return value.   *      A standard Tcl return value.
415   *   *
416   * Side effects:   * Side effects:
417   *      The alignment for the embedded image may change.   *      The alignment for the embedded image may change.
418   *   *
419   *--------------------------------------------------------------   *--------------------------------------------------------------
420   */   */
421    
422          /* ARGSUSED */          /* ARGSUSED */
423  static int  static int
424  AlignParseProc(clientData, interp, tkwin, value, widgRec, offset)  AlignParseProc(clientData, interp, tkwin, value, widgRec, offset)
425      ClientData clientData;              /* Not used.*/      ClientData clientData;              /* Not used.*/
426      Tcl_Interp *interp;                 /* Used for reporting errors. */      Tcl_Interp *interp;                 /* Used for reporting errors. */
427      Tk_Window tkwin;                    /* Window for text widget. */      Tk_Window tkwin;                    /* Window for text widget. */
428      char *value;                        /* Value of option. */      char *value;                        /* Value of option. */
429      char *widgRec;                      /* Pointer to TkTextEmbWindow      char *widgRec;                      /* Pointer to TkTextEmbWindow
430                                           * structure. */                                           * structure. */
431      int offset;                         /* Offset into item (ignored). */      int offset;                         /* Offset into item (ignored). */
432  {  {
433      register TkTextEmbImage *embPtr = (TkTextEmbImage *) widgRec;      register TkTextEmbImage *embPtr = (TkTextEmbImage *) widgRec;
434    
435      if (strcmp(value, "baseline") == 0) {      if (strcmp(value, "baseline") == 0) {
436          embPtr->align = ALIGN_BASELINE;          embPtr->align = ALIGN_BASELINE;
437      } else if (strcmp(value, "bottom") == 0) {      } else if (strcmp(value, "bottom") == 0) {
438          embPtr->align = ALIGN_BOTTOM;          embPtr->align = ALIGN_BOTTOM;
439      } else if (strcmp(value, "center") == 0) {      } else if (strcmp(value, "center") == 0) {
440          embPtr->align = ALIGN_CENTER;          embPtr->align = ALIGN_CENTER;
441      } else if (strcmp(value, "top") == 0) {      } else if (strcmp(value, "top") == 0) {
442          embPtr->align = ALIGN_TOP;          embPtr->align = ALIGN_TOP;
443      } else {      } else {
444          Tcl_AppendResult(interp, "bad alignment \"", value,          Tcl_AppendResult(interp, "bad alignment \"", value,
445                  "\": must be baseline, bottom, center, or top",                  "\": must be baseline, bottom, center, or top",
446                  (char *) NULL);                  (char *) NULL);
447          return TCL_ERROR;          return TCL_ERROR;
448      }      }
449      return TCL_OK;      return TCL_OK;
450  }  }
451    
452  /*  /*
453   *--------------------------------------------------------------   *--------------------------------------------------------------
454   *   *
455   * AlignPrintProc --   * AlignPrintProc --
456   *   *
457   *      This procedure is invoked by the Tk configuration code   *      This procedure is invoked by the Tk configuration code
458   *      to produce a printable string for the "-align" configuration   *      to produce a printable string for the "-align" configuration
459   *      option for embedded images.   *      option for embedded images.
460   *   *
461   * Results:   * Results:
462   *      The return value is a string describing the embedded   *      The return value is a string describing the embedded
463   *      images's current alignment.   *      images's current alignment.
464   *   *
465   * Side effects:   * Side effects:
466   *      None.   *      None.
467   *   *
468   *--------------------------------------------------------------   *--------------------------------------------------------------
469   */   */
470    
471          /* ARGSUSED */          /* ARGSUSED */
472  static char *  static char *
473  AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)  AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
474      ClientData clientData;              /* Ignored. */      ClientData clientData;              /* Ignored. */
475      Tk_Window tkwin;                    /* Window for text widget. */      Tk_Window tkwin;                    /* Window for text widget. */
476      char *widgRec;                      /* Pointer to TkTextEmbImage      char *widgRec;                      /* Pointer to TkTextEmbImage
477                                           * structure. */                                           * structure. */
478      int offset;                         /* Ignored. */      int offset;                         /* Ignored. */
479      Tcl_FreeProc **freeProcPtr;         /* Pointer to variable to fill in with      Tcl_FreeProc **freeProcPtr;         /* Pointer to variable to fill in with
480                                           * information about how to reclaim                                           * information about how to reclaim
481                                           * storage for return string. */                                           * storage for return string. */
482  {  {
483      switch (((TkTextEmbImage *) widgRec)->align) {      switch (((TkTextEmbImage *) widgRec)->align) {
484          case ALIGN_BASELINE:          case ALIGN_BASELINE:
485              return "baseline";              return "baseline";
486          case ALIGN_BOTTOM:          case ALIGN_BOTTOM:
487              return "bottom";              return "bottom";
488          case ALIGN_CENTER:          case ALIGN_CENTER:
489              return "center";              return "center";
490          case ALIGN_TOP:          case ALIGN_TOP:
491              return "top";              return "top";
492          default:          default:
493              return "??";              return "??";
494      }      }
495  }  }
496    
497  /*  /*
498   *--------------------------------------------------------------   *--------------------------------------------------------------
499   *   *
500   * EmbImageDeleteProc --   * EmbImageDeleteProc --
501   *   *
502   *      This procedure is invoked by the text B-tree code whenever   *      This procedure is invoked by the text B-tree code whenever
503   *      an embedded image lies in a range of characters being deleted.   *      an embedded image lies in a range of characters being deleted.
504   *   *
505   * Results:   * Results:
506   *      Returns 0 to indicate that the deletion has been accepted.   *      Returns 0 to indicate that the deletion has been accepted.
507   *   *
508   * Side effects:   * Side effects:
509   *      The embedded image is deleted, if it exists, and any resources   *      The embedded image is deleted, if it exists, and any resources
510   *      associated with it are released.   *      associated with it are released.
511   *   *
512   *--------------------------------------------------------------   *--------------------------------------------------------------
513   */   */
514    
515          /* ARGSUSED */          /* ARGSUSED */
516  static int  static int
517  EmbImageDeleteProc(eiPtr, linePtr, treeGone)  EmbImageDeleteProc(eiPtr, linePtr, treeGone)
518      TkTextSegment *eiPtr;               /* Segment being deleted. */      TkTextSegment *eiPtr;               /* Segment being deleted. */
519      TkTextLine *linePtr;                /* Line containing segment. */      TkTextLine *linePtr;                /* Line containing segment. */
520      int treeGone;                       /* Non-zero means the entire tree is      int treeGone;                       /* Non-zero means the entire tree is
521                                           * being deleted, so everything must                                           * being deleted, so everything must
522                                           * get cleaned up. */                                           * get cleaned up. */
523  {  {
524      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
525    
526      if (eiPtr->body.ei.image != NULL) {      if (eiPtr->body.ei.image != NULL) {
527          hPtr = Tcl_FindHashEntry(&eiPtr->body.ei.textPtr->imageTable,          hPtr = Tcl_FindHashEntry(&eiPtr->body.ei.textPtr->imageTable,
528                  eiPtr->body.ei.name);                  eiPtr->body.ei.name);
529          if (hPtr != NULL) {          if (hPtr != NULL) {
530              /*              /*
531               * (It's possible for there to be no hash table entry for this               * (It's possible for there to be no hash table entry for this
532               * image, if an error occurred while creating the image segment               * image, if an error occurred while creating the image segment
533               * but before the image got added to the table)               * but before the image got added to the table)
534               */               */
535    
536              Tcl_DeleteHashEntry(hPtr);              Tcl_DeleteHashEntry(hPtr);
537          }          }
538          Tk_FreeImage(eiPtr->body.ei.image);          Tk_FreeImage(eiPtr->body.ei.image);
539      }      }
540      Tk_FreeOptions(configSpecs, (char *) &eiPtr->body.ei,      Tk_FreeOptions(configSpecs, (char *) &eiPtr->body.ei,
541              eiPtr->body.ei.textPtr->display, 0);              eiPtr->body.ei.textPtr->display, 0);
542      if (eiPtr->body.ei.name != NULL) {      if (eiPtr->body.ei.name != NULL) {
543          ckfree(eiPtr->body.ei.name);          ckfree(eiPtr->body.ei.name);
544      }      }
545      ckfree((char *) eiPtr);      ckfree((char *) eiPtr);
546      return 0;      return 0;
547  }  }
548    
549  /*  /*
550   *--------------------------------------------------------------   *--------------------------------------------------------------
551   *   *
552   * EmbImageCleanupProc --   * EmbImageCleanupProc --
553   *   *
554   *      This procedure is invoked by the B-tree code whenever a   *      This procedure is invoked by the B-tree code whenever a
555   *      segment containing an embedded image is moved from one   *      segment containing an embedded image is moved from one
556   *      line to another.   *      line to another.
557   *   *
558   * Results:   * Results:
559   *      None.   *      None.
560   *   *
561   * Side effects:   * Side effects:
562   *      The linePtr field of the segment gets updated.   *      The linePtr field of the segment gets updated.
563   *   *
564   *--------------------------------------------------------------   *--------------------------------------------------------------
565   */   */
566    
567  static TkTextSegment *  static TkTextSegment *
568  EmbImageCleanupProc(eiPtr, linePtr)  EmbImageCleanupProc(eiPtr, linePtr)
569      TkTextSegment *eiPtr;               /* Mark segment that's being moved. */      TkTextSegment *eiPtr;               /* Mark segment that's being moved. */
570      TkTextLine *linePtr;                /* Line that now contains segment. */      TkTextLine *linePtr;                /* Line that now contains segment. */
571  {  {
572      eiPtr->body.ei.linePtr = linePtr;      eiPtr->body.ei.linePtr = linePtr;
573      return eiPtr;      return eiPtr;
574  }  }
575    
576  /*  /*
577   *--------------------------------------------------------------   *--------------------------------------------------------------
578   *   *
579   * EmbImageLayoutProc --   * EmbImageLayoutProc --
580   *   *
581   *      This procedure is the "layoutProc" for embedded image   *      This procedure is the "layoutProc" for embedded image
582   *      segments.   *      segments.
583   *   *
584   * Results:   * Results:
585   *      1 is returned to indicate that the segment should be   *      1 is returned to indicate that the segment should be
586   *      displayed.  The chunkPtr structure is filled in.   *      displayed.  The chunkPtr structure is filled in.
587   *   *
588   * Side effects:   * Side effects:
589   *      None, except for filling in chunkPtr.   *      None, except for filling in chunkPtr.
590   *   *
591   *--------------------------------------------------------------   *--------------------------------------------------------------
592   */   */
593    
594          /*ARGSUSED*/          /*ARGSUSED*/
595  static int  static int
596  EmbImageLayoutProc(textPtr, indexPtr, eiPtr, offset, maxX, maxChars,  EmbImageLayoutProc(textPtr, indexPtr, eiPtr, offset, maxX, maxChars,
597          noCharsYet, wrapMode, chunkPtr)          noCharsYet, wrapMode, chunkPtr)
598      TkText *textPtr;            /* Text widget being layed out. */      TkText *textPtr;            /* Text widget being layed out. */
599      TkTextIndex *indexPtr;      /* Identifies first character in chunk. */      TkTextIndex *indexPtr;      /* Identifies first character in chunk. */
600      TkTextSegment *eiPtr;       /* Segment corresponding to indexPtr. */      TkTextSegment *eiPtr;       /* Segment corresponding to indexPtr. */
601      int offset;                 /* Offset within segPtr corresponding to      int offset;                 /* Offset within segPtr corresponding to
602                                   * indexPtr (always 0). */                                   * indexPtr (always 0). */
603      int maxX;                   /* Chunk must not occupy pixels at this      int maxX;                   /* Chunk must not occupy pixels at this
604                                   * position or higher. */                                   * position or higher. */
605      int maxChars;               /* Chunk must not include more than this      int maxChars;               /* Chunk must not include more than this
606                                   * many characters. */                                   * many characters. */
607      int noCharsYet;             /* Non-zero means no characters have been      int noCharsYet;             /* Non-zero means no characters have been
608                                   * assigned to this line yet. */                                   * assigned to this line yet. */
609      TkWrapMode wrapMode;        /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR,      TkWrapMode wrapMode;        /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR,
610                                   * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */                                   * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */
611      register TkTextDispChunk *chunkPtr;      register TkTextDispChunk *chunkPtr;
612                                  /* Structure to fill in with information                                  /* Structure to fill in with information
613                                   * about this chunk.  The x field has already                                   * about this chunk.  The x field has already
614                                   * been set by the caller. */                                   * been set by the caller. */
615  {  {
616      int width, height;      int width, height;
617    
618      if (offset != 0) {      if (offset != 0) {
619          panic("Non-zero offset in EmbImageLayoutProc");          panic("Non-zero offset in EmbImageLayoutProc");
620      }      }
621    
622      /*      /*
623       * See if there's room for this image on this line.       * See if there's room for this image on this line.
624       */       */
625    
626      if (eiPtr->body.ei.image == NULL) {      if (eiPtr->body.ei.image == NULL) {
627          width = 0;          width = 0;
628          height = 0;          height = 0;
629      } else {      } else {
630          Tk_SizeOfImage(eiPtr->body.ei.image, &width, &height);          Tk_SizeOfImage(eiPtr->body.ei.image, &width, &height);
631          width += 2*eiPtr->body.ei.padX;          width += 2*eiPtr->body.ei.padX;
632          height += 2*eiPtr->body.ei.padY;          height += 2*eiPtr->body.ei.padY;
633      }      }
634      if ((width > (maxX - chunkPtr->x))      if ((width > (maxX - chunkPtr->x))
635              && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {              && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
636          return 0;          return 0;
637      }      }
638    
639      /*      /*
640       * Fill in the chunk structure.       * Fill in the chunk structure.
641       */       */
642    
643      chunkPtr->displayProc = EmbImageDisplayProc;      chunkPtr->displayProc = EmbImageDisplayProc;
644      chunkPtr->undisplayProc = (Tk_ChunkUndisplayProc *) NULL;      chunkPtr->undisplayProc = (Tk_ChunkUndisplayProc *) NULL;
645      chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;      chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;
646      chunkPtr->bboxProc = EmbImageBboxProc;      chunkPtr->bboxProc = EmbImageBboxProc;
647      chunkPtr->numBytes = 1;      chunkPtr->numBytes = 1;
648      if (eiPtr->body.ei.align == ALIGN_BASELINE) {      if (eiPtr->body.ei.align == ALIGN_BASELINE) {
649          chunkPtr->minAscent = height - eiPtr->body.ei.padY;          chunkPtr->minAscent = height - eiPtr->body.ei.padY;
650          chunkPtr->minDescent = eiPtr->body.ei.padY;          chunkPtr->minDescent = eiPtr->body.ei.padY;
651          chunkPtr->minHeight = 0;          chunkPtr->minHeight = 0;
652      } else {      } else {
653          chunkPtr->minAscent = 0;          chunkPtr->minAscent = 0;
654          chunkPtr->minDescent = 0;          chunkPtr->minDescent = 0;
655          chunkPtr->minHeight = height;          chunkPtr->minHeight = height;
656      }      }
657      chunkPtr->width = width;      chunkPtr->width = width;
658      chunkPtr->breakIndex = -1;      chunkPtr->breakIndex = -1;
659      chunkPtr->breakIndex = 1;      chunkPtr->breakIndex = 1;
660      chunkPtr->clientData = (ClientData) eiPtr;      chunkPtr->clientData = (ClientData) eiPtr;
661      eiPtr->body.ei.chunkCount += 1;      eiPtr->body.ei.chunkCount += 1;
662      return 1;      return 1;
663  }  }
664    
665  /*  /*
666   *--------------------------------------------------------------   *--------------------------------------------------------------
667   *   *
668   * EmbImageCheckProc --   * EmbImageCheckProc --
669   *   *
670   *      This procedure is invoked by the B-tree code to perform   *      This procedure is invoked by the B-tree code to perform
671   *      consistency checks on embedded images.   *      consistency checks on embedded images.
672   *   *
673   * Results:   * Results:
674   *      None.   *      None.
675   *   *
676   * Side effects:   * Side effects:
677   *      The procedure panics if it detects anything wrong with   *      The procedure panics if it detects anything wrong with
678   *      the embedded image.   *      the embedded image.
679   *   *
680   *--------------------------------------------------------------   *--------------------------------------------------------------
681   */   */
682    
683  static void  static void
684  EmbImageCheckProc(eiPtr, linePtr)  EmbImageCheckProc(eiPtr, linePtr)
685      TkTextSegment *eiPtr;               /* Segment to check. */      TkTextSegment *eiPtr;               /* Segment to check. */
686      TkTextLine *linePtr;                /* Line containing segment. */      TkTextLine *linePtr;                /* Line containing segment. */
687  {  {
688      if (eiPtr->nextPtr == NULL) {      if (eiPtr->nextPtr == NULL) {
689          panic("EmbImageCheckProc: embedded image is last segment in line");          panic("EmbImageCheckProc: embedded image is last segment in line");
690      }      }
691      if (eiPtr->size != 1) {      if (eiPtr->size != 1) {
692          panic("EmbImageCheckProc: embedded image has size %d", eiPtr->size);          panic("EmbImageCheckProc: embedded image has size %d", eiPtr->size);
693      }      }
694  }  }
695    
696  /*  /*
697   *--------------------------------------------------------------   *--------------------------------------------------------------
698   *   *
699   * EmbImageDisplayProc --   * EmbImageDisplayProc --
700   *   *
701   *      This procedure is invoked by the text displaying code   *      This procedure is invoked by the text displaying code
702   *      when it is time to actually draw an embedded image   *      when it is time to actually draw an embedded image
703   *      chunk on the screen.   *      chunk on the screen.
704   *   *
705   * Results:   * Results:
706   *      None.   *      None.
707   *   *
708   * Side effects:   * Side effects:
709   *      The embedded image gets moved to the correct location   *      The embedded image gets moved to the correct location
710   *      and drawn onto the display.   *      and drawn onto the display.
711   *   *
712   *--------------------------------------------------------------   *--------------------------------------------------------------
713   */   */
714    
715  static void  static void
716  EmbImageDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)  EmbImageDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
717      TkTextDispChunk *chunkPtr;          /* Chunk that is to be drawn. */      TkTextDispChunk *chunkPtr;          /* Chunk that is to be drawn. */
718      int x;                              /* X-position in dst at which to      int x;                              /* X-position in dst at which to
719                                           * draw this chunk (differs from                                           * draw this chunk (differs from
720                                           * the x-position in the chunk because                                           * the x-position in the chunk because
721                                           * of scrolling). */                                           * of scrolling). */
722      int y;                              /* Top of rectangular bounding box      int y;                              /* Top of rectangular bounding box
723                                           * for line: tells where to draw this                                           * for line: tells where to draw this
724                                           * chunk in dst (x-position is in                                           * chunk in dst (x-position is in
725                                           * the chunk itself). */                                           * the chunk itself). */
726      int lineHeight;                     /* Total height of line. */      int lineHeight;                     /* Total height of line. */
727      int baseline;                       /* Offset of baseline from y. */      int baseline;                       /* Offset of baseline from y. */
728      Display *display;                   /* Display to use for drawing. */      Display *display;                   /* Display to use for drawing. */
729      Drawable dst;                       /* Pixmap or window in which to draw */      Drawable dst;                       /* Pixmap or window in which to draw */
730      int screenY;                        /* Y-coordinate in text window that      int screenY;                        /* Y-coordinate in text window that
731                                           * corresponds to y. */                                           * corresponds to y. */
732  {  {
733      TkTextSegment *eiPtr = (TkTextSegment *) chunkPtr->clientData;      TkTextSegment *eiPtr = (TkTextSegment *) chunkPtr->clientData;
734      int lineX, imageX, imageY, width, height;      int lineX, imageX, imageY, width, height;
735      Tk_Image image;      Tk_Image image;
736    
737      image = eiPtr->body.ei.image;      image = eiPtr->body.ei.image;
738      if (image == NULL) {      if (image == NULL) {
739          return;          return;
740      }      }
741      if ((x + chunkPtr->width) <= 0) {      if ((x + chunkPtr->width) <= 0) {
742          return;          return;
743      }      }
744    
745      /*      /*
746       * Compute the image's location and size in the text widget, taking       * Compute the image's location and size in the text widget, taking
747       * into account the align value for the image.       * into account the align value for the image.
748       */       */
749    
750      EmbImageBboxProc(chunkPtr, 0, y, lineHeight, baseline, &lineX,      EmbImageBboxProc(chunkPtr, 0, y, lineHeight, baseline, &lineX,
751              &imageY, &width, &height);              &imageY, &width, &height);
752      imageX = lineX - chunkPtr->x + x;      imageX = lineX - chunkPtr->x + x;
753    
754      Tk_RedrawImage(image, 0, 0, width, height, dst,      Tk_RedrawImage(image, 0, 0, width, height, dst,
755              imageX, imageY);              imageX, imageY);
756  }  }
757    
758  /*  /*
759   *--------------------------------------------------------------   *--------------------------------------------------------------
760   *   *
761   * EmbImageBboxProc --   * EmbImageBboxProc --
762   *   *
763   *      This procedure is called to compute the bounding box of   *      This procedure is called to compute the bounding box of
764   *      the area occupied by an embedded image.   *      the area occupied by an embedded image.
765   *   *
766   * Results:   * Results:
767   *      There is no return value.  *xPtr and *yPtr are filled in   *      There is no return value.  *xPtr and *yPtr are filled in
768   *      with the coordinates of the upper left corner of the   *      with the coordinates of the upper left corner of the
769   *      image, and *widthPtr and *heightPtr are filled in with   *      image, and *widthPtr and *heightPtr are filled in with
770   *      the dimensions of the image in pixels.  Note:  not all   *      the dimensions of the image in pixels.  Note:  not all
771   *      of the returned bbox is necessarily visible on the screen   *      of the returned bbox is necessarily visible on the screen
772   *      (the rightmost part might be off-screen to the right,   *      (the rightmost part might be off-screen to the right,
773   *      and the bottommost part might be off-screen to the bottom).   *      and the bottommost part might be off-screen to the bottom).
774   *   *
775   * Side effects:   * Side effects:
776   *      None.   *      None.
777   *   *
778   *--------------------------------------------------------------   *--------------------------------------------------------------
779   */   */
780    
781  static void  static void
782  EmbImageBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,  EmbImageBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
783          widthPtr, heightPtr)          widthPtr, heightPtr)
784      TkTextDispChunk *chunkPtr;          /* Chunk containing desired char. */      TkTextDispChunk *chunkPtr;          /* Chunk containing desired char. */
785      int index;                          /* Index of desired character within      int index;                          /* Index of desired character within
786                                           * the chunk. */                                           * the chunk. */
787      int y;                              /* Topmost pixel in area allocated      int y;                              /* Topmost pixel in area allocated
788                                           * for this line. */                                           * for this line. */
789      int lineHeight;                     /* Total height of line. */      int lineHeight;                     /* Total height of line. */
790      int baseline;                       /* Location of line's baseline, in      int baseline;                       /* Location of line's baseline, in
791                                           * pixels measured down from y. */                                           * pixels measured down from y. */
792      int *xPtr, *yPtr;                   /* Gets filled in with coords of      int *xPtr, *yPtr;                   /* Gets filled in with coords of
793                                           * character's upper-left pixel. */                                           * character's upper-left pixel. */
794      int *widthPtr;                      /* Gets filled in with width of      int *widthPtr;                      /* Gets filled in with width of
795                                           * character, in pixels. */                                           * character, in pixels. */
796      int *heightPtr;                     /* Gets filled in with height of      int *heightPtr;                     /* Gets filled in with height of
797                                           * character, in pixels. */                                           * character, in pixels. */
798  {  {
799      TkTextSegment *eiPtr = (TkTextSegment *) chunkPtr->clientData;      TkTextSegment *eiPtr = (TkTextSegment *) chunkPtr->clientData;
800      Tk_Image image;      Tk_Image image;
801    
802      image = eiPtr->body.ei.image;      image = eiPtr->body.ei.image;
803      if (image != NULL) {      if (image != NULL) {
804          Tk_SizeOfImage(image, widthPtr, heightPtr);          Tk_SizeOfImage(image, widthPtr, heightPtr);
805      } else {      } else {
806          *widthPtr = 0;          *widthPtr = 0;
807          *heightPtr = 0;          *heightPtr = 0;
808      }      }
809      *xPtr = chunkPtr->x + eiPtr->body.ei.padX;      *xPtr = chunkPtr->x + eiPtr->body.ei.padX;
810      switch (eiPtr->body.ei.align) {      switch (eiPtr->body.ei.align) {
811          case ALIGN_BOTTOM:          case ALIGN_BOTTOM:
812              *yPtr = y + (lineHeight - *heightPtr - eiPtr->body.ei.padY);              *yPtr = y + (lineHeight - *heightPtr - eiPtr->body.ei.padY);
813              break;              break;
814          case ALIGN_CENTER:          case ALIGN_CENTER:
815              *yPtr = y + (lineHeight - *heightPtr)/2;              *yPtr = y + (lineHeight - *heightPtr)/2;
816              break;              break;
817          case ALIGN_TOP:          case ALIGN_TOP:
818              *yPtr = y + eiPtr->body.ei.padY;              *yPtr = y + eiPtr->body.ei.padY;
819              break;              break;
820          case ALIGN_BASELINE:          case ALIGN_BASELINE:
821              *yPtr = y + (baseline - *heightPtr);              *yPtr = y + (baseline - *heightPtr);
822              break;              break;
823      }      }
824  }  }
825    
826  /*  /*
827   *--------------------------------------------------------------   *--------------------------------------------------------------
828   *   *
829   * TkTextImageIndex --   * TkTextImageIndex --
830   *   *
831   *      Given the name of an embedded image within a text widget,   *      Given the name of an embedded image within a text widget,
832   *      returns an index corresponding to the image's position   *      returns an index corresponding to the image's position
833   *      in the text.   *      in the text.
834   *   *
835   * Results:   * Results:
836   *      The return value is 1 if there is an embedded image by   *      The return value is 1 if there is an embedded image by
837   *      the given name in the text widget, 0 otherwise.  If the   *      the given name in the text widget, 0 otherwise.  If the
838   *      image exists, *indexPtr is filled in with its index.   *      image exists, *indexPtr is filled in with its index.
839   *   *
840   * Side effects:   * Side effects:
841   *      None.   *      None.
842   *   *
843   *--------------------------------------------------------------   *--------------------------------------------------------------
844   */   */
845    
846  int  int
847  TkTextImageIndex(textPtr, name, indexPtr)  TkTextImageIndex(textPtr, name, indexPtr)
848      TkText *textPtr;            /* Text widget containing image. */      TkText *textPtr;            /* Text widget containing image. */
849      char *name;                 /* Name of image. */      char *name;                 /* Name of image. */
850      TkTextIndex *indexPtr;      /* Index information gets stored here. */      TkTextIndex *indexPtr;      /* Index information gets stored here. */
851  {  {
852      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
853      TkTextSegment *eiPtr;      TkTextSegment *eiPtr;
854    
855      hPtr = Tcl_FindHashEntry(&textPtr->imageTable, name);      hPtr = Tcl_FindHashEntry(&textPtr->imageTable, name);
856      if (hPtr == NULL) {      if (hPtr == NULL) {
857          return 0;          return 0;
858      }      }
859      eiPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);      eiPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
860      indexPtr->tree = textPtr->tree;      indexPtr->tree = textPtr->tree;
861      indexPtr->linePtr = eiPtr->body.ei.linePtr;      indexPtr->linePtr = eiPtr->body.ei.linePtr;
862      indexPtr->byteIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr);      indexPtr->byteIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr);
863      return 1;      return 1;
864  }  }
865    
866  /*  /*
867   *--------------------------------------------------------------   *--------------------------------------------------------------
868   *   *
869   * EmbImageProc --   * EmbImageProc --
870   *   *
871   *      This procedure is called by the image code whenever an   *      This procedure is called by the image code whenever an
872   *      image or its contents changes.   *      image or its contents changes.
873   *   *
874   * Results:   * Results:
875   *      None.   *      None.
876   *   *
877   * Side effects:   * Side effects:
878   *      The image will be redisplayed.   *      The image will be redisplayed.
879   *   *
880   *--------------------------------------------------------------   *--------------------------------------------------------------
881   */   */
882    
883  static void  static void
884  EmbImageProc(clientData, x, y, width, height, imgWidth, imgHeight)  EmbImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
885      ClientData clientData;              /* Pointer to widget record. */      ClientData clientData;              /* Pointer to widget record. */
886      int x, y;                           /* Upper left pixel (within image)      int x, y;                           /* Upper left pixel (within image)
887                                           * that must be redisplayed. */                                           * that must be redisplayed. */
888      int width, height;                  /* Dimensions of area to redisplay      int width, height;                  /* Dimensions of area to redisplay
889                                           * (may be <= 0). */                                           * (may be <= 0). */
890      int imgWidth, imgHeight;            /* New dimensions of image. */      int imgWidth, imgHeight;            /* New dimensions of image. */
891    
892  {  {
893      TkTextSegment *eiPtr = (TkTextSegment *) clientData;      TkTextSegment *eiPtr = (TkTextSegment *) clientData;
894      TkTextIndex index;      TkTextIndex index;
895    
896      index.tree = eiPtr->body.ei.textPtr->tree;      index.tree = eiPtr->body.ei.textPtr->tree;
897      index.linePtr = eiPtr->body.ei.linePtr;      index.linePtr = eiPtr->body.ei.linePtr;
898      index.byteIndex = TkTextSegToOffset(eiPtr, eiPtr->body.ei.linePtr);      index.byteIndex = TkTextSegToOffset(eiPtr, eiPtr->body.ei.linePtr);
899      TkTextChanged(eiPtr->body.ei.textPtr, &index, &index);      TkTextChanged(eiPtr->body.ei.textPtr, &index, &index);
900  }  }
901    
902  /* End of tktextimage.c */  /* End of tktextimage.c */

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25