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