Annotation of micropolis/src/tk/tkgc.c, revision 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.