1caade7ccSmrg/************************************************************
2caade7ccSmrgCopyright (c) 1997 by Silicon Graphics Computer Systems, Inc.
3caade7ccSmrgPermission to use, copy, modify, and distribute this
4caade7ccSmrgsoftware and its documentation for any purpose and without
5caade7ccSmrgfee is hereby granted, provided that the above copyright
6caade7ccSmrgnotice appear in all copies and that both that copyright
7caade7ccSmrgnotice and this permission notice appear in supporting
8caade7ccSmrgdocumentation, and that the name of Silicon Graphics not be
9caade7ccSmrgused in advertising or publicity pertaining to distribution
10caade7ccSmrgof the software without specific prior written permission.
11caade7ccSmrgSilicon Graphics makes no representation about the suitability
12caade7ccSmrgof this software for any purpose. It is provided "as is"
13caade7ccSmrgwithout any express or implied warranty.
14caade7ccSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15caade7ccSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16caade7ccSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
17caade7ccSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
18caade7ccSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19caade7ccSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
20caade7ccSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
21caade7ccSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
22caade7ccSmrg********************************************************/
23e8a5466aSmrg
24caade7ccSmrg#ifdef HAVE_CONFIG_H
25caade7ccSmrg#include <config.h>
26caade7ccSmrg#endif
27caade7ccSmrg#include <X11/Xlibint.h>
28caade7ccSmrg#include <X11/extensions/XEVI.h>
29485f0483Smrg#include <X11/extensions/EVIproto.h>
30caade7ccSmrg#include <X11/extensions/Xext.h>
31caade7ccSmrg#include <X11/extensions/extutil.h>
32caade7ccSmrg#include <X11/Xutil.h>
33af9a7ee5Smrg#include <limits.h>
3453bb355aSmrg#include "reallocarray.h"
35af9a7ee5Smrg
36caade7ccSmrgstatic XExtensionInfo *xevi_info;/* needs to move to globals.c */
37af9a7ee5Smrgstatic const char *xevi_extension_name = EVINAME;
38caade7ccSmrg#define XeviCheckExtension(dpy,i,val) \
39caade7ccSmrg  XextCheckExtension (dpy, i, xevi_extension_name, val)
40caade7ccSmrg/*****************************************************************************
41caade7ccSmrg *                                                                           *
42caade7ccSmrg *			   private utility routines                          *
43caade7ccSmrg *                                                                           *
44caade7ccSmrg *****************************************************************************/
45caade7ccSmrgstatic /* const */ XExtensionHooks xevi_extension_hooks = {
46caade7ccSmrg    NULL,			/* create_gc */
47caade7ccSmrg    NULL,			/* copy_gc */
48caade7ccSmrg    NULL,			/* flush_gc */
49caade7ccSmrg    NULL,			/* free_gc */
50caade7ccSmrg    NULL,			/* create_font */
51caade7ccSmrg    NULL,			/* free_font */
52caade7ccSmrg    NULL,			/* close_display */
53caade7ccSmrg    NULL,			/* wire_to_event */
54caade7ccSmrg    NULL,			/* event_to_wire */
55caade7ccSmrg    NULL,			/* error */
56caade7ccSmrg    NULL,			/* error_string */
57caade7ccSmrg};
58caade7ccSmrgstatic XEXT_GENERATE_FIND_DISPLAY (find_display, xevi_info,
59caade7ccSmrg                                   xevi_extension_name,
60caade7ccSmrg                                   &xevi_extension_hooks, 0, NULL)
61caade7ccSmrgBool XeviQueryExtension (Display *dpy)
62caade7ccSmrg{
63caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
64caade7ccSmrg    if (XextHasExtension(info)) {
65caade7ccSmrg	return True;
66caade7ccSmrg    } else {
67caade7ccSmrg	return False;
68caade7ccSmrg    }
69caade7ccSmrg}
70caade7ccSmrgBool XeviQueryVersion(Display *dpy, int *majorVersion, int *minorVersion)
71caade7ccSmrg{
72caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
73caade7ccSmrg    xEVIQueryVersionReply rep;
74caade7ccSmrg    register xEVIQueryVersionReq *req;
75caade7ccSmrg    XeviCheckExtension (dpy, info, False);
76caade7ccSmrg    LockDisplay(dpy);
77caade7ccSmrg    GetReq(EVIQueryVersion, req);
78caade7ccSmrg    req->reqType = info->codes->major_opcode;
79caade7ccSmrg    req->xeviReqType = X_EVIQueryVersion;
80caade7ccSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
81caade7ccSmrg	UnlockDisplay(dpy);
82caade7ccSmrg	SyncHandle();
83caade7ccSmrg	return False;
84caade7ccSmrg    }
85caade7ccSmrg    *majorVersion = rep.majorVersion;
86caade7ccSmrg    *minorVersion = rep.minorVersion;
87caade7ccSmrg    UnlockDisplay(dpy);
88caade7ccSmrg    SyncHandle();
89caade7ccSmrg    return True;
90caade7ccSmrg}
91caade7ccSmrgstatic Bool notInList(VisualID32 *visual, int sz_visual, VisualID newVisualid)
92caade7ccSmrg{
93caade7ccSmrg    while  (sz_visual-- > 0)  {
94caade7ccSmrg	if (*visual == newVisualid)
95caade7ccSmrg	    return False;
96caade7ccSmrg	visual++;
97caade7ccSmrg    }
98caade7ccSmrg    return True;
99caade7ccSmrg}
100caade7ccSmrgStatus XeviGetVisualInfo(
101caade7ccSmrg    register Display *dpy,
102caade7ccSmrg    VisualID *visual,
103caade7ccSmrg    int n_visual,
104caade7ccSmrg    ExtendedVisualInfo **evi_return,
105caade7ccSmrg    int *n_info_return)
106caade7ccSmrg{
107caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
108caade7ccSmrg    register xEVIGetVisualInfoReq *req;
109caade7ccSmrg    xEVIGetVisualInfoReply rep;
110caade7ccSmrg    int sz_info, sz_xInfo, sz_conflict, sz_xConflict;
111caade7ccSmrg    VisualID32 *temp_conflict, *temp_visual, *xConflictPtr;
112caade7ccSmrg    VisualID *conflict;
113caade7ccSmrg    xExtendedVisualInfo *temp_xInfo;
114caade7ccSmrg    XVisualInfo *vinfo;
115caade7ccSmrg    register ExtendedVisualInfo *infoPtr;
116caade7ccSmrg    register xExtendedVisualInfo *xInfoPtr;
117caade7ccSmrg    register int n_data, visualIndex, vinfoIndex;
118caade7ccSmrg    Bool isValid;
119caade7ccSmrg    XeviCheckExtension (dpy, info, 0);
120caade7ccSmrg    if (!n_info_return || !evi_return) {
121caade7ccSmrg	return BadValue;
122caade7ccSmrg    }
123caade7ccSmrg    *n_info_return = 0;
124caade7ccSmrg    *evi_return = NULL;
125caade7ccSmrg    vinfo = XGetVisualInfo(dpy, 0, NULL, &sz_info);
126caade7ccSmrg    if (!vinfo) {
127caade7ccSmrg	return BadValue;
128caade7ccSmrg    }
129caade7ccSmrg    if (!n_visual || !visual) {		/* copy the all visual */
13053bb355aSmrg	temp_visual = Xcalloc(sz_info, sz_VisualID32);
131caade7ccSmrg    	n_visual = 0;
132caade7ccSmrg        for (vinfoIndex = 0; vinfoIndex < sz_info; vinfoIndex++)
133caade7ccSmrg	    if (notInList(temp_visual, n_visual, vinfo[vinfoIndex].visualid))
134caade7ccSmrg	        temp_visual[n_visual++] = vinfo[vinfoIndex].visualid;
135caade7ccSmrg    }
136caade7ccSmrg    else {	/* check if the visual is valid */
137cb543c5fSchristos	if (n_visual > 65536)
138cb543c5fSchristos		n_visual = 65536;
139caade7ccSmrg        for (visualIndex = 0; visualIndex < n_visual; visualIndex++) {
140caade7ccSmrg	    isValid = False;
141caade7ccSmrg            for (vinfoIndex = 0; vinfoIndex < sz_info; vinfoIndex++) {
142caade7ccSmrg	        if (visual[visualIndex] == vinfo[vinfoIndex].visualid) {
143caade7ccSmrg		    isValid = True;
144caade7ccSmrg		    break;
145caade7ccSmrg	        }
146caade7ccSmrg	    }
147caade7ccSmrg	    if (!isValid) {
148caade7ccSmrg		XFree(vinfo);
149caade7ccSmrg	        return BadValue;
150caade7ccSmrg	    }
151caade7ccSmrg	}
15253bb355aSmrg	temp_visual = Xmallocarray(n_visual, sz_VisualID32);
153caade7ccSmrg        for (visualIndex = 0; visualIndex < n_visual; visualIndex++)
154caade7ccSmrg	    temp_visual[visualIndex] = visual[visualIndex];
155caade7ccSmrg    }
156caade7ccSmrg    XFree(vinfo);
157caade7ccSmrg    LockDisplay(dpy);
158caade7ccSmrg    GetReq(EVIGetVisualInfo, req);
159caade7ccSmrg    req->reqType = info->codes->major_opcode;
160caade7ccSmrg    req->xeviReqType = X_EVIGetVisualInfo;
161caade7ccSmrg    req->n_visual = n_visual;
162caade7ccSmrg    SetReqLen(req, n_visual, 1);
163caade7ccSmrg    Data(dpy, (char *)temp_visual, n_visual * sz_VisualID32);
164caade7ccSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
165caade7ccSmrg	UnlockDisplay(dpy);
166caade7ccSmrg	SyncHandle();
167caade7ccSmrg	Xfree(temp_visual);
168caade7ccSmrg	return BadAccess;
169caade7ccSmrg    }
170caade7ccSmrg    Xfree(temp_visual);
171af9a7ee5Smrg    if ((rep.n_info < 65536) && (rep.n_conflicts < 65536)) {
172af9a7ee5Smrg	sz_info = rep.n_info * sizeof(ExtendedVisualInfo);
173af9a7ee5Smrg	sz_xInfo = rep.n_info * sz_xExtendedVisualInfo;
174af9a7ee5Smrg	sz_conflict = rep.n_conflicts * sizeof(VisualID);
175af9a7ee5Smrg	sz_xConflict = rep.n_conflicts * sz_VisualID32;
1765d8688b9Smrg	*evi_return = Xcalloc(1, sz_info + sz_conflict);
177af9a7ee5Smrg	temp_xInfo = Xmalloc(sz_xInfo);
178af9a7ee5Smrg	temp_conflict = Xmalloc(sz_xConflict);
179af9a7ee5Smrg    } else {
180af9a7ee5Smrg	sz_xInfo = sz_xConflict = 0;
181af9a7ee5Smrg	*evi_return = NULL;
182af9a7ee5Smrg	temp_xInfo = NULL;
183af9a7ee5Smrg	temp_conflict = NULL;
184af9a7ee5Smrg    }
185caade7ccSmrg    if (!*evi_return || !temp_xInfo || !temp_conflict) {
186af9a7ee5Smrg	_XEatDataWords(dpy, rep.length);
187caade7ccSmrg	UnlockDisplay(dpy);
188caade7ccSmrg	SyncHandle();
189e5383a99Smrg	if (*evi_return) {
190e5383a99Smrg	   Xfree(*evi_return);
191e5383a99Smrg	   *evi_return = NULL;
192e5383a99Smrg	}
193caade7ccSmrg	if (temp_xInfo)
194caade7ccSmrg	   Xfree(temp_xInfo);
195caade7ccSmrg	if (temp_conflict)
196caade7ccSmrg	   Xfree(temp_conflict);
197caade7ccSmrg	return BadAlloc;
198caade7ccSmrg    }
199caade7ccSmrg    _XRead(dpy, (char *)temp_xInfo, sz_xInfo);
200caade7ccSmrg    _XRead(dpy, (char *)temp_conflict, sz_xConflict);
201caade7ccSmrg    UnlockDisplay(dpy);
202caade7ccSmrg    SyncHandle();
203af9a7ee5Smrg    infoPtr = *evi_return;
204af9a7ee5Smrg    xInfoPtr = temp_xInfo;
205af9a7ee5Smrg    xConflictPtr = temp_conflict;
206caade7ccSmrg    n_data = rep.n_info;
207caade7ccSmrg    conflict = (VisualID *)(infoPtr + n_data);
208caade7ccSmrg    while (n_data-- > 0) {
209caade7ccSmrg	infoPtr->core_visual_id		= xInfoPtr->core_visual_id;
210caade7ccSmrg	infoPtr->screen			= xInfoPtr->screen;
211caade7ccSmrg	infoPtr->level			= xInfoPtr->level;
212caade7ccSmrg	infoPtr->transparency_type	= xInfoPtr->transparency_type;
213caade7ccSmrg	infoPtr->transparency_value	= xInfoPtr->transparency_value;
214caade7ccSmrg	infoPtr->min_hw_colormaps	= xInfoPtr->min_hw_colormaps;
215caade7ccSmrg	infoPtr->max_hw_colormaps	= xInfoPtr->max_hw_colormaps;
216caade7ccSmrg	infoPtr->num_colormap_conflicts = xInfoPtr->num_colormap_conflicts;
217caade7ccSmrg	infoPtr->colormap_conflicts	= conflict;
218caade7ccSmrg	conflict += infoPtr->num_colormap_conflicts;
219caade7ccSmrg	infoPtr++;
220caade7ccSmrg	xInfoPtr++;
221caade7ccSmrg    }
222caade7ccSmrg    n_data = rep.n_conflicts;
223caade7ccSmrg    conflict = (VisualID *)(infoPtr);
224caade7ccSmrg    while (n_data-- > 0)
225caade7ccSmrg       *conflict++ = *xConflictPtr++;
226caade7ccSmrg    Xfree(temp_xInfo);
227caade7ccSmrg    Xfree(temp_conflict);
228caade7ccSmrg    *n_info_return = rep.n_info;
229caade7ccSmrg    return Success;
230caade7ccSmrg}
231