Annotation of micropolis/src/tk/tkgc.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * tkGC.c --
                      3:  *
                      4:  *     This file maintains a database of read-only graphics contexts 
                      5:  *     for the Tk toolkit, in order to allow GC's to be shared.
                      6:  *
                      7:  * Copyright 1990 Regents of the University of California
                      8:  * Permission to use, copy, modify, and distribute this
                      9:  * software and its documentation for any purpose and without
                     10:  * fee is hereby granted, provided that the above copyright
                     11:  * notice appear in all copies.  The University of California
                     12:  * makes no representations about the suitability of this
                     13:  * software for any purpose.  It is provided "as is" without
                     14:  * express or implied warranty.
                     15:  */
                     16: 
                     17: #ifndef lint
                     18: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkGC.c,v 1.9 92/05/13 08:48:45 ouster Exp $ SPRITE (Berkeley)";
                     19: #endif /* not lint */
                     20: 
                     21: #include "tkconfig.h"
                     22: #include "tk.h"
                     23: 
                     24: /*
                     25:  * One of the following data structures exists for each GC that is
                     26:  * currently active.  The structure is indexed with two hash tables,
                     27:  * one based on font name and one based on XFontStruct address.
                     28:  */
                     29: 
                     30: typedef struct {
                     31:     GC gc;                     /* Graphics context. */
                     32:     Display *display;          /* Display to which gc belongs. */
                     33:     int refCount;              /* Number of active uses of gc. */
                     34:     Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting
                     35:                                 * this structure). */
                     36: } TkGC;
                     37: 
                     38: /*
                     39:  * Hash table to map from a GC's values to a TkGC structure describing
                     40:  * a GC with those values (used by Tk_GetGC).
                     41:  */
                     42: 
                     43: static Tcl_HashTable valueTable;
                     44: typedef struct {
                     45:     XGCValues values;          /* Desired values for GC. */
                     46:     Screen *screen;            /* Screen for which GC is valid. */
                     47: } ValueKey;
                     48: 
                     49: /*
                     50:  * Hash table for GC -> TkGC mapping. This table is indexed by the 
                     51:  * GC identifier, and is used by Tk_FreeGC.
                     52:  */
                     53: 
                     54: static Tcl_HashTable idTable;
                     55: 
                     56: static int initialized = 0;    /* 0 means static structures haven't been
                     57:                                 * initialized yet. */
                     58: 
                     59: /*
                     60:  * Forward declarations for procedures defined in this file:
                     61:  */
                     62: 
                     63: static void            GCInit _ANSI_ARGS_((void));
                     64: 
                     65: /*
                     66:  *----------------------------------------------------------------------
                     67:  *
                     68:  * Tk_GetGC --
                     69:  *
                     70:  *     Given a desired set of values for a graphics context, find
                     71:  *     a read-only graphics context with the desired values.
                     72:  *
                     73:  * Results:
                     74:  *     The return value is the X identifer for the desired graphics
                     75:  *     context.  The caller should never modify this GC, and should
                     76:  *     call Tk_FreeGC when the GC is no longer needed.
                     77:  *
                     78:  * Side effects:
                     79:  *     The GC is added to an internal database with a reference count.
                     80:  *     For each call to this procedure, there should eventually be a call
                     81:  *     to Tk_FreeGC, so that the database can be cleaned up when GC's
                     82:  *     aren't needed anymore.
                     83:  *
                     84:  *----------------------------------------------------------------------
                     85:  */
                     86: 
                     87: GC
                     88: Tk_GetGC(tkwin, valueMask, valuePtr)
                     89:     Tk_Window tkwin;           /* Window in which GC will be used. */
                     90:     register unsigned long valueMask;
                     91:                                /* 1 bits correspond to values specified
                     92:                                 * in *valuesPtr;  other values are set
                     93:                                 * from defaults. */
                     94:     register XGCValues *valuePtr;
                     95:                                /* Values are specified here for bits set
                     96:                                 * in valueMask. */
                     97: {
                     98:     ValueKey key;
                     99:     Tcl_HashEntry *valueHashPtr, *idHashPtr;
                    100:     register TkGC *gcPtr;
                    101:     int new;
                    102: 
                    103:     if (!initialized) {
                    104:        GCInit();
                    105:     }
                    106: 
                    107:     /*
                    108:      * Must zero key at start to clear out pad bytes that may be
                    109:      * part of structure on some systems.
                    110:      */
                    111: 
                    112:     memset((VOID *) &key, 0, sizeof(key));
                    113: 
                    114:     /*
                    115:      * First, check to see if there's already a GC that will work
                    116:      * for this request (exact matches only, sorry).
                    117:      */
                    118: 
                    119:     if (valueMask & GCFunction) {
                    120:        key.values.function = valuePtr->function;
                    121:     } else {
                    122:        key.values.function = GXcopy;
                    123:     }
                    124:     if (valueMask & GCPlaneMask) {
                    125:        key.values.plane_mask = valuePtr->plane_mask;
                    126:     } else {
                    127:        key.values.plane_mask = ~0;
                    128:     }
                    129:     if (valueMask & GCForeground) {
                    130:        key.values.foreground = valuePtr->foreground;
                    131:     } else {
                    132:        key.values.foreground = 0;
                    133:     }
                    134:     if (valueMask & GCBackground) {
                    135:        key.values.background = valuePtr->background;
                    136:     } else {
                    137:        key.values.background = 1;
                    138:     }
                    139:     if (valueMask & GCLineWidth) {
                    140:        key.values.line_width = valuePtr->line_width;
                    141:     } else {
                    142:        key.values.line_width = 0;
                    143:     }
                    144:     if (valueMask & GCLineStyle) {
                    145:        key.values.line_style = valuePtr->line_style;
                    146:     } else {
                    147:        key.values.line_style = LineSolid;
                    148:     }
                    149:     if (valueMask & GCCapStyle) {
                    150:        key.values.cap_style = valuePtr->cap_style;
                    151:     } else {
                    152:        key.values.cap_style = CapButt;
                    153:     }
                    154:     if (valueMask & GCJoinStyle) {
                    155:        key.values.join_style = valuePtr->join_style;
                    156:     } else {
                    157:        key.values.join_style = JoinMiter;
                    158:     }
                    159:     if (valueMask & GCFillStyle) {
                    160:        key.values.fill_style = valuePtr->fill_style;
                    161:     } else {
                    162:        key.values.fill_style = FillSolid;
                    163:     }
                    164:     if (valueMask & GCFillRule) {
                    165:        key.values.fill_rule = valuePtr->fill_rule;
                    166:     } else {
                    167:        key.values.fill_rule = EvenOddRule;
                    168:     }
                    169:     if (valueMask & GCArcMode) {
                    170:        key.values.arc_mode = valuePtr->arc_mode;
                    171:     } else {
                    172:        key.values.arc_mode = ArcPieSlice;
                    173:     }
                    174:     if (valueMask & GCTile) {
                    175:        key.values.tile = valuePtr->tile;
                    176:     } else {
                    177:        key.values.tile = None;
                    178:     }
                    179:     if (valueMask & GCStipple) {
                    180:        key.values.stipple = valuePtr->stipple;
                    181:     } else {
                    182:        key.values.stipple = None;
                    183:     }
                    184:     if (valueMask & GCTileStipXOrigin) {
                    185:        key.values.ts_x_origin = valuePtr->ts_x_origin;
                    186:     } else {
                    187:        key.values.ts_x_origin = 0;
                    188:     }
                    189:     if (valueMask & GCTileStipYOrigin) {
                    190:        key.values.ts_y_origin = valuePtr->ts_y_origin;
                    191:     } else {
                    192:        key.values.ts_y_origin = 0;
                    193:     }
                    194:     if (valueMask & GCFont) {
                    195:        key.values.font = valuePtr->font;
                    196:     } else {
                    197:        key.values.font = None;
                    198:     }
                    199:     if (valueMask & GCSubwindowMode) {
                    200:        key.values.subwindow_mode = valuePtr->subwindow_mode;
                    201:     } else {
                    202:        key.values.subwindow_mode = ClipByChildren;
                    203:     }
                    204:     if (valueMask & GCGraphicsExposures) {
                    205:        key.values.graphics_exposures = valuePtr->graphics_exposures;
                    206:     } else {
                    207:        key.values.graphics_exposures = True;
                    208:     }
                    209:     if (valueMask & GCClipXOrigin) {
                    210:        key.values.clip_x_origin = valuePtr->clip_x_origin;
                    211:     } else {
                    212:        key.values.clip_x_origin = 0;
                    213:     }
                    214:     if (valueMask & GCClipYOrigin) {
                    215:        key.values.clip_y_origin = valuePtr->clip_y_origin;
                    216:     } else {
                    217:        key.values.clip_y_origin = 0;
                    218:     }
                    219:     if (valueMask & GCClipMask) {
                    220:        key.values.clip_mask = valuePtr->clip_mask;
                    221:     } else {
                    222:        key.values.clip_mask = None;
                    223:     }
                    224:     if (valueMask & GCDashOffset) {
                    225:        key.values.dash_offset = valuePtr->dash_offset;
                    226:     } else {
                    227:        key.values.dash_offset = 0;
                    228:     }
                    229:     if (valueMask & GCDashList) {
                    230:        key.values.dashes = valuePtr->dashes;
                    231:     } else {
                    232:        key.values.dashes = 4;
                    233:     }
                    234:     key.screen = Tk_Screen(tkwin);
                    235:     valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &key, &new);
                    236:     if (!new) {
                    237:        gcPtr = (TkGC *) Tcl_GetHashValue(valueHashPtr);
                    238:        gcPtr->refCount++;
                    239:        return gcPtr->gc;
                    240:     }
                    241: 
                    242:     /*
                    243:      * No GC is currently available for this set of values.  Allocate a
                    244:      * new GC and add a new structure to the database.
                    245:      */
                    246: 
                    247:     gcPtr = (TkGC *) ckalloc(sizeof(TkGC));
                    248: #if 0
                    249:     gcPtr->gc = XCreateGC(Tk_Display(tkwin),
                    250:                          RootWindowOfScreen(Tk_Screen(tkwin)),
                    251:                          valueMask, &key.values);
                    252: #else
                    253:     gcPtr->gc = XCreateGC(Tk_Display(tkwin),
                    254:                          Tk_DefaultPixmap(Tk_Screen(tkwin)),
                    255:                          valueMask, &key.values);
                    256: #endif
                    257:     gcPtr->display = Tk_Display(tkwin);
                    258:     gcPtr->refCount = 1;
                    259:     gcPtr->valueHashPtr = valueHashPtr;
                    260:     idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) gcPtr->gc, &new);
                    261:     if (!new) {
                    262:        panic("GC already registered in Tk_GetGC");
                    263:     }
                    264:     Tcl_SetHashValue(valueHashPtr, gcPtr);
                    265:     Tcl_SetHashValue(idHashPtr, gcPtr);
                    266:     return gcPtr->gc;
                    267: }
                    268: 
                    269: /*
                    270:  *----------------------------------------------------------------------
                    271:  *
                    272:  * Tk_FreeGC --
                    273:  *
                    274:  *     This procedure is called to release a font allocated by
                    275:  *     Tk_GetGC.
                    276:  *
                    277:  * Results:
                    278:  *     None.
                    279:  *
                    280:  * Side effects:
                    281:  *     The reference count associated with gc is decremented, and
                    282:  *     gc is officially deallocated if no-one is using it anymore.
                    283:  *
                    284:  *----------------------------------------------------------------------
                    285:  */
                    286: 
                    287: void
                    288: Tk_FreeGC(gc)
                    289:     GC gc;                     /* Graphics context to be released. */
                    290: {
                    291:     Tcl_HashEntry *idHashPtr;
                    292:     register TkGC *gcPtr;
                    293: 
                    294:     if (!initialized) {
                    295:        panic("Tk_FreeGC called before Tk_GetGC");
                    296:     }
                    297: 
                    298:     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) gc);
                    299:     if (idHashPtr == NULL) {
                    300:        panic("Tk_FreeGC received unknown gc argument");
                    301:     }
                    302:     gcPtr = (TkGC *) Tcl_GetHashValue(idHashPtr);
                    303:     gcPtr->refCount--;
                    304:     if (gcPtr->refCount == 0) {
                    305:        XFreeGC(gcPtr->display, gcPtr->gc);
                    306:        Tcl_DeleteHashEntry(gcPtr->valueHashPtr);
                    307:        Tcl_DeleteHashEntry(idHashPtr);
                    308:        ckfree((char *) gcPtr);
                    309:     }
                    310: }
                    311: 
                    312: /*
                    313:  *----------------------------------------------------------------------
                    314:  *
                    315:  * GCInit --
                    316:  *
                    317:  *     Initialize the structures used for GC management.
                    318:  *
                    319:  * Results:
                    320:  *     None.
                    321:  *
                    322:  * Side effects:
                    323:  *     Read the code.
                    324:  *
                    325:  *----------------------------------------------------------------------
                    326:  */
                    327: 
                    328: static void
                    329: GCInit()
                    330: {
                    331:     initialized = 1;
                    332:     Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int));
                    333:     Tcl_InitHashTable(&idTable, TCL_ONE_WORD_KEYS);
                    334: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.