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