XKBList.c revision 61b2299d
1/* $Xorg: XKBList.c,v 1.3 2000/08/17 19:45:02 cpqbld Exp $ */
2/************************************************************
3Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
4
5Permission to use, copy, modify, and distribute this
6software and its documentation for any purpose and without
7fee is hereby granted, provided that the above copyright
8notice appear in all copies and that both that copyright
9notice and this permission notice appear in supporting
10documentation, and that the name of Silicon Graphics not be
11used in advertising or publicity pertaining to distribution
12of the software without specific prior written permission.
13Silicon Graphics makes no representation about the suitability
14of this software for any purpose. It is provided "as is"
15without any express or implied warranty.
16
17SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
20GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
21DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
23OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
24THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
26********************************************************/
27/* $XFree86$ */
28
29#define NEED_REPLIES
30#define NEED_EVENTS
31#define	NEED_MAP_READERS
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35#include "Xlibint.h"
36#include <X11/extensions/XKBproto.h>
37#include "XKBlibint.h"
38
39/***====================================================================***/
40
41static void
42_FreeComponentNames(int num,XkbComponentNamePtr names)
43{
44int			i;
45XkbComponentNamePtr	tmp;
46
47    if ((num<1)||(names==NULL))
48	return;
49    for (i=0,tmp=names;i<num;i++,tmp++) {
50	if (tmp->name) {
51	    _XkbFree(tmp->name);
52	    tmp->name= NULL;
53	}
54    }
55    _XkbFree(names);
56    return;
57}
58
59/***====================================================================***/
60
61static XkbComponentNamePtr
62_ReadListing(XkbReadBufferPtr buf,int count,Status *status_rtrn)
63{
64XkbComponentNamePtr	first,this;
65register int		i;
66CARD16 *		flags;
67int			slen,wlen;
68char *			str;
69
70    if (count<1)
71	return NULL;
72    first= _XkbTypedCalloc(count,XkbComponentNameRec);
73    if (!first)
74	return NULL;
75    for (this=first,i=0;i<count;i++,this++) {
76	flags= (CARD16 *)_XkbGetReadBufferPtr(buf,2*sizeof(CARD16));
77	if (!flags)
78	    goto BAILOUT;
79	this->flags= 	flags[0];
80	slen=		flags[1];
81	wlen= 		((slen+1)/2)*2; /* pad to 2 byte boundary */
82	this->name=	_XkbTypedCalloc(slen+1,char);
83	if (!this->name)
84	    goto BAILOUT;
85	str= (char *)_XkbGetReadBufferPtr(buf,wlen);
86	memcpy(this->name,str,slen);
87    }
88    return first;
89BAILOUT:
90    *status_rtrn= BadAlloc;
91    _FreeComponentNames(i,first);
92    return NULL;
93}
94
95/***====================================================================***/
96
97XkbComponentListPtr
98XkbListComponents(	Display *		dpy,
99			unsigned		deviceSpec,
100			XkbComponentNamesPtr	ptrns,
101			int *			max_inout)
102{
103register xkbListComponentsReq*	req;
104xkbListComponentsReply 		rep;
105XkbInfoPtr 			xkbi;
106XkbComponentListPtr		list;
107XkbReadBufferRec		buf;
108int				left;
109char *				str;
110int extraLen,len,mapLen,codesLen,typesLen,compatLen,symsLen,geomLen;
111
112    if ( (dpy==NULL) || (dpy->flags & XlibDisplayNoXkb) ||
113	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) ||
114	(ptrns==NULL) || (max_inout==NULL))
115	return NULL;
116
117    xkbi= dpy->xkb_info;
118    LockDisplay(dpy);
119    GetReq(kbListComponents, req);
120    req->reqType = 	xkbi->codes->major_opcode;
121    req->xkbReqType = 	X_kbListComponents;
122    req->deviceSpec = 	deviceSpec;
123    req->maxNames =	*max_inout;
124
125    mapLen= codesLen= typesLen= compatLen= symsLen= geomLen= 0;
126    if (ptrns->keymap)
127	mapLen= (int)strlen(ptrns->keymap);
128    if (ptrns->keycodes)
129	codesLen= (int)strlen(ptrns->keycodes);
130    if (ptrns->types)
131	typesLen= (int)strlen(ptrns->types);
132    if (ptrns->compat)
133	compatLen= (int)strlen(ptrns->compat);
134    if (ptrns->symbols)
135	symsLen= (int)strlen(ptrns->symbols);
136    if (ptrns->geometry)
137	geomLen= (int)strlen(ptrns->geometry);
138    if (mapLen>255)	mapLen= 255;
139    if (codesLen>255)	codesLen= 255;
140    if (typesLen>255)	typesLen= 255;
141    if (compatLen>255)	compatLen= 255;
142    if (symsLen>255)	symsLen= 255;
143    if (geomLen>255)	geomLen= 255;
144
145    len= mapLen+codesLen+typesLen+compatLen+symsLen+geomLen+6;
146    len= XkbPaddedSize(len);
147    req->length+= len/4;
148    BufAlloc(char *,str,len);
149    *str++= mapLen;
150    if (mapLen>0) {
151	 memcpy(str,ptrns->keymap,mapLen);
152	 str+= mapLen;
153    }
154    *str++= codesLen;
155    if (codesLen>0) {
156	 memcpy(str,ptrns->keycodes,codesLen);
157	 str+= codesLen;
158    }
159    *str++= typesLen;
160    if (typesLen>0) {
161	 memcpy(str,ptrns->types,typesLen);
162	 str+= typesLen;
163    }
164    *str++= compatLen;
165    if (compatLen>0) {
166	 memcpy(str,ptrns->compat,compatLen);
167	 str+= compatLen;
168    }
169    *str++= symsLen;
170    if (symsLen>0) {
171	 memcpy(str,ptrns->symbols,symsLen);
172	 str+= symsLen;
173    }
174    *str++= geomLen;
175    if (geomLen>0) {
176	 memcpy(str,ptrns->geometry,geomLen);
177	 str+= geomLen;
178    }
179    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse))
180	goto BAILOUT;
181    extraLen= (int)rep.length*4;
182    *max_inout= rep.extra;
183    if (extraLen==0) { /* no matches, but we don't want to report a failure */
184	list= _XkbTypedCalloc(1,XkbComponentListRec);
185	UnlockDisplay(dpy);
186	SyncHandle();
187	return list;
188    }
189    if (_XkbInitReadBuffer(dpy,&buf,extraLen)) {
190	Status status;
191
192	status= Success;
193	list= _XkbTypedCalloc(1,XkbComponentListRec);
194	if (!list) {
195	    _XkbFreeReadBuffer(&buf);
196	    goto BAILOUT;
197	}
198	list->num_keymaps= rep.nKeymaps;
199	list->num_keycodes= rep.nKeycodes;
200	list->num_types= rep.nTypes;
201	list->num_compat= rep.nCompatMaps;
202	list->num_symbols= rep.nSymbols;
203	list->num_geometry= rep.nGeometries;
204	if ((status==Success)&&(list->num_keymaps>0))
205	    list->keymaps= _ReadListing(&buf,list->num_keymaps,&status);
206	if ((status==Success)&&(list->num_keycodes>0))
207	    list->keycodes= _ReadListing(&buf,list->num_keycodes,&status);
208	if ((status==Success)&&(list->num_types>0))
209	    list->types= _ReadListing(&buf,list->num_types,&status);
210	if ((status==Success)&&(list->num_compat>0))
211	    list->compat= _ReadListing(&buf,list->num_compat,&status);
212	if ((status==Success)&&(list->num_symbols>0))
213	    list->symbols= _ReadListing(&buf,list->num_symbols,&status);
214	if ((status==Success)&&(list->num_geometry>0))
215	    list->geometry= _ReadListing(&buf,list->num_geometry,&status);
216	left= _XkbFreeReadBuffer(&buf);
217	if ((status!=Success)||(buf.error)||(left>2)) {
218	    XkbFreeComponentList(list);
219	    goto BAILOUT;
220	}
221	UnlockDisplay(dpy);
222	SyncHandle();
223	return list;
224    }
225BAILOUT:
226    UnlockDisplay(dpy);
227    SyncHandle();
228    return NULL;
229}
230
231void
232XkbFreeComponentList(XkbComponentListPtr list)
233{
234    if (list) {
235	if (list->keymaps)
236	    _FreeComponentNames(list->num_keymaps,list->keymaps);
237	if (list->keycodes)
238	    _FreeComponentNames(list->num_keycodes,list->keycodes);
239	if (list->types)
240	    _FreeComponentNames(list->num_types,list->types);
241	if (list->compat)
242	    _FreeComponentNames(list->num_compat,list->compat);
243	if (list->symbols)
244	    _FreeComponentNames(list->num_symbols,list->symbols);
245	if (list->geometry)
246	    _FreeComponentNames(list->num_geometry,list->geometry);
247	bzero((char *)list,sizeof(XkbComponentListRec));
248	_XkbFree(list);
249    }
250    return;
251}
252