1/*
2 * tkAtom.c --
3 *
4 *	This file manages a cache of X Atoms in order to avoid interactions
5 *	with the X server. It's much like the Xmu routines, except it has a
6 *	cleaner interface (caller doesn't have to provide permanent storage
7 *	for atom names, for example).
8 *
9 * Copyright (c) 1990-1994 The Regents of the University of California.
10 * Copyright (c) 1994 Sun Microsystems, Inc.
11 *
12 * See the file "license.terms" for information on usage and redistribution of
13 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 *
15 * RCS: @(#) $Id$
16 */
17
18#include "tkInt.h"
19
20/*
21 * The following are a list of the predefined atom strings. They should match
22 * those found in xatom.h
23 */
24
25static char * atomNameArray[] = {
26    "PRIMARY",		"SECONDARY",		"ARC",
27    "ATOM",		"BITMAP",		"CARDINAL",
28    "COLORMAP",		"CURSOR",		"CUT_BUFFER0",
29    "CUT_BUFFER1",	"CUT_BUFFER2",		"CUT_BUFFER3",
30    "CUT_BUFFER4",	"CUT_BUFFER5",		"CUT_BUFFER6",
31    "CUT_BUFFER7",	"DRAWABLE",		"FONT",
32    "INTEGER",		"PIXMAP",		"POINT",
33    "RECTANGLE",	"RESOURCE_MANAGER",	"RGB_COLOR_MAP",
34    "RGB_BEST_MAP",	"RGB_BLUE_MAP",		"RGB_DEFAULT_MAP",
35    "RGB_GRAY_MAP",	"RGB_GREEN_MAP",	"RGB_RED_MAP",
36    "STRING",		"VISUALID",		"WINDOW",
37    "WM_COMMAND",	"WM_HINTS",		"WM_CLIENT_MACHINE",
38    "WM_ICON_NAME",	"WM_ICON_SIZE",		"WM_NAME",
39    "WM_NORMAL_HINTS",	"WM_SIZE_HINTS",	"WM_ZOOM_HINTS",
40    "MIN_SPACE",	"NORM_SPACE",		"MAX_SPACE",
41    "END_SPACE",	"SUPERSCRIPT_X",	"SUPERSCRIPT_Y",
42    "SUBSCRIPT_X",	"SUBSCRIPT_Y",		"UNDERLINE_POSITION",
43    "UNDERLINE_THICKNESS", "STRIKEOUT_ASCENT",	"STRIKEOUT_DESCENT",
44    "ITALIC_ANGLE",	"X_HEIGHT",		"QUAD_WIDTH",
45    "WEIGHT",		"POINT_SIZE",		"RESOLUTION",
46    "COPYRIGHT",	"NOTICE",		"FONT_NAME",
47    "FAMILY_NAME",	"FULL_NAME",		"CAP_HEIGHT",
48    "WM_CLASS",		"WM_TRANSIENT_FOR",
49    NULL
50};
51
52/*
53 * Forward references to functions defined in this file:
54 */
55
56static void	AtomInit(TkDisplay *dispPtr);
57
58/*
59 *--------------------------------------------------------------
60 *
61 * Tk_InternAtom --
62 *
63 *	Given a string, produce the equivalent X atom. This function is
64 *	equivalent to XInternAtom, except that it keeps a local cache of
65 *	atoms. Once a name is known, the server need not be contacted again
66 *	for that name.
67 *
68 * Results:
69 *	The return value is the Atom corresponding to name.
70 *
71 * Side effects:
72 *	A new entry may be added to the local atom cache.
73 *
74 *--------------------------------------------------------------
75 */
76
77Atom
78Tk_InternAtom(
79    Tk_Window tkwin,		/* Window token; map name to atom for this
80				 * window's display. */
81    CONST char *name)		/* Name to turn into atom. */
82{
83    register TkDisplay *dispPtr;
84    register Tcl_HashEntry *hPtr;
85    int isNew;
86
87    dispPtr = ((TkWindow *) tkwin)->dispPtr;
88    if (!dispPtr->atomInit) {
89	AtomInit(dispPtr);
90    }
91
92    hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);
93    if (isNew) {
94	Tcl_HashEntry *hPtr2;
95	Atom atom;
96
97	atom = XInternAtom(dispPtr->display, name, False);
98	Tcl_SetHashValue(hPtr, atom);
99	hPtr2 = Tcl_CreateHashEntry(&dispPtr->atomTable, (char*) atom, &isNew);
100	Tcl_SetHashValue(hPtr2, Tcl_GetHashKey(&dispPtr->nameTable, hPtr));
101    }
102    return (Atom) Tcl_GetHashValue(hPtr);
103}
104
105/*
106 *--------------------------------------------------------------
107 *
108 * Tk_GetAtomName --
109 *
110 *	This function is equivalent to XGetAtomName except that it uses the
111 *	local atom cache to avoid contacting the server.
112 *
113 * Results:
114 *	The return value is a character string corresponding to the atom given
115 *	by "atom". This string's storage space is static: it need not be freed
116 *	by the caller, and should not be modified by the caller. If "atom"
117 *	doesn't exist on tkwin's display, then the string "?bad atom?"  is
118 *	returned.
119 *
120 * Side effects:
121 *	None.
122 *
123 *--------------------------------------------------------------
124 */
125
126CONST char *
127Tk_GetAtomName(
128    Tk_Window tkwin,		/* Window token; map atom to name relative to
129				 * this window's display. */
130    Atom atom)			/* Atom whose name is wanted. */
131{
132    register TkDisplay *dispPtr;
133    register Tcl_HashEntry *hPtr;
134
135    dispPtr = ((TkWindow *) tkwin)->dispPtr;
136    if (!dispPtr->atomInit) {
137	AtomInit(dispPtr);
138    }
139
140    hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, (char *) atom);
141    if (hPtr == NULL) {
142	char *name;
143	Tk_ErrorHandler handler;
144	int isNew, mustFree;
145
146	handler = Tk_CreateErrorHandler(dispPtr->display, BadAtom, -1, -1,
147		NULL, (ClientData) NULL);
148	name = XGetAtomName(dispPtr->display, atom);
149	mustFree = 1;
150	if (name == NULL) {
151	    name = "?bad atom?";
152	    mustFree = 0;
153	}
154	Tk_DeleteErrorHandler(handler);
155	hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);
156	Tcl_SetHashValue(hPtr, atom);
157	if (mustFree) {
158	    XFree(name);
159	}
160	name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr);
161	hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, (char *) atom, &isNew);
162	Tcl_SetHashValue(hPtr, name);
163    }
164    return Tcl_GetHashValue(hPtr);
165}
166
167/*
168 *--------------------------------------------------------------
169 *
170 * AtomInit --
171 *
172 *	Initialize atom-related information for a display.
173 *
174 * Results:
175 *	None.
176 *
177 * Side effects:
178 *	Tables get initialized, etc. etc..
179 *
180 *--------------------------------------------------------------
181 */
182
183static void
184AtomInit(
185    register TkDisplay *dispPtr)/* Display to initialize. */
186{
187    Tcl_HashEntry *hPtr;
188    Atom atom;
189
190    dispPtr->atomInit = 1;
191    Tcl_InitHashTable(&dispPtr->nameTable, TCL_STRING_KEYS);
192    Tcl_InitHashTable(&dispPtr->atomTable, TCL_ONE_WORD_KEYS);
193
194    for (atom = 1; atom <= XA_LAST_PREDEFINED; atom++) {
195	char *name;
196	int isNew;
197
198	hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, (char *) atom);
199	if (hPtr != NULL) {
200	    continue;
201	}
202
203	name = atomNameArray[atom - 1];
204	hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);
205	Tcl_SetHashValue(hPtr, atom);
206	name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr);
207	hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, (char *) atom, &isNew);
208	Tcl_SetHashValue(hPtr, name);
209    }
210}
211
212/*
213 * Local Variables:
214 * mode: c
215 * c-basic-offset: 4
216 * fill-column: 78
217 * End:
218 */
219