summaryrefslogtreecommitdiff
path: root/xkbpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'xkbpath.c')
-rw-r--r--xkbpath.c359
1 files changed, 359 insertions, 0 deletions
diff --git a/xkbpath.c b/xkbpath.c
new file mode 100644
index 0000000..8e21a7b
--- /dev/null
+++ b/xkbpath.c
@@ -0,0 +1,359 @@
+/* $Xorg: xkbpath.c,v 1.3 2000/08/17 19:54:34 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1994 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.
+
+ ********************************************************/
+
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+
+#define DEBUG_VAR_NOT_LOCAL
+#define DEBUG_VAR debugFlags
+#include "utils.h"
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#endif
+#include <X11/extensions/XKM.h>
+#include "xkbpath.h"
+
+#ifndef DFLT_XKB_CONFIG_ROOT
+#define DFLT_XKB_CONFIG_ROOT "/usr/lib/X11/xkb"
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#define PATH_CHUNK 8
+
+static int longestPath;
+static int szPath;
+static int nPathEntries;
+static char ** includePath;
+
+Bool
+#if NeedFunctionPrototypes
+XkbParseIncludeMap(char **str_inout,char **file_rtrn,char **map_rtrn,
+ char *nextop_rtrn)
+#else
+XkbParseIncludeMap(str_inout,file_rtrn,map_rtrn,nextop_rtrn)
+ char ** str_inout;
+ char ** file_rtrn;
+ char ** map_rtrn;
+ char * nextop_rtrn;
+#endif
+{
+char *tmp,*str,*next;
+
+ str= *str_inout;
+ if ((*str=='+')||(*str=='|')) {
+ *file_rtrn= *map_rtrn= NULL;
+ *nextop_rtrn= *str;
+ next= str+1;
+ }
+ else if (*str=='%') {
+ *file_rtrn= *map_rtrn= NULL;
+ *nextop_rtrn= str[1];
+ next= str+2;
+ }
+ else {
+ next= strpbrk(str,"|+");
+ if (next) {
+ *nextop_rtrn= *next;
+ *next++= '\0';
+ }
+ else {
+ *nextop_rtrn= '\0';
+ next= NULL;
+ }
+ tmp= strchr(str,'(');
+ if (tmp==NULL) {
+ *file_rtrn= uStringDup(str);
+ *map_rtrn= NULL;
+ }
+ else if (str[0]=='(') {
+ return False;
+ }
+ else {
+ *tmp++= '\0';
+ *file_rtrn= uStringDup(str);
+ str= tmp;
+ tmp= strchr(str,')');
+ if ((tmp==NULL)||(tmp[1]!='\0')) {
+ uFree(*file_rtrn);
+ return False;
+ }
+ *tmp++= '\0';
+ *map_rtrn= uStringDup(str);
+ }
+ }
+ if (*nextop_rtrn=='\0')
+ *str_inout= NULL;
+ else if ((*nextop_rtrn=='|')||(*nextop_rtrn=='+'))
+ *str_inout= next;
+ else return False;
+ return True;
+}
+
+Bool
+#if NeedFunctionPrototypes
+XkbInitIncludePath(void)
+#else
+XkbInitIncludePath()
+#endif
+{
+ szPath= PATH_CHUNK;
+ includePath= (char **)calloc(szPath,sizeof(char *));
+ if (includePath==NULL)
+ return False;
+ XkbAddDirectoryToPath(".");
+ XkbAddDirectoryToPath(DFLT_XKB_CONFIG_ROOT);
+ return True;
+}
+
+void
+#if NeedFunctionPrototypes
+XkbClearIncludePath(void)
+#else
+XkbClearIncludePath()
+#endif
+{
+register int i;
+
+ if (szPath>0) {
+ for (i=0;i<nPathEntries;i++) {
+ if (includePath[i]!=NULL) {
+ uFree(includePath[i]);
+ includePath[i]= NULL;
+ }
+ }
+ nPathEntries= 0;
+ longestPath= 0;
+ }
+ return;
+}
+
+Bool
+#if NeedFunctionPrototypes
+XkbAddDirectoryToPath(char *dir)
+#else
+XkbAddDirectoryToPath(dir)
+ char *dir;
+#endif
+{
+int len;
+ if ((dir==NULL)||(dir[0]=='\0')) {
+ XkbClearIncludePath();
+ return True;
+ }
+ len= strlen(dir);
+ if (len+2>=PATH_MAX) { /* allow for '/' and at least one character */
+ ERROR2("Path entry (%s) too long (maxiumum length is %d)\n",
+ dir,PATH_MAX-3);
+ return False;
+ }
+ if (len>longestPath)
+ longestPath= len;
+ if (nPathEntries>=szPath) {
+ szPath+= PATH_CHUNK;
+ includePath= (char **)realloc(includePath,szPath*sizeof(char *));
+ if (includePath==NULL) {
+ WSGO("Allocation failed (includePath)\n");
+ return False;
+ }
+ }
+ includePath[nPathEntries]= (char *)calloc(strlen(dir)+1,sizeof(char));
+ if (includePath[nPathEntries]==NULL) {
+ WSGO1("Allocation failed (includePath[%d])\n",nPathEntries);
+ return False;
+ }
+ strcpy(includePath[nPathEntries++],dir);
+ return True;
+}
+
+/***====================================================================***/
+
+char *
+#if NeedFunctionPrototypes
+XkbDirectoryForInclude(unsigned type)
+#else
+XkbDirectoryForInclude(type)
+ unsigned type;
+#endif
+{
+static char buf[32];
+
+ switch (type) {
+ case XkmSemanticsFile:
+ strcpy(buf,"semantics");
+ break;
+ case XkmLayoutFile:
+ strcpy(buf,"layout");
+ break;
+ case XkmKeymapFile:
+ strcpy(buf,"keymap");
+ break;
+ case XkmKeyNamesIndex:
+ strcpy(buf,"keycodes");
+ break;
+ case XkmTypesIndex:
+ strcpy(buf,"types");
+ break;
+ case XkmSymbolsIndex:
+ strcpy(buf,"symbols");
+ break;
+ case XkmCompatMapIndex:
+ strcpy(buf,"compat");
+ break;
+ case XkmGeometryFile:
+ case XkmGeometryIndex:
+ strcpy(buf,"geometry");
+ break;
+ default:
+ strcpy(buf,"");
+ break;
+ }
+ return buf;
+}
+
+/***====================================================================***/
+
+typedef struct _FileCacheEntry {
+ char * name;
+ unsigned type;
+ char * path;
+ void * data;
+ struct _FileCacheEntry * next;
+} FileCacheEntry;
+static FileCacheEntry *fileCache;
+
+void *
+#if NeedFunctionPrototypes
+XkbAddFileToCache(char *name,unsigned type,char *path,void *data)
+#else
+XkbAddFileToCache(name,type,path,data)
+ char * name;
+ unsigned type;
+ char * path;
+ void * data;
+#endif
+{
+FileCacheEntry *entry;
+
+ for (entry=fileCache;entry!=NULL;entry=entry->next) {
+ if ((type==entry->type)&&(uStringEqual(name,entry->name))) {
+ void *old= entry->data;
+ WSGO2("Replacing file cache entry (%s/%d)\n",name,type);
+ entry->path= path;
+ entry->data= data;
+ return old;
+ }
+ }
+ entry= uTypedAlloc(FileCacheEntry);
+ if (entry!=NULL) {
+ entry->name= name;
+ entry->type= type;
+ entry->path= path;
+ entry->data= data;
+ entry->next= fileCache;
+ fileCache= entry;
+ }
+ return NULL;
+}
+
+void *
+#if NeedFunctionPrototypes
+XkbFindFileInCache(char *name,unsigned type,char **pathRtrn)
+#else
+XkbFindFileInCache(name,type,pathRtrn)
+ char * name;
+ unsigned type;
+ char ** pathRtrn;
+#endif
+{
+FileCacheEntry *entry;
+
+ for (entry=fileCache;entry!=NULL;entry=entry->next) {
+ if ((type==entry->type)&&(uStringEqual(name,entry->name))) {
+ *pathRtrn= entry->path;
+ return entry->data;
+ }
+ }
+ return NULL;
+}
+
+/***====================================================================***/
+
+FILE *
+#if NeedFunctionPrototypes
+XkbFindFileInPath(char *name,unsigned type,char **pathRtrn)
+#else
+XkbFindFileInPath(name,type,pathRtrn)
+ char * name;
+ unsigned type;
+ char ** pathRtrn;
+#endif
+{
+register int i;
+FILE *file= NULL;
+int nameLen,typeLen,pathLen;
+char buf[PATH_MAX],*typeDir;
+
+ typeDir= XkbDirectoryForInclude(type);
+ nameLen= strlen(name);
+ typeLen= strlen(typeDir);
+ for (i=0;i<nPathEntries;i++) {
+ pathLen= strlen(includePath[i]);
+ if ((nameLen+pathLen+1)>=PATH_MAX) {
+ ERROR2("File name (%s/%s) too long\n",includePath[i],name);
+ ACTION("Ignored\n");
+ continue;
+ }
+ sprintf(buf,"%s/%s",includePath[i],name);
+ file= fopen(buf,"r");
+ if (file!=NULL)
+ break;
+ else if (typeLen<1)
+ continue;
+
+ if ((nameLen+typeLen+pathLen+2)>=PATH_MAX) {
+ ERROR3("File name (%s/%s/%s) too long\n",includePath[i],typeDir,
+ name);
+ ACTION("Ignored\n");
+ continue;
+ }
+ sprintf(buf,"%s/%s/%s",includePath[i],typeDir,name);
+ file= fopen(buf,"r");
+ if (file!=NULL)
+ break;
+ }
+
+ if ((file!=NULL)&&(pathRtrn!=NULL)) {
+ *pathRtrn= (char *)calloc(strlen(buf)+1,sizeof(char));
+ if (*pathRtrn!=NULL)
+ strcpy(*pathRtrn,buf);
+ }
+ return file;
+}
+