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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tix/] [generic/] [tixImgXpm.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
 * tixImgXpm.c --
3
 *
4
 *      This file implements images of type "pixmap" for Tix.
5
 *
6
 * Copyright (c) 1996, Expert Interface Technologies
7
 *
8
 * See the file "license.terms" for information on usage and redistribution
9
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10
 *
11
 */
12
 
13
#include <tixPort.h>
14
#include <tixInt.h>
15
#include <tixImgXpm.h>
16
 
17
/*
18
 * Prototypes for procedures used only locally in this file:
19
 */
20
 
21
static int              ImgXpmCreate _ANSI_ARGS_((Tcl_Interp *interp,
22
                            char *name, int argc, char **argv,
23
                            Tk_ImageType *typePtr, Tk_ImageMaster master,
24
                            ClientData *clientDataPtr));
25
static ClientData       ImgXpmGet _ANSI_ARGS_((Tk_Window tkwin,
26
                            ClientData clientData));
27
static void             ImgXpmDisplay _ANSI_ARGS_((ClientData clientData,
28
                            Display *display, Drawable drawable,
29
                            int imageX, int imageY, int width, int height,
30
                            int drawableX, int drawableY));
31
static void             ImgXpmFree _ANSI_ARGS_((ClientData clientData,
32
                            Display *display));
33
static void             ImgXpmDelete _ANSI_ARGS_((ClientData clientData));
34
static int              ImgXpmCmd _ANSI_ARGS_((ClientData clientData,
35
                            Tcl_Interp *interp, int argc, char **argv));
36
static void             ImgXpmCmdDeletedProc _ANSI_ARGS_((
37
                            ClientData clientData));
38
static void             ImgXpmConfigureInstance _ANSI_ARGS_((
39
                            PixmapInstance *instancePtr));
40
static int              ImgXpmConfigureMaster _ANSI_ARGS_((
41
                            PixmapMaster *masterPtr, int argc, char **argv,
42
                            int flags));
43
static int              ImgXpmGetData _ANSI_ARGS_((Tcl_Interp *interp,
44
                            PixmapMaster *masterPtr));
45
static char **          ImgXpmGetDataFromFile _ANSI_ARGS_((Tcl_Interp * interp,
46
                            char * string, int * numLines_return));
47
static char **          ImgXpmGetDataFromId _ANSI_ARGS_((Tcl_Interp * interp,
48
                            char * id));
49
static char **          ImgXpmGetDataFromString _ANSI_ARGS_((Tcl_Interp*interp,
50
                            char * string, int * numLines_return));
51
static void             ImgXpmGetPixmapFromData _ANSI_ARGS_((
52
                            Tcl_Interp * interp,
53
                            PixmapMaster *masterPtr,
54
                            PixmapInstance *instancePtr));
55
static char *           GetType _ANSI_ARGS_((char * colorDefn,
56
                            int  * type_ret));
57
static char *           GetColor _ANSI_ARGS_((char * colorDefn,
58
                            char * colorName, int * type_ret));
59
 
60
/*
61
 * Information used for parsing configuration specs:
62
 */
63
 
64
static Tk_ConfigSpec configSpecs[] = {
65
    {TK_CONFIG_STRING, "-data", (char *) NULL, (char *) NULL,
66
        (char *) NULL, Tk_Offset(PixmapMaster, dataString), TK_CONFIG_NULL_OK},
67
    {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
68
        (char *) NULL, Tk_Offset(PixmapMaster, fileString), TK_CONFIG_NULL_OK},
69
    {TK_CONFIG_UID, "-id", (char *) NULL, (char *) NULL,
70
        (char *) NULL, Tk_Offset(PixmapMaster, id), TK_CONFIG_NULL_OK},
71
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
72
        (char *) NULL, 0, 0}
73
};
74
 
75
Tk_ImageType tixPixmapImageType = {
76
    "pixmap",                   /* name */
77
    ImgXpmCreate,               /* createProc */
78
    ImgXpmGet,                  /* getProc */
79
    ImgXpmDisplay,              /* displayProc */
80
    ImgXpmFree,                 /* freeProc */
81
    ImgXpmDelete,               /* deleteProc */
82
    (Tk_ImageType *) NULL       /* nextPtr */
83
};
84
 
85
/*
86
 * Local data, used only in this file
87
 */
88
 
89
static Tcl_HashTable xpmTable;
90
static int xpmTableInited = 0;
91
 
92
 
93
/*
94
 *----------------------------------------------------------------------
95
 *
96
 * ImgXpmCreate --
97
 *
98
 *      This procedure is called by the Tk image code to create "pixmap"
99
 *      images.
100
 *
101
 * Results:
102
 *      A standard Tcl result.
103
 *
104
 * Side effects:
105
 *      The data structure for a new image is allocated.
106
 *
107
 *----------------------------------------------------------------------
108
 */
109
static int
110
ImgXpmCreate(interp, name, argc, argv, typePtr, master, clientDataPtr)
111
    Tcl_Interp *interp;         /* Interpreter for application containing
112
                                 * image. */
113
    char *name;                 /* Name to use for image. */
114
    int argc;                   /* Number of arguments. */
115
    char **argv;                /* Argument strings for options (doesn't
116
                                 * include image name or type). */
117
    Tk_ImageType *typePtr;      /* Pointer to our type record (not used). */
118
    Tk_ImageMaster master;      /* Token for image, to be used by us in
119
                                 * later callbacks. */
120
    ClientData *clientDataPtr;  /* Store manager's token for image here;
121
                                 * it will be returned in later callbacks. */
122
{
123
    PixmapMaster *masterPtr;
124
 
125
    masterPtr = (PixmapMaster *) ckalloc(sizeof(PixmapMaster));
126
    masterPtr->tkMaster = master;
127
    masterPtr->interp = interp;
128
    masterPtr->imageCmd = Tcl_CreateCommand(interp, name, ImgXpmCmd,
129
            (ClientData) masterPtr, ImgXpmCmdDeletedProc);
130
 
131
    masterPtr->fileString = NULL;
132
    masterPtr->dataString = NULL;
133
    masterPtr->id = NULL;
134
    masterPtr->data = NULL;
135
    masterPtr->isDataAlloced = 0;
136
    masterPtr->instancePtr = NULL;
137
 
138
    if (ImgXpmConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) {
139
        ImgXpmDelete((ClientData) masterPtr);
140
        return TCL_ERROR;
141
    }
142
    *clientDataPtr = (ClientData) masterPtr;
143
    return TCL_OK;
144
}
145
 
146
/*
147
 *----------------------------------------------------------------------
148
 *
149
 * ImgXpmConfigureMaster --
150
 *
151
 *      This procedure is called when a pixmap image is created or
152
 *      reconfigured.  It process configuration options and resets
153
 *      any instances of the image.
154
 *
155
 * Results:
156
 *      A standard Tcl return value.  If TCL_ERROR is returned then
157
 *      an error message is left in masterPtr->interp->result.
158
 *
159
 * Side effects:
160
 *      Existing instances of the image will be redisplayed to match
161
 *      the new configuration options.
162
 *
163
 *      If any error occurs, the state of *masterPtr is restored to
164
 *      previous state.
165
 *
166
 *----------------------------------------------------------------------
167
 */
168
static int
169
ImgXpmConfigureMaster(masterPtr, argc, argv, flags)
170
    PixmapMaster *masterPtr;    /* Pointer to data structure describing
171
                                 * overall pixmap image to (reconfigure). */
172
    int argc;                   /* Number of entries in argv. */
173
    char **argv;                /* Pairs of configuration options for image. */
174
    int flags;                  /* Flags to pass to Tk_ConfigureWidget,
175
                                 * such as TK_CONFIG_ARGV_ONLY. */
176
{
177
    PixmapInstance *instancePtr;
178
    char * oldData, * oldFile;
179
    Tk_Uid oldId;
180
 
181
    oldData = masterPtr->dataString;
182
    oldFile = masterPtr->fileString;
183
    oldId   = masterPtr->id;
184
 
185
    if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp),
186
            configSpecs, argc, argv, (char *) masterPtr, flags)
187
            != TCL_OK) {
188
        return TCL_ERROR;
189
    }
190
 
191
    if (masterPtr->id != NULL ||
192
        masterPtr->dataString != NULL ||
193
        masterPtr->fileString != NULL) {
194
        if (ImgXpmGetData(masterPtr->interp, masterPtr) != TCL_OK) {
195
            goto error;
196
        }
197
    } else {
198
        Tcl_AppendResult(masterPtr->interp,
199
            "must specify one of -data, -file or -id", NULL);
200
        goto error;
201
    }
202
 
203
    /*
204
     * Cycle through all of the instances of this image, regenerating
205
     * the information for each instance.  Then force the image to be
206
     * redisplayed everywhere that it is used.
207
     */
208
    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
209
        instancePtr = instancePtr->nextPtr) {
210
        ImgXpmConfigureInstance(instancePtr);
211
    }
212
 
213
    if (masterPtr->data) {
214
        Tk_ImageChanged(masterPtr->tkMaster, 0, 0,
215
            masterPtr->size[0], masterPtr->size[1],
216
            masterPtr->size[0], masterPtr->size[1]);
217
    } else {
218
        Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, 0, 0);
219
    }
220
 
221
    return TCL_OK;
222
 
223
  error:
224
    /* Restore it to the original (possible valid) mode */
225
    if (masterPtr->dataString && masterPtr->dataString != oldData) {
226
        ckfree(masterPtr->dataString);
227
    }
228
    if (masterPtr->fileString && masterPtr->fileString != oldFile) {
229
        ckfree(masterPtr->fileString);
230
    }
231
    masterPtr->dataString = oldData;
232
    masterPtr->fileString = oldFile;
233
    masterPtr->id = oldId;
234
    return TCL_ERROR;
235
}
236
 
237
/*
238
 *----------------------------------------------------------------------
239
 *
240
 * ImgXpmGetData --
241
 *
242
 *      Given a file name or ASCII string, this procedure parses the
243
 *      file or string contents to produce binary data for a pixmap.
244
 *
245
 * Results:
246
 *      If the pixmap description was parsed successfully then the data
247
 *      is read into an array of strings. This array will later be used
248
 *      to create X Pixmaps for each instance.
249
 *
250
 * Side effects:
251
 *      The masterPtr->data array is allocated when successful. Contents of
252
 *      *masterPtr is changed only when successful.
253
 *----------------------------------------------------------------------
254
 */
255
static int
256
ImgXpmGetData(interp, masterPtr)
257
    Tcl_Interp *interp;                 /* For reporting errors. */
258
    PixmapMaster *masterPtr;
259
{
260
    char ** data = NULL;
261
    int  isAllocated;                   /* do we need to free "data"? */
262
    int listArgc;
263
    char ** listArgv = NULL;
264
    int numLines;
265
    int size[2];
266
    int cpp;
267
    int ncolors;
268
    int code = TCL_OK;
269
 
270
    if (masterPtr->id != NULL) {
271
        data = ImgXpmGetDataFromId(interp, masterPtr->id);
272
        isAllocated = 0;
273
    }
274
    else if (masterPtr->fileString != NULL) {
275
        data = ImgXpmGetDataFromFile(interp, masterPtr->fileString, &numLines);
276
        isAllocated = 1;
277
    }
278
    else if (masterPtr->dataString != NULL) {
279
        data = ImgXpmGetDataFromString(interp,masterPtr->dataString,&numLines);
280
        isAllocated = 1;
281
    }
282
    else {
283
        /* Should have been enforced by ImgXpmConfigureMaster() */
284
        panic("ImgXpmGetData(): -data, -file and -id are all NULL");
285
    }
286
 
287
    if (data == NULL) {
288
        /* nothing has been allocated yet. Don't need to goto done */
289
        return TCL_ERROR;
290
    }
291
 
292
    /* Parse the first line of the data and get info about this pixmap */
293
    if (Tcl_SplitList(interp, data[0], &listArgc, &listArgv) != TCL_OK) {
294
        code = TCL_ERROR; goto done;
295
    }
296
 
297
    if (listArgc < 4) { /* file format error */
298
        code = TCL_ERROR; goto done;
299
    }
300
 
301
    if (Tcl_GetInt(interp, listArgv[0], &size[0]) != TCL_OK) {
302
        code = TCL_ERROR; goto done;
303
    }
304
    if (Tcl_GetInt(interp, listArgv[1], &size[1]) != TCL_OK) {
305
        code = TCL_ERROR; goto done;
306
    }
307
    if (Tcl_GetInt(interp, listArgv[2], &ncolors) != TCL_OK) {
308
        code = TCL_ERROR; goto done;
309
    }
310
    if (Tcl_GetInt(interp, listArgv[3], &cpp) != TCL_OK) {
311
        code = TCL_ERROR; goto done;
312
    }
313
 
314
    if (isAllocated) {
315
        if (numLines != size[1] + ncolors + 1) {
316
            /* the number of lines read from the file/data
317
             * is not the same as specified in the data
318
             */
319
            code = TCL_ERROR; goto done;
320
        }
321
    }
322
 
323
  done:
324
    if (code == TCL_OK) {
325
        if (masterPtr->isDataAlloced && masterPtr->data) {
326
            ckfree((char*)masterPtr->data);
327
        }
328
        masterPtr->isDataAlloced = isAllocated;
329
        masterPtr->data = data;
330
        masterPtr->size[0] = size[0];
331
        masterPtr->size[1] = size[1];
332
        masterPtr->cpp = cpp;
333
        masterPtr->ncolors = ncolors;
334
    } else {
335
        if (isAllocated && data) {
336
            ckfree((char*)data);
337
        }
338
 
339
        Tcl_ResetResult(interp);
340
        Tcl_AppendResult(interp, "File format error", NULL);
341
    }
342
 
343
    if (listArgv) {
344
        ckfree((char*)listArgv);
345
    }
346
 
347
    return code;
348
}
349
 
350
static char ** ImgXpmGetDataFromId(interp, id)
351
    Tcl_Interp * interp;
352
    char * id;
353
{
354
    Tcl_HashEntry * hashPtr;
355
 
356
    if (xpmTableInited == 0) {
357
        hashPtr = NULL;
358
    } else {
359
        hashPtr = Tcl_FindHashEntry(&xpmTable, id);
360
    }
361
 
362
    if (hashPtr == NULL) {
363
        Tcl_AppendResult(interp, "unknown pixmap ID \"", id,
364
            "\"", NULL);
365
        return (char**)NULL;
366
    } else {
367
        return (char**)Tcl_GetHashValue(hashPtr);
368
    }
369
}
370
 
371
static char ** ImgXpmGetDataFromString(interp, string, numLines_return)
372
    Tcl_Interp * interp;
373
    char * string;
374
    int * numLines_return;
375
{
376
    int quoted;
377
    char * p, * list;
378
    int numLines;
379
    char ** data;
380
 
381
    /* skip the leading blanks (leading blanks are not defined in the
382
     * the XPM definition, but skipping them shouldn't hurt. Also, the ability
383
     * to skip the leading blanks is good for using in-line XPM data in TCL
384
     * scripts
385
     */
386
    while (isspace(*string)) {
387
        ++ string;
388
    }
389
 
390
    /* parse the header */
391
    if (strncmp("/* XPM", string, 6) != 0) {
392
        goto error;
393
    }
394
 
395
    /* strip the comments */
396
    for (quoted = 0, p=string; *p;) {
397
        if (!quoted) {
398
            if (*p == '"') {
399
                quoted = 1;
400
                ++ p;
401
                continue;
402
            }
403
 
404
            if (*p == '/' && *(p+1) == '*') {
405
                *p++ = ' ';
406
                *p++ = ' ';
407
                while (1) {
408
                    if (*p == 0) {
409
                        break;
410
                    }
411
                    if (*p == '*' && *(p+1) == '/') {
412
                        *p++ = ' ';
413
                        *p++ = ' ';
414
                        break;
415
                    }
416
                    *p++ = ' ';
417
                }
418
                continue;
419
            }
420
            ++ p;
421
        } else {
422
            if (*p == '"') {
423
                quoted = 0;
424
            }
425
            ++ p;
426
        }
427
    }
428
 
429
    /* Search for the opening brace */
430
    for (p=string; *p;) {
431
        if (*p != '{') {
432
            ++ p;
433
        } else {
434
            ++p;
435
            break;
436
        }
437
    }
438
 
439
    /* Change the buffer in to a proper TCL list */
440
    quoted = 0;
441
    list = p;
442
 
443
    while (*p) {
444
        if (!quoted) {
445
            if (*p == '"') {
446
                quoted = 1;
447
                ++ p;
448
                continue;
449
            }
450
 
451
            if (isspace(*p)) {
452
                *p = ' ';
453
            }
454
            else if (*p == ',') {
455
                *p = ' ';
456
            }
457
            else if (*p == '}') {
458
                *p = 0;
459
                break;
460
            }
461
            ++p;
462
        }
463
        else {
464
            if (*p == '"') {
465
                quoted = 0;
466
            }
467
            ++ p;
468
        }
469
    }
470
 
471
    /* The following code depends on the fact that Tcl_SplitList
472
     * strips away double quoates inside a list: ie:
473
     * if string == "\"1\" \"2\"" then
474
     *          list[0] = "1"
475
     *          list[1] = "2"
476
     * and NOT
477
     *
478
     *          list[0] = "\"1\""
479
     *          list[1] = "\"2\""
480
     */
481
    if (Tcl_SplitList(interp, list, &numLines, &data) != TCL_OK) {
482
        goto error;
483
    } else {
484
        if (numLines == 0) {
485
            /* error: empty data? */
486
            if (data != NULL) {
487
                ckfree((char*)data);
488
                goto error;
489
            }
490
        }
491
        * numLines_return = numLines;
492
        return data;
493
    }
494
 
495
  error:
496
    Tcl_AppendResult(interp, "File format error", NULL);
497
    return (char**) NULL;
498
}
499
 
500
static char ** ImgXpmGetDataFromFile(interp, fileName, numLines_return)
501
    Tcl_Interp * interp;
502
    char * fileName;
503
    int * numLines_return;
504
{
505
    int fileId, size;
506
    char ** data;
507
    struct stat statBuf;
508
    char *cmdBuffer = NULL;
509
    Tcl_DString buffer;                 /* initialized by Tcl_TildeSubst */
510
 
511
    fileName = Tcl_TildeSubst(interp, fileName, &buffer);
512
    if (fileName == NULL) {
513
        goto error;
514
    }
515
 
516
    fileId = open(fileName, O_RDONLY, 0);
517
    if (fileId < 0) {
518
        Tcl_AppendResult(interp, "couldn't read file \"", fileName,
519
                "\": ", Tcl_PosixError(interp), (char *) NULL);
520
        goto error;
521
    }
522
    if (fstat(fileId, &statBuf) == -1) {
523
        Tcl_AppendResult(interp, "couldn't stat file \"", fileName,
524
                "\": ", Tcl_PosixError(interp), (char *) NULL);
525
        close(fileId);
526
        goto error;
527
    }
528
    cmdBuffer = (char *) ckalloc((unsigned) statBuf.st_size+1);
529
    size = read(fileId, cmdBuffer, (size_t) statBuf.st_size);
530
    if (size < 0) {
531
        Tcl_AppendResult(interp, "error in reading file \"", fileName,
532
                "\": ", Tcl_PosixError(interp), (char *) NULL);
533
        close(fileId);
534
        goto error;
535
    }
536
    if (close(fileId) != 0) {
537
        Tcl_AppendResult(interp, "error closing file \"", fileName,
538
                "\": ", Tcl_PosixError(interp), (char *) NULL);
539
        goto error;
540
    }
541
    cmdBuffer[size] = 0;
542
 
543
    data = ImgXpmGetDataFromString(interp, cmdBuffer, numLines_return);
544
    ckfree(cmdBuffer);
545
    Tcl_DStringFree(&buffer);
546
    return data;
547
 
548
  error:
549
    if (cmdBuffer != NULL) {
550
        ckfree(cmdBuffer);
551
    }
552
    Tcl_DStringFree(&buffer);
553
    return (char**)NULL;
554
}
555
 
556
 
557
static char *
558
GetType(colorDefn, type_ret)
559
    char * colorDefn;
560
    int  * type_ret;
561
{
562
    char * p = colorDefn;
563
 
564
    /* skip white spaces */
565
    while (*p && isspace(*p)) {
566
        p ++;
567
    }
568
 
569
    /* parse the type */
570
    if (p[0] != '\0' && p[0] == 'm' &&
571
        p[1] != '\0' && isspace(p[1])) {
572
        *type_ret = XPM_MONO;
573
        p += 2;
574
    }
575
    else if (p[0] != '\0' && p[0] == 'g' &&
576
             p[1] != '\0' && p[1] == '4' &&
577
             p[2] != '\0' && isspace(p[2])) {
578
        *type_ret = XPM_GRAY_4;
579
        p += 3;
580
    }
581
    else if (p[0] != '\0' && p[0] == 'g' &&
582
             p[1] != '\0' && isspace(p[1])) {
583
        *type_ret = XPM_GRAY;
584
        p += 2;
585
    }
586
    else if (p[0] != '\0' && p[0] == 'c' &&
587
             p[1] != '\0' && isspace(p[1])) {
588
        *type_ret = XPM_COLOR;
589
        p += 2;
590
    }
591
    else if (p[0] != '\0' && p[0] == 's' &&
592
             p[1] != '\0' && isspace(p[1])) {
593
        *type_ret = XPM_SYMBOLIC;
594
        p += 2;
595
    }
596
    else {
597
        *type_ret = XPM_UNKNOWN;
598
        return NULL;
599
    }
600
 
601
    return p;
602
}
603
 
604
/*
605
 * colorName is guaranteed to be big enough
606
 */
607
static char *
608
GetColor(colorDefn, colorName, type_ret)
609
    char * colorDefn;
610
    char * colorName;           /* if found, name is copied to this array */
611
    int  * type_ret;
612
{
613
    int type;
614
    char * p;
615
 
616
    if (!colorDefn) {
617
        return NULL;
618
    }
619
 
620
    if ((colorDefn = GetType(colorDefn, &type)) == NULL) {
621
        /* unknown type */
622
        return NULL;
623
    }
624
    else {
625
        *type_ret = type;
626
    }
627
 
628
    /* skip white spaces */
629
    while (*colorDefn && isspace(*colorDefn)) {
630
        colorDefn ++;
631
    }
632
 
633
    p = colorName;
634
 
635
    while (1) {
636
        int dummy;
637
 
638
        while (*colorDefn && !isspace(*colorDefn)) {
639
            *p++ = *colorDefn++;
640
        }
641
 
642
        if (!*colorDefn) {
643
            break;
644
        }
645
 
646
        if (GetType(colorDefn, &dummy) == NULL) {
647
            /* the next string should also be considered as a part of a color
648
             * name */
649
 
650
            while (*colorDefn && isspace(*colorDefn)) {
651
                *p++ = *colorDefn++;
652
            }
653
        } else {
654
            break;
655
        }
656
        if (!*colorDefn) {
657
            break;
658
        }
659
    }
660
 
661
    /* Mark the end of the colorName */
662
    *p = '\0';
663
 
664
    return colorDefn;
665
}
666
 
667
/*----------------------------------------------------------------------
668
 * ImgXpmGetPixmapFromData --
669
 *
670
 *      Creates a pixmap for an image instance.
671
 *----------------------------------------------------------------------
672
 */
673
static void
674
ImgXpmGetPixmapFromData(interp, masterPtr, instancePtr)
675
    Tcl_Interp * interp;
676
    PixmapMaster *masterPtr;
677
    PixmapInstance *instancePtr;
678
{
679
    XImage * image = NULL, * mask = NULL;
680
    int depth, i, j, k, lOffset, isTransp = 0, isMono;
681
    ColorStruct * colors;
682
 
683
    depth = Tk_Depth(instancePtr->tkwin);
684
 
685
    switch ((Tk_Visual(instancePtr->tkwin))->class) {
686
      case StaticGray:
687
      case GrayScale:
688
        isMono = 1;
689
        break;
690
      default:
691
        isMono = 0;
692
    }
693
 
694
    TixpXpmAllocTmpBuffer(masterPtr, instancePtr, &image, &mask);
695
 
696
    /*
697
     * Parse the colors
698
     */
699
    lOffset = 1;
700
    colors = (ColorStruct*)ckalloc(sizeof(ColorStruct)*masterPtr->ncolors);
701
 
702
    /*
703
     * Initialize the color structures
704
     */
705
    for (i=0; i<masterPtr->ncolors; i++) {
706
        colors[i].colorPtr = NULL;
707
        if (masterPtr->cpp == 1) {
708
            colors[i].c = 0;
709
        } else {
710
            colors[i].cstring = (char*)ckalloc(masterPtr->cpp);
711
            colors[i].cstring[0] = 0;
712
        }
713
    }
714
 
715
    for (i=0; i<masterPtr->ncolors; i++) {
716
        char * colorDefn;               /* the color definition line */
717
        char * colorName;               /* temp place to hold the color name
718
                                         * defined for one type of visual */
719
        char * useName;                 /* the color name used for this
720
                                         * color. If there are many names
721
                                         * defined, choose the name that is
722
                                         * "best" for the target visual
723
                                         */
724
        int found;
725
 
726
        colorDefn = masterPtr->data[i+lOffset]+masterPtr->cpp;
727
        colorName = (char*)ckalloc(strlen(colorDefn));
728
        useName   = (char*)ckalloc(strlen(colorDefn));
729
        found     = 0;
730
 
731
        while (colorDefn && *colorDefn) {
732
            int type;
733
 
734
            if ((colorDefn=GetColor(colorDefn, colorName, &type)) == NULL) {
735
                break;
736
            }
737
            if (colorName[0] == '\0') {
738
                continue;
739
            }
740
 
741
            switch (type) {
742
              case XPM_MONO:
743
                if (isMono && depth == 1) {
744
                    strcpy(useName, colorName);
745
                    found = 1; goto gotcolor;
746
                }
747
                break;
748
              case XPM_GRAY_4:
749
                if (isMono && depth == 4) {
750
                    strcpy(useName, colorName);
751
                    found = 1; goto gotcolor;
752
                }
753
                break;
754
              case XPM_GRAY:
755
                if (isMono && depth > 4) {
756
                    strcpy(useName, colorName);
757
                    found = 1; goto gotcolor;
758
                }
759
                break;
760
              case XPM_COLOR:
761
                if (!isMono) {
762
                    strcpy(useName, colorName);
763
                    found = 1; goto gotcolor;
764
                }
765
                break;
766
            }
767
            if (type != XPM_SYMBOLIC && type != XPM_UNKNOWN) {
768
                if (!found) {                   /* use this color as default */
769
                    strcpy(useName, colorName);
770
                    found = 1;
771
                }
772
            }
773
        }
774
 
775
      gotcolor:
776
        if (masterPtr->cpp == 1) {
777
            colors[i].c = masterPtr->data[i+lOffset][0];
778
        } else {
779
            strncpy(colors[i].cstring, masterPtr->data[i+lOffset],
780
                (size_t)masterPtr->cpp);
781
        }
782
 
783
        if (found) {
784
            if (strcasecmp(useName, "none") != 0) {
785
                colors[i].colorPtr = Tk_GetColor(interp,
786
                    instancePtr->tkwin, Tk_GetUid(useName));
787
                if (colors[i].colorPtr == NULL) {
788
                    colors[i].colorPtr = Tk_GetColor(interp,
789
                        instancePtr->tkwin, Tk_GetUid("black"));
790
                }
791
            }
792
        } else {
793
            colors[i].colorPtr = Tk_GetColor(interp,
794
                instancePtr->tkwin, Tk_GetUid("black"));
795
        }
796
 
797
        ckfree(colorName);
798
        ckfree(useName);
799
    }
800
 
801
    lOffset += masterPtr->ncolors;
802
 
803
    /*
804
     * Parse the main body of the image
805
     */
806
    for (i=0; i<masterPtr->size[1]; i++) {
807
        char * p = masterPtr->data[i+lOffset];
808
 
809
        for (j=0; j<masterPtr->size[0]; j++) {
810
            if (masterPtr->cpp == 1) {
811
                for (k=0; k<masterPtr->ncolors; k++) {
812
                    if (*p == colors[k].c) {
813
                        TixpXpmSetPixel(instancePtr, image, mask, j, i,
814
                                colors[k].colorPtr, &isTransp);
815
                        break;
816
                    }
817
                }
818
                if (*p) {
819
                    p++;
820
                }
821
            } else {
822
                for (k=0; k<masterPtr->ncolors; k++) {
823
                    if (strncmp(p, colors[k].cstring,
824
                            (size_t)masterPtr->cpp) == 0) {
825
                        TixpXpmSetPixel(instancePtr, image, mask, j, i,
826
                                colors[k].colorPtr, &isTransp);
827
                        break;
828
                    }
829
                }
830
                for (k=0; *p && k<masterPtr->cpp; k++) {
831
                    p++;
832
                }
833
            }
834
        }
835
    }
836
 
837
    instancePtr->colors = colors;
838
 
839
    TixpXpmRealizePixmap(masterPtr, instancePtr, image, mask, isTransp);
840
    TixpXpmFreeTmpBuffer(masterPtr, instancePtr, image, mask);
841
}
842
 
843
/*
844
 *----------------------------------------------------------------------
845
 *
846
 * ImgXpmConfigureInstance --
847
 *
848
 *      This procedure is called to create displaying information for
849
 *      a pixmap image instance based on the configuration information
850
 *      in the master.  It is invoked both when new instances are
851
 *      created and when the master is reconfigured.
852
 *
853
 * Results:
854
 *      None.
855
 *
856
 * Side effects:
857
 *      Generates errors via Tk_BackgroundError if there are problems
858
 *      in setting up the instance.
859
 *
860
 *----------------------------------------------------------------------
861
 */
862
static void
863
ImgXpmConfigureInstance(instancePtr)
864
    PixmapInstance *instancePtr;        /* Instance to reconfigure. */
865
{
866
    PixmapMaster *masterPtr = instancePtr->masterPtr;
867
 
868
    if (instancePtr->pixmap != None) {
869
        Tk_FreePixmap(Tk_Display(instancePtr->tkwin), instancePtr->pixmap);
870
    }
871
    TixpXpmFreeInstanceData(instancePtr, 0, Tk_Display(instancePtr->tkwin));
872
 
873
    if (instancePtr->colors != NULL) {
874
        int i;
875
        for (i=0; i<masterPtr->ncolors; i++) {
876
            if (instancePtr->colors[i].colorPtr != NULL) {
877
                Tk_FreeColor(instancePtr->colors[i].colorPtr);
878
            }
879
            if (masterPtr->cpp != 1) {
880
                ckfree(instancePtr->colors[i].cstring);
881
            }
882
        }
883
        ckfree((char*)instancePtr->colors);
884
    }
885
 
886
    if (Tk_WindowId(instancePtr->tkwin) == None) {
887
        Tk_MakeWindowExist(instancePtr->tkwin);
888
    }
889
 
890
    /*
891
     * Assumption: masterPtr->data is always non NULL (enfored by
892
     * ImgXpmConfigureMaster()). Also, the data must be in a valid
893
     * format (partially enforced by ImgXpmConfigureMaster(), see comments
894
     * inside that function).
895
     */
896
    ImgXpmGetPixmapFromData(masterPtr->interp, masterPtr, instancePtr);
897
}
898
 
899
/*
900
 *--------------------------------------------------------------
901
 *
902
 * ImgXpmCmd --
903
 *
904
 *      This procedure is invoked to process the Tcl command
905
 *      that corresponds to an image managed by this module.
906
 *      See the user documentation for details on what it does.
907
 *
908
 * Results:
909
 *      A standard Tcl result.
910
 *
911
 * Side effects:
912
 *      See the user documentation.
913
 *
914
 *--------------------------------------------------------------
915
 */
916
 
917
static int
918
ImgXpmCmd(clientData, interp, argc, argv)
919
    ClientData clientData;      /* Information about button widget. */
920
    Tcl_Interp *interp;         /* Current interpreter. */
921
    int argc;                   /* Number of arguments. */
922
    char **argv;                /* Argument strings. */
923
{
924
    PixmapMaster *masterPtr = (PixmapMaster *) clientData;
925
    int c, code;
926
    size_t length;
927
 
928
    if (argc < 2) {
929
        sprintf(interp->result,
930
            "wrong # args: should be \"%.50s option ?arg arg ...?\"",
931
            argv[0]);
932
        return TCL_ERROR;
933
    }
934
    c = argv[1][0];
935
    length = strlen(argv[1]);
936
 
937
    if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
938
            && (length >= 2)) {
939
        if (argc != 3) {
940
            Tcl_AppendResult(interp, "wrong # args: should be \"",
941
                    argv[0], " cget option\"",
942
                    (char *) NULL);
943
            return TCL_ERROR;
944
        }
945
        return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
946
                (char *) masterPtr, argv[2], 0);
947
    } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
948
            && (length >= 2)) {
949
        if (argc == 2) {
950
            code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
951
                    configSpecs, (char *) masterPtr, (char *) NULL, 0);
952
        } else if (argc == 3) {
953
            code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
954
                    configSpecs, (char *) masterPtr, argv[2], 0);
955
        } else {
956
            code = ImgXpmConfigureMaster(masterPtr, argc-2, argv+2,
957
                    TK_CONFIG_ARGV_ONLY);
958
        }
959
        return code;
960
    } else if ((c == 'r') && (strncmp(argv[1], "refcount", length) == 0)) {
961
        /*
962
         * The "refcount" command is for debugging only
963
         */
964
        PixmapInstance *instancePtr;
965
        int count = 0;
966
        char buff[30];
967
 
968
        for (instancePtr=masterPtr->instancePtr; instancePtr;
969
             instancePtr = instancePtr->nextPtr) {
970
            count += instancePtr->refCount;
971
        }
972
        sprintf(buff, "%d", count);
973
        Tcl_SetResult(interp, buff, TCL_VOLATILE);
974
        return TCL_OK;
975
    } else {
976
        Tcl_AppendResult(interp, "bad option \"", argv[1],
977
            "\": must be cget, configure or refcount", (char *) NULL);
978
        return TCL_ERROR;
979
    }
980
}
981
 
982
/*
983
 *----------------------------------------------------------------------
984
 *
985
 * ImgXpmGet --
986
 *
987
 *      This procedure is called for each use of a pixmap image in a
988
 *      widget.
989
 *
990
 * Results:
991
 *      The return value is a token for the instance, which is passed
992
 *      back to us in calls to ImgXpmDisplay and ImgXpmFre.
993
 *
994
 * Side effects:
995
 *      A data structure is set up for the instance (or, an existing
996
 *      instance is re-used for the new one).
997
 *
998
 *----------------------------------------------------------------------
999
 */
1000
 
1001
static ClientData
1002
ImgXpmGet(tkwin, masterData)
1003
    Tk_Window tkwin;            /* Window in which the instance will be
1004
                                 * used. */
1005
    ClientData masterData;      /* Pointer to our master structure for the
1006
                                 * image. */
1007
{
1008
    PixmapMaster *masterPtr = (PixmapMaster *) masterData;
1009
    PixmapInstance *instancePtr;
1010
 
1011
    /*
1012
     * See if there is already an instance for this window.  If so
1013
     * then just re-use it.
1014
     */
1015
 
1016
    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
1017
            instancePtr = instancePtr->nextPtr) {
1018
        if (instancePtr->tkwin == tkwin) {
1019
            instancePtr->refCount++;
1020
            return (ClientData) instancePtr;
1021
        }
1022
    }
1023
 
1024
    /*
1025
     * The image isn't already in use in this window.  Make a new
1026
     * instance of the image.
1027
     */
1028
    instancePtr = (PixmapInstance *) ckalloc(sizeof(PixmapInstance));
1029
    instancePtr->refCount = 1;
1030
    instancePtr->masterPtr = masterPtr;
1031
    instancePtr->tkwin = tkwin;
1032
    instancePtr->pixmap = None;
1033
    instancePtr->nextPtr = masterPtr->instancePtr;
1034
    instancePtr->colors = NULL;
1035
    masterPtr->instancePtr = instancePtr;
1036
 
1037
    TixpInitPixmapInstance(masterPtr, instancePtr);
1038
    ImgXpmConfigureInstance(instancePtr);
1039
 
1040
    /*
1041
     * If this is the first instance, must set the size of the image.
1042
     */
1043
    if (instancePtr->nextPtr == NULL) {
1044
        if (masterPtr->data) {
1045
            Tk_ImageChanged(masterPtr->tkMaster, 0, 0,
1046
                masterPtr->size[0], masterPtr->size[1],
1047
                masterPtr->size[0], masterPtr->size[1]);
1048
        } else {
1049
            Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, 0, 0);
1050
        }
1051
    }
1052
 
1053
    return (ClientData) instancePtr;
1054
}
1055
 
1056
/*
1057
 *----------------------------------------------------------------------
1058
 *
1059
 * ImgXpmDisplay --
1060
 *
1061
 *      This procedure is invoked to draw a pixmap image.
1062
 *
1063
 * Results:
1064
 *      None.
1065
 *
1066
 * Side effects:
1067
 *      A portion of the image gets rendered in a pixmap or window.
1068
 *
1069
 *----------------------------------------------------------------------
1070
 */
1071
 
1072
static void
1073
ImgXpmDisplay(clientData, display, drawable, imageX, imageY, width,
1074
        height, drawableX, drawableY)
1075
    ClientData clientData;      /* Pointer to PixmapInstance structure for
1076
                                 * for instance to be displayed. */
1077
    Display *display;           /* Display on which to draw image. */
1078
    Drawable drawable;          /* Pixmap or window in which to draw image. */
1079
    int imageX, imageY;         /* Upper-left corner of region within image
1080
                                 * to draw. */
1081
    int width, height;          /* Dimensions of region within image to draw.*/
1082
    int drawableX, drawableY;   /* Coordinates within drawable that
1083
                                 * correspond to imageX and imageY. */
1084
{
1085
    TixpXpmDisplay(clientData, display, drawable, imageX, imageY, width,
1086
        height, drawableX, drawableY);
1087
}
1088
 
1089
/*
1090
 *----------------------------------------------------------------------
1091
 *
1092
 * ImgXpmFree --
1093
 *
1094
 *      This procedure is called when a widget ceases to use a
1095
 *      particular instance of an image.
1096
 *
1097
 * Results:
1098
 *      None.
1099
 *
1100
 * Side effects:
1101
 *      Internal data structures get cleaned up.
1102
 *
1103
 *----------------------------------------------------------------------
1104
 */
1105
 
1106
static void
1107
ImgXpmFree(clientData, display)
1108
    ClientData clientData;      /* Pointer to PixmapInstance structure for
1109
                                 * for instance to be displayed. */
1110
    Display *display;           /* Display containing window that used image.*/
1111
{
1112
    PixmapInstance *instancePtr = (PixmapInstance *) clientData;
1113
    PixmapInstance *prevPtr;
1114
 
1115
    instancePtr->refCount--;
1116
    if (instancePtr->refCount > 0) {
1117
        return;
1118
    }
1119
 
1120
    /*
1121
     * There are no more uses of the image within this widget.  Free
1122
     * the instance structure.
1123
     */
1124
    if (instancePtr->pixmap != None) {
1125
        Tk_FreePixmap(display, instancePtr->pixmap);
1126
    }
1127
    TixpXpmFreeInstanceData(instancePtr, 1, display);
1128
 
1129
    if (instancePtr->colors != NULL) {
1130
        int i;
1131
        for (i=0; i<instancePtr->masterPtr->ncolors; i++) {
1132
            if (instancePtr->colors[i].colorPtr != NULL) {
1133
                Tk_FreeColor(instancePtr->colors[i].colorPtr);
1134
            }
1135
            if (instancePtr->masterPtr->cpp != 1) {
1136
                ckfree(instancePtr->colors[i].cstring);
1137
            }
1138
        }
1139
        ckfree((char*)instancePtr->colors);
1140
    }
1141
 
1142
    if (instancePtr->masterPtr->instancePtr == instancePtr) {
1143
        instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
1144
    } else {
1145
        for (prevPtr = instancePtr->masterPtr->instancePtr;
1146
                prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
1147
            /* Empty loop body */
1148
        }
1149
        prevPtr->nextPtr = instancePtr->nextPtr;
1150
    }
1151
    ckfree((char *) instancePtr);
1152
}
1153
 
1154
/*
1155
 *----------------------------------------------------------------------
1156
 *
1157
 * ImgXpmDelete --
1158
 *
1159
 *      This procedure is called by the image code to delete the
1160
 *      master structure for an image.
1161
 *
1162
 * Results:
1163
 *      None.
1164
 *
1165
 * Side effects:
1166
 *      Resources associated with the image get freed.
1167
 *
1168
 *----------------------------------------------------------------------
1169
 */
1170
 
1171
static void
1172
ImgXpmDelete(masterData)
1173
    ClientData masterData;      /* Pointer to PixmapMaster structure for
1174
                                 * image.  Must not have any more instances. */
1175
{
1176
    PixmapMaster *masterPtr = (PixmapMaster *) masterData;
1177
 
1178
    if (masterPtr->instancePtr != NULL) {
1179
        panic("tried to delete pixmap image when instances still exist");
1180
    }
1181
    masterPtr->tkMaster = NULL;
1182
    if (masterPtr->imageCmd != NULL) {
1183
        Tcl_DeleteCommand(masterPtr->interp,
1184
                Tcl_GetCommandName(masterPtr->interp, masterPtr->imageCmd));
1185
    }
1186
    if (masterPtr->isDataAlloced && masterPtr->data != NULL) {
1187
        ckfree((char*)masterPtr->data);
1188
        masterPtr->data = NULL;
1189
    }
1190
 
1191
    Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0);
1192
    ckfree((char *) masterPtr);
1193
}
1194
 
1195
/*
1196
 *----------------------------------------------------------------------
1197
 *
1198
 * ImgXpmCmdDeletedProc --
1199
 *
1200
 *      This procedure is invoked when the image command for an image
1201
 *      is deleted.  It deletes the image.
1202
 *
1203
 * Results:
1204
 *      None.
1205
 *
1206
 * Side effects:
1207
 *      The image is deleted.
1208
 *
1209
 *----------------------------------------------------------------------
1210
 */
1211
static void
1212
ImgXpmCmdDeletedProc(clientData)
1213
    ClientData clientData;      /* Pointer to PixmapMaster structure for
1214
                                 * image. */
1215
{
1216
    PixmapMaster *masterPtr = (PixmapMaster *) clientData;
1217
 
1218
    masterPtr->imageCmd = NULL;
1219
    if (masterPtr->tkMaster != NULL) {
1220
        if (Tk_MainWindow(masterPtr->interp) != NULL) {
1221
            Tk_DeleteImage(masterPtr->interp,
1222
                    Tk_NameOfImage(masterPtr->tkMaster));
1223
        }
1224
    }
1225
}
1226
 
1227
 
1228
/*
1229
 *----------------------------------------------------------------------
1230
 *
1231
 * Tix_DefinePixmap
1232
 *
1233
 *      Define an XPM data structure with an unique name, so that you can
1234
 *      later refer to this pixmap using the -id switch in [image create
1235
 *      pixmap].
1236
 *
1237
 * Results:
1238
 *      None.
1239
 *
1240
 * Side effects:
1241
 *      The data is stored in a HashTable.
1242
 *----------------------------------------------------------------------
1243
 */
1244
int
1245
Tix_DefinePixmap(interp, name, data)
1246
    Tcl_Interp * interp;
1247
    Tk_Uid name;                /* Name to use for bitmap.  Must not already
1248
                                 * be defined as a bitmap. */
1249
    char **data;
1250
{
1251
    int new;
1252
    Tcl_HashEntry *hshPtr;
1253
 
1254
    if (!xpmTableInited) {
1255
        xpmTableInited = 1;
1256
        Tcl_InitHashTable(&xpmTable, TCL_ONE_WORD_KEYS);
1257
    }
1258
 
1259
    hshPtr = Tcl_CreateHashEntry(&xpmTable, name, &new);
1260
    if (!new) {
1261
        Tcl_AppendResult(interp, "pixmap \"", name,
1262
                "\" is already defined", (char *) NULL);
1263
        return TCL_ERROR;
1264
    }
1265
    Tcl_SetHashValue(hshPtr, (char*)data);
1266
    return TCL_OK;
1267
}

powered by: WebSVN 2.1.0

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