|
|
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.