maprules.c revision 6747b715
105b261ecSmrg/************************************************************ 205b261ecSmrg Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc. 305b261ecSmrg 405b261ecSmrg Permission to use, copy, modify, and distribute this 505b261ecSmrg software and its documentation for any purpose and without 605b261ecSmrg fee is hereby granted, provided that the above copyright 705b261ecSmrg notice appear in all copies and that both that copyright 805b261ecSmrg notice and this permission notice appear in supporting 905b261ecSmrg documentation, and that the name of Silicon Graphics not be 1005b261ecSmrg used in advertising or publicity pertaining to distribution 1105b261ecSmrg of the software without specific prior written permission. 1205b261ecSmrg Silicon Graphics makes no representation about the suitability 1305b261ecSmrg of this software for any purpose. It is provided "as is" 1405b261ecSmrg without any express or implied warranty. 1505b261ecSmrg 1605b261ecSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1705b261ecSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1805b261ecSmrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1905b261ecSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2005b261ecSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2105b261ecSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 2205b261ecSmrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 2305b261ecSmrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 2405b261ecSmrg 2505b261ecSmrg ********************************************************/ 2605b261ecSmrg 2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2805b261ecSmrg#include <dix-config.h> 2905b261ecSmrg#endif 3005b261ecSmrg 3105b261ecSmrg#include <stdio.h> 3205b261ecSmrg#include <ctype.h> 3305b261ecSmrg#include <stdlib.h> 3405b261ecSmrg 3505b261ecSmrg#define X_INCLUDE_STRING_H 3605b261ecSmrg#define XOS_USE_NO_LOCKING 3705b261ecSmrg#include <X11/Xos_r.h> 3805b261ecSmrg 3905b261ecSmrg#include <X11/Xproto.h> 4005b261ecSmrg#include <X11/X.h> 4105b261ecSmrg#include <X11/Xos.h> 4205b261ecSmrg#include <X11/Xfuncs.h> 4305b261ecSmrg#include <X11/Xatom.h> 4405b261ecSmrg#include <X11/keysym.h> 4505b261ecSmrg#include "misc.h" 4605b261ecSmrg#include "inputstr.h" 4705b261ecSmrg#include "dix.h" 484642e01fSmrg#include "os.h" 494642e01fSmrg#include "xkbstr.h" 5005b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS 5105b261ecSmrg#include <xkbsrv.h> 5205b261ecSmrg 5305b261ecSmrg/***====================================================================***/ 5405b261ecSmrg 556747b715Smrg 566747b715Smrg 5705b261ecSmrg#define DFLT_LINE_SIZE 128 5805b261ecSmrg 5905b261ecSmrgtypedef struct { 6005b261ecSmrg int line_num; 6105b261ecSmrg int sz_line; 6205b261ecSmrg int num_line; 6305b261ecSmrg char buf[DFLT_LINE_SIZE]; 6405b261ecSmrg char * line; 6505b261ecSmrg} InputLine; 6605b261ecSmrg 6705b261ecSmrgstatic void 6805b261ecSmrgInitInputLine(InputLine *line) 6905b261ecSmrg{ 7005b261ecSmrg line->line_num= 1; 7105b261ecSmrg line->num_line= 0; 7205b261ecSmrg line->sz_line= DFLT_LINE_SIZE; 7305b261ecSmrg line->line= line->buf; 7405b261ecSmrg return; 7505b261ecSmrg} 7605b261ecSmrg 7705b261ecSmrgstatic void 7805b261ecSmrgFreeInputLine(InputLine *line) 7905b261ecSmrg{ 8005b261ecSmrg if (line->line!=line->buf) 816747b715Smrg free(line->line); 8205b261ecSmrg line->line_num= 1; 8305b261ecSmrg line->num_line= 0; 8405b261ecSmrg line->sz_line= DFLT_LINE_SIZE; 8505b261ecSmrg line->line= line->buf; 8605b261ecSmrg return; 8705b261ecSmrg} 8805b261ecSmrg 8905b261ecSmrgstatic int 9005b261ecSmrgInputLineAddChar(InputLine *line,int ch) 9105b261ecSmrg{ 9205b261ecSmrg if (line->num_line>=line->sz_line) { 9305b261ecSmrg if (line->line==line->buf) { 946747b715Smrg line->line= malloc(line->sz_line*2); 9505b261ecSmrg memcpy(line->line,line->buf,line->sz_line); 9605b261ecSmrg } 9705b261ecSmrg else { 986747b715Smrg line->line= realloc((char *)line->line,line->sz_line*2); 9905b261ecSmrg } 10005b261ecSmrg line->sz_line*= 2; 10105b261ecSmrg } 10205b261ecSmrg line->line[line->num_line++]= ch; 10305b261ecSmrg return ch; 10405b261ecSmrg} 10505b261ecSmrg 10605b261ecSmrg#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\ 10705b261ecSmrg (int)((l)->line[(l)->num_line++]= (c)):\ 10805b261ecSmrg InputLineAddChar(l,c)) 10905b261ecSmrg 11005b261ecSmrgstatic Bool 11105b261ecSmrgGetInputLine(FILE *file,InputLine *line,Bool checkbang) 11205b261ecSmrg{ 11305b261ecSmrgint ch; 11405b261ecSmrgBool endOfFile,spacePending,slashPending,inComment; 11505b261ecSmrg 1166747b715Smrg endOfFile= FALSE; 11705b261ecSmrg while ((!endOfFile)&&(line->num_line==0)) { 1186747b715Smrg spacePending= slashPending= inComment= FALSE; 11905b261ecSmrg while (((ch=getc(file))!='\n')&&(ch!=EOF)) { 12005b261ecSmrg if (ch=='\\') { 12105b261ecSmrg if ((ch=getc(file))==EOF) 12205b261ecSmrg break; 12305b261ecSmrg if (ch=='\n') { 1246747b715Smrg inComment= FALSE; 12505b261ecSmrg ch= ' '; 12605b261ecSmrg line->line_num++; 12705b261ecSmrg } 12805b261ecSmrg } 12905b261ecSmrg if (inComment) 13005b261ecSmrg continue; 13105b261ecSmrg if (ch=='/') { 13205b261ecSmrg if (slashPending) { 1336747b715Smrg inComment= TRUE; 1346747b715Smrg slashPending= FALSE; 13505b261ecSmrg } 13605b261ecSmrg else { 1376747b715Smrg slashPending= TRUE; 13805b261ecSmrg } 13905b261ecSmrg continue; 14005b261ecSmrg } 14105b261ecSmrg else if (slashPending) { 14205b261ecSmrg if (spacePending) { 14305b261ecSmrg ADD_CHAR(line,' '); 1446747b715Smrg spacePending= FALSE; 14505b261ecSmrg } 14605b261ecSmrg ADD_CHAR(line,'/'); 1476747b715Smrg slashPending= FALSE; 14805b261ecSmrg } 14905b261ecSmrg if (isspace(ch)) { 15005b261ecSmrg while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) { 15105b261ecSmrg ch= getc(file); 15205b261ecSmrg } 15305b261ecSmrg if (ch==EOF) 15405b261ecSmrg break; 15505b261ecSmrg if ((ch!='\n')&&(line->num_line>0)) 1566747b715Smrg spacePending= TRUE; 15705b261ecSmrg ungetc(ch,file); 15805b261ecSmrg } 15905b261ecSmrg else { 16005b261ecSmrg if (spacePending) { 16105b261ecSmrg ADD_CHAR(line,' '); 1626747b715Smrg spacePending= FALSE; 16305b261ecSmrg } 16405b261ecSmrg if (checkbang && ch=='!') { 16505b261ecSmrg if (line->num_line!=0) { 1664642e01fSmrg DebugF("The '!' legal only at start of line\n"); 1674642e01fSmrg DebugF("Line containing '!' ignored\n"); 16805b261ecSmrg line->num_line= 0; 16905b261ecSmrg inComment= 0; 17005b261ecSmrg break; 17105b261ecSmrg } 17205b261ecSmrg 17305b261ecSmrg } 17405b261ecSmrg ADD_CHAR(line,ch); 17505b261ecSmrg } 17605b261ecSmrg } 17705b261ecSmrg if (ch==EOF) 1786747b715Smrg endOfFile= TRUE; 17905b261ecSmrg/* else line->num_line++;*/ 18005b261ecSmrg } 18105b261ecSmrg if ((line->num_line==0)&&(endOfFile)) 1826747b715Smrg return FALSE; 18305b261ecSmrg ADD_CHAR(line,'\0'); 1846747b715Smrg return TRUE; 18505b261ecSmrg} 18605b261ecSmrg 18705b261ecSmrg/***====================================================================***/ 18805b261ecSmrg 18905b261ecSmrg#define MODEL 0 19005b261ecSmrg#define LAYOUT 1 19105b261ecSmrg#define VARIANT 2 19205b261ecSmrg#define OPTION 3 19305b261ecSmrg#define KEYCODES 4 19405b261ecSmrg#define SYMBOLS 5 19505b261ecSmrg#define TYPES 6 19605b261ecSmrg#define COMPAT 7 19705b261ecSmrg#define GEOMETRY 8 1986747b715Smrg#define MAX_WORDS 9 19905b261ecSmrg 20005b261ecSmrg#define PART_MASK 0x000F 20105b261ecSmrg#define COMPONENT_MASK 0x03F0 20205b261ecSmrg 20305b261ecSmrgstatic char * cname[MAX_WORDS] = { 20405b261ecSmrg "model", "layout", "variant", "option", 2056747b715Smrg "keycodes", "symbols", "types", "compat", "geometry" 20605b261ecSmrg}; 20705b261ecSmrg 20805b261ecSmrgtypedef struct _RemapSpec { 20905b261ecSmrg int number; 21005b261ecSmrg int num_remap; 21105b261ecSmrg struct { 21205b261ecSmrg int word; 21305b261ecSmrg int index; 21405b261ecSmrg } remap[MAX_WORDS]; 21505b261ecSmrg} RemapSpec; 21605b261ecSmrg 21705b261ecSmrgtypedef struct _FileSpec { 21805b261ecSmrg char * name[MAX_WORDS]; 21905b261ecSmrg struct _FileSpec * pending; 22005b261ecSmrg} FileSpec; 22105b261ecSmrg 22205b261ecSmrgtypedef struct { 22305b261ecSmrg char * model; 22405b261ecSmrg char * layout[XkbNumKbdGroups+1]; 22505b261ecSmrg char * variant[XkbNumKbdGroups+1]; 22605b261ecSmrg char * options; 22705b261ecSmrg} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; 22805b261ecSmrg 22905b261ecSmrg#define NDX_BUFF_SIZE 4 23005b261ecSmrg 23105b261ecSmrg/***====================================================================***/ 23205b261ecSmrg 23305b261ecSmrgstatic char* 23405b261ecSmrgget_index(char *str, int *ndx) 23505b261ecSmrg{ 23605b261ecSmrg char ndx_buf[NDX_BUFF_SIZE]; 23705b261ecSmrg char *end; 23805b261ecSmrg 23905b261ecSmrg if (*str != '[') { 24005b261ecSmrg *ndx = 0; 24105b261ecSmrg return str; 24205b261ecSmrg } 24305b261ecSmrg str++; 24405b261ecSmrg end = strchr(str, ']'); 24505b261ecSmrg if (end == NULL) { 24605b261ecSmrg *ndx = -1; 24705b261ecSmrg return str - 1; 24805b261ecSmrg } 24905b261ecSmrg if ( (end - str) >= NDX_BUFF_SIZE) { 25005b261ecSmrg *ndx = -1; 25105b261ecSmrg return end + 1; 25205b261ecSmrg } 25305b261ecSmrg strncpy(ndx_buf, str, end - str); 25405b261ecSmrg ndx_buf[end - str] = '\0'; 25505b261ecSmrg *ndx = atoi(ndx_buf); 25605b261ecSmrg return end + 1; 25705b261ecSmrg} 25805b261ecSmrg 25905b261ecSmrgstatic void 26005b261ecSmrgSetUpRemap(InputLine *line,RemapSpec *remap) 26105b261ecSmrg{ 26205b261ecSmrgchar * tok,*str; 26305b261ecSmrgunsigned present, l_ndx_present, v_ndx_present; 26405b261ecSmrgregister int i; 26505b261ecSmrgint len, ndx; 26605b261ecSmrg_Xstrtokparams strtok_buf; 26705b261ecSmrgBool found; 26805b261ecSmrg 26905b261ecSmrg 27005b261ecSmrg l_ndx_present = v_ndx_present = present= 0; 27105b261ecSmrg str= &line->line[1]; 27205b261ecSmrg len = remap->number; 2736747b715Smrg memset((char *)remap, 0, sizeof(RemapSpec)); 27405b261ecSmrg remap->number = len; 27505b261ecSmrg while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { 2766747b715Smrg found= FALSE; 27705b261ecSmrg str= NULL; 27805b261ecSmrg if (strcmp(tok,"=")==0) 27905b261ecSmrg continue; 28005b261ecSmrg for (i=0;i<MAX_WORDS;i++) { 28105b261ecSmrg len = strlen(cname[i]); 28205b261ecSmrg if (strncmp(cname[i],tok,len)==0) { 28305b261ecSmrg if(strlen(tok) > len) { 28405b261ecSmrg char *end = get_index(tok+len, &ndx); 28505b261ecSmrg if ((i != LAYOUT && i != VARIANT) || 28605b261ecSmrg *end != '\0' || ndx == -1) 28705b261ecSmrg break; 28805b261ecSmrg if (ndx < 1 || ndx > XkbNumKbdGroups) { 2894642e01fSmrg DebugF("Illegal %s index: %d\n", cname[i], ndx); 2904642e01fSmrg DebugF("Index must be in range 1..%d\n", 29105b261ecSmrg XkbNumKbdGroups); 29205b261ecSmrg break; 29305b261ecSmrg } 29405b261ecSmrg } else { 29505b261ecSmrg ndx = 0; 29605b261ecSmrg } 2976747b715Smrg found= TRUE; 29805b261ecSmrg if (present&(1<<i)) { 29905b261ecSmrg if ((i == LAYOUT && l_ndx_present&(1<<ndx)) || 30005b261ecSmrg (i == VARIANT && v_ndx_present&(1<<ndx)) ) { 3014642e01fSmrg DebugF("Component \"%s\" listed twice\n",tok); 3024642e01fSmrg DebugF("Second definition ignored\n"); 30305b261ecSmrg break; 30405b261ecSmrg } 30505b261ecSmrg } 30605b261ecSmrg present |= (1<<i); 30705b261ecSmrg if (i == LAYOUT) 30805b261ecSmrg l_ndx_present |= 1 << ndx; 30905b261ecSmrg if (i == VARIANT) 31005b261ecSmrg v_ndx_present |= 1 << ndx; 31105b261ecSmrg remap->remap[remap->num_remap].word= i; 31205b261ecSmrg remap->remap[remap->num_remap++].index= ndx; 31305b261ecSmrg break; 31405b261ecSmrg } 31505b261ecSmrg } 31605b261ecSmrg if (!found) { 31705b261ecSmrg fprintf(stderr,"Unknown component \"%s\" ignored\n",tok); 31805b261ecSmrg } 31905b261ecSmrg } 32005b261ecSmrg if ((present&PART_MASK)==0) { 32105b261ecSmrg unsigned mask= PART_MASK; 3224642e01fSmrg ErrorF("Mapping needs at least one of "); 32305b261ecSmrg for (i=0; (i<MAX_WORDS); i++) { 32405b261ecSmrg if ((1L<<i)&mask) { 32505b261ecSmrg mask&= ~(1L<<i); 3264642e01fSmrg if (mask) DebugF("\"%s,\" ",cname[i]); 3274642e01fSmrg else DebugF("or \"%s\"\n",cname[i]); 32805b261ecSmrg } 32905b261ecSmrg } 3304642e01fSmrg DebugF("Illegal mapping ignored\n"); 33105b261ecSmrg remap->num_remap= 0; 33205b261ecSmrg return; 33305b261ecSmrg } 33405b261ecSmrg if ((present&COMPONENT_MASK)==0) { 3354642e01fSmrg DebugF("Mapping needs at least one component\n"); 3364642e01fSmrg DebugF("Illegal mapping ignored\n"); 33705b261ecSmrg remap->num_remap= 0; 33805b261ecSmrg return; 33905b261ecSmrg } 34005b261ecSmrg remap->number++; 34105b261ecSmrg return; 34205b261ecSmrg} 34305b261ecSmrg 34405b261ecSmrgstatic Bool 34505b261ecSmrgMatchOneOf(char *wanted,char *vals_defined) 34605b261ecSmrg{ 34705b261ecSmrgchar *str,*next; 34805b261ecSmrgint want_len= strlen(wanted); 34905b261ecSmrg 35005b261ecSmrg for (str=vals_defined,next=NULL;str!=NULL;str=next) { 35105b261ecSmrg int len; 35205b261ecSmrg next= strchr(str,','); 35305b261ecSmrg if (next) { 35405b261ecSmrg len= next-str; 35505b261ecSmrg next++; 35605b261ecSmrg } 35705b261ecSmrg else { 35805b261ecSmrg len= strlen(str); 35905b261ecSmrg } 36005b261ecSmrg if ((len==want_len)&&(strncmp(wanted,str,len)==0)) 3616747b715Smrg return TRUE; 36205b261ecSmrg } 3636747b715Smrg return FALSE; 36405b261ecSmrg} 36505b261ecSmrg 36605b261ecSmrg/***====================================================================***/ 36705b261ecSmrg 36805b261ecSmrgstatic Bool 36905b261ecSmrgCheckLine( InputLine * line, 37005b261ecSmrg RemapSpec * remap, 37105b261ecSmrg XkbRF_RulePtr rule, 37205b261ecSmrg XkbRF_GroupPtr group) 37305b261ecSmrg{ 37405b261ecSmrgchar * str,*tok; 37505b261ecSmrgregister int nread, i; 37605b261ecSmrgFileSpec tmp; 37705b261ecSmrg_Xstrtokparams strtok_buf; 3786747b715SmrgBool append = FALSE; 37905b261ecSmrg 38005b261ecSmrg if (line->line[0]=='!') { 38105b261ecSmrg if (line->line[1] == '$' || 38205b261ecSmrg (line->line[1] == ' ' && line->line[2] == '$')) { 38305b261ecSmrg char *gname = strchr(line->line, '$'); 38405b261ecSmrg char *words = strchr(gname, ' '); 38505b261ecSmrg if(!words) 3866747b715Smrg return FALSE; 38705b261ecSmrg *words++ = '\0'; 38805b261ecSmrg for (; *words; words++) { 38905b261ecSmrg if (*words != '=' && *words != ' ') 39005b261ecSmrg break; 39105b261ecSmrg } 39205b261ecSmrg if (*words == '\0') 3936747b715Smrg return FALSE; 39405b261ecSmrg group->name = _XkbDupString(gname); 39505b261ecSmrg group->words = _XkbDupString(words); 39605b261ecSmrg for (i = 1, words = group->words; *words; words++) { 39705b261ecSmrg if ( *words == ' ') { 39805b261ecSmrg *words++ = '\0'; 39905b261ecSmrg i++; 40005b261ecSmrg } 40105b261ecSmrg } 40205b261ecSmrg group->number = i; 4036747b715Smrg return TRUE; 40405b261ecSmrg } else { 40505b261ecSmrg SetUpRemap(line,remap); 4066747b715Smrg return FALSE; 40705b261ecSmrg } 40805b261ecSmrg } 40905b261ecSmrg 41005b261ecSmrg if (remap->num_remap==0) { 4114642e01fSmrg DebugF("Must have a mapping before first line of data\n"); 4124642e01fSmrg DebugF("Illegal line of data ignored\n"); 4136747b715Smrg return FALSE; 41405b261ecSmrg } 4156747b715Smrg memset((char *)&tmp, 0, sizeof(FileSpec)); 41605b261ecSmrg str= line->line; 41705b261ecSmrg for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) { 41805b261ecSmrg str= NULL; 41905b261ecSmrg if (strcmp(tok,"=")==0) { 42005b261ecSmrg nread--; 42105b261ecSmrg continue; 42205b261ecSmrg } 42305b261ecSmrg if (nread>remap->num_remap) { 4244642e01fSmrg DebugF("Too many words on a line\n"); 4254642e01fSmrg DebugF("Extra word \"%s\" ignored\n",tok); 42605b261ecSmrg continue; 42705b261ecSmrg } 42805b261ecSmrg tmp.name[remap->remap[nread].word]= tok; 42905b261ecSmrg if (*tok == '+' || *tok == '|') 4306747b715Smrg append = TRUE; 43105b261ecSmrg } 43205b261ecSmrg if (nread<remap->num_remap) { 4334642e01fSmrg DebugF("Too few words on a line: %s\n", line->line); 4344642e01fSmrg DebugF("line ignored\n"); 4356747b715Smrg return FALSE; 43605b261ecSmrg } 43705b261ecSmrg 43805b261ecSmrg rule->flags= 0; 43905b261ecSmrg rule->number = remap->number; 44005b261ecSmrg if (tmp.name[OPTION]) 44105b261ecSmrg rule->flags|= XkbRF_Option; 44205b261ecSmrg else if (append) 44305b261ecSmrg rule->flags|= XkbRF_Append; 44405b261ecSmrg else 44505b261ecSmrg rule->flags|= XkbRF_Normal; 44605b261ecSmrg rule->model= _XkbDupString(tmp.name[MODEL]); 44705b261ecSmrg rule->layout= _XkbDupString(tmp.name[LAYOUT]); 44805b261ecSmrg rule->variant= _XkbDupString(tmp.name[VARIANT]); 44905b261ecSmrg rule->option= _XkbDupString(tmp.name[OPTION]); 45005b261ecSmrg 45105b261ecSmrg rule->keycodes= _XkbDupString(tmp.name[KEYCODES]); 45205b261ecSmrg rule->symbols= _XkbDupString(tmp.name[SYMBOLS]); 45305b261ecSmrg rule->types= _XkbDupString(tmp.name[TYPES]); 45405b261ecSmrg rule->compat= _XkbDupString(tmp.name[COMPAT]); 45505b261ecSmrg rule->geometry= _XkbDupString(tmp.name[GEOMETRY]); 45605b261ecSmrg 45705b261ecSmrg rule->layout_num = rule->variant_num = 0; 45805b261ecSmrg for (i = 0; i < nread; i++) { 45905b261ecSmrg if (remap->remap[i].index) { 46005b261ecSmrg if (remap->remap[i].word == LAYOUT) 46105b261ecSmrg rule->layout_num = remap->remap[i].index; 46205b261ecSmrg if (remap->remap[i].word == VARIANT) 46305b261ecSmrg rule->variant_num = remap->remap[i].index; 46405b261ecSmrg } 46505b261ecSmrg } 4666747b715Smrg return TRUE; 46705b261ecSmrg} 46805b261ecSmrg 46905b261ecSmrgstatic char * 47005b261ecSmrg_Concat(char *str1,char *str2) 47105b261ecSmrg{ 47205b261ecSmrgint len; 47305b261ecSmrg 47405b261ecSmrg if ((!str1)||(!str2)) 47505b261ecSmrg return str1; 47605b261ecSmrg len= strlen(str1)+strlen(str2)+1; 4776747b715Smrg str1= realloc(str1,len * sizeof(char)); 47805b261ecSmrg if (str1) 47905b261ecSmrg strcat(str1,str2); 48005b261ecSmrg return str1; 48105b261ecSmrg} 48205b261ecSmrg 48305b261ecSmrgstatic void 48405b261ecSmrgsqueeze_spaces(char *p1) 48505b261ecSmrg{ 48605b261ecSmrg char *p2; 48705b261ecSmrg for (p2 = p1; *p2; p2++) { 48805b261ecSmrg *p1 = *p2; 48905b261ecSmrg if (*p1 != ' ') p1++; 49005b261ecSmrg } 49105b261ecSmrg *p1 = '\0'; 49205b261ecSmrg} 49305b261ecSmrg 49405b261ecSmrgstatic Bool 49505b261ecSmrgMakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) 49605b261ecSmrg{ 49705b261ecSmrg 4986747b715Smrg memset((char *)mdefs, 0, sizeof(XkbRF_MultiDefsRec)); 49905b261ecSmrg mdefs->model = defs->model; 50005b261ecSmrg mdefs->options = _XkbDupString(defs->options); 50105b261ecSmrg if (mdefs->options) squeeze_spaces(mdefs->options); 50205b261ecSmrg 50305b261ecSmrg if (defs->layout) { 50405b261ecSmrg if (!strchr(defs->layout, ',')) { 50505b261ecSmrg mdefs->layout[0] = defs->layout; 50605b261ecSmrg } else { 50705b261ecSmrg char *p; 50805b261ecSmrg int i; 50905b261ecSmrg mdefs->layout[1] = _XkbDupString(defs->layout); 51005b261ecSmrg if (mdefs->layout[1] == NULL) 5116747b715Smrg return FALSE; 51205b261ecSmrg squeeze_spaces(mdefs->layout[1]); 51305b261ecSmrg p = mdefs->layout[1]; 51405b261ecSmrg for (i = 2; i <= XkbNumKbdGroups; i++) { 51505b261ecSmrg if ((p = strchr(p, ','))) { 51605b261ecSmrg *p++ = '\0'; 51705b261ecSmrg mdefs->layout[i] = p; 51805b261ecSmrg } else { 51905b261ecSmrg break; 52005b261ecSmrg } 52105b261ecSmrg } 52205b261ecSmrg if (p && (p = strchr(p, ','))) 52305b261ecSmrg *p = '\0'; 52405b261ecSmrg } 52505b261ecSmrg } 52605b261ecSmrg 52705b261ecSmrg if (defs->variant) { 52805b261ecSmrg if (!strchr(defs->variant, ',')) { 52905b261ecSmrg mdefs->variant[0] = defs->variant; 53005b261ecSmrg } else { 53105b261ecSmrg char *p; 53205b261ecSmrg int i; 53305b261ecSmrg mdefs->variant[1] = _XkbDupString(defs->variant); 53405b261ecSmrg if (mdefs->variant[1] == NULL) 5356747b715Smrg return FALSE; 53605b261ecSmrg squeeze_spaces(mdefs->variant[1]); 53705b261ecSmrg p = mdefs->variant[1]; 53805b261ecSmrg for (i = 2; i <= XkbNumKbdGroups; i++) { 53905b261ecSmrg if ((p = strchr(p, ','))) { 54005b261ecSmrg *p++ = '\0'; 54105b261ecSmrg mdefs->variant[i] = p; 54205b261ecSmrg } else { 54305b261ecSmrg break; 54405b261ecSmrg } 54505b261ecSmrg } 54605b261ecSmrg if (p && (p = strchr(p, ','))) 54705b261ecSmrg *p = '\0'; 54805b261ecSmrg } 54905b261ecSmrg } 5506747b715Smrg return TRUE; 55105b261ecSmrg} 55205b261ecSmrg 55305b261ecSmrgstatic void 55405b261ecSmrgFreeMultiDefs(XkbRF_MultiDefsPtr defs) 55505b261ecSmrg{ 5566747b715Smrg free(defs->options); 5576747b715Smrg free(defs->layout[1]); 5586747b715Smrg free(defs->variant[1]); 55905b261ecSmrg} 56005b261ecSmrg 56105b261ecSmrgstatic void 56205b261ecSmrgApply(char *src, char **dst) 56305b261ecSmrg{ 56405b261ecSmrg if (src) { 56505b261ecSmrg if (*src == '+' || *src == '!') { 56605b261ecSmrg *dst= _Concat(*dst, src); 56705b261ecSmrg } else { 56805b261ecSmrg if (*dst == NULL) 56905b261ecSmrg *dst= _XkbDupString(src); 57005b261ecSmrg } 57105b261ecSmrg } 57205b261ecSmrg} 57305b261ecSmrg 57405b261ecSmrgstatic void 57505b261ecSmrgXkbRF_ApplyRule( XkbRF_RulePtr rule, 57605b261ecSmrg XkbComponentNamesPtr names) 57705b261ecSmrg{ 57805b261ecSmrg rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ 57905b261ecSmrg 58005b261ecSmrg Apply(rule->keycodes, &names->keycodes); 58105b261ecSmrg Apply(rule->symbols, &names->symbols); 58205b261ecSmrg Apply(rule->types, &names->types); 58305b261ecSmrg Apply(rule->compat, &names->compat); 58405b261ecSmrg Apply(rule->geometry, &names->geometry); 58505b261ecSmrg} 58605b261ecSmrg 58705b261ecSmrgstatic Bool 58805b261ecSmrgCheckGroup( XkbRF_RulesPtr rules, 58905b261ecSmrg char * group_name, 59005b261ecSmrg char * name) 59105b261ecSmrg{ 59205b261ecSmrg int i; 59305b261ecSmrg char *p; 59405b261ecSmrg XkbRF_GroupPtr group; 59505b261ecSmrg 59605b261ecSmrg for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { 59705b261ecSmrg if (! strcmp(group->name, group_name)) { 59805b261ecSmrg break; 59905b261ecSmrg } 60005b261ecSmrg } 60105b261ecSmrg if (i == rules->num_groups) 6026747b715Smrg return FALSE; 60305b261ecSmrg for (i = 0, p = group->words; i < group->number; i++, p += strlen(p)+1) { 60405b261ecSmrg if (! strcmp(p, name)) { 6056747b715Smrg return TRUE; 60605b261ecSmrg } 60705b261ecSmrg } 6086747b715Smrg return FALSE; 60905b261ecSmrg} 61005b261ecSmrg 61105b261ecSmrgstatic int 61205b261ecSmrgXkbRF_CheckApplyRule( XkbRF_RulePtr rule, 61305b261ecSmrg XkbRF_MultiDefsPtr mdefs, 61405b261ecSmrg XkbComponentNamesPtr names, 61505b261ecSmrg XkbRF_RulesPtr rules) 61605b261ecSmrg{ 6176747b715Smrg Bool pending = FALSE; 61805b261ecSmrg 61905b261ecSmrg if (rule->model != NULL) { 62005b261ecSmrg if(mdefs->model == NULL) 62105b261ecSmrg return 0; 62205b261ecSmrg if (strcmp(rule->model, "*") == 0) { 6236747b715Smrg pending = TRUE; 62405b261ecSmrg } else { 62505b261ecSmrg if (rule->model[0] == '$') { 62605b261ecSmrg if (!CheckGroup(rules, rule->model, mdefs->model)) 62705b261ecSmrg return 0; 62805b261ecSmrg } else { 62905b261ecSmrg if (strcmp(rule->model, mdefs->model) != 0) 63005b261ecSmrg return 0; 63105b261ecSmrg } 63205b261ecSmrg } 63305b261ecSmrg } 63405b261ecSmrg if (rule->option != NULL) { 63505b261ecSmrg if (mdefs->options == NULL) 63605b261ecSmrg return 0; 63705b261ecSmrg if ((!MatchOneOf(rule->option,mdefs->options))) 63805b261ecSmrg return 0; 63905b261ecSmrg } 64005b261ecSmrg 64105b261ecSmrg if (rule->layout != NULL) { 64205b261ecSmrg if(mdefs->layout[rule->layout_num] == NULL || 64305b261ecSmrg *mdefs->layout[rule->layout_num] == '\0') 64405b261ecSmrg return 0; 64505b261ecSmrg if (strcmp(rule->layout, "*") == 0) { 6466747b715Smrg pending = TRUE; 64705b261ecSmrg } else { 64805b261ecSmrg if (rule->layout[0] == '$') { 64905b261ecSmrg if (!CheckGroup(rules, rule->layout, 65005b261ecSmrg mdefs->layout[rule->layout_num])) 65105b261ecSmrg return 0; 65205b261ecSmrg } else { 65305b261ecSmrg if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0) 65405b261ecSmrg return 0; 65505b261ecSmrg } 65605b261ecSmrg } 65705b261ecSmrg } 65805b261ecSmrg if (rule->variant != NULL) { 65905b261ecSmrg if (mdefs->variant[rule->variant_num] == NULL || 66005b261ecSmrg *mdefs->variant[rule->variant_num] == '\0') 66105b261ecSmrg return 0; 66205b261ecSmrg if (strcmp(rule->variant, "*") == 0) { 6636747b715Smrg pending = TRUE; 66405b261ecSmrg } else { 66505b261ecSmrg if (rule->variant[0] == '$') { 66605b261ecSmrg if (!CheckGroup(rules, rule->variant, 66705b261ecSmrg mdefs->variant[rule->variant_num])) 66805b261ecSmrg return 0; 66905b261ecSmrg } else { 67005b261ecSmrg if (strcmp(rule->variant, 67105b261ecSmrg mdefs->variant[rule->variant_num]) != 0) 67205b261ecSmrg return 0; 67305b261ecSmrg } 67405b261ecSmrg } 67505b261ecSmrg } 67605b261ecSmrg if (pending) { 67705b261ecSmrg rule->flags|= XkbRF_PendingMatch; 67805b261ecSmrg return rule->number; 67905b261ecSmrg } 68005b261ecSmrg /* exact match, apply it now */ 68105b261ecSmrg XkbRF_ApplyRule(rule,names); 68205b261ecSmrg return rule->number; 68305b261ecSmrg} 68405b261ecSmrg 68505b261ecSmrgstatic void 68605b261ecSmrgXkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) 68705b261ecSmrg{ 68805b261ecSmrgregister int i; 68905b261ecSmrgXkbRF_RulePtr rule; 69005b261ecSmrg 69105b261ecSmrg for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { 69205b261ecSmrg rule->flags&= ~XkbRF_PendingMatch; 69305b261ecSmrg } 69405b261ecSmrg} 69505b261ecSmrg 69605b261ecSmrgstatic void 69705b261ecSmrgXkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) 69805b261ecSmrg{ 69905b261ecSmrgint i; 70005b261ecSmrgXkbRF_RulePtr rule; 70105b261ecSmrg 70205b261ecSmrg for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { 70305b261ecSmrg if ((rule->flags&XkbRF_PendingMatch)==0) 70405b261ecSmrg continue; 70505b261ecSmrg XkbRF_ApplyRule(rule,names); 70605b261ecSmrg } 70705b261ecSmrg} 70805b261ecSmrg 70905b261ecSmrgstatic void 71005b261ecSmrgXkbRF_CheckApplyRules( XkbRF_RulesPtr rules, 71105b261ecSmrg XkbRF_MultiDefsPtr mdefs, 71205b261ecSmrg XkbComponentNamesPtr names, 71305b261ecSmrg int flags) 71405b261ecSmrg{ 71505b261ecSmrgint i; 71605b261ecSmrgXkbRF_RulePtr rule; 71705b261ecSmrgint skip; 71805b261ecSmrg 71905b261ecSmrg for (rule = rules->rules, i=0; i < rules->num_rules; rule++, i++) { 72005b261ecSmrg if ((rule->flags & flags) != flags) 72105b261ecSmrg continue; 72205b261ecSmrg skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules); 72305b261ecSmrg if (skip && !(flags & XkbRF_Option)) { 72405b261ecSmrg for ( ;(i < rules->num_rules) && (rule->number == skip); 72505b261ecSmrg rule++, i++); 72605b261ecSmrg rule--; i--; 72705b261ecSmrg } 72805b261ecSmrg } 72905b261ecSmrg} 73005b261ecSmrg 73105b261ecSmrg/***====================================================================***/ 73205b261ecSmrg 73305b261ecSmrgstatic char * 73405b261ecSmrgXkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) 73505b261ecSmrg{ 73605b261ecSmrgchar *str, *outstr, *orig, *var; 73705b261ecSmrgint len, ndx; 73805b261ecSmrg 73905b261ecSmrg orig= name; 74005b261ecSmrg str= index(name,'%'); 74105b261ecSmrg if (str==NULL) 74205b261ecSmrg return name; 74305b261ecSmrg len= strlen(name); 74405b261ecSmrg while (str!=NULL) { 74505b261ecSmrg char pfx= str[1]; 74605b261ecSmrg int extra_len= 0; 74705b261ecSmrg if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { 74805b261ecSmrg extra_len= 1; 74905b261ecSmrg str++; 75005b261ecSmrg } 75105b261ecSmrg else if (pfx=='(') { 75205b261ecSmrg extra_len= 2; 75305b261ecSmrg str++; 75405b261ecSmrg } 75505b261ecSmrg var = str + 1; 75605b261ecSmrg str = get_index(var + 1, &ndx); 75705b261ecSmrg if (ndx == -1) { 75805b261ecSmrg str = index(str,'%'); 75905b261ecSmrg continue; 76005b261ecSmrg } 76105b261ecSmrg if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) 76205b261ecSmrg len+= strlen(mdefs->layout[ndx])+extra_len; 76305b261ecSmrg else if ((*var=='m')&&mdefs->model) 76405b261ecSmrg len+= strlen(mdefs->model)+extra_len; 76505b261ecSmrg else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) 76605b261ecSmrg len+= strlen(mdefs->variant[ndx])+extra_len; 76705b261ecSmrg if ((pfx=='(')&&(*str==')')) { 76805b261ecSmrg str++; 76905b261ecSmrg } 77005b261ecSmrg str= index(&str[0],'%'); 77105b261ecSmrg } 7726747b715Smrg name= malloc(len+1); 77305b261ecSmrg str= orig; 77405b261ecSmrg outstr= name; 77505b261ecSmrg while (*str!='\0') { 77605b261ecSmrg if (str[0]=='%') { 77705b261ecSmrg char pfx,sfx; 77805b261ecSmrg str++; 77905b261ecSmrg pfx= str[0]; 78005b261ecSmrg sfx= '\0'; 78105b261ecSmrg if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { 78205b261ecSmrg str++; 78305b261ecSmrg } 78405b261ecSmrg else if (pfx=='(') { 78505b261ecSmrg sfx= ')'; 78605b261ecSmrg str++; 78705b261ecSmrg } 78805b261ecSmrg else pfx= '\0'; 78905b261ecSmrg 79005b261ecSmrg var = str; 79105b261ecSmrg str = get_index(var + 1, &ndx); 79205b261ecSmrg if (ndx == -1) { 79305b261ecSmrg continue; 79405b261ecSmrg } 79505b261ecSmrg if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) { 79605b261ecSmrg if (pfx) *outstr++= pfx; 79705b261ecSmrg strcpy(outstr,mdefs->layout[ndx]); 79805b261ecSmrg outstr+= strlen(mdefs->layout[ndx]); 79905b261ecSmrg if (sfx) *outstr++= sfx; 80005b261ecSmrg } 80105b261ecSmrg else if ((*var=='m')&&(mdefs->model)) { 80205b261ecSmrg if (pfx) *outstr++= pfx; 80305b261ecSmrg strcpy(outstr,mdefs->model); 80405b261ecSmrg outstr+= strlen(mdefs->model); 80505b261ecSmrg if (sfx) *outstr++= sfx; 80605b261ecSmrg } 80705b261ecSmrg else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) { 80805b261ecSmrg if (pfx) *outstr++= pfx; 80905b261ecSmrg strcpy(outstr,mdefs->variant[ndx]); 81005b261ecSmrg outstr+= strlen(mdefs->variant[ndx]); 81105b261ecSmrg if (sfx) *outstr++= sfx; 81205b261ecSmrg } 81305b261ecSmrg if ((pfx=='(')&&(*str==')')) 81405b261ecSmrg str++; 81505b261ecSmrg } 81605b261ecSmrg else { 81705b261ecSmrg *outstr++= *str++; 81805b261ecSmrg } 81905b261ecSmrg } 82005b261ecSmrg *outstr++= '\0'; 82105b261ecSmrg if (orig!=name) 8226747b715Smrg free(orig); 82305b261ecSmrg return name; 82405b261ecSmrg} 82505b261ecSmrg 82605b261ecSmrg/***====================================================================***/ 82705b261ecSmrg 82805b261ecSmrgBool 82905b261ecSmrgXkbRF_GetComponents( XkbRF_RulesPtr rules, 83005b261ecSmrg XkbRF_VarDefsPtr defs, 83105b261ecSmrg XkbComponentNamesPtr names) 83205b261ecSmrg{ 83305b261ecSmrg XkbRF_MultiDefsRec mdefs; 83405b261ecSmrg 83505b261ecSmrg MakeMultiDefs(&mdefs, defs); 83605b261ecSmrg 8376747b715Smrg memset((char *)names, 0, sizeof(XkbComponentNamesRec)); 83805b261ecSmrg XkbRF_ClearPartialMatches(rules); 83905b261ecSmrg XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal); 84005b261ecSmrg XkbRF_ApplyPartialMatches(rules, names); 84105b261ecSmrg XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append); 84205b261ecSmrg XkbRF_ApplyPartialMatches(rules, names); 84305b261ecSmrg XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option); 84405b261ecSmrg 84505b261ecSmrg if (names->keycodes) 84605b261ecSmrg names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs); 84705b261ecSmrg if (names->symbols) 84805b261ecSmrg names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs); 84905b261ecSmrg if (names->types) 85005b261ecSmrg names->types= XkbRF_SubstituteVars(names->types, &mdefs); 85105b261ecSmrg if (names->compat) 85205b261ecSmrg names->compat= XkbRF_SubstituteVars(names->compat, &mdefs); 85305b261ecSmrg if (names->geometry) 85405b261ecSmrg names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs); 85505b261ecSmrg 85605b261ecSmrg FreeMultiDefs(&mdefs); 85705b261ecSmrg return (names->keycodes && names->symbols && names->types && 8586747b715Smrg names->compat && names->geometry); 85905b261ecSmrg} 86005b261ecSmrg 8616747b715Smrgstatic XkbRF_RulePtr 86205b261ecSmrgXkbRF_AddRule(XkbRF_RulesPtr rules) 86305b261ecSmrg{ 86405b261ecSmrg if (rules->sz_rules<1) { 86505b261ecSmrg rules->sz_rules= 16; 86605b261ecSmrg rules->num_rules= 0; 8676747b715Smrg rules->rules= calloc(rules->sz_rules, sizeof(XkbRF_RuleRec)); 86805b261ecSmrg } 86905b261ecSmrg else if (rules->num_rules>=rules->sz_rules) { 87005b261ecSmrg rules->sz_rules*= 2; 8716747b715Smrg rules->rules= realloc(rules->rules, 8726747b715Smrg rules->sz_rules * sizeof(XkbRF_RuleRec)); 87305b261ecSmrg } 87405b261ecSmrg if (!rules->rules) { 87505b261ecSmrg rules->sz_rules= rules->num_rules= 0; 8764642e01fSmrg DebugF("Allocation failure in XkbRF_AddRule\n"); 87705b261ecSmrg return NULL; 87805b261ecSmrg } 8796747b715Smrg memset((char *)&rules->rules[rules->num_rules], 0, sizeof(XkbRF_RuleRec)); 88005b261ecSmrg return &rules->rules[rules->num_rules++]; 88105b261ecSmrg} 88205b261ecSmrg 8836747b715Smrgstatic XkbRF_GroupPtr 88405b261ecSmrgXkbRF_AddGroup(XkbRF_RulesPtr rules) 88505b261ecSmrg{ 88605b261ecSmrg if (rules->sz_groups<1) { 88705b261ecSmrg rules->sz_groups= 16; 88805b261ecSmrg rules->num_groups= 0; 8896747b715Smrg rules->groups= calloc(rules->sz_groups, sizeof(XkbRF_GroupRec)); 89005b261ecSmrg } 89105b261ecSmrg else if (rules->num_groups >= rules->sz_groups) { 89205b261ecSmrg rules->sz_groups *= 2; 8936747b715Smrg rules->groups= realloc(rules->groups, 8946747b715Smrg rules->sz_groups * sizeof(XkbRF_GroupRec)); 89505b261ecSmrg } 89605b261ecSmrg if (!rules->groups) { 89705b261ecSmrg rules->sz_groups= rules->num_groups= 0; 89805b261ecSmrg return NULL; 89905b261ecSmrg } 90005b261ecSmrg 9016747b715Smrg memset((char *)&rules->groups[rules->num_groups], 0, sizeof(XkbRF_GroupRec)); 90205b261ecSmrg return &rules->groups[rules->num_groups++]; 90305b261ecSmrg} 90405b261ecSmrg 90505b261ecSmrgBool 90605b261ecSmrgXkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) 90705b261ecSmrg{ 90805b261ecSmrgInputLine line; 90905b261ecSmrgRemapSpec remap; 91005b261ecSmrgXkbRF_RuleRec trule,*rule; 91105b261ecSmrgXkbRF_GroupRec tgroup,*group; 91205b261ecSmrg 91305b261ecSmrg if (!(rules && file)) 9146747b715Smrg return FALSE; 9156747b715Smrg memset((char *)&remap, 0, sizeof(RemapSpec)); 9166747b715Smrg memset((char *)&tgroup, 0, sizeof(XkbRF_GroupRec)); 91705b261ecSmrg InitInputLine(&line); 9186747b715Smrg while (GetInputLine(file,&line,TRUE)) { 91905b261ecSmrg if (CheckLine(&line,&remap,&trule,&tgroup)) { 92005b261ecSmrg if (tgroup.number) { 92105b261ecSmrg if ((group= XkbRF_AddGroup(rules))!=NULL) { 92205b261ecSmrg *group= tgroup; 9236747b715Smrg memset((char *)&tgroup, 0, sizeof(XkbRF_GroupRec)); 92405b261ecSmrg } 92505b261ecSmrg } else { 92605b261ecSmrg if ((rule= XkbRF_AddRule(rules))!=NULL) { 92705b261ecSmrg *rule= trule; 9286747b715Smrg memset((char *)&trule, 0, sizeof(XkbRF_RuleRec)); 92905b261ecSmrg } 93005b261ecSmrg } 93105b261ecSmrg } 93205b261ecSmrg line.num_line= 0; 93305b261ecSmrg } 93405b261ecSmrg FreeInputLine(&line); 9356747b715Smrg return TRUE; 93605b261ecSmrg} 93705b261ecSmrg 93805b261ecSmrgBool 93905b261ecSmrgXkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) 94005b261ecSmrg{ 94105b261ecSmrgFILE * file; 94205b261ecSmrgchar buf[PATH_MAX]; 94305b261ecSmrgBool ok; 94405b261ecSmrg 94505b261ecSmrg if ((!base)||(!rules)) 9466747b715Smrg return FALSE; 94705b261ecSmrg if (locale) { 94805b261ecSmrg if (strlen(base)+strlen(locale)+2 > PATH_MAX) 9496747b715Smrg return FALSE; 95005b261ecSmrg sprintf(buf,"%s-%s", base, locale); 95105b261ecSmrg } 95205b261ecSmrg else { 95305b261ecSmrg if (strlen(base)+1 > PATH_MAX) 9546747b715Smrg return FALSE; 95505b261ecSmrg strcpy(buf,base); 95605b261ecSmrg } 95705b261ecSmrg 95805b261ecSmrg file= fopen(buf, "r"); 95905b261ecSmrg if ((!file)&&(locale)) { /* fallback if locale was specified */ 96005b261ecSmrg strcpy(buf,base); 96105b261ecSmrg file= fopen(buf, "r"); 96205b261ecSmrg } 96305b261ecSmrg if (!file) 9646747b715Smrg return FALSE; 96505b261ecSmrg ok= XkbRF_LoadRules(file,rules); 96605b261ecSmrg fclose(file); 96705b261ecSmrg return ok; 96805b261ecSmrg} 96905b261ecSmrg 97005b261ecSmrg/***====================================================================***/ 97105b261ecSmrg 97205b261ecSmrgXkbRF_RulesPtr 9736747b715SmrgXkbRF_Create(void) 97405b261ecSmrg{ 9756747b715Smrg return calloc(1, sizeof( XkbRF_RulesRec)); 97605b261ecSmrg} 97705b261ecSmrg 97805b261ecSmrg/***====================================================================***/ 97905b261ecSmrg 98005b261ecSmrgvoid 98105b261ecSmrgXkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) 98205b261ecSmrg{ 98305b261ecSmrgint i; 98405b261ecSmrgXkbRF_RulePtr rule; 98505b261ecSmrgXkbRF_GroupPtr group; 98605b261ecSmrg 98705b261ecSmrg if (!rules) 98805b261ecSmrg return; 98905b261ecSmrg if (rules->rules) { 99005b261ecSmrg for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { 9916747b715Smrg free(rule->model); 9926747b715Smrg free(rule->layout); 9936747b715Smrg free(rule->variant); 9946747b715Smrg free(rule->option); 9956747b715Smrg free(rule->keycodes); 9966747b715Smrg free(rule->symbols); 9976747b715Smrg free(rule->types); 9986747b715Smrg free(rule->compat); 9996747b715Smrg free(rule->geometry); 10006747b715Smrg memset((char *)rule, 0, sizeof(XkbRF_RuleRec)); 100105b261ecSmrg } 10026747b715Smrg free(rules->rules); 100305b261ecSmrg rules->num_rules= rules->sz_rules= 0; 100405b261ecSmrg rules->rules= NULL; 100505b261ecSmrg } 100605b261ecSmrg 100705b261ecSmrg if (rules->groups) { 100805b261ecSmrg for (i=0, group=rules->groups;i<rules->num_groups;i++,group++) { 10096747b715Smrg free(group->name); 10106747b715Smrg free(group->words); 101105b261ecSmrg } 10126747b715Smrg free(rules->groups); 101305b261ecSmrg rules->num_groups= 0; 101405b261ecSmrg rules->groups= NULL; 101505b261ecSmrg } 101605b261ecSmrg if (freeRules) 10176747b715Smrg free(rules); 101805b261ecSmrg return; 101905b261ecSmrg} 1020