maprules.c revision 05b261ec
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#define NEED_EVENTS 4005b261ecSmrg#include <X11/Xproto.h> 4105b261ecSmrg#include <X11/X.h> 4205b261ecSmrg#include <X11/Xos.h> 4305b261ecSmrg#include <X11/Xfuncs.h> 4405b261ecSmrg#include <X11/Xatom.h> 4505b261ecSmrg#include <X11/keysym.h> 4605b261ecSmrg#include "misc.h" 4705b261ecSmrg#include "inputstr.h" 4805b261ecSmrg#include "dix.h" 4905b261ecSmrg#include <X11/extensions/XKBstr.h> 5005b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS 5105b261ecSmrg#include <xkbsrv.h> 5205b261ecSmrg 5305b261ecSmrg#ifdef DEBUG 5405b261ecSmrg#define PR_DEBUG(s) fprintf(stderr,s) 5505b261ecSmrg#define PR_DEBUG1(s,a) fprintf(stderr,s,a) 5605b261ecSmrg#define PR_DEBUG2(s,a,b) fprintf(stderr,s,a,b) 5705b261ecSmrg#else 5805b261ecSmrg#define PR_DEBUG(s) 5905b261ecSmrg#define PR_DEBUG1(s,a) 6005b261ecSmrg#define PR_DEBUG2(s,a,b) 6105b261ecSmrg#endif 6205b261ecSmrg 6305b261ecSmrg/***====================================================================***/ 6405b261ecSmrg 6505b261ecSmrg#define DFLT_LINE_SIZE 128 6605b261ecSmrg 6705b261ecSmrgtypedef struct { 6805b261ecSmrg int line_num; 6905b261ecSmrg int sz_line; 7005b261ecSmrg int num_line; 7105b261ecSmrg char buf[DFLT_LINE_SIZE]; 7205b261ecSmrg char * line; 7305b261ecSmrg} InputLine; 7405b261ecSmrg 7505b261ecSmrgstatic void 7605b261ecSmrgInitInputLine(InputLine *line) 7705b261ecSmrg{ 7805b261ecSmrg line->line_num= 1; 7905b261ecSmrg line->num_line= 0; 8005b261ecSmrg line->sz_line= DFLT_LINE_SIZE; 8105b261ecSmrg line->line= line->buf; 8205b261ecSmrg return; 8305b261ecSmrg} 8405b261ecSmrg 8505b261ecSmrgstatic void 8605b261ecSmrgFreeInputLine(InputLine *line) 8705b261ecSmrg{ 8805b261ecSmrg if (line->line!=line->buf) 8905b261ecSmrg _XkbFree(line->line); 9005b261ecSmrg line->line_num= 1; 9105b261ecSmrg line->num_line= 0; 9205b261ecSmrg line->sz_line= DFLT_LINE_SIZE; 9305b261ecSmrg line->line= line->buf; 9405b261ecSmrg return; 9505b261ecSmrg} 9605b261ecSmrg 9705b261ecSmrgstatic int 9805b261ecSmrgInputLineAddChar(InputLine *line,int ch) 9905b261ecSmrg{ 10005b261ecSmrg if (line->num_line>=line->sz_line) { 10105b261ecSmrg if (line->line==line->buf) { 10205b261ecSmrg line->line= (char *)_XkbAlloc(line->sz_line*2); 10305b261ecSmrg memcpy(line->line,line->buf,line->sz_line); 10405b261ecSmrg } 10505b261ecSmrg else { 10605b261ecSmrg line->line=(char *)_XkbRealloc((char *)line->line,line->sz_line*2); 10705b261ecSmrg } 10805b261ecSmrg line->sz_line*= 2; 10905b261ecSmrg } 11005b261ecSmrg line->line[line->num_line++]= ch; 11105b261ecSmrg return ch; 11205b261ecSmrg} 11305b261ecSmrg 11405b261ecSmrg#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\ 11505b261ecSmrg (int)((l)->line[(l)->num_line++]= (c)):\ 11605b261ecSmrg InputLineAddChar(l,c)) 11705b261ecSmrg 11805b261ecSmrgstatic Bool 11905b261ecSmrgGetInputLine(FILE *file,InputLine *line,Bool checkbang) 12005b261ecSmrg{ 12105b261ecSmrgint ch; 12205b261ecSmrgBool endOfFile,spacePending,slashPending,inComment; 12305b261ecSmrg 12405b261ecSmrg endOfFile= False; 12505b261ecSmrg while ((!endOfFile)&&(line->num_line==0)) { 12605b261ecSmrg spacePending= slashPending= inComment= False; 12705b261ecSmrg while (((ch=getc(file))!='\n')&&(ch!=EOF)) { 12805b261ecSmrg if (ch=='\\') { 12905b261ecSmrg if ((ch=getc(file))==EOF) 13005b261ecSmrg break; 13105b261ecSmrg if (ch=='\n') { 13205b261ecSmrg inComment= False; 13305b261ecSmrg ch= ' '; 13405b261ecSmrg line->line_num++; 13505b261ecSmrg } 13605b261ecSmrg } 13705b261ecSmrg if (inComment) 13805b261ecSmrg continue; 13905b261ecSmrg if (ch=='/') { 14005b261ecSmrg if (slashPending) { 14105b261ecSmrg inComment= True; 14205b261ecSmrg slashPending= False; 14305b261ecSmrg } 14405b261ecSmrg else { 14505b261ecSmrg slashPending= True; 14605b261ecSmrg } 14705b261ecSmrg continue; 14805b261ecSmrg } 14905b261ecSmrg else if (slashPending) { 15005b261ecSmrg if (spacePending) { 15105b261ecSmrg ADD_CHAR(line,' '); 15205b261ecSmrg spacePending= False; 15305b261ecSmrg } 15405b261ecSmrg ADD_CHAR(line,'/'); 15505b261ecSmrg slashPending= False; 15605b261ecSmrg } 15705b261ecSmrg if (isspace(ch)) { 15805b261ecSmrg while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) { 15905b261ecSmrg ch= getc(file); 16005b261ecSmrg } 16105b261ecSmrg if (ch==EOF) 16205b261ecSmrg break; 16305b261ecSmrg if ((ch!='\n')&&(line->num_line>0)) 16405b261ecSmrg spacePending= True; 16505b261ecSmrg ungetc(ch,file); 16605b261ecSmrg } 16705b261ecSmrg else { 16805b261ecSmrg if (spacePending) { 16905b261ecSmrg ADD_CHAR(line,' '); 17005b261ecSmrg spacePending= False; 17105b261ecSmrg } 17205b261ecSmrg if (checkbang && ch=='!') { 17305b261ecSmrg if (line->num_line!=0) { 17405b261ecSmrg PR_DEBUG("The '!' legal only at start of line\n"); 17505b261ecSmrg PR_DEBUG("Line containing '!' ignored\n"); 17605b261ecSmrg line->num_line= 0; 17705b261ecSmrg inComment= 0; 17805b261ecSmrg break; 17905b261ecSmrg } 18005b261ecSmrg 18105b261ecSmrg } 18205b261ecSmrg ADD_CHAR(line,ch); 18305b261ecSmrg } 18405b261ecSmrg } 18505b261ecSmrg if (ch==EOF) 18605b261ecSmrg endOfFile= True; 18705b261ecSmrg/* else line->num_line++;*/ 18805b261ecSmrg } 18905b261ecSmrg if ((line->num_line==0)&&(endOfFile)) 19005b261ecSmrg return False; 19105b261ecSmrg ADD_CHAR(line,'\0'); 19205b261ecSmrg return True; 19305b261ecSmrg} 19405b261ecSmrg 19505b261ecSmrg/***====================================================================***/ 19605b261ecSmrg 19705b261ecSmrg#define MODEL 0 19805b261ecSmrg#define LAYOUT 1 19905b261ecSmrg#define VARIANT 2 20005b261ecSmrg#define OPTION 3 20105b261ecSmrg#define KEYCODES 4 20205b261ecSmrg#define SYMBOLS 5 20305b261ecSmrg#define TYPES 6 20405b261ecSmrg#define COMPAT 7 20505b261ecSmrg#define GEOMETRY 8 20605b261ecSmrg#define KEYMAP 9 20705b261ecSmrg#define MAX_WORDS 10 20805b261ecSmrg 20905b261ecSmrg#define PART_MASK 0x000F 21005b261ecSmrg#define COMPONENT_MASK 0x03F0 21105b261ecSmrg 21205b261ecSmrgstatic char * cname[MAX_WORDS] = { 21305b261ecSmrg "model", "layout", "variant", "option", 21405b261ecSmrg "keycodes", "symbols", "types", "compat", "geometry", "keymap" 21505b261ecSmrg}; 21605b261ecSmrg 21705b261ecSmrgtypedef struct _RemapSpec { 21805b261ecSmrg int number; 21905b261ecSmrg int num_remap; 22005b261ecSmrg struct { 22105b261ecSmrg int word; 22205b261ecSmrg int index; 22305b261ecSmrg } remap[MAX_WORDS]; 22405b261ecSmrg} RemapSpec; 22505b261ecSmrg 22605b261ecSmrgtypedef struct _FileSpec { 22705b261ecSmrg char * name[MAX_WORDS]; 22805b261ecSmrg struct _FileSpec * pending; 22905b261ecSmrg} FileSpec; 23005b261ecSmrg 23105b261ecSmrgtypedef struct { 23205b261ecSmrg char * model; 23305b261ecSmrg char * layout[XkbNumKbdGroups+1]; 23405b261ecSmrg char * variant[XkbNumKbdGroups+1]; 23505b261ecSmrg char * options; 23605b261ecSmrg} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; 23705b261ecSmrg 23805b261ecSmrg#define NDX_BUFF_SIZE 4 23905b261ecSmrg 24005b261ecSmrg/***====================================================================***/ 24105b261ecSmrg 24205b261ecSmrgstatic char* 24305b261ecSmrgget_index(char *str, int *ndx) 24405b261ecSmrg{ 24505b261ecSmrg char ndx_buf[NDX_BUFF_SIZE]; 24605b261ecSmrg char *end; 24705b261ecSmrg 24805b261ecSmrg if (*str != '[') { 24905b261ecSmrg *ndx = 0; 25005b261ecSmrg return str; 25105b261ecSmrg } 25205b261ecSmrg str++; 25305b261ecSmrg end = strchr(str, ']'); 25405b261ecSmrg if (end == NULL) { 25505b261ecSmrg *ndx = -1; 25605b261ecSmrg return str - 1; 25705b261ecSmrg } 25805b261ecSmrg if ( (end - str) >= NDX_BUFF_SIZE) { 25905b261ecSmrg *ndx = -1; 26005b261ecSmrg return end + 1; 26105b261ecSmrg } 26205b261ecSmrg strncpy(ndx_buf, str, end - str); 26305b261ecSmrg ndx_buf[end - str] = '\0'; 26405b261ecSmrg *ndx = atoi(ndx_buf); 26505b261ecSmrg return end + 1; 26605b261ecSmrg} 26705b261ecSmrg 26805b261ecSmrgstatic void 26905b261ecSmrgSetUpRemap(InputLine *line,RemapSpec *remap) 27005b261ecSmrg{ 27105b261ecSmrgchar * tok,*str; 27205b261ecSmrgunsigned present, l_ndx_present, v_ndx_present; 27305b261ecSmrgregister int i; 27405b261ecSmrgint len, ndx; 27505b261ecSmrg_Xstrtokparams strtok_buf; 27605b261ecSmrg#ifdef DEBUG 27705b261ecSmrgBool found; 27805b261ecSmrg#endif 27905b261ecSmrg 28005b261ecSmrg 28105b261ecSmrg l_ndx_present = v_ndx_present = present= 0; 28205b261ecSmrg str= &line->line[1]; 28305b261ecSmrg len = remap->number; 28405b261ecSmrg bzero((char *)remap,sizeof(RemapSpec)); 28505b261ecSmrg remap->number = len; 28605b261ecSmrg while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { 28705b261ecSmrg#ifdef DEBUG 28805b261ecSmrg found= False; 28905b261ecSmrg#endif 29005b261ecSmrg str= NULL; 29105b261ecSmrg if (strcmp(tok,"=")==0) 29205b261ecSmrg continue; 29305b261ecSmrg for (i=0;i<MAX_WORDS;i++) { 29405b261ecSmrg len = strlen(cname[i]); 29505b261ecSmrg if (strncmp(cname[i],tok,len)==0) { 29605b261ecSmrg if(strlen(tok) > len) { 29705b261ecSmrg char *end = get_index(tok+len, &ndx); 29805b261ecSmrg if ((i != LAYOUT && i != VARIANT) || 29905b261ecSmrg *end != '\0' || ndx == -1) 30005b261ecSmrg break; 30105b261ecSmrg if (ndx < 1 || ndx > XkbNumKbdGroups) { 30205b261ecSmrg PR_DEBUG2("Illegal %s index: %d\n", cname[i], ndx); 30305b261ecSmrg PR_DEBUG1("Index must be in range 1..%d\n", 30405b261ecSmrg XkbNumKbdGroups); 30505b261ecSmrg break; 30605b261ecSmrg } 30705b261ecSmrg } else { 30805b261ecSmrg ndx = 0; 30905b261ecSmrg } 31005b261ecSmrg#ifdef DEBUG 31105b261ecSmrg found= True; 31205b261ecSmrg#endif 31305b261ecSmrg if (present&(1<<i)) { 31405b261ecSmrg if ((i == LAYOUT && l_ndx_present&(1<<ndx)) || 31505b261ecSmrg (i == VARIANT && v_ndx_present&(1<<ndx)) ) { 31605b261ecSmrg PR_DEBUG1("Component \"%s\" listed twice\n",tok); 31705b261ecSmrg PR_DEBUG("Second definition ignored\n"); 31805b261ecSmrg break; 31905b261ecSmrg } 32005b261ecSmrg } 32105b261ecSmrg present |= (1<<i); 32205b261ecSmrg if (i == LAYOUT) 32305b261ecSmrg l_ndx_present |= 1 << ndx; 32405b261ecSmrg if (i == VARIANT) 32505b261ecSmrg v_ndx_present |= 1 << ndx; 32605b261ecSmrg remap->remap[remap->num_remap].word= i; 32705b261ecSmrg remap->remap[remap->num_remap++].index= ndx; 32805b261ecSmrg break; 32905b261ecSmrg } 33005b261ecSmrg } 33105b261ecSmrg#ifdef DEBUG 33205b261ecSmrg if (!found) { 33305b261ecSmrg fprintf(stderr,"Unknown component \"%s\" ignored\n",tok); 33405b261ecSmrg } 33505b261ecSmrg#endif 33605b261ecSmrg } 33705b261ecSmrg if ((present&PART_MASK)==0) { 33805b261ecSmrg#ifdef DEBUG 33905b261ecSmrg unsigned mask= PART_MASK; 34005b261ecSmrg fprintf(stderr,"Mapping needs at least one of "); 34105b261ecSmrg for (i=0; (i<MAX_WORDS); i++) { 34205b261ecSmrg if ((1L<<i)&mask) { 34305b261ecSmrg mask&= ~(1L<<i); 34405b261ecSmrg if (mask) fprintf(stderr,"\"%s,\" ",cname[i]); 34505b261ecSmrg else fprintf(stderr,"or \"%s\"\n",cname[i]); 34605b261ecSmrg } 34705b261ecSmrg } 34805b261ecSmrg fprintf(stderr,"Illegal mapping ignored\n"); 34905b261ecSmrg#endif 35005b261ecSmrg remap->num_remap= 0; 35105b261ecSmrg return; 35205b261ecSmrg } 35305b261ecSmrg if ((present&COMPONENT_MASK)==0) { 35405b261ecSmrg PR_DEBUG("Mapping needs at least one component\n"); 35505b261ecSmrg PR_DEBUG("Illegal mapping ignored\n"); 35605b261ecSmrg remap->num_remap= 0; 35705b261ecSmrg return; 35805b261ecSmrg } 35905b261ecSmrg if (((present&COMPONENT_MASK)&(1<<KEYMAP))&& 36005b261ecSmrg ((present&COMPONENT_MASK)!=(1<<KEYMAP))) { 36105b261ecSmrg PR_DEBUG("Keymap cannot appear with other components\n"); 36205b261ecSmrg PR_DEBUG("Illegal mapping ignored\n"); 36305b261ecSmrg remap->num_remap= 0; 36405b261ecSmrg return; 36505b261ecSmrg } 36605b261ecSmrg remap->number++; 36705b261ecSmrg return; 36805b261ecSmrg} 36905b261ecSmrg 37005b261ecSmrgstatic Bool 37105b261ecSmrgMatchOneOf(char *wanted,char *vals_defined) 37205b261ecSmrg{ 37305b261ecSmrgchar *str,*next; 37405b261ecSmrgint want_len= strlen(wanted); 37505b261ecSmrg 37605b261ecSmrg for (str=vals_defined,next=NULL;str!=NULL;str=next) { 37705b261ecSmrg int len; 37805b261ecSmrg next= strchr(str,','); 37905b261ecSmrg if (next) { 38005b261ecSmrg len= next-str; 38105b261ecSmrg next++; 38205b261ecSmrg } 38305b261ecSmrg else { 38405b261ecSmrg len= strlen(str); 38505b261ecSmrg } 38605b261ecSmrg if ((len==want_len)&&(strncmp(wanted,str,len)==0)) 38705b261ecSmrg return True; 38805b261ecSmrg } 38905b261ecSmrg return False; 39005b261ecSmrg} 39105b261ecSmrg 39205b261ecSmrg/***====================================================================***/ 39305b261ecSmrg 39405b261ecSmrgstatic Bool 39505b261ecSmrgCheckLine( InputLine * line, 39605b261ecSmrg RemapSpec * remap, 39705b261ecSmrg XkbRF_RulePtr rule, 39805b261ecSmrg XkbRF_GroupPtr group) 39905b261ecSmrg{ 40005b261ecSmrgchar * str,*tok; 40105b261ecSmrgregister int nread, i; 40205b261ecSmrgFileSpec tmp; 40305b261ecSmrg_Xstrtokparams strtok_buf; 40405b261ecSmrgBool append = False; 40505b261ecSmrg 40605b261ecSmrg if (line->line[0]=='!') { 40705b261ecSmrg if (line->line[1] == '$' || 40805b261ecSmrg (line->line[1] == ' ' && line->line[2] == '$')) { 40905b261ecSmrg char *gname = strchr(line->line, '$'); 41005b261ecSmrg char *words = strchr(gname, ' '); 41105b261ecSmrg if(!words) 41205b261ecSmrg return False; 41305b261ecSmrg *words++ = '\0'; 41405b261ecSmrg for (; *words; words++) { 41505b261ecSmrg if (*words != '=' && *words != ' ') 41605b261ecSmrg break; 41705b261ecSmrg } 41805b261ecSmrg if (*words == '\0') 41905b261ecSmrg return False; 42005b261ecSmrg group->name = _XkbDupString(gname); 42105b261ecSmrg group->words = _XkbDupString(words); 42205b261ecSmrg for (i = 1, words = group->words; *words; words++) { 42305b261ecSmrg if ( *words == ' ') { 42405b261ecSmrg *words++ = '\0'; 42505b261ecSmrg i++; 42605b261ecSmrg } 42705b261ecSmrg } 42805b261ecSmrg group->number = i; 42905b261ecSmrg return True; 43005b261ecSmrg } else { 43105b261ecSmrg SetUpRemap(line,remap); 43205b261ecSmrg return False; 43305b261ecSmrg } 43405b261ecSmrg } 43505b261ecSmrg 43605b261ecSmrg if (remap->num_remap==0) { 43705b261ecSmrg PR_DEBUG("Must have a mapping before first line of data\n"); 43805b261ecSmrg PR_DEBUG("Illegal line of data ignored\n"); 43905b261ecSmrg return False; 44005b261ecSmrg } 44105b261ecSmrg bzero((char *)&tmp,sizeof(FileSpec)); 44205b261ecSmrg str= line->line; 44305b261ecSmrg for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) { 44405b261ecSmrg str= NULL; 44505b261ecSmrg if (strcmp(tok,"=")==0) { 44605b261ecSmrg nread--; 44705b261ecSmrg continue; 44805b261ecSmrg } 44905b261ecSmrg if (nread>remap->num_remap) { 45005b261ecSmrg PR_DEBUG("Too many words on a line\n"); 45105b261ecSmrg PR_DEBUG1("Extra word \"%s\" ignored\n",tok); 45205b261ecSmrg continue; 45305b261ecSmrg } 45405b261ecSmrg tmp.name[remap->remap[nread].word]= tok; 45505b261ecSmrg if (*tok == '+' || *tok == '|') 45605b261ecSmrg append = True; 45705b261ecSmrg } 45805b261ecSmrg if (nread<remap->num_remap) { 45905b261ecSmrg PR_DEBUG1("Too few words on a line: %s\n", line->line); 46005b261ecSmrg PR_DEBUG("line ignored\n"); 46105b261ecSmrg return False; 46205b261ecSmrg } 46305b261ecSmrg 46405b261ecSmrg rule->flags= 0; 46505b261ecSmrg rule->number = remap->number; 46605b261ecSmrg if (tmp.name[OPTION]) 46705b261ecSmrg rule->flags|= XkbRF_Option; 46805b261ecSmrg else if (append) 46905b261ecSmrg rule->flags|= XkbRF_Append; 47005b261ecSmrg else 47105b261ecSmrg rule->flags|= XkbRF_Normal; 47205b261ecSmrg rule->model= _XkbDupString(tmp.name[MODEL]); 47305b261ecSmrg rule->layout= _XkbDupString(tmp.name[LAYOUT]); 47405b261ecSmrg rule->variant= _XkbDupString(tmp.name[VARIANT]); 47505b261ecSmrg rule->option= _XkbDupString(tmp.name[OPTION]); 47605b261ecSmrg 47705b261ecSmrg rule->keycodes= _XkbDupString(tmp.name[KEYCODES]); 47805b261ecSmrg rule->symbols= _XkbDupString(tmp.name[SYMBOLS]); 47905b261ecSmrg rule->types= _XkbDupString(tmp.name[TYPES]); 48005b261ecSmrg rule->compat= _XkbDupString(tmp.name[COMPAT]); 48105b261ecSmrg rule->geometry= _XkbDupString(tmp.name[GEOMETRY]); 48205b261ecSmrg rule->keymap= _XkbDupString(tmp.name[KEYMAP]); 48305b261ecSmrg 48405b261ecSmrg rule->layout_num = rule->variant_num = 0; 48505b261ecSmrg for (i = 0; i < nread; i++) { 48605b261ecSmrg if (remap->remap[i].index) { 48705b261ecSmrg if (remap->remap[i].word == LAYOUT) 48805b261ecSmrg rule->layout_num = remap->remap[i].index; 48905b261ecSmrg if (remap->remap[i].word == VARIANT) 49005b261ecSmrg rule->variant_num = remap->remap[i].index; 49105b261ecSmrg } 49205b261ecSmrg } 49305b261ecSmrg return True; 49405b261ecSmrg} 49505b261ecSmrg 49605b261ecSmrgstatic char * 49705b261ecSmrg_Concat(char *str1,char *str2) 49805b261ecSmrg{ 49905b261ecSmrgint len; 50005b261ecSmrg 50105b261ecSmrg if ((!str1)||(!str2)) 50205b261ecSmrg return str1; 50305b261ecSmrg len= strlen(str1)+strlen(str2)+1; 50405b261ecSmrg str1= _XkbTypedRealloc(str1,len,char); 50505b261ecSmrg if (str1) 50605b261ecSmrg strcat(str1,str2); 50705b261ecSmrg return str1; 50805b261ecSmrg} 50905b261ecSmrg 51005b261ecSmrgstatic void 51105b261ecSmrgsqueeze_spaces(char *p1) 51205b261ecSmrg{ 51305b261ecSmrg char *p2; 51405b261ecSmrg for (p2 = p1; *p2; p2++) { 51505b261ecSmrg *p1 = *p2; 51605b261ecSmrg if (*p1 != ' ') p1++; 51705b261ecSmrg } 51805b261ecSmrg *p1 = '\0'; 51905b261ecSmrg} 52005b261ecSmrg 52105b261ecSmrgstatic Bool 52205b261ecSmrgMakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) 52305b261ecSmrg{ 52405b261ecSmrg 52505b261ecSmrg bzero((char *)mdefs,sizeof(XkbRF_MultiDefsRec)); 52605b261ecSmrg mdefs->model = defs->model; 52705b261ecSmrg mdefs->options = _XkbDupString(defs->options); 52805b261ecSmrg if (mdefs->options) squeeze_spaces(mdefs->options); 52905b261ecSmrg 53005b261ecSmrg if (defs->layout) { 53105b261ecSmrg if (!strchr(defs->layout, ',')) { 53205b261ecSmrg mdefs->layout[0] = defs->layout; 53305b261ecSmrg } else { 53405b261ecSmrg char *p; 53505b261ecSmrg int i; 53605b261ecSmrg mdefs->layout[1] = _XkbDupString(defs->layout); 53705b261ecSmrg if (mdefs->layout[1] == NULL) 53805b261ecSmrg return False; 53905b261ecSmrg squeeze_spaces(mdefs->layout[1]); 54005b261ecSmrg p = mdefs->layout[1]; 54105b261ecSmrg for (i = 2; i <= XkbNumKbdGroups; i++) { 54205b261ecSmrg if ((p = strchr(p, ','))) { 54305b261ecSmrg *p++ = '\0'; 54405b261ecSmrg mdefs->layout[i] = p; 54505b261ecSmrg } else { 54605b261ecSmrg break; 54705b261ecSmrg } 54805b261ecSmrg } 54905b261ecSmrg if (p && (p = strchr(p, ','))) 55005b261ecSmrg *p = '\0'; 55105b261ecSmrg } 55205b261ecSmrg } 55305b261ecSmrg 55405b261ecSmrg if (defs->variant) { 55505b261ecSmrg if (!strchr(defs->variant, ',')) { 55605b261ecSmrg mdefs->variant[0] = defs->variant; 55705b261ecSmrg } else { 55805b261ecSmrg char *p; 55905b261ecSmrg int i; 56005b261ecSmrg mdefs->variant[1] = _XkbDupString(defs->variant); 56105b261ecSmrg if (mdefs->variant[1] == NULL) 56205b261ecSmrg return False; 56305b261ecSmrg squeeze_spaces(mdefs->variant[1]); 56405b261ecSmrg p = mdefs->variant[1]; 56505b261ecSmrg for (i = 2; i <= XkbNumKbdGroups; i++) { 56605b261ecSmrg if ((p = strchr(p, ','))) { 56705b261ecSmrg *p++ = '\0'; 56805b261ecSmrg mdefs->variant[i] = p; 56905b261ecSmrg } else { 57005b261ecSmrg break; 57105b261ecSmrg } 57205b261ecSmrg } 57305b261ecSmrg if (p && (p = strchr(p, ','))) 57405b261ecSmrg *p = '\0'; 57505b261ecSmrg } 57605b261ecSmrg } 57705b261ecSmrg return True; 57805b261ecSmrg} 57905b261ecSmrg 58005b261ecSmrgstatic void 58105b261ecSmrgFreeMultiDefs(XkbRF_MultiDefsPtr defs) 58205b261ecSmrg{ 58305b261ecSmrg if (defs->options) _XkbFree(defs->options); 58405b261ecSmrg if (defs->layout[1]) _XkbFree(defs->layout[1]); 58505b261ecSmrg if (defs->variant[1]) _XkbFree(defs->variant[1]); 58605b261ecSmrg} 58705b261ecSmrg 58805b261ecSmrgstatic void 58905b261ecSmrgApply(char *src, char **dst) 59005b261ecSmrg{ 59105b261ecSmrg if (src) { 59205b261ecSmrg if (*src == '+' || *src == '!') { 59305b261ecSmrg *dst= _Concat(*dst, src); 59405b261ecSmrg } else { 59505b261ecSmrg if (*dst == NULL) 59605b261ecSmrg *dst= _XkbDupString(src); 59705b261ecSmrg } 59805b261ecSmrg } 59905b261ecSmrg} 60005b261ecSmrg 60105b261ecSmrgstatic void 60205b261ecSmrgXkbRF_ApplyRule( XkbRF_RulePtr rule, 60305b261ecSmrg XkbComponentNamesPtr names) 60405b261ecSmrg{ 60505b261ecSmrg rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ 60605b261ecSmrg 60705b261ecSmrg Apply(rule->keycodes, &names->keycodes); 60805b261ecSmrg Apply(rule->symbols, &names->symbols); 60905b261ecSmrg Apply(rule->types, &names->types); 61005b261ecSmrg Apply(rule->compat, &names->compat); 61105b261ecSmrg Apply(rule->geometry, &names->geometry); 61205b261ecSmrg Apply(rule->keymap, &names->keymap); 61305b261ecSmrg} 61405b261ecSmrg 61505b261ecSmrgstatic Bool 61605b261ecSmrgCheckGroup( XkbRF_RulesPtr rules, 61705b261ecSmrg char * group_name, 61805b261ecSmrg char * name) 61905b261ecSmrg{ 62005b261ecSmrg int i; 62105b261ecSmrg char *p; 62205b261ecSmrg XkbRF_GroupPtr group; 62305b261ecSmrg 62405b261ecSmrg for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { 62505b261ecSmrg if (! strcmp(group->name, group_name)) { 62605b261ecSmrg break; 62705b261ecSmrg } 62805b261ecSmrg } 62905b261ecSmrg if (i == rules->num_groups) 63005b261ecSmrg return False; 63105b261ecSmrg for (i = 0, p = group->words; i < group->number; i++, p += strlen(p)+1) { 63205b261ecSmrg if (! strcmp(p, name)) { 63305b261ecSmrg return True; 63405b261ecSmrg } 63505b261ecSmrg } 63605b261ecSmrg return False; 63705b261ecSmrg} 63805b261ecSmrg 63905b261ecSmrgstatic int 64005b261ecSmrgXkbRF_CheckApplyRule( XkbRF_RulePtr rule, 64105b261ecSmrg XkbRF_MultiDefsPtr mdefs, 64205b261ecSmrg XkbComponentNamesPtr names, 64305b261ecSmrg XkbRF_RulesPtr rules) 64405b261ecSmrg{ 64505b261ecSmrg Bool pending = False; 64605b261ecSmrg 64705b261ecSmrg if (rule->model != NULL) { 64805b261ecSmrg if(mdefs->model == NULL) 64905b261ecSmrg return 0; 65005b261ecSmrg if (strcmp(rule->model, "*") == 0) { 65105b261ecSmrg pending = True; 65205b261ecSmrg } else { 65305b261ecSmrg if (rule->model[0] == '$') { 65405b261ecSmrg if (!CheckGroup(rules, rule->model, mdefs->model)) 65505b261ecSmrg return 0; 65605b261ecSmrg } else { 65705b261ecSmrg if (strcmp(rule->model, mdefs->model) != 0) 65805b261ecSmrg return 0; 65905b261ecSmrg } 66005b261ecSmrg } 66105b261ecSmrg } 66205b261ecSmrg if (rule->option != NULL) { 66305b261ecSmrg if (mdefs->options == NULL) 66405b261ecSmrg return 0; 66505b261ecSmrg if ((!MatchOneOf(rule->option,mdefs->options))) 66605b261ecSmrg return 0; 66705b261ecSmrg } 66805b261ecSmrg 66905b261ecSmrg if (rule->layout != NULL) { 67005b261ecSmrg if(mdefs->layout[rule->layout_num] == NULL || 67105b261ecSmrg *mdefs->layout[rule->layout_num] == '\0') 67205b261ecSmrg return 0; 67305b261ecSmrg if (strcmp(rule->layout, "*") == 0) { 67405b261ecSmrg pending = True; 67505b261ecSmrg } else { 67605b261ecSmrg if (rule->layout[0] == '$') { 67705b261ecSmrg if (!CheckGroup(rules, rule->layout, 67805b261ecSmrg mdefs->layout[rule->layout_num])) 67905b261ecSmrg return 0; 68005b261ecSmrg } else { 68105b261ecSmrg if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0) 68205b261ecSmrg return 0; 68305b261ecSmrg } 68405b261ecSmrg } 68505b261ecSmrg } 68605b261ecSmrg if (rule->variant != NULL) { 68705b261ecSmrg if (mdefs->variant[rule->variant_num] == NULL || 68805b261ecSmrg *mdefs->variant[rule->variant_num] == '\0') 68905b261ecSmrg return 0; 69005b261ecSmrg if (strcmp(rule->variant, "*") == 0) { 69105b261ecSmrg pending = True; 69205b261ecSmrg } else { 69305b261ecSmrg if (rule->variant[0] == '$') { 69405b261ecSmrg if (!CheckGroup(rules, rule->variant, 69505b261ecSmrg mdefs->variant[rule->variant_num])) 69605b261ecSmrg return 0; 69705b261ecSmrg } else { 69805b261ecSmrg if (strcmp(rule->variant, 69905b261ecSmrg mdefs->variant[rule->variant_num]) != 0) 70005b261ecSmrg return 0; 70105b261ecSmrg } 70205b261ecSmrg } 70305b261ecSmrg } 70405b261ecSmrg if (pending) { 70505b261ecSmrg rule->flags|= XkbRF_PendingMatch; 70605b261ecSmrg return rule->number; 70705b261ecSmrg } 70805b261ecSmrg /* exact match, apply it now */ 70905b261ecSmrg XkbRF_ApplyRule(rule,names); 71005b261ecSmrg return rule->number; 71105b261ecSmrg} 71205b261ecSmrg 71305b261ecSmrgstatic void 71405b261ecSmrgXkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) 71505b261ecSmrg{ 71605b261ecSmrgregister int i; 71705b261ecSmrgXkbRF_RulePtr rule; 71805b261ecSmrg 71905b261ecSmrg for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { 72005b261ecSmrg rule->flags&= ~XkbRF_PendingMatch; 72105b261ecSmrg } 72205b261ecSmrg} 72305b261ecSmrg 72405b261ecSmrgstatic void 72505b261ecSmrgXkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) 72605b261ecSmrg{ 72705b261ecSmrgint i; 72805b261ecSmrgXkbRF_RulePtr rule; 72905b261ecSmrg 73005b261ecSmrg for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { 73105b261ecSmrg if ((rule->flags&XkbRF_PendingMatch)==0) 73205b261ecSmrg continue; 73305b261ecSmrg XkbRF_ApplyRule(rule,names); 73405b261ecSmrg } 73505b261ecSmrg} 73605b261ecSmrg 73705b261ecSmrgstatic void 73805b261ecSmrgXkbRF_CheckApplyRules( XkbRF_RulesPtr rules, 73905b261ecSmrg XkbRF_MultiDefsPtr mdefs, 74005b261ecSmrg XkbComponentNamesPtr names, 74105b261ecSmrg int flags) 74205b261ecSmrg{ 74305b261ecSmrgint i; 74405b261ecSmrgXkbRF_RulePtr rule; 74505b261ecSmrgint skip; 74605b261ecSmrg 74705b261ecSmrg for (rule = rules->rules, i=0; i < rules->num_rules; rule++, i++) { 74805b261ecSmrg if ((rule->flags & flags) != flags) 74905b261ecSmrg continue; 75005b261ecSmrg skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules); 75105b261ecSmrg if (skip && !(flags & XkbRF_Option)) { 75205b261ecSmrg for ( ;(i < rules->num_rules) && (rule->number == skip); 75305b261ecSmrg rule++, i++); 75405b261ecSmrg rule--; i--; 75505b261ecSmrg } 75605b261ecSmrg } 75705b261ecSmrg} 75805b261ecSmrg 75905b261ecSmrg/***====================================================================***/ 76005b261ecSmrg 76105b261ecSmrgstatic char * 76205b261ecSmrgXkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) 76305b261ecSmrg{ 76405b261ecSmrgchar *str, *outstr, *orig, *var; 76505b261ecSmrgint len, ndx; 76605b261ecSmrg 76705b261ecSmrg orig= name; 76805b261ecSmrg str= index(name,'%'); 76905b261ecSmrg if (str==NULL) 77005b261ecSmrg return name; 77105b261ecSmrg len= strlen(name); 77205b261ecSmrg while (str!=NULL) { 77305b261ecSmrg char pfx= str[1]; 77405b261ecSmrg int extra_len= 0; 77505b261ecSmrg if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { 77605b261ecSmrg extra_len= 1; 77705b261ecSmrg str++; 77805b261ecSmrg } 77905b261ecSmrg else if (pfx=='(') { 78005b261ecSmrg extra_len= 2; 78105b261ecSmrg str++; 78205b261ecSmrg } 78305b261ecSmrg var = str + 1; 78405b261ecSmrg str = get_index(var + 1, &ndx); 78505b261ecSmrg if (ndx == -1) { 78605b261ecSmrg str = index(str,'%'); 78705b261ecSmrg continue; 78805b261ecSmrg } 78905b261ecSmrg if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) 79005b261ecSmrg len+= strlen(mdefs->layout[ndx])+extra_len; 79105b261ecSmrg else if ((*var=='m')&&mdefs->model) 79205b261ecSmrg len+= strlen(mdefs->model)+extra_len; 79305b261ecSmrg else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) 79405b261ecSmrg len+= strlen(mdefs->variant[ndx])+extra_len; 79505b261ecSmrg if ((pfx=='(')&&(*str==')')) { 79605b261ecSmrg str++; 79705b261ecSmrg } 79805b261ecSmrg str= index(&str[0],'%'); 79905b261ecSmrg } 80005b261ecSmrg name= (char *)_XkbAlloc(len+1); 80105b261ecSmrg str= orig; 80205b261ecSmrg outstr= name; 80305b261ecSmrg while (*str!='\0') { 80405b261ecSmrg if (str[0]=='%') { 80505b261ecSmrg char pfx,sfx; 80605b261ecSmrg str++; 80705b261ecSmrg pfx= str[0]; 80805b261ecSmrg sfx= '\0'; 80905b261ecSmrg if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { 81005b261ecSmrg str++; 81105b261ecSmrg } 81205b261ecSmrg else if (pfx=='(') { 81305b261ecSmrg sfx= ')'; 81405b261ecSmrg str++; 81505b261ecSmrg } 81605b261ecSmrg else pfx= '\0'; 81705b261ecSmrg 81805b261ecSmrg var = str; 81905b261ecSmrg str = get_index(var + 1, &ndx); 82005b261ecSmrg if (ndx == -1) { 82105b261ecSmrg continue; 82205b261ecSmrg } 82305b261ecSmrg if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) { 82405b261ecSmrg if (pfx) *outstr++= pfx; 82505b261ecSmrg strcpy(outstr,mdefs->layout[ndx]); 82605b261ecSmrg outstr+= strlen(mdefs->layout[ndx]); 82705b261ecSmrg if (sfx) *outstr++= sfx; 82805b261ecSmrg } 82905b261ecSmrg else if ((*var=='m')&&(mdefs->model)) { 83005b261ecSmrg if (pfx) *outstr++= pfx; 83105b261ecSmrg strcpy(outstr,mdefs->model); 83205b261ecSmrg outstr+= strlen(mdefs->model); 83305b261ecSmrg if (sfx) *outstr++= sfx; 83405b261ecSmrg } 83505b261ecSmrg else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) { 83605b261ecSmrg if (pfx) *outstr++= pfx; 83705b261ecSmrg strcpy(outstr,mdefs->variant[ndx]); 83805b261ecSmrg outstr+= strlen(mdefs->variant[ndx]); 83905b261ecSmrg if (sfx) *outstr++= sfx; 84005b261ecSmrg } 84105b261ecSmrg if ((pfx=='(')&&(*str==')')) 84205b261ecSmrg str++; 84305b261ecSmrg } 84405b261ecSmrg else { 84505b261ecSmrg *outstr++= *str++; 84605b261ecSmrg } 84705b261ecSmrg } 84805b261ecSmrg *outstr++= '\0'; 84905b261ecSmrg if (orig!=name) 85005b261ecSmrg _XkbFree(orig); 85105b261ecSmrg return name; 85205b261ecSmrg} 85305b261ecSmrg 85405b261ecSmrg/***====================================================================***/ 85505b261ecSmrg 85605b261ecSmrgBool 85705b261ecSmrgXkbRF_GetComponents( XkbRF_RulesPtr rules, 85805b261ecSmrg XkbRF_VarDefsPtr defs, 85905b261ecSmrg XkbComponentNamesPtr names) 86005b261ecSmrg{ 86105b261ecSmrg XkbRF_MultiDefsRec mdefs; 86205b261ecSmrg 86305b261ecSmrg MakeMultiDefs(&mdefs, defs); 86405b261ecSmrg 86505b261ecSmrg bzero((char *)names,sizeof(XkbComponentNamesRec)); 86605b261ecSmrg XkbRF_ClearPartialMatches(rules); 86705b261ecSmrg XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal); 86805b261ecSmrg XkbRF_ApplyPartialMatches(rules, names); 86905b261ecSmrg XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append); 87005b261ecSmrg XkbRF_ApplyPartialMatches(rules, names); 87105b261ecSmrg XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option); 87205b261ecSmrg 87305b261ecSmrg if (names->keycodes) 87405b261ecSmrg names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs); 87505b261ecSmrg if (names->symbols) 87605b261ecSmrg names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs); 87705b261ecSmrg if (names->types) 87805b261ecSmrg names->types= XkbRF_SubstituteVars(names->types, &mdefs); 87905b261ecSmrg if (names->compat) 88005b261ecSmrg names->compat= XkbRF_SubstituteVars(names->compat, &mdefs); 88105b261ecSmrg if (names->geometry) 88205b261ecSmrg names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs); 88305b261ecSmrg if (names->keymap) 88405b261ecSmrg names->keymap= XkbRF_SubstituteVars(names->keymap, &mdefs); 88505b261ecSmrg 88605b261ecSmrg FreeMultiDefs(&mdefs); 88705b261ecSmrg return (names->keycodes && names->symbols && names->types && 88805b261ecSmrg names->compat && names->geometry ) || names->keymap; 88905b261ecSmrg} 89005b261ecSmrg 89105b261ecSmrgXkbRF_RulePtr 89205b261ecSmrgXkbRF_AddRule(XkbRF_RulesPtr rules) 89305b261ecSmrg{ 89405b261ecSmrg if (rules->sz_rules<1) { 89505b261ecSmrg rules->sz_rules= 16; 89605b261ecSmrg rules->num_rules= 0; 89705b261ecSmrg rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); 89805b261ecSmrg } 89905b261ecSmrg else if (rules->num_rules>=rules->sz_rules) { 90005b261ecSmrg rules->sz_rules*= 2; 90105b261ecSmrg rules->rules= _XkbTypedRealloc(rules->rules,rules->sz_rules, 90205b261ecSmrg XkbRF_RuleRec); 90305b261ecSmrg } 90405b261ecSmrg if (!rules->rules) { 90505b261ecSmrg rules->sz_rules= rules->num_rules= 0; 90605b261ecSmrg#ifdef DEBUG 90705b261ecSmrg fprintf(stderr,"Allocation failure in XkbRF_AddRule\n"); 90805b261ecSmrg#endif 90905b261ecSmrg return NULL; 91005b261ecSmrg } 91105b261ecSmrg bzero((char *)&rules->rules[rules->num_rules],sizeof(XkbRF_RuleRec)); 91205b261ecSmrg return &rules->rules[rules->num_rules++]; 91305b261ecSmrg} 91405b261ecSmrg 91505b261ecSmrgXkbRF_GroupPtr 91605b261ecSmrgXkbRF_AddGroup(XkbRF_RulesPtr rules) 91705b261ecSmrg{ 91805b261ecSmrg if (rules->sz_groups<1) { 91905b261ecSmrg rules->sz_groups= 16; 92005b261ecSmrg rules->num_groups= 0; 92105b261ecSmrg rules->groups= _XkbTypedCalloc(rules->sz_groups,XkbRF_GroupRec); 92205b261ecSmrg } 92305b261ecSmrg else if (rules->num_groups >= rules->sz_groups) { 92405b261ecSmrg rules->sz_groups *= 2; 92505b261ecSmrg rules->groups= _XkbTypedRealloc(rules->groups,rules->sz_groups, 92605b261ecSmrg XkbRF_GroupRec); 92705b261ecSmrg } 92805b261ecSmrg if (!rules->groups) { 92905b261ecSmrg rules->sz_groups= rules->num_groups= 0; 93005b261ecSmrg return NULL; 93105b261ecSmrg } 93205b261ecSmrg 93305b261ecSmrg bzero((char *)&rules->groups[rules->num_groups],sizeof(XkbRF_GroupRec)); 93405b261ecSmrg return &rules->groups[rules->num_groups++]; 93505b261ecSmrg} 93605b261ecSmrg 93705b261ecSmrgBool 93805b261ecSmrgXkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) 93905b261ecSmrg{ 94005b261ecSmrgInputLine line; 94105b261ecSmrgRemapSpec remap; 94205b261ecSmrgXkbRF_RuleRec trule,*rule; 94305b261ecSmrgXkbRF_GroupRec tgroup,*group; 94405b261ecSmrg 94505b261ecSmrg if (!(rules && file)) 94605b261ecSmrg return False; 94705b261ecSmrg bzero((char *)&remap,sizeof(RemapSpec)); 94805b261ecSmrg bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); 94905b261ecSmrg InitInputLine(&line); 95005b261ecSmrg while (GetInputLine(file,&line,True)) { 95105b261ecSmrg if (CheckLine(&line,&remap,&trule,&tgroup)) { 95205b261ecSmrg if (tgroup.number) { 95305b261ecSmrg if ((group= XkbRF_AddGroup(rules))!=NULL) { 95405b261ecSmrg *group= tgroup; 95505b261ecSmrg bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); 95605b261ecSmrg } 95705b261ecSmrg } else { 95805b261ecSmrg if ((rule= XkbRF_AddRule(rules))!=NULL) { 95905b261ecSmrg *rule= trule; 96005b261ecSmrg bzero((char *)&trule,sizeof(XkbRF_RuleRec)); 96105b261ecSmrg } 96205b261ecSmrg } 96305b261ecSmrg } 96405b261ecSmrg line.num_line= 0; 96505b261ecSmrg } 96605b261ecSmrg FreeInputLine(&line); 96705b261ecSmrg return True; 96805b261ecSmrg} 96905b261ecSmrg 97005b261ecSmrgBool 97105b261ecSmrgXkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) 97205b261ecSmrg{ 97305b261ecSmrgFILE * file; 97405b261ecSmrgchar buf[PATH_MAX]; 97505b261ecSmrgBool ok; 97605b261ecSmrg 97705b261ecSmrg if ((!base)||(!rules)) 97805b261ecSmrg return False; 97905b261ecSmrg if (locale) { 98005b261ecSmrg if (strlen(base)+strlen(locale)+2 > PATH_MAX) 98105b261ecSmrg return False; 98205b261ecSmrg sprintf(buf,"%s-%s", base, locale); 98305b261ecSmrg } 98405b261ecSmrg else { 98505b261ecSmrg if (strlen(base)+1 > PATH_MAX) 98605b261ecSmrg return False; 98705b261ecSmrg strcpy(buf,base); 98805b261ecSmrg } 98905b261ecSmrg 99005b261ecSmrg file= fopen(buf, "r"); 99105b261ecSmrg if ((!file)&&(locale)) { /* fallback if locale was specified */ 99205b261ecSmrg strcpy(buf,base); 99305b261ecSmrg file= fopen(buf, "r"); 99405b261ecSmrg } 99505b261ecSmrg if (!file) 99605b261ecSmrg return False; 99705b261ecSmrg ok= XkbRF_LoadRules(file,rules); 99805b261ecSmrg fclose(file); 99905b261ecSmrg return ok; 100005b261ecSmrg} 100105b261ecSmrg 100205b261ecSmrg/***====================================================================***/ 100305b261ecSmrg 100405b261ecSmrg#define HEAD_NONE 0 100505b261ecSmrg#define HEAD_MODEL 1 100605b261ecSmrg#define HEAD_LAYOUT 2 100705b261ecSmrg#define HEAD_VARIANT 3 100805b261ecSmrg#define HEAD_OPTION 4 100905b261ecSmrg#define HEAD_EXTRA 5 101005b261ecSmrg 101105b261ecSmrgXkbRF_VarDescPtr 101205b261ecSmrgXkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars) 101305b261ecSmrg{ 101405b261ecSmrg if (vars->sz_desc<1) { 101505b261ecSmrg vars->sz_desc= 16; 101605b261ecSmrg vars->num_desc= 0; 101705b261ecSmrg vars->desc= _XkbTypedCalloc(vars->sz_desc,XkbRF_VarDescRec); 101805b261ecSmrg } 101905b261ecSmrg else if (vars->num_desc>=vars->sz_desc) { 102005b261ecSmrg vars->sz_desc*= 2; 102105b261ecSmrg vars->desc= _XkbTypedRealloc(vars->desc,vars->sz_desc,XkbRF_VarDescRec); 102205b261ecSmrg } 102305b261ecSmrg if (!vars->desc) { 102405b261ecSmrg vars->sz_desc= vars->num_desc= 0; 102505b261ecSmrg PR_DEBUG("Allocation failure in XkbRF_AddVarDesc\n"); 102605b261ecSmrg return NULL; 102705b261ecSmrg } 102805b261ecSmrg vars->desc[vars->num_desc].name= NULL; 102905b261ecSmrg vars->desc[vars->num_desc].desc= NULL; 103005b261ecSmrg return &vars->desc[vars->num_desc++]; 103105b261ecSmrg} 103205b261ecSmrg 103305b261ecSmrgXkbRF_VarDescPtr 103405b261ecSmrgXkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from) 103505b261ecSmrg{ 103605b261ecSmrgXkbRF_VarDescPtr nd; 103705b261ecSmrg 103805b261ecSmrg if ((nd=XkbRF_AddVarDesc(vars))!=NULL) { 103905b261ecSmrg nd->name= _XkbDupString(from->name); 104005b261ecSmrg nd->desc= _XkbDupString(from->desc); 104105b261ecSmrg } 104205b261ecSmrg return nd; 104305b261ecSmrg} 104405b261ecSmrg 104505b261ecSmrgXkbRF_DescribeVarsPtr 104605b261ecSmrgXkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name) 104705b261ecSmrg{ 104805b261ecSmrg if (rules->sz_extra<1) { 104905b261ecSmrg rules->num_extra= 0; 105005b261ecSmrg rules->sz_extra= 1; 105105b261ecSmrg rules->extra_names= _XkbTypedCalloc(rules->sz_extra,char *); 105205b261ecSmrg rules->extra= _XkbTypedCalloc(rules->sz_extra, XkbRF_DescribeVarsRec); 105305b261ecSmrg } 105405b261ecSmrg else if (rules->num_extra>=rules->sz_extra) { 105505b261ecSmrg rules->sz_extra*= 2; 105605b261ecSmrg rules->extra_names= _XkbTypedRealloc(rules->extra_names,rules->sz_extra, 105705b261ecSmrg char *); 105805b261ecSmrg rules->extra=_XkbTypedRealloc(rules->extra, rules->sz_extra, 105905b261ecSmrg XkbRF_DescribeVarsRec); 106005b261ecSmrg } 106105b261ecSmrg if ((!rules->extra_names)||(!rules->extra)) { 106205b261ecSmrg PR_DEBUG("allocation error in extra parts\n"); 106305b261ecSmrg rules->sz_extra= rules->num_extra= 0; 106405b261ecSmrg rules->extra_names= NULL; 106505b261ecSmrg rules->extra= NULL; 106605b261ecSmrg return NULL; 106705b261ecSmrg } 106805b261ecSmrg rules->extra_names[rules->num_extra]= _XkbDupString(name); 106905b261ecSmrg bzero(&rules->extra[rules->num_extra],sizeof(XkbRF_DescribeVarsRec)); 107005b261ecSmrg return &rules->extra[rules->num_extra++]; 107105b261ecSmrg} 107205b261ecSmrg 107305b261ecSmrgBool 107405b261ecSmrgXkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules) 107505b261ecSmrg{ 107605b261ecSmrgInputLine line; 107705b261ecSmrgXkbRF_VarDescRec tmp; 107805b261ecSmrgchar *tok; 107905b261ecSmrgint len,headingtype,extra_ndx = 0; 108005b261ecSmrg 108105b261ecSmrg bzero((char *)&tmp, sizeof(XkbRF_VarDescRec)); 108205b261ecSmrg headingtype = HEAD_NONE; 108305b261ecSmrg InitInputLine(&line); 108405b261ecSmrg for ( ; GetInputLine(file,&line,False); line.num_line= 0) { 108505b261ecSmrg if (line.line[0]=='!') { 108605b261ecSmrg tok = strtok(&(line.line[1]), " \t"); 108705b261ecSmrg if (strcasecmp(tok,"model") == 0) 108805b261ecSmrg headingtype = HEAD_MODEL; 108905b261ecSmrg else if (strcasecmp(tok,"layout") == 0) 109005b261ecSmrg headingtype = HEAD_LAYOUT; 109105b261ecSmrg else if (strcasecmp(tok,"variant") == 0) 109205b261ecSmrg headingtype = HEAD_VARIANT; 109305b261ecSmrg else if (strcasecmp(tok,"option") == 0) 109405b261ecSmrg headingtype = HEAD_OPTION; 109505b261ecSmrg else { 109605b261ecSmrg int i; 109705b261ecSmrg headingtype = HEAD_EXTRA; 109805b261ecSmrg extra_ndx= -1; 109905b261ecSmrg for (i=0;(i<rules->num_extra)&&(extra_ndx<0);i++) { 110005b261ecSmrg if (!strcasecmp(tok,rules->extra_names[i])) 110105b261ecSmrg extra_ndx= i; 110205b261ecSmrg } 110305b261ecSmrg if (extra_ndx<0) { 110405b261ecSmrg XkbRF_DescribeVarsPtr var; 110505b261ecSmrg PR_DEBUG1("Extra heading \"%s\" encountered\n",tok); 110605b261ecSmrg var= XkbRF_AddVarToDescribe(rules,tok); 110705b261ecSmrg if (var) 110805b261ecSmrg extra_ndx= var-rules->extra; 110905b261ecSmrg else headingtype= HEAD_NONE; 111005b261ecSmrg } 111105b261ecSmrg } 111205b261ecSmrg continue; 111305b261ecSmrg } 111405b261ecSmrg 111505b261ecSmrg if (headingtype == HEAD_NONE) { 111605b261ecSmrg PR_DEBUG("Must have a heading before first line of data\n"); 111705b261ecSmrg PR_DEBUG("Illegal line of data ignored\n"); 111805b261ecSmrg continue; 111905b261ecSmrg } 112005b261ecSmrg 112105b261ecSmrg len = strlen(line.line); 112205b261ecSmrg if ((tmp.name= strtok(line.line, " \t")) == NULL) { 112305b261ecSmrg PR_DEBUG("Huh? No token on line\n"); 112405b261ecSmrg PR_DEBUG("Illegal line of data ignored\n"); 112505b261ecSmrg continue; 112605b261ecSmrg } 112705b261ecSmrg if (strlen(tmp.name) == len) { 112805b261ecSmrg PR_DEBUG("No description found\n"); 112905b261ecSmrg PR_DEBUG("Illegal line of data ignored\n"); 113005b261ecSmrg continue; 113105b261ecSmrg } 113205b261ecSmrg 113305b261ecSmrg tok = line.line + strlen(tmp.name) + 1; 113405b261ecSmrg while ((*tok!='\n')&&isspace(*tok)) 113505b261ecSmrg tok++; 113605b261ecSmrg if (*tok == '\0') { 113705b261ecSmrg PR_DEBUG("No description found\n"); 113805b261ecSmrg PR_DEBUG("Illegal line of data ignored\n"); 113905b261ecSmrg continue; 114005b261ecSmrg } 114105b261ecSmrg tmp.desc= tok; 114205b261ecSmrg switch (headingtype) { 114305b261ecSmrg case HEAD_MODEL: 114405b261ecSmrg XkbRF_AddVarDescCopy(&rules->models,&tmp); 114505b261ecSmrg break; 114605b261ecSmrg case HEAD_LAYOUT: 114705b261ecSmrg XkbRF_AddVarDescCopy(&rules->layouts,&tmp); 114805b261ecSmrg break; 114905b261ecSmrg case HEAD_VARIANT: 115005b261ecSmrg XkbRF_AddVarDescCopy(&rules->variants,&tmp); 115105b261ecSmrg break; 115205b261ecSmrg case HEAD_OPTION: 115305b261ecSmrg XkbRF_AddVarDescCopy(&rules->options,&tmp); 115405b261ecSmrg break; 115505b261ecSmrg case HEAD_EXTRA: 115605b261ecSmrg XkbRF_AddVarDescCopy(&rules->extra[extra_ndx],&tmp); 115705b261ecSmrg break; 115805b261ecSmrg } 115905b261ecSmrg } 116005b261ecSmrg FreeInputLine(&line); 116105b261ecSmrg if ((rules->models.num_desc==0) && (rules->layouts.num_desc==0) && 116205b261ecSmrg (rules->variants.num_desc==0) && (rules->options.num_desc==0) && 116305b261ecSmrg (rules->num_extra==0)) { 116405b261ecSmrg return False; 116505b261ecSmrg } 116605b261ecSmrg return True; 116705b261ecSmrg} 116805b261ecSmrg 116905b261ecSmrgBool 117005b261ecSmrgXkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules) 117105b261ecSmrg{ 117205b261ecSmrgFILE * file; 117305b261ecSmrgchar buf[PATH_MAX]; 117405b261ecSmrgBool ok; 117505b261ecSmrg 117605b261ecSmrg if ((!base)||(!rules)) 117705b261ecSmrg return False; 117805b261ecSmrg if (locale) { 117905b261ecSmrg if (strlen(base)+strlen(locale)+6 > PATH_MAX) 118005b261ecSmrg return False; 118105b261ecSmrg sprintf(buf,"%s-%s.lst", base, locale); 118205b261ecSmrg } 118305b261ecSmrg else { 118405b261ecSmrg if (strlen(base)+5 > PATH_MAX) 118505b261ecSmrg return False; 118605b261ecSmrg sprintf(buf,"%s.lst", base); 118705b261ecSmrg } 118805b261ecSmrg 118905b261ecSmrg file= fopen(buf, "r"); 119005b261ecSmrg if ((!file)&&(locale)) { /* fallback if locale was specified */ 119105b261ecSmrg sprintf(buf,"%s.lst", base); 119205b261ecSmrg 119305b261ecSmrg file= fopen(buf, "r"); 119405b261ecSmrg } 119505b261ecSmrg if (!file) 119605b261ecSmrg return False; 119705b261ecSmrg ok= XkbRF_LoadDescriptions(file,rules); 119805b261ecSmrg fclose(file); 119905b261ecSmrg return ok; 120005b261ecSmrg} 120105b261ecSmrg 120205b261ecSmrg/***====================================================================***/ 120305b261ecSmrg 120405b261ecSmrgXkbRF_RulesPtr 120505b261ecSmrgXkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules) 120605b261ecSmrg{ 120705b261ecSmrgXkbRF_RulesPtr rules; 120805b261ecSmrg 120905b261ecSmrg if ((!base)||((!wantDesc)&&(!wantRules))) 121005b261ecSmrg return NULL; 121105b261ecSmrg if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) 121205b261ecSmrg return NULL; 121305b261ecSmrg if (wantDesc&&(!XkbRF_LoadDescriptionsByName(base,locale,rules))) { 121405b261ecSmrg XkbRF_Free(rules,True); 121505b261ecSmrg return NULL; 121605b261ecSmrg } 121705b261ecSmrg if (wantRules&&(!XkbRF_LoadRulesByName(base,locale,rules))) { 121805b261ecSmrg XkbRF_Free(rules,True); 121905b261ecSmrg return NULL; 122005b261ecSmrg } 122105b261ecSmrg return rules; 122205b261ecSmrg} 122305b261ecSmrg 122405b261ecSmrgXkbRF_RulesPtr 122505b261ecSmrgXkbRF_Create(int szRules,int szExtra) 122605b261ecSmrg{ 122705b261ecSmrgXkbRF_RulesPtr rules; 122805b261ecSmrg 122905b261ecSmrg if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) 123005b261ecSmrg return NULL; 123105b261ecSmrg if (szRules>0) { 123205b261ecSmrg rules->sz_rules= szRules; 123305b261ecSmrg rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); 123405b261ecSmrg if (!rules->rules) { 123505b261ecSmrg _XkbFree(rules); 123605b261ecSmrg return NULL; 123705b261ecSmrg } 123805b261ecSmrg } 123905b261ecSmrg if (szExtra>0) { 124005b261ecSmrg rules->sz_extra= szExtra; 124105b261ecSmrg rules->extra= _XkbTypedCalloc(rules->sz_extra,XkbRF_DescribeVarsRec); 124205b261ecSmrg if (!rules->extra) { 124305b261ecSmrg if (rules->rules) 124405b261ecSmrg _XkbFree(rules->rules); 124505b261ecSmrg _XkbFree(rules); 124605b261ecSmrg return NULL; 124705b261ecSmrg } 124805b261ecSmrg } 124905b261ecSmrg return rules; 125005b261ecSmrg} 125105b261ecSmrg 125205b261ecSmrg/***====================================================================***/ 125305b261ecSmrg 125405b261ecSmrgstatic void 125505b261ecSmrgXkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var) 125605b261ecSmrg{ 125705b261ecSmrgregister int i; 125805b261ecSmrg 125905b261ecSmrg for (i=0;i<var->num_desc;i++) { 126005b261ecSmrg if (var->desc[i].name) 126105b261ecSmrg _XkbFree(var->desc[i].name); 126205b261ecSmrg if (var->desc[i].desc) 126305b261ecSmrg _XkbFree(var->desc[i].desc); 126405b261ecSmrg var->desc[i].name= var->desc[i].desc= NULL; 126505b261ecSmrg } 126605b261ecSmrg if (var->desc) 126705b261ecSmrg _XkbFree(var->desc); 126805b261ecSmrg var->desc= NULL; 126905b261ecSmrg return; 127005b261ecSmrg} 127105b261ecSmrg 127205b261ecSmrgvoid 127305b261ecSmrgXkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) 127405b261ecSmrg{ 127505b261ecSmrgint i; 127605b261ecSmrgXkbRF_RulePtr rule; 127705b261ecSmrgXkbRF_GroupPtr group; 127805b261ecSmrg 127905b261ecSmrg if (!rules) 128005b261ecSmrg return; 128105b261ecSmrg XkbRF_ClearVarDescriptions(&rules->models); 128205b261ecSmrg XkbRF_ClearVarDescriptions(&rules->layouts); 128305b261ecSmrg XkbRF_ClearVarDescriptions(&rules->variants); 128405b261ecSmrg XkbRF_ClearVarDescriptions(&rules->options); 128505b261ecSmrg if (rules->extra) { 128605b261ecSmrg for (i = 0; i < rules->num_extra; i++) { 128705b261ecSmrg XkbRF_ClearVarDescriptions(&rules->extra[i]); 128805b261ecSmrg } 128905b261ecSmrg _XkbFree(rules->extra); 129005b261ecSmrg rules->num_extra= rules->sz_extra= 0; 129105b261ecSmrg rules->extra= NULL; 129205b261ecSmrg } 129305b261ecSmrg if (rules->rules) { 129405b261ecSmrg for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { 129505b261ecSmrg if (rule->model) _XkbFree(rule->model); 129605b261ecSmrg if (rule->layout) _XkbFree(rule->layout); 129705b261ecSmrg if (rule->variant) _XkbFree(rule->variant); 129805b261ecSmrg if (rule->option) _XkbFree(rule->option); 129905b261ecSmrg if (rule->keycodes) _XkbFree(rule->keycodes); 130005b261ecSmrg if (rule->symbols) _XkbFree(rule->symbols); 130105b261ecSmrg if (rule->types) _XkbFree(rule->types); 130205b261ecSmrg if (rule->compat) _XkbFree(rule->compat); 130305b261ecSmrg if (rule->geometry) _XkbFree(rule->geometry); 130405b261ecSmrg if (rule->keymap) _XkbFree(rule->keymap); 130505b261ecSmrg bzero((char *)rule,sizeof(XkbRF_RuleRec)); 130605b261ecSmrg } 130705b261ecSmrg _XkbFree(rules->rules); 130805b261ecSmrg rules->num_rules= rules->sz_rules= 0; 130905b261ecSmrg rules->rules= NULL; 131005b261ecSmrg } 131105b261ecSmrg 131205b261ecSmrg if (rules->groups) { 131305b261ecSmrg for (i=0, group=rules->groups;i<rules->num_groups;i++,group++) { 131405b261ecSmrg if (group->name) _XkbFree(group->name); 131505b261ecSmrg if (group->words) _XkbFree(group->words); 131605b261ecSmrg } 131705b261ecSmrg _XkbFree(rules->groups); 131805b261ecSmrg rules->num_groups= 0; 131905b261ecSmrg rules->groups= NULL; 132005b261ecSmrg } 132105b261ecSmrg if (freeRules) 132205b261ecSmrg _XkbFree(rules); 132305b261ecSmrg return; 132405b261ecSmrg} 1325