XKBList.c revision e9fcaa8a
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_MAP_READERS
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "Xlibint.h"
32#include <X11/extensions/XKBproto.h>
33#include "XKBlibint.h"
34
35/***====================================================================***/
36
37static void
38_FreeComponentNames(int num,XkbComponentNamePtr names)
39{
40int			i;
41XkbComponentNamePtr	tmp;
42
43    if ((num<1)||(names==NULL))
44	return;
45    for (i=0,tmp=names;i<num;i++,tmp++) {
46	if (tmp->name) {
47	    _XkbFree(tmp->name);
48	    tmp->name= NULL;
49	}
50    }
51    _XkbFree(names);
52    return;
53}
54
55/***====================================================================***/
56
57static XkbComponentNamePtr
58_ReadListing(XkbReadBufferPtr buf,int count,Status *status_rtrn)
59{
60XkbComponentNamePtr	first,this;
61register int		i;
62CARD16 *		flags;
63int			slen,wlen;
64char *			str;
65
66    if (count<1)
67	return NULL;
68    first= _XkbTypedCalloc(count,XkbComponentNameRec);
69    if (!first)
70	return NULL;
71    for (this=first,i=0;i<count;i++,this++) {
72	flags= (CARD16 *)_XkbGetReadBufferPtr(buf,2*sizeof(CARD16));
73	if (!flags)
74	    goto BAILOUT;
75	this->flags= 	flags[0];
76	slen=		flags[1];
77	wlen= 		((slen+1)/2)*2; /* pad to 2 byte boundary */
78	this->name=	_XkbTypedCalloc(slen+1,char);
79	if (!this->name)
80	    goto BAILOUT;
81	str= (char *)_XkbGetReadBufferPtr(buf,wlen);
82	memcpy(this->name,str,slen);
83    }
84    return first;
85BAILOUT:
86    *status_rtrn= BadAlloc;
87    _FreeComponentNames(i,first);
88    return NULL;
89}
90
91/***====================================================================***/
92
93XkbComponentListPtr
94XkbListComponents(	Display *		dpy,
95			unsigned		deviceSpec,
96			XkbComponentNamesPtr	ptrns,
97			int *			max_inout)
98{
99register xkbListComponentsReq*	req;
100xkbListComponentsReply 		rep;
101XkbInfoPtr 			xkbi;
102XkbComponentListPtr		list;
103XkbReadBufferRec		buf;
104int				left;
105char *				str;
106int extraLen,len,mapLen,codesLen,typesLen,compatLen,symsLen,geomLen;
107
108    if ( (dpy==NULL) || (dpy->flags & XlibDisplayNoXkb) ||
109	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) ||
110	(ptrns==NULL) || (max_inout==NULL))
111	return NULL;
112
113    xkbi= dpy->xkb_info;
114    LockDisplay(dpy);
115    GetReq(kbListComponents, req);
116    req->reqType = 	xkbi->codes->major_opcode;
117    req->xkbReqType = 	X_kbListComponents;
118    req->deviceSpec = 	deviceSpec;
119    req->maxNames =	*max_inout;
120
121    mapLen= codesLen= typesLen= compatLen= symsLen= geomLen= 0;
122    if (ptrns->keymap)
123	mapLen= (int)strlen(ptrns->keymap);
124    if (ptrns->keycodes)
125	codesLen= (int)strlen(ptrns->keycodes);
126    if (ptrns->types)
127	typesLen= (int)strlen(ptrns->types);
128    if (ptrns->compat)
129	compatLen= (int)strlen(ptrns->compat);
130    if (ptrns->symbols)
131	symsLen= (int)strlen(ptrns->symbols);
132    if (ptrns->geometry)
133	geomLen= (int)strlen(ptrns->geometry);
134    if (mapLen>255)	mapLen= 255;
135    if (codesLen>255)	codesLen= 255;
136    if (typesLen>255)	typesLen= 255;
137    if (compatLen>255)	compatLen= 255;
138    if (symsLen>255)	symsLen= 255;
139    if (geomLen>255)	geomLen= 255;
140
141    len= mapLen+codesLen+typesLen+compatLen+symsLen+geomLen+6;
142    len= XkbPaddedSize(len);
143    req->length+= len/4;
144    BufAlloc(char *,str,len);
145    *str++= mapLen;
146    if (mapLen>0) {
147	 memcpy(str,ptrns->keymap,mapLen);
148	 str+= mapLen;
149    }
150    *str++= codesLen;
151    if (codesLen>0) {
152	 memcpy(str,ptrns->keycodes,codesLen);
153	 str+= codesLen;
154    }
155    *str++= typesLen;
156    if (typesLen>0) {
157	 memcpy(str,ptrns->types,typesLen);
158	 str+= typesLen;
159    }
160    *str++= compatLen;
161    if (compatLen>0) {
162	 memcpy(str,ptrns->compat,compatLen);
163	 str+= compatLen;
164    }
165    *str++= symsLen;
166    if (symsLen>0) {
167	 memcpy(str,ptrns->symbols,symsLen);
168	 str+= symsLen;
169    }
170    *str++= geomLen;
171    if (geomLen>0) {
172	 memcpy(str,ptrns->geometry,geomLen);
173	 str+= geomLen;
174    }
175    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse))
176	goto BAILOUT;
177    extraLen= (int)rep.length*4;
178    *max_inout= rep.extra;
179    if (extraLen==0) { /* no matches, but we don't want to report a failure */
180	list= _XkbTypedCalloc(1,XkbComponentListRec);
181	UnlockDisplay(dpy);
182	SyncHandle();
183	return list;
184    }
185    if (_XkbInitReadBuffer(dpy,&buf,extraLen)) {
186	Status status;
187
188	status= Success;
189	list= _XkbTypedCalloc(1,XkbComponentListRec);
190	if (!list) {
191	    _XkbFreeReadBuffer(&buf);
192	    goto BAILOUT;
193	}
194	list->num_keymaps= rep.nKeymaps;
195	list->num_keycodes= rep.nKeycodes;
196	list->num_types= rep.nTypes;
197	list->num_compat= rep.nCompatMaps;
198	list->num_symbols= rep.nSymbols;
199	list->num_geometry= rep.nGeometries;
200	if ((status==Success)&&(list->num_keymaps>0))
201	    list->keymaps= _ReadListing(&buf,list->num_keymaps,&status);
202	if ((status==Success)&&(list->num_keycodes>0))
203	    list->keycodes= _ReadListing(&buf,list->num_keycodes,&status);
204	if ((status==Success)&&(list->num_types>0))
205	    list->types= _ReadListing(&buf,list->num_types,&status);
206	if ((status==Success)&&(list->num_compat>0))
207	    list->compat= _ReadListing(&buf,list->num_compat,&status);
208	if ((status==Success)&&(list->num_symbols>0))
209	    list->symbols= _ReadListing(&buf,list->num_symbols,&status);
210	if ((status==Success)&&(list->num_geometry>0))
211	    list->geometry= _ReadListing(&buf,list->num_geometry,&status);
212	left= _XkbFreeReadBuffer(&buf);
213	if ((status!=Success)||(buf.error)||(left>2)) {
214	    XkbFreeComponentList(list);
215	    goto BAILOUT;
216	}
217	UnlockDisplay(dpy);
218	SyncHandle();
219	return list;
220    }
221BAILOUT:
222    UnlockDisplay(dpy);
223    SyncHandle();
224    return NULL;
225}
226
227void
228XkbFreeComponentList(XkbComponentListPtr list)
229{
230    if (list) {
231	if (list->keymaps)
232	    _FreeComponentNames(list->num_keymaps,list->keymaps);
233	if (list->keycodes)
234	    _FreeComponentNames(list->num_keycodes,list->keycodes);
235	if (list->types)
236	    _FreeComponentNames(list->num_types,list->types);
237	if (list->compat)
238	    _FreeComponentNames(list->num_compat,list->compat);
239	if (list->symbols)
240	    _FreeComponentNames(list->num_symbols,list->symbols);
241	if (list->geometry)
242	    _FreeComponentNames(list->num_geometry,list->geometry);
243	bzero((char *)list,sizeof(XkbComponentListRec));
244	_XkbFree(list);
245    }
246    return;
247}
248