306 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			7.9 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>
 | |
| #define	NEED_EVENTS 1
 | |
| #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>
 | |
| 
 | |
| #ifndef PATH_MAX
 | |
| #ifdef MAXPATHLEN
 | |
| #define	PATH_MAX MAXPATHLEN
 | |
| #else
 | |
| #define	PATH_MAX 1024
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #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] = {
 | |
| 	"keymap", "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= _XkbTypedRealloc(list->pool,list->szPool,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
 | |
| #ifdef DEBUG_CMD
 | |
| 	ErrorF("xkb executes: %s\n",buf);
 | |
| #endif
 | |
| 	if (System(buf) < 0)
 | |
| 	    ErrorF("Could not invoke keymap compiler\n");
 | |
| 	else
 | |
| 	    in= fopen(tmpname, "r");
 | |
| #endif
 | |
|     }
 | |
|     if (!in)
 | |
|     {
 | |
|         if (buf != NULL)
 | |
| 	    xfree (buf);
 | |
| #ifdef WIN32
 | |
| 	unlink(tmpname);
 | |
| #endif
 | |
| 	return BadImplementation;
 | |
|     }
 | |
|     list->nFound[what]= 0;
 | |
|     if (buf) {
 | |
|         xfree(buf);
 | |
|         buf = NULL;
 | |
|     }
 | |
|     buf = xalloc(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("xkbcomp returned exit code %d\n",rval);
 | |
|     }
 | |
| #else
 | |
|     fclose(in);
 | |
|     unlink(tmpname);
 | |
| #endif
 | |
|     if (buf != NULL)
 | |
|         xfree (buf);
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| /* ARGSUSED */
 | |
| Status
 | |
| XkbDDXList(DeviceIntPtr	dev,XkbSrvListInfoPtr list,ClientPtr client)
 | |
| {
 | |
| Status	status;
 | |
| 
 | |
|     status= XkbDDXListComponent(dev,_XkbListKeymaps,list,client);
 | |
|     if (status==Success)
 | |
| 	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;
 | |
| }
 |