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 935c4bbdfSmrg documentation, and that the name of Silicon Graphics not be 1035c4bbdfSmrg used in advertising or publicity pertaining to distribution 1105b261ecSmrg of the software without specific prior written permission. 1235c4bbdfSmrg 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. 1535c4bbdfSmrg 1635c4bbdfSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1735c4bbdfSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1805b261ecSmrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1935c4bbdfSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2035c4bbdfSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2135c4bbdfSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 2205b261ecSmrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 2305b261ecSmrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 2405b261ecSmrg 2505b261ecSmrg ********************************************************/ 2605b261ecSmrg 2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2805b261ecSmrg#include <dix-config.h> 2905b261ecSmrg#endif 3005b261ecSmrg 3105b261ecSmrg#include <stdio.h> 3205b261ecSmrg#include <ctype.h> 3305b261ecSmrg#include <stdlib.h> 3405b261ecSmrg 3505b261ecSmrg#define X_INCLUDE_STRING_H 3605b261ecSmrg#define XOS_USE_NO_LOCKING 3705b261ecSmrg#include <X11/Xos_r.h> 3805b261ecSmrg 3905b261ecSmrg#include <X11/Xproto.h> 4005b261ecSmrg#include <X11/X.h> 4105b261ecSmrg#include <X11/Xos.h> 4205b261ecSmrg#include <X11/Xfuncs.h> 4305b261ecSmrg#include <X11/Xatom.h> 4405b261ecSmrg#include <X11/keysym.h> 4505b261ecSmrg#include "misc.h" 4605b261ecSmrg#include "inputstr.h" 4705b261ecSmrg#include "dix.h" 484642e01fSmrg#include "os.h" 494642e01fSmrg#include "xkbstr.h" 5005b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS 5105b261ecSmrg#include <xkbsrv.h> 5205b261ecSmrg 5305b261ecSmrg/***====================================================================***/ 5405b261ecSmrg 5505b261ecSmrg#define DFLT_LINE_SIZE 128 5605b261ecSmrg 5705b261ecSmrgtypedef struct { 5835c4bbdfSmrg int line_num; 5935c4bbdfSmrg int sz_line; 6035c4bbdfSmrg int num_line; 6135c4bbdfSmrg char buf[DFLT_LINE_SIZE]; 6235c4bbdfSmrg char *line; 6305b261ecSmrg} InputLine; 6405b261ecSmrg 6505b261ecSmrgstatic void 6635c4bbdfSmrgInitInputLine(InputLine * line) 6705b261ecSmrg{ 6835c4bbdfSmrg line->line_num = 1; 6935c4bbdfSmrg line->num_line = 0; 7035c4bbdfSmrg line->sz_line = DFLT_LINE_SIZE; 7135c4bbdfSmrg line->line = line->buf; 7205b261ecSmrg return; 7305b261ecSmrg} 7405b261ecSmrg 7505b261ecSmrgstatic void 7635c4bbdfSmrgFreeInputLine(InputLine * line) 7705b261ecSmrg{ 7835c4bbdfSmrg if (line->line != line->buf) 7935c4bbdfSmrg free(line->line); 8035c4bbdfSmrg line->line_num = 1; 8135c4bbdfSmrg line->num_line = 0; 8235c4bbdfSmrg line->sz_line = DFLT_LINE_SIZE; 8335c4bbdfSmrg line->line = line->buf; 8405b261ecSmrg return; 8505b261ecSmrg} 8605b261ecSmrg 8705b261ecSmrgstatic int 8835c4bbdfSmrgInputLineAddChar(InputLine * line, int ch) 8905b261ecSmrg{ 9035c4bbdfSmrg if (line->num_line >= line->sz_line) { 9135c4bbdfSmrg if (line->line == line->buf) { 9235c4bbdfSmrg line->line = xallocarray(line->sz_line, 2); 9335c4bbdfSmrg memcpy(line->line, line->buf, line->sz_line); 9435c4bbdfSmrg } 9535c4bbdfSmrg else { 9635c4bbdfSmrg line->line = reallocarray(line->line, line->sz_line, 2); 9735c4bbdfSmrg } 9835c4bbdfSmrg line->sz_line *= 2; 9935c4bbdfSmrg } 10035c4bbdfSmrg line->line[line->num_line++] = ch; 10105b261ecSmrg return ch; 10205b261ecSmrg} 10305b261ecSmrg 10405b261ecSmrg#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\ 10505b261ecSmrg (int)((l)->line[(l)->num_line++]= (c)):\ 10605b261ecSmrg InputLineAddChar(l,c)) 10705b261ecSmrg 10805b261ecSmrgstatic Bool 10935c4bbdfSmrgGetInputLine(FILE * file, InputLine * line, Bool checkbang) 11005b261ecSmrg{ 11135c4bbdfSmrg int ch; 11235c4bbdfSmrg Bool endOfFile, spacePending, slashPending, inComment; 11335c4bbdfSmrg 11435c4bbdfSmrg endOfFile = FALSE; 11535c4bbdfSmrg while ((!endOfFile) && (line->num_line == 0)) { 11635c4bbdfSmrg spacePending = slashPending = inComment = FALSE; 11735c4bbdfSmrg while (((ch = getc(file)) != '\n') && (ch != EOF)) { 11835c4bbdfSmrg if (ch == '\\') { 11935c4bbdfSmrg if ((ch = getc(file)) == EOF) 12035c4bbdfSmrg break; 12135c4bbdfSmrg if (ch == '\n') { 12235c4bbdfSmrg inComment = FALSE; 12335c4bbdfSmrg ch = ' '; 12435c4bbdfSmrg line->line_num++; 12535c4bbdfSmrg } 12635c4bbdfSmrg } 12735c4bbdfSmrg if (inComment) 12835c4bbdfSmrg continue; 12935c4bbdfSmrg if (ch == '/') { 13035c4bbdfSmrg if (slashPending) { 13135c4bbdfSmrg inComment = TRUE; 13235c4bbdfSmrg slashPending = FALSE; 13335c4bbdfSmrg } 13435c4bbdfSmrg else { 13535c4bbdfSmrg slashPending = TRUE; 13635c4bbdfSmrg } 13735c4bbdfSmrg continue; 13835c4bbdfSmrg } 13935c4bbdfSmrg else if (slashPending) { 14035c4bbdfSmrg if (spacePending) { 14135c4bbdfSmrg ADD_CHAR(line, ' '); 14235c4bbdfSmrg spacePending = FALSE; 14335c4bbdfSmrg } 14435c4bbdfSmrg ADD_CHAR(line, '/'); 14535c4bbdfSmrg slashPending = FALSE; 14635c4bbdfSmrg } 14735c4bbdfSmrg if (isspace(ch)) { 14835c4bbdfSmrg while (isspace(ch) && (ch != '\n') && (ch != EOF)) { 14935c4bbdfSmrg ch = getc(file); 15035c4bbdfSmrg } 15135c4bbdfSmrg if (ch == EOF) 15235c4bbdfSmrg break; 15335c4bbdfSmrg if ((ch != '\n') && (line->num_line > 0)) 15435c4bbdfSmrg spacePending = TRUE; 15535c4bbdfSmrg ungetc(ch, file); 15635c4bbdfSmrg } 15735c4bbdfSmrg else { 15835c4bbdfSmrg if (spacePending) { 15935c4bbdfSmrg ADD_CHAR(line, ' '); 16035c4bbdfSmrg spacePending = FALSE; 16135c4bbdfSmrg } 16235c4bbdfSmrg if (checkbang && ch == '!') { 16335c4bbdfSmrg if (line->num_line != 0) { 16435c4bbdfSmrg DebugF("The '!' legal only at start of line\n"); 16535c4bbdfSmrg DebugF("Line containing '!' ignored\n"); 16635c4bbdfSmrg line->num_line = 0; 16735c4bbdfSmrg inComment = 0; 16835c4bbdfSmrg break; 16935c4bbdfSmrg } 17035c4bbdfSmrg 17135c4bbdfSmrg } 17235c4bbdfSmrg ADD_CHAR(line, ch); 17335c4bbdfSmrg } 17435c4bbdfSmrg } 17535c4bbdfSmrg if (ch == EOF) 17635c4bbdfSmrg endOfFile = TRUE; 17705b261ecSmrg/* else line->num_line++;*/ 17835c4bbdfSmrg } 17935c4bbdfSmrg if ((line->num_line == 0) && (endOfFile)) 18035c4bbdfSmrg return FALSE; 18135c4bbdfSmrg ADD_CHAR(line, '\0'); 18235c4bbdfSmrg return TRUE; 18305b261ecSmrg} 18405b261ecSmrg 18505b261ecSmrg/***====================================================================***/ 18605b261ecSmrg 18705b261ecSmrg#define MODEL 0 18805b261ecSmrg#define LAYOUT 1 18905b261ecSmrg#define VARIANT 2 19005b261ecSmrg#define OPTION 3 19105b261ecSmrg#define KEYCODES 4 19205b261ecSmrg#define SYMBOLS 5 19305b261ecSmrg#define TYPES 6 19405b261ecSmrg#define COMPAT 7 19505b261ecSmrg#define GEOMETRY 8 1966747b715Smrg#define MAX_WORDS 9 19705b261ecSmrg 19805b261ecSmrg#define PART_MASK 0x000F 19905b261ecSmrg#define COMPONENT_MASK 0x03F0 20005b261ecSmrg 20135c4bbdfSmrgstatic const char *cname[MAX_WORDS] = { 20235c4bbdfSmrg "model", "layout", "variant", "option", 20335c4bbdfSmrg "keycodes", "symbols", "types", "compat", "geometry" 20405b261ecSmrg}; 20505b261ecSmrg 20635c4bbdfSmrgtypedef struct _RemapSpec { 20735c4bbdfSmrg int number; 20835c4bbdfSmrg int num_remap; 20935c4bbdfSmrg struct { 21035c4bbdfSmrg int word; 21135c4bbdfSmrg int index; 21235c4bbdfSmrg } remap[MAX_WORDS]; 21305b261ecSmrg} RemapSpec; 21405b261ecSmrg 21505b261ecSmrgtypedef struct _FileSpec { 21635c4bbdfSmrg char *name[MAX_WORDS]; 21735c4bbdfSmrg struct _FileSpec *pending; 21805b261ecSmrg} FileSpec; 21905b261ecSmrg 22005b261ecSmrgtypedef struct { 22135c4bbdfSmrg const char *model; 22235c4bbdfSmrg const char *layout[XkbNumKbdGroups + 1]; 22335c4bbdfSmrg const char *variant[XkbNumKbdGroups + 1]; 22435c4bbdfSmrg const char *options; 22505b261ecSmrg} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; 22605b261ecSmrg 22705b261ecSmrg#define NDX_BUFF_SIZE 4 22805b261ecSmrg 22905b261ecSmrg/***====================================================================***/ 23005b261ecSmrg 23135c4bbdfSmrgstatic char * 23205b261ecSmrgget_index(char *str, int *ndx) 23305b261ecSmrg{ 23435c4bbdfSmrg char ndx_buf[NDX_BUFF_SIZE]; 23535c4bbdfSmrg char *end; 23635c4bbdfSmrg 23735c4bbdfSmrg if (*str != '[') { 23835c4bbdfSmrg *ndx = 0; 23935c4bbdfSmrg return str; 24035c4bbdfSmrg } 24135c4bbdfSmrg str++; 24235c4bbdfSmrg end = strchr(str, ']'); 24335c4bbdfSmrg if (end == NULL) { 24435c4bbdfSmrg *ndx = -1; 24535c4bbdfSmrg return str - 1; 24635c4bbdfSmrg } 24735c4bbdfSmrg if ((end - str) >= NDX_BUFF_SIZE) { 24835c4bbdfSmrg *ndx = -1; 24935c4bbdfSmrg return end + 1; 25035c4bbdfSmrg } 25135c4bbdfSmrg strlcpy(ndx_buf, str, 1 + end - str); 25235c4bbdfSmrg *ndx = atoi(ndx_buf); 25335c4bbdfSmrg return end + 1; 25405b261ecSmrg} 25505b261ecSmrg 25605b261ecSmrgstatic void 25735c4bbdfSmrgSetUpRemap(InputLine * line, RemapSpec * remap) 25805b261ecSmrg{ 25935c4bbdfSmrg char *tok, *str; 26035c4bbdfSmrg unsigned present, l_ndx_present, v_ndx_present; 26135c4bbdfSmrg register int i; 26235c4bbdfSmrg int len, ndx; 26335c4bbdfSmrg _Xstrtokparams strtok_buf; 26435c4bbdfSmrg Bool found; 26535c4bbdfSmrg 26635c4bbdfSmrg l_ndx_present = v_ndx_present = present = 0; 26735c4bbdfSmrg str = &line->line[1]; 26835c4bbdfSmrg len = remap->number; 26935c4bbdfSmrg memset((char *) remap, 0, sizeof(RemapSpec)); 27035c4bbdfSmrg remap->number = len; 27135c4bbdfSmrg while ((tok = _XStrtok(str, " ", strtok_buf)) != NULL) { 27235c4bbdfSmrg found = FALSE; 27335c4bbdfSmrg str = NULL; 27435c4bbdfSmrg if (strcmp(tok, "=") == 0) 27535c4bbdfSmrg continue; 27635c4bbdfSmrg for (i = 0; i < MAX_WORDS; i++) { 27705b261ecSmrg len = strlen(cname[i]); 27835c4bbdfSmrg if (strncmp(cname[i], tok, len) == 0) { 27935c4bbdfSmrg if (strlen(tok) > len) { 28035c4bbdfSmrg char *end = get_index(tok + len, &ndx); 28135c4bbdfSmrg 28235c4bbdfSmrg if ((i != LAYOUT && i != VARIANT) || 28335c4bbdfSmrg *end != '\0' || ndx == -1) 28435c4bbdfSmrg break; 28535c4bbdfSmrg if (ndx < 1 || ndx > XkbNumKbdGroups) { 28635c4bbdfSmrg DebugF("Illegal %s index: %d\n", cname[i], ndx); 28735c4bbdfSmrg DebugF("Index must be in range 1..%d\n", 28835c4bbdfSmrg XkbNumKbdGroups); 28935c4bbdfSmrg break; 29035c4bbdfSmrg } 29135c4bbdfSmrg } 29235c4bbdfSmrg else { 29335c4bbdfSmrg ndx = 0; 29405b261ecSmrg } 29535c4bbdfSmrg found = TRUE; 29635c4bbdfSmrg if (present & (1 << i)) { 29735c4bbdfSmrg if ((i == LAYOUT && l_ndx_present & (1 << ndx)) || 29835c4bbdfSmrg (i == VARIANT && v_ndx_present & (1 << ndx))) { 29935c4bbdfSmrg DebugF("Component \"%s\" listed twice\n", tok); 30035c4bbdfSmrg DebugF("Second definition ignored\n"); 30135c4bbdfSmrg break; 30235c4bbdfSmrg } 30335c4bbdfSmrg } 30435c4bbdfSmrg present |= (1 << i); 30505b261ecSmrg if (i == LAYOUT) 30605b261ecSmrg l_ndx_present |= 1 << ndx; 30705b261ecSmrg if (i == VARIANT) 30805b261ecSmrg v_ndx_present |= 1 << ndx; 30935c4bbdfSmrg remap->remap[remap->num_remap].word = i; 31035c4bbdfSmrg remap->remap[remap->num_remap++].index = ndx; 31135c4bbdfSmrg break; 31235c4bbdfSmrg } 31335c4bbdfSmrg } 31435c4bbdfSmrg if (!found) { 31535c4bbdfSmrg fprintf(stderr, "Unknown component \"%s\" ignored\n", tok); 31635c4bbdfSmrg } 31735c4bbdfSmrg } 31835c4bbdfSmrg if ((present & PART_MASK) == 0) { 31935c4bbdfSmrg unsigned mask = PART_MASK; 32035c4bbdfSmrg 32135c4bbdfSmrg ErrorF("Mapping needs at least one of "); 32235c4bbdfSmrg for (i = 0; (i < MAX_WORDS); i++) { 32335c4bbdfSmrg if ((1L << i) & mask) { 32435c4bbdfSmrg mask &= ~(1L << i); 32535c4bbdfSmrg if (mask) 32635c4bbdfSmrg DebugF("\"%s,\" ", cname[i]); 32735c4bbdfSmrg else 32835c4bbdfSmrg DebugF("or \"%s\"\n", cname[i]); 32935c4bbdfSmrg } 33035c4bbdfSmrg } 33135c4bbdfSmrg DebugF("Illegal mapping ignored\n"); 33235c4bbdfSmrg remap->num_remap = 0; 33335c4bbdfSmrg return; 33435c4bbdfSmrg } 33535c4bbdfSmrg if ((present & COMPONENT_MASK) == 0) { 33635c4bbdfSmrg DebugF("Mapping needs at least one component\n"); 33735c4bbdfSmrg DebugF("Illegal mapping ignored\n"); 33835c4bbdfSmrg remap->num_remap = 0; 33935c4bbdfSmrg return; 34035c4bbdfSmrg } 34135c4bbdfSmrg remap->number++; 34235c4bbdfSmrg return; 34305b261ecSmrg} 34405b261ecSmrg 34505b261ecSmrgstatic Bool 34635c4bbdfSmrgMatchOneOf(const char *wanted, const char *vals_defined) 34705b261ecSmrg{ 34835c4bbdfSmrg const char *str, *next; 34935c4bbdfSmrg int want_len = strlen(wanted); 35035c4bbdfSmrg 35135c4bbdfSmrg for (str = vals_defined, next = NULL; str != NULL; str = next) { 35235c4bbdfSmrg int len; 35335c4bbdfSmrg 35435c4bbdfSmrg next = strchr(str, ','); 35535c4bbdfSmrg if (next) { 35635c4bbdfSmrg len = next - str; 35735c4bbdfSmrg next++; 35835c4bbdfSmrg } 35935c4bbdfSmrg else { 36035c4bbdfSmrg len = strlen(str); 36135c4bbdfSmrg } 36235c4bbdfSmrg if ((len == want_len) && (strncmp(wanted, str, len) == 0)) 36335c4bbdfSmrg return TRUE; 36405b261ecSmrg } 3656747b715Smrg return FALSE; 36605b261ecSmrg} 36705b261ecSmrg 36805b261ecSmrg/***====================================================================***/ 36905b261ecSmrg 37005b261ecSmrgstatic Bool 37135c4bbdfSmrgCheckLine(InputLine * line, 37235c4bbdfSmrg RemapSpec * remap, XkbRF_RulePtr rule, XkbRF_GroupPtr group) 37305b261ecSmrg{ 37435c4bbdfSmrg char *str, *tok; 37535c4bbdfSmrg register int nread, i; 37635c4bbdfSmrg FileSpec tmp; 37735c4bbdfSmrg _Xstrtokparams strtok_buf; 37835c4bbdfSmrg Bool append = FALSE; 37905b261ecSmrg 38035c4bbdfSmrg if (line->line[0] == '!') { 38105b261ecSmrg if (line->line[1] == '$' || 38205b261ecSmrg (line->line[1] == ' ' && line->line[2] == '$')) { 38305b261ecSmrg char *gname = strchr(line->line, '$'); 38405b261ecSmrg char *words = strchr(gname, ' '); 38535c4bbdfSmrg 38635c4bbdfSmrg if (!words) 3876747b715Smrg return FALSE; 38805b261ecSmrg *words++ = '\0'; 38905b261ecSmrg for (; *words; words++) { 39005b261ecSmrg if (*words != '=' && *words != ' ') 39105b261ecSmrg break; 39205b261ecSmrg } 39305b261ecSmrg if (*words == '\0') 3946747b715Smrg return FALSE; 39535c4bbdfSmrg group->name = Xstrdup(gname); 39635c4bbdfSmrg group->words = Xstrdup(words); 39705b261ecSmrg for (i = 1, words = group->words; *words; words++) { 39835c4bbdfSmrg if (*words == ' ') { 39935c4bbdfSmrg *words++ = '\0'; 40035c4bbdfSmrg i++; 40135c4bbdfSmrg } 40205b261ecSmrg } 40305b261ecSmrg group->number = i; 4046747b715Smrg return TRUE; 40535c4bbdfSmrg } 40635c4bbdfSmrg else { 40735c4bbdfSmrg SetUpRemap(line, remap); 40835c4bbdfSmrg return FALSE; 40935c4bbdfSmrg } 41035c4bbdfSmrg } 41135c4bbdfSmrg 41235c4bbdfSmrg if (remap->num_remap == 0) { 41335c4bbdfSmrg DebugF("Must have a mapping before first line of data\n"); 41435c4bbdfSmrg DebugF("Illegal line of data ignored\n"); 41535c4bbdfSmrg return FALSE; 41635c4bbdfSmrg } 41735c4bbdfSmrg memset((char *) &tmp, 0, sizeof(FileSpec)); 41835c4bbdfSmrg str = line->line; 41935c4bbdfSmrg for (nread = 0; (tok = _XStrtok(str, " ", strtok_buf)) != NULL; nread++) { 42035c4bbdfSmrg str = NULL; 42135c4bbdfSmrg if (strcmp(tok, "=") == 0) { 42235c4bbdfSmrg nread--; 42335c4bbdfSmrg continue; 42435c4bbdfSmrg } 42535c4bbdfSmrg if (nread > remap->num_remap) { 42635c4bbdfSmrg DebugF("Too many words on a line\n"); 42735c4bbdfSmrg DebugF("Extra word \"%s\" ignored\n", tok); 42835c4bbdfSmrg continue; 42935c4bbdfSmrg } 43035c4bbdfSmrg tmp.name[remap->remap[nread].word] = tok; 43135c4bbdfSmrg if (*tok == '+' || *tok == '|') 43235c4bbdfSmrg append = TRUE; 43335c4bbdfSmrg } 43435c4bbdfSmrg if (nread < remap->num_remap) { 43535c4bbdfSmrg DebugF("Too few words on a line: %s\n", line->line); 43635c4bbdfSmrg DebugF("line ignored\n"); 43735c4bbdfSmrg return FALSE; 43835c4bbdfSmrg } 43935c4bbdfSmrg 44035c4bbdfSmrg rule->flags = 0; 44105b261ecSmrg rule->number = remap->number; 44205b261ecSmrg if (tmp.name[OPTION]) 44335c4bbdfSmrg rule->flags |= XkbRF_Option; 44405b261ecSmrg else if (append) 44535c4bbdfSmrg rule->flags |= XkbRF_Append; 44605b261ecSmrg else 44735c4bbdfSmrg rule->flags |= XkbRF_Normal; 44835c4bbdfSmrg rule->model = Xstrdup(tmp.name[MODEL]); 44935c4bbdfSmrg rule->layout = Xstrdup(tmp.name[LAYOUT]); 45035c4bbdfSmrg rule->variant = Xstrdup(tmp.name[VARIANT]); 45135c4bbdfSmrg rule->option = Xstrdup(tmp.name[OPTION]); 45235c4bbdfSmrg 45335c4bbdfSmrg rule->keycodes = Xstrdup(tmp.name[KEYCODES]); 45435c4bbdfSmrg rule->symbols = Xstrdup(tmp.name[SYMBOLS]); 45535c4bbdfSmrg rule->types = Xstrdup(tmp.name[TYPES]); 45635c4bbdfSmrg rule->compat = Xstrdup(tmp.name[COMPAT]); 45735c4bbdfSmrg rule->geometry = Xstrdup(tmp.name[GEOMETRY]); 45805b261ecSmrg 45905b261ecSmrg rule->layout_num = rule->variant_num = 0; 46005b261ecSmrg for (i = 0; i < nread; i++) { 46105b261ecSmrg if (remap->remap[i].index) { 46235c4bbdfSmrg if (remap->remap[i].word == LAYOUT) 46335c4bbdfSmrg rule->layout_num = remap->remap[i].index; 46435c4bbdfSmrg if (remap->remap[i].word == VARIANT) 46535c4bbdfSmrg rule->variant_num = remap->remap[i].index; 46605b261ecSmrg } 46705b261ecSmrg } 4686747b715Smrg return TRUE; 46905b261ecSmrg} 47005b261ecSmrg 47105b261ecSmrgstatic char * 47235c4bbdfSmrg_Concat(char *str1, const char *str2) 47305b261ecSmrg{ 47435c4bbdfSmrg int len; 47505b261ecSmrg 47635c4bbdfSmrg if ((!str1) || (!str2)) 47735c4bbdfSmrg return str1; 47835c4bbdfSmrg len = strlen(str1) + strlen(str2) + 1; 47935c4bbdfSmrg str1 = realloc(str1, len * sizeof(char)); 48005b261ecSmrg if (str1) 48135c4bbdfSmrg strcat(str1, str2); 48205b261ecSmrg return str1; 48305b261ecSmrg} 48405b261ecSmrg 48505b261ecSmrgstatic void 48605b261ecSmrgsqueeze_spaces(char *p1) 48705b261ecSmrg{ 48835c4bbdfSmrg char *p2; 48935c4bbdfSmrg 49035c4bbdfSmrg for (p2 = p1; *p2; p2++) { 49135c4bbdfSmrg *p1 = *p2; 49235c4bbdfSmrg if (*p1 != ' ') 49335c4bbdfSmrg p1++; 49435c4bbdfSmrg } 49535c4bbdfSmrg *p1 = '\0'; 49605b261ecSmrg} 49705b261ecSmrg 49805b261ecSmrgstatic Bool 49905b261ecSmrgMakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) 50005b261ecSmrg{ 50135c4bbdfSmrg char *options; 50235c4bbdfSmrg memset((char *) mdefs, 0, sizeof(XkbRF_MultiDefsRec)); 50335c4bbdfSmrg mdefs->model = defs->model; 50435c4bbdfSmrg options = Xstrdup(defs->options); 50535c4bbdfSmrg if (options) 50635c4bbdfSmrg squeeze_spaces(options); 50735c4bbdfSmrg mdefs->options = options; 50835c4bbdfSmrg 50935c4bbdfSmrg if (defs->layout) { 51035c4bbdfSmrg if (!strchr(defs->layout, ',')) { 51135c4bbdfSmrg mdefs->layout[0] = defs->layout; 51235c4bbdfSmrg } 51335c4bbdfSmrg else { 51435c4bbdfSmrg char *p; 51535c4bbdfSmrg char *layout; 51635c4bbdfSmrg int i; 51705b261ecSmrg 51835c4bbdfSmrg layout = Xstrdup(defs->layout); 51935c4bbdfSmrg if (layout == NULL) 52035c4bbdfSmrg return FALSE; 52135c4bbdfSmrg squeeze_spaces(layout); 52235c4bbdfSmrg mdefs->layout[1] = layout; 52335c4bbdfSmrg p = layout; 52435c4bbdfSmrg for (i = 2; i <= XkbNumKbdGroups; i++) { 52535c4bbdfSmrg if ((p = strchr(p, ','))) { 52635c4bbdfSmrg *p++ = '\0'; 52735c4bbdfSmrg mdefs->layout[i] = p; 52835c4bbdfSmrg } 52935c4bbdfSmrg else { 53035c4bbdfSmrg break; 53135c4bbdfSmrg } 53235c4bbdfSmrg } 53335c4bbdfSmrg if (p && (p = strchr(p, ','))) 53435c4bbdfSmrg *p = '\0'; 53535c4bbdfSmrg } 53635c4bbdfSmrg } 53735c4bbdfSmrg 53835c4bbdfSmrg if (defs->variant) { 53935c4bbdfSmrg if (!strchr(defs->variant, ',')) { 54035c4bbdfSmrg mdefs->variant[0] = defs->variant; 54135c4bbdfSmrg } 54235c4bbdfSmrg else { 54335c4bbdfSmrg char *p; 54435c4bbdfSmrg char *variant; 54535c4bbdfSmrg int i; 54635c4bbdfSmrg 54735c4bbdfSmrg variant = Xstrdup(defs->variant); 54835c4bbdfSmrg if (variant == NULL) 54935c4bbdfSmrg return FALSE; 55035c4bbdfSmrg squeeze_spaces(variant); 55135c4bbdfSmrg mdefs->variant[1] = variant; 55235c4bbdfSmrg p = variant; 55335c4bbdfSmrg for (i = 2; i <= XkbNumKbdGroups; i++) { 55435c4bbdfSmrg if ((p = strchr(p, ','))) { 55535c4bbdfSmrg *p++ = '\0'; 55635c4bbdfSmrg mdefs->variant[i] = p; 55735c4bbdfSmrg } 55835c4bbdfSmrg else { 55935c4bbdfSmrg break; 56035c4bbdfSmrg } 56135c4bbdfSmrg } 56235c4bbdfSmrg if (p && (p = strchr(p, ','))) 56335c4bbdfSmrg *p = '\0'; 56435c4bbdfSmrg } 56535c4bbdfSmrg } 56635c4bbdfSmrg return TRUE; 56705b261ecSmrg} 56805b261ecSmrg 56905b261ecSmrgstatic void 57005b261ecSmrgFreeMultiDefs(XkbRF_MultiDefsPtr defs) 57105b261ecSmrg{ 57235c4bbdfSmrg free((void *) defs->options); 57335c4bbdfSmrg free((void *) defs->layout[1]); 57435c4bbdfSmrg free((void *) defs->variant[1]); 57505b261ecSmrg} 57605b261ecSmrg 57705b261ecSmrgstatic void 57835c4bbdfSmrgApply(const char *src, char **dst) 57905b261ecSmrg{ 58005b261ecSmrg if (src) { 5811b5d61b8Smrg if (*src == '+' || *src == '|') { 58235c4bbdfSmrg *dst = _Concat(*dst, src); 58335c4bbdfSmrg } 58435c4bbdfSmrg else { 58505b261ecSmrg if (*dst == NULL) 58635c4bbdfSmrg *dst = Xstrdup(src); 58705b261ecSmrg } 58805b261ecSmrg } 58905b261ecSmrg} 59005b261ecSmrg 59105b261ecSmrgstatic void 59235c4bbdfSmrgXkbRF_ApplyRule(XkbRF_RulePtr rule, XkbComponentNamesPtr names) 59305b261ecSmrg{ 59435c4bbdfSmrg rule->flags &= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ 59505b261ecSmrg 59605b261ecSmrg Apply(rule->keycodes, &names->keycodes); 59735c4bbdfSmrg Apply(rule->symbols, &names->symbols); 59835c4bbdfSmrg Apply(rule->types, &names->types); 59935c4bbdfSmrg Apply(rule->compat, &names->compat); 60005b261ecSmrg Apply(rule->geometry, &names->geometry); 60105b261ecSmrg} 60205b261ecSmrg 60305b261ecSmrgstatic Bool 60435c4bbdfSmrgCheckGroup(XkbRF_RulesPtr rules, const char *group_name, const char *name) 60505b261ecSmrg{ 60635c4bbdfSmrg int i; 60735c4bbdfSmrg char *p; 60835c4bbdfSmrg XkbRF_GroupPtr group; 60935c4bbdfSmrg 61035c4bbdfSmrg for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { 61135c4bbdfSmrg if (!strcmp(group->name, group_name)) { 61235c4bbdfSmrg break; 61335c4bbdfSmrg } 61435c4bbdfSmrg } 61535c4bbdfSmrg if (i == rules->num_groups) 61635c4bbdfSmrg return FALSE; 61735c4bbdfSmrg for (i = 0, p = group->words; i < group->number; i++, p += strlen(p) + 1) { 61835c4bbdfSmrg if (!strcmp(p, name)) { 61935c4bbdfSmrg return TRUE; 62035c4bbdfSmrg } 62135c4bbdfSmrg } 62235c4bbdfSmrg return FALSE; 62305b261ecSmrg} 62405b261ecSmrg 62505b261ecSmrgstatic int 62635c4bbdfSmrgXkbRF_CheckApplyRule(XkbRF_RulePtr rule, 62735c4bbdfSmrg XkbRF_MultiDefsPtr mdefs, 62835c4bbdfSmrg XkbComponentNamesPtr names, XkbRF_RulesPtr rules) 62905b261ecSmrg{ 6306747b715Smrg Bool pending = FALSE; 63105b261ecSmrg 63205b261ecSmrg if (rule->model != NULL) { 63335c4bbdfSmrg if (mdefs->model == NULL) 63405b261ecSmrg return 0; 63505b261ecSmrg if (strcmp(rule->model, "*") == 0) { 6366747b715Smrg pending = TRUE; 63735c4bbdfSmrg } 63835c4bbdfSmrg else { 63905b261ecSmrg if (rule->model[0] == '$') { 64035c4bbdfSmrg if (!CheckGroup(rules, rule->model, mdefs->model)) 64135c4bbdfSmrg return 0; 64235c4bbdfSmrg } 64335c4bbdfSmrg else { 64435c4bbdfSmrg if (strcmp(rule->model, mdefs->model) != 0) 64535c4bbdfSmrg return 0; 64635c4bbdfSmrg } 64735c4bbdfSmrg } 64805b261ecSmrg } 64905b261ecSmrg if (rule->option != NULL) { 65035c4bbdfSmrg if (mdefs->options == NULL) 65135c4bbdfSmrg return 0; 65235c4bbdfSmrg if ((!MatchOneOf(rule->option, mdefs->options))) 65335c4bbdfSmrg return 0; 65405b261ecSmrg } 65505b261ecSmrg 65605b261ecSmrg if (rule->layout != NULL) { 65735c4bbdfSmrg if (mdefs->layout[rule->layout_num] == NULL || 65835c4bbdfSmrg *mdefs->layout[rule->layout_num] == '\0') 65935c4bbdfSmrg return 0; 66005b261ecSmrg if (strcmp(rule->layout, "*") == 0) { 6616747b715Smrg pending = TRUE; 66235c4bbdfSmrg } 66335c4bbdfSmrg else { 66405b261ecSmrg if (rule->layout[0] == '$') { 66535c4bbdfSmrg if (!CheckGroup(rules, rule->layout, 66635c4bbdfSmrg mdefs->layout[rule->layout_num])) 66735c4bbdfSmrg return 0; 66835c4bbdfSmrg } 66935c4bbdfSmrg else { 67035c4bbdfSmrg if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0) 67135c4bbdfSmrg return 0; 67235c4bbdfSmrg } 67335c4bbdfSmrg } 67405b261ecSmrg } 67505b261ecSmrg if (rule->variant != NULL) { 67635c4bbdfSmrg if (mdefs->variant[rule->variant_num] == NULL || 67735c4bbdfSmrg *mdefs->variant[rule->variant_num] == '\0') 67835c4bbdfSmrg return 0; 67905b261ecSmrg if (strcmp(rule->variant, "*") == 0) { 6806747b715Smrg pending = TRUE; 68135c4bbdfSmrg } 68235c4bbdfSmrg else { 68305b261ecSmrg if (rule->variant[0] == '$') { 68435c4bbdfSmrg if (!CheckGroup(rules, rule->variant, 68535c4bbdfSmrg mdefs->variant[rule->variant_num])) 68635c4bbdfSmrg return 0; 68735c4bbdfSmrg } 68835c4bbdfSmrg else { 68935c4bbdfSmrg if (strcmp(rule->variant, 69035c4bbdfSmrg mdefs->variant[rule->variant_num]) != 0) 69135c4bbdfSmrg return 0; 69235c4bbdfSmrg } 69335c4bbdfSmrg } 69405b261ecSmrg } 69505b261ecSmrg if (pending) { 69635c4bbdfSmrg rule->flags |= XkbRF_PendingMatch; 69735c4bbdfSmrg return rule->number; 69805b261ecSmrg } 69905b261ecSmrg /* exact match, apply it now */ 70035c4bbdfSmrg XkbRF_ApplyRule(rule, names); 70105b261ecSmrg return rule->number; 70205b261ecSmrg} 70305b261ecSmrg 70405b261ecSmrgstatic void 70505b261ecSmrgXkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) 70605b261ecSmrg{ 70735c4bbdfSmrg register int i; 70835c4bbdfSmrg XkbRF_RulePtr rule; 70905b261ecSmrg 71035c4bbdfSmrg for (i = 0, rule = rules->rules; i < rules->num_rules; i++, rule++) { 71135c4bbdfSmrg rule->flags &= ~XkbRF_PendingMatch; 71205b261ecSmrg } 71305b261ecSmrg} 71405b261ecSmrg 71505b261ecSmrgstatic void 71635c4bbdfSmrgXkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules, XkbComponentNamesPtr names) 71705b261ecSmrg{ 71835c4bbdfSmrg int i; 71935c4bbdfSmrg XkbRF_RulePtr rule; 72005b261ecSmrg 72105b261ecSmrg for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { 72235c4bbdfSmrg if ((rule->flags & XkbRF_PendingMatch) == 0) 72335c4bbdfSmrg continue; 72435c4bbdfSmrg XkbRF_ApplyRule(rule, names); 72505b261ecSmrg } 72605b261ecSmrg} 72705b261ecSmrg 72805b261ecSmrgstatic void 72935c4bbdfSmrgXkbRF_CheckApplyRules(XkbRF_RulesPtr rules, 73035c4bbdfSmrg XkbRF_MultiDefsPtr mdefs, 73135c4bbdfSmrg XkbComponentNamesPtr names, int flags) 73205b261ecSmrg{ 73335c4bbdfSmrg int i; 73435c4bbdfSmrg XkbRF_RulePtr rule; 73535c4bbdfSmrg int skip; 73635c4bbdfSmrg 73735c4bbdfSmrg for (rule = rules->rules, i = 0; i < rules->num_rules; rule++, i++) { 73835c4bbdfSmrg if ((rule->flags & flags) != flags) 73935c4bbdfSmrg continue; 74035c4bbdfSmrg skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules); 74135c4bbdfSmrg if (skip && !(flags & XkbRF_Option)) { 74235c4bbdfSmrg for (; (i < rules->num_rules) && (rule->number == skip); 74335c4bbdfSmrg rule++, i++); 74435c4bbdfSmrg rule--; 74535c4bbdfSmrg i--; 74635c4bbdfSmrg } 74705b261ecSmrg } 74805b261ecSmrg} 74905b261ecSmrg 75005b261ecSmrg/***====================================================================***/ 75105b261ecSmrg 75205b261ecSmrgstatic char * 75305b261ecSmrgXkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) 75405b261ecSmrg{ 75535c4bbdfSmrg char *str, *outstr, *orig, *var; 75635c4bbdfSmrg int len, ndx; 75735c4bbdfSmrg 75835c4bbdfSmrg orig = name; 75935c4bbdfSmrg str = index(name, '%'); 76035c4bbdfSmrg if (str == NULL) 76135c4bbdfSmrg return name; 76235c4bbdfSmrg len = strlen(name); 76335c4bbdfSmrg while (str != NULL) { 76435c4bbdfSmrg char pfx = str[1]; 76535c4bbdfSmrg int extra_len = 0; 76635c4bbdfSmrg 76735c4bbdfSmrg if ((pfx == '+') || (pfx == '|') || (pfx == '_') || (pfx == '-')) { 76835c4bbdfSmrg extra_len = 1; 76935c4bbdfSmrg str++; 77035c4bbdfSmrg } 77135c4bbdfSmrg else if (pfx == '(') { 77235c4bbdfSmrg extra_len = 2; 77335c4bbdfSmrg str++; 77435c4bbdfSmrg } 77535c4bbdfSmrg var = str + 1; 77635c4bbdfSmrg str = get_index(var + 1, &ndx); 77735c4bbdfSmrg if (ndx == -1) { 77835c4bbdfSmrg str = index(str, '%'); 77935c4bbdfSmrg continue; 78035c4bbdfSmrg } 78135c4bbdfSmrg if ((*var == 'l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) 78235c4bbdfSmrg len += strlen(mdefs->layout[ndx]) + extra_len; 78335c4bbdfSmrg else if ((*var == 'm') && mdefs->model) 78435c4bbdfSmrg len += strlen(mdefs->model) + extra_len; 78535c4bbdfSmrg else if ((*var == 'v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) 78635c4bbdfSmrg len += strlen(mdefs->variant[ndx]) + extra_len; 78735c4bbdfSmrg if ((pfx == '(') && (*str == ')')) { 78835c4bbdfSmrg str++; 78935c4bbdfSmrg } 79035c4bbdfSmrg str = index(&str[0], '%'); 79135c4bbdfSmrg } 79235c4bbdfSmrg name = malloc(len + 1); 79335c4bbdfSmrg str = orig; 79435c4bbdfSmrg outstr = name; 79535c4bbdfSmrg while (*str != '\0') { 79635c4bbdfSmrg if (str[0] == '%') { 79735c4bbdfSmrg char pfx, sfx; 79835c4bbdfSmrg 79935c4bbdfSmrg str++; 80035c4bbdfSmrg pfx = str[0]; 80135c4bbdfSmrg sfx = '\0'; 80235c4bbdfSmrg if ((pfx == '+') || (pfx == '|') || (pfx == '_') || (pfx == '-')) { 80335c4bbdfSmrg str++; 80405b261ecSmrg } 80535c4bbdfSmrg else if (pfx == '(') { 80635c4bbdfSmrg sfx = ')'; 80735c4bbdfSmrg str++; 80835c4bbdfSmrg } 80935c4bbdfSmrg else 81035c4bbdfSmrg pfx = '\0'; 81135c4bbdfSmrg 81235c4bbdfSmrg var = str; 81335c4bbdfSmrg str = get_index(var + 1, &ndx); 81435c4bbdfSmrg if (ndx == -1) { 81535c4bbdfSmrg continue; 81635c4bbdfSmrg } 81735c4bbdfSmrg if ((*var == 'l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) { 81835c4bbdfSmrg if (pfx) 81935c4bbdfSmrg *outstr++ = pfx; 82035c4bbdfSmrg strcpy(outstr, mdefs->layout[ndx]); 82135c4bbdfSmrg outstr += strlen(mdefs->layout[ndx]); 82235c4bbdfSmrg if (sfx) 82335c4bbdfSmrg *outstr++ = sfx; 82435c4bbdfSmrg } 82535c4bbdfSmrg else if ((*var == 'm') && (mdefs->model)) { 82635c4bbdfSmrg if (pfx) 82735c4bbdfSmrg *outstr++ = pfx; 82835c4bbdfSmrg strcpy(outstr, mdefs->model); 82935c4bbdfSmrg outstr += strlen(mdefs->model); 83035c4bbdfSmrg if (sfx) 83135c4bbdfSmrg *outstr++ = sfx; 83235c4bbdfSmrg } 83335c4bbdfSmrg else if ((*var == 'v') && mdefs->variant[ndx] && 83435c4bbdfSmrg *mdefs->variant[ndx]) { 83535c4bbdfSmrg if (pfx) 83635c4bbdfSmrg *outstr++ = pfx; 83735c4bbdfSmrg strcpy(outstr, mdefs->variant[ndx]); 83835c4bbdfSmrg outstr += strlen(mdefs->variant[ndx]); 83935c4bbdfSmrg if (sfx) 84035c4bbdfSmrg *outstr++ = sfx; 84135c4bbdfSmrg } 84235c4bbdfSmrg if ((pfx == '(') && (*str == ')')) 84335c4bbdfSmrg str++; 84435c4bbdfSmrg } 84535c4bbdfSmrg else { 84635c4bbdfSmrg *outstr++ = *str++; 84735c4bbdfSmrg } 84835c4bbdfSmrg } 84935c4bbdfSmrg *outstr++ = '\0'; 85035c4bbdfSmrg if (orig != name) 85135c4bbdfSmrg free(orig); 85205b261ecSmrg return name; 85305b261ecSmrg} 85405b261ecSmrg 85505b261ecSmrg/***====================================================================***/ 85605b261ecSmrg 85705b261ecSmrgBool 85835c4bbdfSmrgXkbRF_GetComponents(XkbRF_RulesPtr rules, 85935c4bbdfSmrg XkbRF_VarDefsPtr defs, XkbComponentNamesPtr names) 86005b261ecSmrg{ 86105b261ecSmrg XkbRF_MultiDefsRec mdefs; 86205b261ecSmrg 86305b261ecSmrg MakeMultiDefs(&mdefs, defs); 86405b261ecSmrg 86535c4bbdfSmrg memset((char *) names, 0, 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); 87235c4bbdfSmrg XkbRF_ApplyPartialMatches(rules, names); 87305b261ecSmrg 87405b261ecSmrg if (names->keycodes) 87535c4bbdfSmrg names->keycodes = XkbRF_SubstituteVars(names->keycodes, &mdefs); 87635c4bbdfSmrg if (names->symbols) 87735c4bbdfSmrg names->symbols = XkbRF_SubstituteVars(names->symbols, &mdefs); 87805b261ecSmrg if (names->types) 87935c4bbdfSmrg names->types = XkbRF_SubstituteVars(names->types, &mdefs); 88005b261ecSmrg if (names->compat) 88135c4bbdfSmrg names->compat = XkbRF_SubstituteVars(names->compat, &mdefs); 88205b261ecSmrg if (names->geometry) 88335c4bbdfSmrg names->geometry = XkbRF_SubstituteVars(names->geometry, &mdefs); 88405b261ecSmrg 88505b261ecSmrg FreeMultiDefs(&mdefs); 88605b261ecSmrg return (names->keycodes && names->symbols && names->types && 88735c4bbdfSmrg names->compat && names->geometry); 88805b261ecSmrg} 88905b261ecSmrg 8906747b715Smrgstatic XkbRF_RulePtr 89135c4bbdfSmrgXkbRF_AddRule(XkbRF_RulesPtr rules) 89205b261ecSmrg{ 89335c4bbdfSmrg if (rules->sz_rules < 1) { 89435c4bbdfSmrg rules->sz_rules = 16; 89535c4bbdfSmrg rules->num_rules = 0; 89635c4bbdfSmrg rules->rules = calloc(rules->sz_rules, sizeof(XkbRF_RuleRec)); 89705b261ecSmrg } 89835c4bbdfSmrg else if (rules->num_rules >= rules->sz_rules) { 89935c4bbdfSmrg rules->sz_rules *= 2; 90035c4bbdfSmrg rules->rules = reallocarray(rules->rules, 90135c4bbdfSmrg rules->sz_rules, sizeof(XkbRF_RuleRec)); 90205b261ecSmrg } 90305b261ecSmrg if (!rules->rules) { 90435c4bbdfSmrg rules->sz_rules = rules->num_rules = 0; 90535c4bbdfSmrg DebugF("Allocation failure in XkbRF_AddRule\n"); 90635c4bbdfSmrg return NULL; 90705b261ecSmrg } 90835c4bbdfSmrg memset((char *) &rules->rules[rules->num_rules], 0, sizeof(XkbRF_RuleRec)); 90905b261ecSmrg return &rules->rules[rules->num_rules++]; 91005b261ecSmrg} 91105b261ecSmrg 9126747b715Smrgstatic XkbRF_GroupPtr 91335c4bbdfSmrgXkbRF_AddGroup(XkbRF_RulesPtr rules) 91405b261ecSmrg{ 91535c4bbdfSmrg if (rules->sz_groups < 1) { 91635c4bbdfSmrg rules->sz_groups = 16; 91735c4bbdfSmrg rules->num_groups = 0; 91835c4bbdfSmrg rules->groups = calloc(rules->sz_groups, sizeof(XkbRF_GroupRec)); 91905b261ecSmrg } 92005b261ecSmrg else if (rules->num_groups >= rules->sz_groups) { 92135c4bbdfSmrg rules->sz_groups *= 2; 92235c4bbdfSmrg rules->groups = reallocarray(rules->groups, 92335c4bbdfSmrg rules->sz_groups, sizeof(XkbRF_GroupRec)); 92405b261ecSmrg } 92505b261ecSmrg if (!rules->groups) { 92635c4bbdfSmrg rules->sz_groups = rules->num_groups = 0; 92735c4bbdfSmrg return NULL; 92805b261ecSmrg } 92905b261ecSmrg 93035c4bbdfSmrg memset((char *) &rules->groups[rules->num_groups], 0, 93135c4bbdfSmrg sizeof(XkbRF_GroupRec)); 93205b261ecSmrg return &rules->groups[rules->num_groups++]; 93305b261ecSmrg} 93405b261ecSmrg 93505b261ecSmrgBool 93635c4bbdfSmrgXkbRF_LoadRules(FILE * file, XkbRF_RulesPtr rules) 93705b261ecSmrg{ 93835c4bbdfSmrg InputLine line; 93935c4bbdfSmrg RemapSpec remap; 94035c4bbdfSmrg XkbRF_RuleRec trule, *rule; 94135c4bbdfSmrg XkbRF_GroupRec tgroup, *group; 94205b261ecSmrg 94305b261ecSmrg if (!(rules && file)) 94435c4bbdfSmrg return FALSE; 94535c4bbdfSmrg memset((char *) &remap, 0, sizeof(RemapSpec)); 94635c4bbdfSmrg memset((char *) &tgroup, 0, sizeof(XkbRF_GroupRec)); 94705b261ecSmrg InitInputLine(&line); 94835c4bbdfSmrg while (GetInputLine(file, &line, TRUE)) { 94935c4bbdfSmrg if (CheckLine(&line, &remap, &trule, &tgroup)) { 95005b261ecSmrg if (tgroup.number) { 95135c4bbdfSmrg if ((group = XkbRF_AddGroup(rules)) != NULL) { 95235c4bbdfSmrg *group = tgroup; 95335c4bbdfSmrg memset((char *) &tgroup, 0, sizeof(XkbRF_GroupRec)); 95435c4bbdfSmrg } 95535c4bbdfSmrg } 95635c4bbdfSmrg else { 95735c4bbdfSmrg if ((rule = XkbRF_AddRule(rules)) != NULL) { 95835c4bbdfSmrg *rule = trule; 95935c4bbdfSmrg memset((char *) &trule, 0, sizeof(XkbRF_RuleRec)); 96035c4bbdfSmrg } 96135c4bbdfSmrg } 96235c4bbdfSmrg } 96335c4bbdfSmrg line.num_line = 0; 96405b261ecSmrg } 96505b261ecSmrg FreeInputLine(&line); 9666747b715Smrg return TRUE; 96705b261ecSmrg} 96805b261ecSmrg 96905b261ecSmrgBool 97035c4bbdfSmrgXkbRF_LoadRulesByName(char *base, char *locale, XkbRF_RulesPtr rules) 97105b261ecSmrg{ 97235c4bbdfSmrg FILE *file; 97335c4bbdfSmrg char buf[PATH_MAX]; 97435c4bbdfSmrg Bool ok; 97505b261ecSmrg 97635c4bbdfSmrg if ((!base) || (!rules)) 97735c4bbdfSmrg return FALSE; 97805b261ecSmrg if (locale) { 97935c4bbdfSmrg if (snprintf(buf, PATH_MAX, "%s-%s", base, locale) >= PATH_MAX) 98035c4bbdfSmrg return FALSE; 98105b261ecSmrg } 98205b261ecSmrg else { 98335c4bbdfSmrg if (strlen(base) + 1 > PATH_MAX) 98435c4bbdfSmrg return FALSE; 98535c4bbdfSmrg strcpy(buf, base); 98605b261ecSmrg } 98705b261ecSmrg 98835c4bbdfSmrg file = fopen(buf, "r"); 98935c4bbdfSmrg if ((!file) && (locale)) { /* fallback if locale was specified */ 99035c4bbdfSmrg strcpy(buf, base); 99135c4bbdfSmrg file = fopen(buf, "r"); 99205b261ecSmrg } 99305b261ecSmrg if (!file) 99435c4bbdfSmrg return FALSE; 99535c4bbdfSmrg ok = XkbRF_LoadRules(file, rules); 99605b261ecSmrg fclose(file); 99705b261ecSmrg return ok; 99805b261ecSmrg} 99905b261ecSmrg 100005b261ecSmrg/***====================================================================***/ 100105b261ecSmrg 100205b261ecSmrgXkbRF_RulesPtr 10036747b715SmrgXkbRF_Create(void) 100405b261ecSmrg{ 100535c4bbdfSmrg return calloc(1, sizeof(XkbRF_RulesRec)); 100605b261ecSmrg} 100705b261ecSmrg 100805b261ecSmrg/***====================================================================***/ 100905b261ecSmrg 101005b261ecSmrgvoid 101135c4bbdfSmrgXkbRF_Free(XkbRF_RulesPtr rules, Bool freeRules) 101205b261ecSmrg{ 101335c4bbdfSmrg int i; 101435c4bbdfSmrg XkbRF_RulePtr rule; 101535c4bbdfSmrg XkbRF_GroupPtr group; 101605b261ecSmrg 101705b261ecSmrg if (!rules) 101835c4bbdfSmrg return; 101905b261ecSmrg if (rules->rules) { 102035c4bbdfSmrg for (i = 0, rule = rules->rules; i < rules->num_rules; i++, rule++) { 102135c4bbdfSmrg free((void *) rule->model); 102235c4bbdfSmrg free((void *) rule->layout); 102335c4bbdfSmrg free((void *) rule->variant); 102435c4bbdfSmrg free((void *) rule->option); 102535c4bbdfSmrg free((void *) rule->keycodes); 102635c4bbdfSmrg free((void *) rule->symbols); 102735c4bbdfSmrg free((void *) rule->types); 102835c4bbdfSmrg free((void *) rule->compat); 102935c4bbdfSmrg free((void *) rule->geometry); 103035c4bbdfSmrg memset((char *) rule, 0, sizeof(XkbRF_RuleRec)); 103135c4bbdfSmrg } 103235c4bbdfSmrg free(rules->rules); 103335c4bbdfSmrg rules->num_rules = rules->sz_rules = 0; 103435c4bbdfSmrg rules->rules = NULL; 103505b261ecSmrg } 103605b261ecSmrg 103705b261ecSmrg if (rules->groups) { 103835c4bbdfSmrg for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { 103935c4bbdfSmrg free((void *) group->name); 104035c4bbdfSmrg free(group->words); 104135c4bbdfSmrg } 104235c4bbdfSmrg free(rules->groups); 104335c4bbdfSmrg rules->num_groups = 0; 104435c4bbdfSmrg rules->groups = NULL; 104505b261ecSmrg } 104605b261ecSmrg if (freeRules) 104735c4bbdfSmrg free(rules); 104805b261ecSmrg return; 104905b261ecSmrg} 1050