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

Annotation of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tktextimage.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25