~ubuntu-branches/ubuntu/precise/xcircuit/precise

« back to all changes in this revision

Viewing changes to tkPixmap.c

  • Committer: Bazaar Package Importer
  • Author(s): David Z Maze
  • Date: 2003-08-24 09:08:10 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20030824090810-5d6ptk9msqsbsnqv
Tags: 3.1.19-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*--------------------------------------------------------------*/
 
2
/*                                                              */ 
 
3
/* tkPixmap.c --- routines for implementing an "xpm" format     */
 
4
/*      pixmap image type in Tk.  Lifted mostly from Tk's       */
 
5
/*      bitmap image format source "tkImgBmap.c"                */
 
6
/*                                                              */ 
 
7
/*--------------------------------------------------------------*/
 
8
 
 
9
#if defined(TCL_WRAPPER) && defined(HAVE_XPM)
 
10
 
 
11
#include <stdio.h>
 
12
#include <stdlib.h>
 
13
 
 
14
#include <X11/Intrinsic.h>
 
15
#include <X11/StringDefs.h>
 
16
 
 
17
#include <X11/xpm.h>
 
18
 
 
19
#include <tk.h>
 
20
 
 
21
/*
 
22
 * The following data structure represents the master for an XPM-format
 
23
 * pixmap image:
 
24
 */
 
25
 
 
26
typedef struct XPMMaster {
 
27
    Tk_ImageMaster tkMaster;    /* Tk's token for image master.  NULL means
 
28
                                 * the image is being deleted. */
 
29
    Tcl_Interp *interp;         /* Interpreter for application that is
 
30
                                 * using image. */
 
31
    Tcl_Command imageCmd;       /* Token for image command (used to delete
 
32
                                 * it when the image goes away).  NULL means
 
33
                                 * the image command has already been
 
34
                                 * deleted. */
 
35
    XpmImage *imageData;        /* Contains primary information about the image */
 
36
    XpmInfo  *imageInfo;        /* Contains comment and extension information */
 
37
    char *fileString;           /* Value of -file option (malloc'ed). */
 
38
    struct XPMInstance *instancePtr;
 
39
                                /* First in list of all instances associated
 
40
                                 * with this master. */
 
41
} XPMMaster;
 
42
 
 
43
/*
 
44
 * The following data structure represents all of the instances of an
 
45
 * image that lie within a particular window:
 
46
 */
 
47
 
 
48
typedef struct XPMInstance {
 
49
    int refCount;               /* Number of instances that share this
 
50
                                 * data structure. */
 
51
    XPMMaster *masterPtr;       /* Pointer to master for image. */
 
52
    Tk_Window tkwin;            /* Window in which the instances will be
 
53
                                 * displayed. */
 
54
    Pixmap pixmap;              /* The pixmap to display. */
 
55
    Pixmap mask;                /* The bitmap to use for the shapemask */
 
56
    GC gc;                      /* Graphics context for displaying pixmap */
 
57
    struct XPMInstance *nextPtr;
 
58
                                /* Next in list of all instance structures
 
59
                                 * associated with masterPtr (NULL means
 
60
                                 * end of list). */
 
61
} XPMInstance;
 
62
 
 
63
/*
 
64
 * The type record for bitmap images:
 
65
 */
 
66
 
 
67
static int              ImgXPMCreate _ANSI_ARGS_((Tcl_Interp *interp,
 
68
                            char *name, int argc, Tcl_Obj *CONST objv[],
 
69
                            Tk_ImageType *typePtr, Tk_ImageMaster master,
 
70
                            ClientData *clientDataPtr));
 
71
static ClientData       ImgXPMGet _ANSI_ARGS_((Tk_Window tkwin,
 
72
                            ClientData clientData));
 
73
static void             ImgXPMDisplay _ANSI_ARGS_((ClientData clientData,
 
74
                            Display *display, Drawable drawable, 
 
75
                            int imageX, int imageY, int width, int height,
 
76
                            int drawableX, int drawableY));
 
77
static void             ImgXPMFree _ANSI_ARGS_((ClientData clientData,
 
78
                            Display *display));
 
79
static void             ImgXPMDelete _ANSI_ARGS_((ClientData clientData));
 
80
 
 
81
Tk_ImageType tkXPMImageType = {
 
82
    "xpm",                      /* name */
 
83
    ImgXPMCreate,               /* createProc */
 
84
    ImgXPMGet,                  /* getProc */
 
85
    ImgXPMDisplay,              /* displayProc */
 
86
    ImgXPMFree,                 /* freeProc */
 
87
    ImgXPMDelete,               /* deleteProc */
 
88
    NULL,                       /* postscriptProc */
 
89
    (Tk_ImageType *) NULL       /* nextPtr */
 
90
};
 
91
 
 
92
/*
 
93
 * Information used for parsing configuration specs:
 
94
 * Size defaults to a 16x16 area.
 
95
 */
 
96
 
 
97
static Tk_ConfigSpec configSpecs[] = {
 
98
    {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
 
99
        (char *) NULL, Tk_Offset(XPMMaster, fileString), TK_CONFIG_NULL_OK},
 
100
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
 
101
        (char *) NULL, 0, 0}
 
102
};
 
103
 
 
104
/*
 
105
 * Prototypes for procedures used only locally in this file:
 
106
 */
 
107
 
 
108
static int              ImgXPMCmd _ANSI_ARGS_((ClientData clientData,
 
109
                            Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]));
 
110
static void             ImgXPMCmdDeletedProc _ANSI_ARGS_((
 
111
                            ClientData clientData));
 
112
static void             ImgXPMConfigureInstance _ANSI_ARGS_((
 
113
                            XPMInstance *instancePtr));
 
114
static int              ImgXPMConfigureMaster _ANSI_ARGS_((
 
115
                            XPMMaster *masterPtr, int argc, Tcl_Obj *CONST objv[],
 
116
                            int flags));
 
117
 
 
118
/*
 
119
 *----------------------------------------------------------------------
 
120
 *
 
121
 * ImgXPMCreate --
 
122
 *
 
123
 *      This procedure is called by the Tk image code to create "test"
 
124
 *      images.
 
125
 *
 
126
 * Results:
 
127
 *      A standard Tcl result.
 
128
 *
 
129
 * Side effects:
 
130
 *      The data structure for a new image is allocated.
 
131
 *
 
132
 *----------------------------------------------------------------------
 
133
 */
 
134
 
 
135
        /* ARGSUSED */
 
136
static int
 
137
ImgXPMCreate(interp, name, argc, argv, typePtr, master, clientDataPtr)
 
138
    Tcl_Interp *interp;         /* Interpreter for application containing
 
139
                                 * image. */
 
140
    char *name;                 /* Name to use for image. */
 
141
    int argc;                   /* Number of arguments. */
 
142
    Tcl_Obj *CONST argv[];      /* Argument objects for options (doesn't
 
143
                                 * include image name or type). */
 
144
    Tk_ImageType *typePtr;      /* Pointer to our type record (not used). */
 
145
    Tk_ImageMaster master;      /* Token for image, to be used by us in
 
146
                                 * later callbacks. */
 
147
    ClientData *clientDataPtr;  /* Store manager's token for image here;
 
148
                                 * it will be returned in later callbacks. */
 
149
{
 
150
    XPMMaster *masterPtr;
 
151
 
 
152
    masterPtr = (XPMMaster *) ckalloc(sizeof(XPMMaster));
 
153
    masterPtr->tkMaster = master;
 
154
    masterPtr->interp = interp;
 
155
    masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgXPMCmd,
 
156
            (ClientData) masterPtr, ImgXPMCmdDeletedProc);
 
157
    masterPtr->imageData = NULL;
 
158
    masterPtr->imageInfo = NULL;
 
159
    masterPtr->fileString = NULL;
 
160
    masterPtr->instancePtr = NULL;
 
161
    if (ImgXPMConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) {
 
162
        ImgXPMDelete((ClientData) masterPtr);
 
163
        return TCL_ERROR;
 
164
    }
 
165
    *clientDataPtr = (ClientData) masterPtr;
 
166
    return TCL_OK;
 
167
}
 
168
 
 
169
/*
 
170
 *----------------------------------------------------------------------
 
171
 *
 
172
 * ImgXPMConfigureMaster --
 
173
 *
 
174
 *      This procedure is called when a bitmap image is created or
 
175
 *      reconfigured.  It process configuration options and resets
 
176
 *      any instances of the image.
 
177
 *
 
178
 * Results:
 
179
 *      A standard Tcl return value.  If TCL_ERROR is returned then
 
180
 *      an error message is left in the masterPtr->interp's result.
 
181
 *
 
182
 * Side effects:
 
183
 *      Existing instances of the image will be redisplayed to match
 
184
 *      the new configuration options.
 
185
 *
 
186
 *----------------------------------------------------------------------
 
187
 */
 
188
 
 
189
static int
 
190
ImgXPMConfigureMaster(masterPtr, objc, objv, flags)
 
191
    XPMMaster *masterPtr;       /* Pointer to data structure describing
 
192
                                 * overall pixmap image to (reconfigure). */
 
193
    int objc;                   /* Number of entries in objv. */
 
194
    Tcl_Obj *CONST objv[];      /* Pairs of configuration options for image. */
 
195
    int flags;                  /* Flags to pass to Tk_ConfigureWidget,
 
196
                                 * such as TK_CONFIG_ARGV_ONLY. */
 
197
{
 
198
    XPMInstance *instancePtr;
 
199
    int maskWidth, maskHeight, dummy1;
 
200
 
 
201
    char **argv = (char **) Tcl_Alloc((objc+1) * sizeof(char *));
 
202
    for (dummy1 = 0; dummy1 < objc; dummy1++) {
 
203
        argv[dummy1]=Tcl_GetString(objv[dummy1]);
 
204
    }
 
205
    argv[objc] = NULL;
 
206
 
 
207
    if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp),
 
208
            configSpecs, objc, argv, (char *) masterPtr, flags)
 
209
            != TCL_OK) {
 
210
        Tcl_Free((char *) argv);
 
211
        return TCL_ERROR;
 
212
    }
 
213
    Tcl_Free((char *) argv);
 
214
 
 
215
    /*
 
216
     * Parse the pixmap and/or mask to create binary data.  Make sure that
 
217
     * the pixmap and mask have the same dimensions.
 
218
     */
 
219
 
 
220
    if (masterPtr->imageData != NULL) {
 
221
        XpmFreeXpmImage(masterPtr->imageData);
 
222
        masterPtr->imageData = NULL;
 
223
    }
 
224
    if (masterPtr->imageInfo != NULL) {
 
225
        XpmFreeXpmInfo(masterPtr->imageInfo);
 
226
        masterPtr->imageInfo = NULL;
 
227
    }
 
228
    if (masterPtr->fileString != NULL) {
 
229
        masterPtr->imageData = (XpmImage *)malloc(sizeof(XpmImage));
 
230
        masterPtr->imageInfo = (XpmInfo *)malloc(sizeof(XpmInfo));
 
231
        if (XpmReadFileToXpmImage(masterPtr->fileString,
 
232
                masterPtr->imageData, masterPtr->imageInfo) != XpmSuccess) {
 
233
            free((char *)masterPtr->imageData);
 
234
            free((char *)masterPtr->imageInfo);
 
235
            masterPtr->imageData = NULL;
 
236
            masterPtr->imageInfo = NULL;
 
237
            return TCL_ERROR;
 
238
        }
 
239
    }
 
240
 
 
241
    /*
 
242
     * Cycle through all of the instances of this image, regenerating
 
243
     * the information for each instance.  Then force the image to be
 
244
     * redisplayed everywhere that it is used.
 
245
     */
 
246
 
 
247
    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
 
248
            instancePtr = instancePtr->nextPtr) {
 
249
        ImgXPMConfigureInstance(instancePtr);
 
250
    }
 
251
    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->imageData->width,
 
252
            masterPtr->imageData->height, masterPtr->imageData->width,
 
253
            masterPtr->imageData->height);
 
254
    return TCL_OK;
 
255
}
 
256
 
 
257
/*
 
258
 *----------------------------------------------------------------------
 
259
 *
 
260
 * ImgXPMConfigureInstance --
 
261
 *
 
262
 *      This procedure is called to create displaying information for
 
263
 *      a xpm image instance based on the configuration information
 
264
 *      in the master.  It is invoked both when new instances are
 
265
 *      created and when the master is reconfigured.
 
266
 *
 
267
 * Results:
 
268
 *      None.
 
269
 *
 
270
 * Side effects:
 
271
 *      Generates errors via Tcl_BackgroundError if there are problems
 
272
 *      in setting up the instance.
 
273
 *
 
274
 *----------------------------------------------------------------------
 
275
 */
 
276
 
 
277
static void
 
278
ImgXPMConfigureInstance(instancePtr)
 
279
    XPMInstance *instancePtr;   /* Instance to reconfigure. */
 
280
{
 
281
    XPMMaster *masterPtr = instancePtr->masterPtr;
 
282
    XGCValues gcValues;
 
283
    GC gc;
 
284
    unsigned int gcmask;
 
285
    Pixmap oldMask;
 
286
    Tk_Window tkwind = instancePtr->tkwin;
 
287
    Window xwind;
 
288
    XpmAttributes locattr;
 
289
    Display *dpy = Tk_Display(instancePtr->tkwin);
 
290
 
 
291
    if ((xwind = Tk_WindowId(tkwind)) == 0)
 
292
        Tk_MakeWindowExist(tkwind);
 
293
 
 
294
    if ((xwind = Tk_WindowId(tkwind)) == 0)
 
295
        goto error;
 
296
 
 
297
    /*
 
298
     * For each of the options in masterPtr, translate the string
 
299
     * form into an internal form appropriate for instancePtr.
 
300
     */
 
301
 
 
302
    if (instancePtr->pixmap != None) {
 
303
        XFreePixmap(dpy, instancePtr->pixmap);
 
304
        instancePtr->pixmap = None;
 
305
    }
 
306
 
 
307
    if (masterPtr->imageData != NULL) {
 
308
        if (masterPtr->imageData->width <= 0
 
309
                || masterPtr->imageData->height <= 0) goto error;
 
310
        oldMask = instancePtr->mask;
 
311
        instancePtr->mask = None;
 
312
        locattr.valuemask = XpmSize | XpmCloseness;
 
313
        locattr.closeness = 65536;
 
314
 
 
315
        XpmCreatePixmapFromXpmImage(dpy, xwind, masterPtr->imageData,
 
316
                &instancePtr->pixmap, &instancePtr->mask, &locattr);
 
317
        if (oldMask != None) {
 
318
            XFreePixmap(dpy, oldMask);
 
319
        }
 
320
    }
 
321
 
 
322
    /* Create the GC for copying the pixmap */
 
323
 
 
324
    if (masterPtr->imageData != NULL) {
 
325
        gcValues.graphics_exposures = False;
 
326
        gcmask = GCGraphicsExposures;
 
327
        gc = Tk_GetGC(instancePtr->tkwin, gcmask, &gcValues);
 
328
        XSetClipMask(dpy, gc, instancePtr->mask);
 
329
    } else {
 
330
        gc = None;
 
331
    }
 
332
    if (instancePtr->gc != None) {
 
333
        Tk_FreeGC(dpy, instancePtr->gc);
 
334
    }
 
335
    instancePtr->gc = gc;
 
336
    return;
 
337
 
 
338
error:
 
339
 
 
340
    /*
 
341
     * An error occurred: clear the graphics context in the instance to
 
342
     * make it clear that this instance cannot be displayed.  Then report
 
343
     * the error.
 
344
     */
 
345
 
 
346
    if (instancePtr->gc != None)
 
347
        Tk_FreeGC(dpy, instancePtr->gc);
 
348
    instancePtr->gc = None; 
 
349
 
 
350
    Tcl_AddErrorInfo(masterPtr->interp, "\n    (while configuring image \"");
 
351
    Tcl_AddErrorInfo(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
 
352
    Tcl_AddErrorInfo(masterPtr->interp, "\")");
 
353
    Tcl_BackgroundError(masterPtr->interp);
 
354
}
 
355
 
 
356
 
 
357
/*
 
358
 *--------------------------------------------------------------
 
359
 *
 
360
 * ImgXPMCmd --
 
361
 *
 
362
 *      This procedure is invoked to process the Tcl command
 
363
 *      that corresponds to an image managed by this module.
 
364
 *      See the user documentation for details on what it does.
 
365
 *
 
366
 * Results:
 
367
 *      A standard Tcl result.
 
368
 *
 
369
 * Side effects:
 
370
 *      See the user documentation.
 
371
 *
 
372
 *--------------------------------------------------------------
 
373
 */
 
374
 
 
375
static int
 
376
ImgXPMCmd(clientData, interp, objc, objv)
 
377
    ClientData clientData;      /* Information about the image master. */
 
378
    Tcl_Interp *interp;         /* Current interpreter. */
 
379
    int objc;                   /* Number of arguments. */
 
380
    Tcl_Obj *CONST objv[];      /* Argument objects. */
 
381
{
 
382
    static char *xpmOptions[] = {"cget", "configure", (char *) NULL};
 
383
    XPMMaster *masterPtr = (XPMMaster *) clientData;
 
384
    int code, index;
 
385
 
 
386
    if (objc < 2) {
 
387
        Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
 
388
        return TCL_ERROR;
 
389
    }
 
390
    if (Tcl_GetIndexFromObj(interp, objv[1], xpmOptions, "option", 0,
 
391
            &index) != TCL_OK) {
 
392
        return TCL_ERROR;
 
393
    }
 
394
    switch (index) {
 
395
      case 0: {
 
396
        if (objc != 3) {
 
397
            Tcl_WrongNumArgs(interp, 2, objv, "option");
 
398
            return TCL_ERROR;
 
399
        }
 
400
        return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
 
401
                (char *) masterPtr, Tcl_GetString(objv[2]), 0);
 
402
      }
 
403
      case 1: {
 
404
        if (objc == 2) {
 
405
            code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
 
406
                    configSpecs, (char *) masterPtr, (char *) NULL, 0);
 
407
        } else if (objc == 3) {
 
408
            code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
 
409
                    configSpecs, (char *) masterPtr,
 
410
                    Tcl_GetString(objv[2]), 0);
 
411
        } else {
 
412
            code = ImgXPMConfigureMaster(masterPtr, objc-2, objv+2,
 
413
                    TK_CONFIG_ARGV_ONLY);
 
414
        }
 
415
        return code;
 
416
      }
 
417
      default: {
 
418
        panic("bad const entries to xpmOptions in ImgXPMCmd");
 
419
      }
 
420
    }
 
421
    return TCL_OK;
 
422
}
 
423
 
 
424
/*
 
425
 *----------------------------------------------------------------------
 
426
 *
 
427
 * ImgXPMGet --
 
428
 *
 
429
 *      This procedure is called for each use of a xpm image in a
 
430
 *      widget.
 
431
 *
 
432
 * Results:
 
433
 *      The return value is a token for the instance, which is passed
 
434
 *      back to us in calls to ImgXPMDisplay and ImgXPMFree.
 
435
 *
 
436
 * Side effects:
 
437
 *      A data structure is set up for the instance (or, an existing
 
438
 *      instance is re-used for the new one).
 
439
 *
 
440
 *----------------------------------------------------------------------
 
441
 */
 
442
 
 
443
static ClientData
 
444
ImgXPMGet(tkwin, masterData)
 
445
    Tk_Window tkwin;            /* Window in which the instance will be
 
446
                                 * used. */
 
447
    ClientData masterData;      /* Pointer to our master structure for the
 
448
                                 * image. */
 
449
{
 
450
    XPMMaster *masterPtr = (XPMMaster *) masterData;
 
451
    XPMInstance *instancePtr;
 
452
 
 
453
    /*
 
454
     * See if there is already an instance for this window.  If so
 
455
     * then just re-use it.
 
456
     */
 
457
 
 
458
    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
 
459
            instancePtr = instancePtr->nextPtr) {
 
460
        if (instancePtr->tkwin == tkwin) {
 
461
            instancePtr->refCount++;
 
462
            return (ClientData) instancePtr;
 
463
        }
 
464
    }
 
465
 
 
466
    /*
 
467
     * The image isn't already in use in this window.  Make a new
 
468
     * instance of the image.
 
469
     */
 
470
 
 
471
    instancePtr = (XPMInstance *) Tcl_Alloc(sizeof(XPMInstance));
 
472
    instancePtr->refCount = 1;
 
473
    instancePtr->masterPtr = masterPtr;
 
474
    instancePtr->tkwin = tkwin;
 
475
    instancePtr->pixmap = None;
 
476
    instancePtr->mask = None;
 
477
    instancePtr->gc = None;
 
478
    instancePtr->nextPtr = masterPtr->instancePtr;
 
479
    masterPtr->instancePtr = instancePtr;
 
480
    ImgXPMConfigureInstance(instancePtr);
 
481
 
 
482
    /*
 
483
     * If this is the first instance, must set the size of the image.
 
484
     */
 
485
 
 
486
    if (instancePtr->nextPtr == NULL) {
 
487
        if (masterPtr->imageData != NULL)
 
488
            Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
 
489
                        masterPtr->imageData->width, masterPtr->imageData->height);
 
490
        else
 
491
            Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, 0, 0);
 
492
    }
 
493
 
 
494
    return (ClientData) instancePtr;
 
495
}
 
496
 
 
497
/*
 
498
 *----------------------------------------------------------------------
 
499
 *
 
500
 * ImgXPMDisplay --
 
501
 *
 
502
 *      This procedure is invoked to draw a xpm image.
 
503
 *
 
504
 * Results:
 
505
 *      None.
 
506
 *
 
507
 * Side effects:
 
508
 *      A portion of the image gets rendered in a pixmap or window.
 
509
 *
 
510
 *----------------------------------------------------------------------
 
511
 */
 
512
 
 
513
static void
 
514
ImgXPMDisplay(clientData, display, drawable, imageX, imageY, width,
 
515
        height, drawableX, drawableY)
 
516
    ClientData clientData;      /* Pointer to BitmapInstance structure for
 
517
                                 * for instance to be displayed. */
 
518
    Display *display;           /* Display on which to draw image. */
 
519
    Drawable drawable;          /* Pixmap or window in which to draw image. */
 
520
    int imageX, imageY;         /* Upper-left corner of region within image
 
521
                                 * to draw. */
 
522
    int width, height;          /* Dimensions of region within image to draw. */
 
523
    int drawableX, drawableY;   /* Coordinates within drawable that
 
524
                                 * correspond to imageX and imageY. */
 
525
{
 
526
    XPMInstance *instancePtr = (XPMInstance *) clientData;
 
527
    int masking;
 
528
 
 
529
    /*
 
530
     * If there's no GC, then an error occurred during image creation
 
531
     * and it should not be displayed.
 
532
     */
 
533
 
 
534
    if (instancePtr->gc == None) return;
 
535
 
 
536
    masking = (instancePtr->mask != None);
 
537
    if (masking) {
 
538
        XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
 
539
                drawableY - imageY);
 
540
    }
 
541
    XCopyArea(display, instancePtr->pixmap, drawable, instancePtr->gc,
 
542
            imageX, imageY, (unsigned) width, (unsigned) height,
 
543
            drawableX, drawableY);
 
544
    if (masking) {
 
545
        XSetClipOrigin(display, instancePtr->gc, 0, 0);
 
546
    }
 
547
}
 
548
 
 
549
/*
 
550
 *----------------------------------------------------------------------
 
551
 *
 
552
 * ImgXPMFree --
 
553
 *
 
554
 *      This procedure is called when a widget ceases to use a
 
555
 *      particular instance of an image.
 
556
 *
 
557
 * Results:
 
558
 *      None.
 
559
 *
 
560
 * Side effects:
 
561
 *      Internal data structures get cleaned up.
 
562
 *
 
563
 *----------------------------------------------------------------------
 
564
 */
 
565
 
 
566
static void
 
567
ImgXPMFree(clientData, display)
 
568
    ClientData clientData;      /* Pointer to BitmapInstance structure for
 
569
                                 * for instance to be displayed. */
 
570
    Display *display;           /* Display containing window that used image. */
 
571
{
 
572
    XPMInstance *instancePtr = (XPMInstance *) clientData;
 
573
    XPMInstance *prevPtr;
 
574
 
 
575
    instancePtr->refCount--;
 
576
    if (instancePtr->refCount > 0) {
 
577
        return;
 
578
    }
 
579
 
 
580
    /*
 
581
     * There are no more uses of the image within this widget.  Free
 
582
     * the instance structure.
 
583
     */
 
584
 
 
585
    if (instancePtr->pixmap != None) {
 
586
        XFreePixmap(display, instancePtr->pixmap);
 
587
    }
 
588
    if (instancePtr->mask != None) {
 
589
        XFreePixmap(display, instancePtr->mask);
 
590
    }
 
591
    if (instancePtr->masterPtr->instancePtr == instancePtr) {
 
592
        instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
 
593
    } else {
 
594
        for (prevPtr = instancePtr->masterPtr->instancePtr;
 
595
                prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
 
596
            /* Empty loop body */
 
597
        }
 
598
        prevPtr->nextPtr = instancePtr->nextPtr;
 
599
    }
 
600
    Tcl_Free((char *) instancePtr);
 
601
}
 
602
 
 
603
/*
 
604
 *----------------------------------------------------------------------
 
605
 *
 
606
 * ImgXPMDelete --
 
607
 *
 
608
 *      This procedure is called by the image code to delete the
 
609
 *      master structure for an image.
 
610
 *
 
611
 * Results:
 
612
 *      None.
 
613
 *
 
614
 * Side effects:
 
615
 *      Resources associated with the image get freed.
 
616
 *
 
617
 *----------------------------------------------------------------------
 
618
 */
 
619
 
 
620
static void
 
621
ImgXPMDelete(masterData)
 
622
    ClientData masterData;      /* Pointer to BitmapMaster structure for
 
623
                                 * image.  Must not have any more instances. */
 
624
{
 
625
    XPMMaster *masterPtr = (XPMMaster *) masterData;
 
626
 
 
627
    if (masterPtr->instancePtr != NULL) {
 
628
        panic("tried to delete xpm image when instances still exist");
 
629
    }
 
630
    masterPtr->tkMaster = NULL;
 
631
    if (masterPtr->imageCmd != NULL) {
 
632
        Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);
 
633
    }
 
634
    if (masterPtr->imageData != NULL) {
 
635
        XpmFreeXpmImage(masterPtr->imageData);
 
636
    }
 
637
    if (masterPtr->imageInfo != NULL) {
 
638
        XpmFreeXpmInfo(masterPtr->imageInfo);
 
639
    }
 
640
    Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0);
 
641
    Tcl_Free((char *) masterPtr);
 
642
}
 
643
 
 
644
/*
 
645
 *----------------------------------------------------------------------
 
646
 *
 
647
 * ImgXPMCmdDeletedProc --
 
648
 *
 
649
 *      This procedure is invoked when the image command for an image
 
650
 *      is deleted.  It deletes the image.
 
651
 *
 
652
 * Results:
 
653
 *      None.
 
654
 *
 
655
 * Side effects:
 
656
 *      The image is deleted.
 
657
 *
 
658
 *----------------------------------------------------------------------
 
659
 */
 
660
 
 
661
static void
 
662
ImgXPMCmdDeletedProc(clientData)
 
663
    ClientData clientData;      /* Pointer to BitmapMaster structure for
 
664
                                 * image. */
 
665
{
 
666
    XPMMaster *masterPtr = (XPMMaster *) clientData;
 
667
 
 
668
    masterPtr->imageCmd = NULL;
 
669
    if (masterPtr->tkMaster != NULL) {
 
670
        Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
 
671
    }
 
672
}
 
673
 
 
674
/*
 
675
 *---------------------------------------------------------
 
676
 * register the XPM image type with the Tk "image" command
 
677
 *---------------------------------------------------------
 
678
 */
 
679
 
 
680
void
 
681
RegisterXPMImageType()
 
682
{
 
683
    Tk_CreateImageType(&tkXPMImageType);
 
684
}
 
685
 
 
686
#endif   /* TCL_WRAPPER && HAVE_XPM */