291 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			291 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
/************************************************************
 | 
						|
Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this
 | 
						|
software and its documentation for any purpose and without
 | 
						|
fee is hereby granted, provided that the above copyright
 | 
						|
notice appear in all copies and that both that copyright
 | 
						|
notice and this permission notice appear in supporting
 | 
						|
documentation, and that the name of Silicon Graphics not be 
 | 
						|
used in advertising or publicity pertaining to distribution 
 | 
						|
of the software without specific prior written permission.
 | 
						|
Silicon Graphics makes no representation about the suitability 
 | 
						|
of this software for any purpose. It is provided "as is"
 | 
						|
without any express or implied warranty.
 | 
						|
 | 
						|
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
 | 
						|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
 | 
						|
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
 | 
						|
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
 | 
						|
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
 | 
						|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
 | 
						|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
 | 
						|
THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 | 
						|
********************************************************/
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <ctype.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xos.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include <X11/keysym.h>
 | 
						|
#include <X11/extensions/XKM.h>
 | 
						|
#include "inputstr.h"
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#define	XKBSRV_NEED_FILE_FUNCS
 | 
						|
#include <xkbsrv.h>
 | 
						|
#include <X11/extensions/XI.h>
 | 
						|
 | 
						|
#ifdef WIN32
 | 
						|
/* from ddxLoad.c */
 | 
						|
extern const char* Win32TempDir();
 | 
						|
extern int Win32System(const char *cmdline);
 | 
						|
#undef System
 | 
						|
#define System Win32System
 | 
						|
 | 
						|
#define W32_tmparg " '%s'"
 | 
						|
#define W32_tmpfile ,tmpname
 | 
						|
#define W32_tmplen strlen(tmpname)+3
 | 
						|
#else
 | 
						|
#define W32_tmparg
 | 
						|
#define W32_tmpfile 
 | 
						|
#define W32_tmplen 0
 | 
						|
#endif 
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
static char *componentDirs[_XkbListNumComponents] = {
 | 
						|
	"keycodes", "types", "compat", "symbols", "geometry"
 | 
						|
};
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
static Status
 | 
						|
_AddListComponent(	XkbSrvListInfoPtr	list,
 | 
						|
			int			what,
 | 
						|
			unsigned		flags,
 | 
						|
			char *			str,
 | 
						|
			ClientPtr		client)
 | 
						|
{
 | 
						|
int		slen,wlen;
 | 
						|
unsigned char *	wire8;
 | 
						|
unsigned short *wire16;
 | 
						|
char *		tmp;
 | 
						|
 | 
						|
    if (list->nTotal>=list->maxRtrn) {
 | 
						|
	list->nTotal++;
 | 
						|
	return Success;
 | 
						|
    }
 | 
						|
    tmp= strchr(str,')');
 | 
						|
    if ((tmp==NULL)&&((tmp=strchr(str,'('))==NULL)) {
 | 
						|
	slen= strlen(str);
 | 
						|
	while ((slen>0) && isspace(str[slen-1])) {
 | 
						|
	    slen--;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	slen= (tmp-str+1);
 | 
						|
    }
 | 
						|
    wlen= (((slen+1)/2)*2)+4;	/* four bytes for flags and length, pad to */
 | 
						|
				/* 2-byte boundary */
 | 
						|
    if ((list->szPool-list->nPool)<wlen) {
 | 
						|
	if (wlen>1024)	list->szPool+= XkbPaddedSize(wlen*2);
 | 
						|
	else		list->szPool+= 1024;
 | 
						|
	list->pool= realloc(list->pool, list->szPool * sizeof(char));
 | 
						|
	if (!list->pool)
 | 
						|
	    return BadAlloc;
 | 
						|
    }
 | 
						|
    wire16= (unsigned short *)&list->pool[list->nPool];
 | 
						|
    wire8= (unsigned char *)&wire16[2];
 | 
						|
    wire16[0]= flags;
 | 
						|
    wire16[1]= slen;
 | 
						|
    memcpy(wire8,str,slen);
 | 
						|
    if (client->swapped) {
 | 
						|
	register int n;
 | 
						|
	swaps(&wire16[0],n);
 | 
						|
	swaps(&wire16[1],n);
 | 
						|
    }
 | 
						|
    list->nPool+= wlen;
 | 
						|
    list->nFound[what]++;
 | 
						|
    list->nTotal++;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
static Status
 | 
						|
XkbDDXListComponent(	DeviceIntPtr 		dev,
 | 
						|
			int			what,
 | 
						|
			XkbSrvListInfoPtr	list,
 | 
						|
			ClientPtr		client)
 | 
						|
{
 | 
						|
char 	*file,*map,*tmp,*buf=NULL;
 | 
						|
FILE 	*in;
 | 
						|
Status	status;
 | 
						|
int	rval;
 | 
						|
Bool	haveDir;
 | 
						|
#ifdef WIN32
 | 
						|
char	tmpname[PATH_MAX];
 | 
						|
#endif
 | 
						|
 | 
						|
    if ((list->pattern[what]==NULL)||(list->pattern[what][0]=='\0'))
 | 
						|
	return Success;
 | 
						|
    file= list->pattern[what];
 | 
						|
    map= strrchr(file,'(');
 | 
						|
    if (map!=NULL) {
 | 
						|
	char *tmp;
 | 
						|
	map++;
 | 
						|
	tmp= strrchr(map,')');
 | 
						|
	if ((tmp==NULL)||(tmp[1]!='\0')) {
 | 
						|
	    /* illegal pattern.  No error, but no match */
 | 
						|
	    return Success;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    in= NULL;
 | 
						|
    haveDir= TRUE;
 | 
						|
#ifdef WIN32
 | 
						|
    strcpy(tmpname, Win32TempDir());
 | 
						|
    strcat(tmpname, "\\xkb_XXXXXX");
 | 
						|
    (void) mktemp(tmpname);
 | 
						|
#endif
 | 
						|
    if (XkbBaseDirectory!=NULL) {
 | 
						|
	if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) {
 | 
						|
	    buf = Xprintf("%s/%s.dir",XkbBaseDirectory,componentDirs[what]);
 | 
						|
	    in= fopen(buf,"r");
 | 
						|
	}
 | 
						|
	if (!in) {
 | 
						|
	    haveDir= FALSE;
 | 
						|
	    buf = Xprintf(
 | 
						|
		"'%s/xkbcomp' '-R%s/%s' -w %ld -l -vlfhpR '%s'" W32_tmparg,
 | 
						|
                XkbBinDirectory,XkbBaseDirectory,componentDirs[what],(long)
 | 
						|
		((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)),
 | 
						|
		file W32_tmpfile
 | 
						|
                );
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) {
 | 
						|
	    buf = Xprintf("%s.dir",componentDirs[what]);
 | 
						|
	    in= fopen(buf,"r");
 | 
						|
	}
 | 
						|
	if (!in) {
 | 
						|
	    haveDir= FALSE;
 | 
						|
	    buf = Xprintf(
 | 
						|
		"xkbcomp -R%s -w %ld -l -vlfhpR '%s'" W32_tmparg,
 | 
						|
                componentDirs[what],(long)
 | 
						|
		((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)),
 | 
						|
		file W32_tmpfile
 | 
						|
                );
 | 
						|
	}
 | 
						|
    }
 | 
						|
    status= Success;
 | 
						|
    if (!haveDir)
 | 
						|
    {  
 | 
						|
#ifndef WIN32
 | 
						|
	in= Popen(buf,"r");
 | 
						|
#else
 | 
						|
        if (xkbDebugFlags)
 | 
						|
            DebugF("[xkb] xkbList executes: %s\n",buf);
 | 
						|
	if (System(buf) < 0)
 | 
						|
	    ErrorF("[xkb] Could not invoke keymap compiler\n");
 | 
						|
	else
 | 
						|
	    in= fopen(tmpname, "r");
 | 
						|
#endif
 | 
						|
    }
 | 
						|
    if (!in)
 | 
						|
    {
 | 
						|
        if (buf != NULL)
 | 
						|
	    free(buf);
 | 
						|
#ifdef WIN32
 | 
						|
	unlink(tmpname);
 | 
						|
#endif
 | 
						|
	return BadImplementation;
 | 
						|
    }
 | 
						|
    list->nFound[what]= 0;
 | 
						|
    free(buf);
 | 
						|
    buf = malloc(PATH_MAX * sizeof(char));
 | 
						|
    if (!buf)
 | 
						|
        return BadAlloc;
 | 
						|
    while ((status==Success)&&((tmp=fgets(buf,PATH_MAX,in))!=NULL)) {
 | 
						|
	unsigned flags;
 | 
						|
	register unsigned int i;
 | 
						|
	if (*tmp=='#') /* comment, skip it */
 | 
						|
	    continue;
 | 
						|
	if (!strncmp(tmp, "Warning:", 8) || !strncmp(tmp, "        ", 8))
 | 
						|
	    /* skip warnings too */
 | 
						|
	    continue;
 | 
						|
	flags= 0;
 | 
						|
	/* each line in the listing is supposed to start with two */
 | 
						|
	/* groups of eight characters, which specify the general  */
 | 
						|
	/* flags and the flags that are specific to the component */
 | 
						|
	/* if they're missing, fail with BadImplementation	  */
 | 
						|
	for (i=0;(i<8)&&(status==Success);i++) { /* read the general flags */
 | 
						|
	   if (isalpha(*tmp))	flags|= (1L<<i);
 | 
						|
	   else if (*tmp!='-')	status= BadImplementation;
 | 
						|
	   tmp++;
 | 
						|
	}
 | 
						|
	if (status != Success)  break;
 | 
						|
	if (!isspace(*tmp)) {
 | 
						|
	     status= BadImplementation;
 | 
						|
	     break;
 | 
						|
	}
 | 
						|
	else tmp++;
 | 
						|
	for (i=0;(i<8)&&(status==Success);i++) { /* read the component flags */
 | 
						|
	   if (isalpha(*tmp))	flags|= (1L<<(i+8));
 | 
						|
	   else if (*tmp!='-')	status= BadImplementation;
 | 
						|
	   tmp++;
 | 
						|
	}
 | 
						|
	if (status != Success)  break;
 | 
						|
	if (isspace(*tmp)) {
 | 
						|
	    while (isspace(*tmp)) {
 | 
						|
		tmp++;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    status= BadImplementation;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	status= _AddListComponent(list,what,flags,tmp,client);
 | 
						|
    }
 | 
						|
#ifndef WIN32
 | 
						|
    if (haveDir)
 | 
						|
	fclose(in);
 | 
						|
    else if ((rval=Pclose(in))!=0) {
 | 
						|
	if (xkbDebugFlags)
 | 
						|
	    ErrorF("[xkb] xkbcomp returned exit code %d\n",rval);
 | 
						|
    }
 | 
						|
#else
 | 
						|
    fclose(in);
 | 
						|
    unlink(tmpname);
 | 
						|
#endif
 | 
						|
    if (buf != NULL)
 | 
						|
        free(buf);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
/* ARGSUSED */
 | 
						|
Status
 | 
						|
XkbDDXList(DeviceIntPtr	dev,XkbSrvListInfoPtr list,ClientPtr client)
 | 
						|
{
 | 
						|
Status	status;
 | 
						|
 | 
						|
    status= XkbDDXListComponent(dev,_XkbListKeycodes,list,client);
 | 
						|
    if (status==Success)
 | 
						|
	status= XkbDDXListComponent(dev,_XkbListTypes,list,client);
 | 
						|
    if (status==Success)
 | 
						|
	status= XkbDDXListComponent(dev,_XkbListCompat,list,client);
 | 
						|
    if (status==Success)
 | 
						|
	status= XkbDDXListComponent(dev,_XkbListSymbols,list,client);
 | 
						|
    if (status==Success)
 | 
						|
	status= XkbDDXListComponent(dev,_XkbListGeometry,list,client);
 | 
						|
    return status;
 | 
						|
}
 |