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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (6 years, 3 months ago) by dashley
File MIME type: text/plain
File size: 27802 byte(s)
License and property (keyword) changes.
1 /* $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:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25