OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkTextImage.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.