|
|
1.1 ! root 1: /* $Header: Context.c,v 1.1 87/09/11 08:16:18 toddb Exp $ */ ! 2: #ifndef lint ! 3: static char *sccsid = "@(#)Context.c 1.5 2/24/87"; ! 4: #endif lint ! 5: ! 6: /* ! 7: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. ! 8: * ! 9: * All Rights Reserved ! 10: * ! 11: * Permission to use, copy, modify, and distribute this software and its ! 12: * documentation for any purpose and without fee is hereby granted, ! 13: * provided that the above copyright notice appear in all copies and that ! 14: * both that copyright notice and this permission notice appear in ! 15: * supporting documentation, and that the name of Digital Equipment ! 16: * Corporation not be used in advertising or publicity pertaining to ! 17: * distribution of the software without specific, written prior permission. ! 18: * ! 19: * ! 20: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 21: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 22: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 23: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 24: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 25: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 26: * SOFTWARE. ! 27: */ ! 28: ! 29: ! 30: /* Created by weissman, Thu Jun 26 15:18:59 1986 */ ! 31: ! 32: /* This module implements a simple sparse array. ! 33: ! 34: XSaveContext(a,b,c,d) will store d in position (a,b,c) of the array. ! 35: XFindContext(a,b,c,&d) will set d to be the value in position (a,b,c). ! 36: XDeleteContext(a,b,c) will delete the entry in (a,b,c). ! 37: ! 38: a is a display id, b is a window id, and c is a Context. d is just a ! 39: caddr_t. This code will work with any range of parameters, but is geared ! 40: to be most efficient with very few (one or two) different a's. ! 41: ! 42: */ ! 43: ! 44: #include <stdio.h> ! 45: #include "Xlib.h" ! 46: #include "Xutil.h" ! 47: #include "Xlibos.h" ! 48: ! 49: #define INITHASHSIZE 1024 /* Number of entries originally in the hash table. */ ! 50: ! 51: ! 52: typedef struct _TableEntryRec { /* Stores one entry. */ ! 53: Window window; ! 54: XContext context; ! 55: caddr_t data; ! 56: struct _TableEntryRec *next; ! 57: } TableEntryRec, *TableEntry; ! 58: ! 59: typedef struct _DspRec { /* Stores hash table for one display. */ ! 60: Display *display; /* Which display this is a hash for. */ ! 61: TableEntry *table; /* Pointer to array of hash entries. */ ! 62: int size; /* Current size of hash table. */ ! 63: int numentries; /* Number of entries currently in table. */ ! 64: int maxentries; /* How many entries we can take before ! 65: increasing table size. */ ! 66: } DspRec, *Dsp; ! 67: ! 68: static Dsp *DspArray = NULL; /* Pointer to array of display entries. */ ! 69: static int numDsp = 0; /* How many display entries we have. */ ! 70: ! 71: ! 72: /* Assign dsp to be the Dsp entry that contains display. */ ! 73: ! 74: static Dsp lastdsp = NULL; ! 75: #define FindCorrectDsp \ ! 76: if (lastdsp && display == lastdsp->display) dsp = lastdsp; \ ! 77: else dsp = lastdsp = FindDsp(display); ! 78: ! 79: ! 80: /* Given a Window and a context, returns a value between 0 and HashSize-1. ! 81: Currently, this requires that HashSize be a power of 2. ! 82: */ ! 83: ! 84: #define HashValue(window, context, HashSize) \ ! 85: ((((int)window << 3) + (int)context) & ((HashSize) - 1)) ! 86: ! 87: ! 88: /* Resize the given dsp to have the given number of hash buckets. */ ! 89: ! 90: static int ResizeTable(dsp, NewSize) ! 91: Dsp dsp; ! 92: int NewSize; ! 93: { ! 94: TableEntry *OldHashTable; ! 95: register TableEntry CurEntry, NextEntry; ! 96: register int i, OldHashSize, CurHash; ! 97: OldHashTable = dsp->table; ! 98: OldHashSize = dsp->size; ! 99: dsp->table = (TableEntry *) Xcalloc((unsigned)NewSize,sizeof(TableEntry)); ! 100: if (dsp->table == NULL) { ! 101: dsp->table = OldHashTable; ! 102: return XCNOMEM; ! 103: } ! 104: dsp->size = NewSize; ! 105: dsp->maxentries = NewSize; /* When to next resize the hash table. */ ! 106: if (OldHashTable != NULL) { ! 107: for (i=0 ; i<OldHashSize ; i++) { ! 108: CurEntry = OldHashTable[i] ; ! 109: while (CurEntry != NULL) { ! 110: (void) XDeleteContext(dsp->display, ! 111: CurEntry->window, CurEntry->context); ! 112: NextEntry = CurEntry->next; ! 113: CurHash = HashValue(CurEntry->window, CurEntry->context, ! 114: NewSize); ! 115: CurEntry->next = dsp->table[CurHash]; ! 116: dsp->table[CurHash] = CurEntry; ! 117: CurEntry = NextEntry; ! 118: } ! 119: } ! 120: Xfree((char *) OldHashTable); ! 121: } ! 122: return 0; ! 123: } ! 124: ! 125: ! 126: /* Given a display, find the corresponding dsp. */ ! 127: ! 128: static Dsp FindDsp(display) ! 129: Display *display; ! 130: { ! 131: int i; ! 132: Dsp dsp; ! 133: for (i=0 ; i<numDsp ; i++) ! 134: if (DspArray[i]->display == display) return DspArray[i]; ! 135: numDsp++; ! 136: if (DspArray == NULL) ! 137: DspArray = (Dsp *) Xmalloc(sizeof(Dsp)); ! 138: else ! 139: DspArray = (Dsp *) Xrealloc( ! 140: (char *)DspArray, (unsigned) sizeof(Dsp) * numDsp); ! 141: dsp = DspArray[numDsp - 1] = (Dsp) Xmalloc(sizeof(DspRec)); ! 142: dsp->display = display; ! 143: dsp->table = NULL; ! 144: dsp->size = INITHASHSIZE / 2; ! 145: dsp->numentries = 0; ! 146: dsp->maxentries = -1; ! 147: (void) ResizeTable(dsp, dsp->size * 2); ! 148: return dsp; ! 149: } ! 150: ! 151: ! 152: ! 153: /* Public routines. */ ! 154: ! 155: /* Save the given value of data to correspond with the keys Window and context. ! 156: If an entry with the given Window and context already exists, this one will ! 157: override it; however, such an override has costs in time and space. It ! 158: is better to call XDeleteContext first if you know the entry already exists. ! 159: Returns nonzero error code if an error has occured, 0 otherwise. ! 160: Possible errors are Out-of-memory. ! 161: */ ! 162: ! 163: int XSaveContext(display, window, context, data) ! 164: register Display *display; ! 165: register Window window; ! 166: register XContext context; ! 167: caddr_t data; ! 168: { ! 169: register int CurHash; ! 170: register TableEntry CurEntry; ! 171: register Dsp dsp; ! 172: FindCorrectDsp; ! 173: if (++(dsp->numentries) > dsp->maxentries) ! 174: if (ResizeTable(dsp, dsp->size * 2) == XCNOMEM) ! 175: return XCNOMEM; ! 176: CurEntry = (TableEntry) Xmalloc(sizeof(TableEntryRec)); ! 177: if (CurEntry == NULL) return XCNOMEM; ! 178: CurEntry->window = window; ! 179: CurEntry->context = context; ! 180: CurEntry->data = data; ! 181: CurHash = HashValue(window, context, dsp->size); ! 182: CurEntry->next = dsp->table[CurHash]; ! 183: dsp->table[CurHash] = CurEntry; ! 184: return 0; ! 185: } ! 186: ! 187: ! 188: ! 189: /* Given a window and context, returns the associated data. Note that data ! 190: here is a pointer since it is a return value. Returns nonzero error code ! 191: if an error has occured, 0 otherwise. Possible errors are Entry-not-found. ! 192: */ ! 193: ! 194: int XFindContext(display, window, context, data) ! 195: register Display *display; ! 196: register Window window; ! 197: register XContext context; ! 198: caddr_t *data; /* RETURN */ ! 199: { ! 200: register TableEntry CurEntry; ! 201: register Dsp dsp; ! 202: FindCorrectDsp; ! 203: for (CurEntry = dsp->table[HashValue(window, context, dsp->size)]; ! 204: CurEntry != NULL; ! 205: CurEntry = CurEntry->next) ! 206: { ! 207: if (CurEntry->window == window && CurEntry->context == context) { ! 208: *data = CurEntry->data; ! 209: return 0; ! 210: } ! 211: } ! 212: return XCNOENT; ! 213: } ! 214: ! 215: ! 216: ! 217: /* Deletes all entries for the given window and context from the datastructure. ! 218: This returns the same thing that FindContext would have returned if called ! 219: with the same arguments. ! 220: */ ! 221: ! 222: int XDeleteContext(display, window, context) ! 223: register Display *display; ! 224: register Window window; ! 225: register XContext context; ! 226: { ! 227: register int CurHash; ! 228: int Result; ! 229: register TableEntry CurEntry, PrevEntry, NextEntry; ! 230: register Dsp dsp; ! 231: ! 232: FindCorrectDsp; ! 233: Result = XCNOENT; ! 234: CurHash = HashValue(window, context, dsp->size); ! 235: PrevEntry = NULL; ! 236: CurEntry = dsp->table[CurHash]; ! 237: while (CurEntry != NULL) { ! 238: if (CurEntry->window == window && CurEntry->context == context) { ! 239: dsp->numentries--; ! 240: Result = 0; ! 241: NextEntry = CurEntry->next; ! 242: if (PrevEntry == NULL) { ! 243: dsp->table[CurHash] = NextEntry; ! 244: } else { ! 245: PrevEntry->next = NextEntry; ! 246: } ! 247: Xfree((char *) CurEntry); ! 248: CurEntry = NextEntry; ! 249: } else { ! 250: PrevEntry = CurEntry; ! 251: CurEntry = CurEntry->next; ! 252: } ! 253: } ! 254: return Result; ! 255: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.