1706f2543Smrg/************************************************************ 2706f2543SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3706f2543Smrg 4706f2543SmrgPermission to use, copy, modify, and distribute this 5706f2543Smrgsoftware and its documentation for any purpose and without 6706f2543Smrgfee is hereby granted, provided that the above copyright 7706f2543Smrgnotice appear in all copies and that both that copyright 8706f2543Smrgnotice and this permission notice appear in supporting 9706f2543Smrgdocumentation, and that the name of Silicon Graphics not be 10706f2543Smrgused in advertising or publicity pertaining to distribution 11706f2543Smrgof the software without specific prior written permission. 12706f2543SmrgSilicon Graphics makes no representation about the suitability 13706f2543Smrgof this software for any purpose. It is provided "as is" 14706f2543Smrgwithout any express or implied warranty. 15706f2543Smrg 16706f2543SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18706f2543SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19706f2543SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20706f2543SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21706f2543SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23706f2543SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 24706f2543Smrg 25706f2543Smrg********************************************************/ 26706f2543Smrg 27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 28706f2543Smrg#include <dix-config.h> 29706f2543Smrg#endif 30706f2543Smrg 31706f2543Smrg#include <xkb-config.h> 32706f2543Smrg 33706f2543Smrg#include <stdio.h> 34706f2543Smrg#include <ctype.h> 35706f2543Smrg#include <X11/X.h> 36706f2543Smrg#include <X11/Xos.h> 37706f2543Smrg#include <X11/Xproto.h> 38706f2543Smrg#include <X11/keysym.h> 39706f2543Smrg#include <X11/extensions/XKM.h> 40706f2543Smrg#include "inputstr.h" 41706f2543Smrg#include "scrnintstr.h" 42706f2543Smrg#include "windowstr.h" 43706f2543Smrg#define XKBSRV_NEED_FILE_FUNCS 44706f2543Smrg#include <xkbsrv.h> 45706f2543Smrg#include <X11/extensions/XI.h> 46706f2543Smrg#include "xkb.h" 47706f2543Smrg 48706f2543Smrg /* 49706f2543Smrg * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is 50706f2543Smrg * relative to the top-level XKB configuration directory. 51706f2543Smrg * Making the server write to a subdirectory of that directory 52706f2543Smrg * requires some work in the general case (install procedure 53706f2543Smrg * has to create links to /var or somesuch on many machines), 54706f2543Smrg * so we just compile into /usr/tmp for now. 55706f2543Smrg */ 56706f2543Smrg#ifndef XKM_OUTPUT_DIR 57706f2543Smrg#define XKM_OUTPUT_DIR "compiled/" 58706f2543Smrg#endif 59706f2543Smrg 60706f2543Smrg#define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\"" 61706f2543Smrg#define ERROR_PREFIX "\"> \"" 62706f2543Smrg#define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\"" 63706f2543Smrg#define POST_ERROR_MSG2 "\"End of messages from xkbcomp\"" 64706f2543Smrg 65706f2543Smrg#if defined(WIN32) 66706f2543Smrg#define PATHSEPARATOR "\\" 67706f2543Smrg#else 68706f2543Smrg#define PATHSEPARATOR "/" 69706f2543Smrg#endif 70706f2543Smrg 71706f2543Smrg#ifdef WIN32 72706f2543Smrg 73706f2543Smrg#include <X11/Xwindows.h> 74706f2543Smrgconst char* 75706f2543SmrgWin32TempDir() 76706f2543Smrg{ 77706f2543Smrg static char buffer[PATH_MAX]; 78706f2543Smrg if (GetTempPath(sizeof(buffer), buffer)) 79706f2543Smrg { 80706f2543Smrg int len; 81706f2543Smrg buffer[sizeof(buffer)-1] = 0; 82706f2543Smrg len = strlen(buffer); 83706f2543Smrg if (len > 0) 84706f2543Smrg if (buffer[len-1] == '\\') 85706f2543Smrg buffer[len-1] = 0; 86706f2543Smrg return buffer; 87706f2543Smrg } 88706f2543Smrg if (getenv("TEMP") != NULL) 89706f2543Smrg return getenv("TEMP"); 90706f2543Smrg else if (getenv("TMP") != NULL) 91706f2543Smrg return getenv("TEMP"); 92706f2543Smrg else 93706f2543Smrg return "/tmp"; 94706f2543Smrg} 95706f2543Smrg 96706f2543Smrgint 97706f2543SmrgWin32System(const char *cmdline) 98706f2543Smrg{ 99706f2543Smrg STARTUPINFO si; 100706f2543Smrg PROCESS_INFORMATION pi; 101706f2543Smrg DWORD dwExitCode; 102706f2543Smrg char *cmd = strdup(cmdline); 103706f2543Smrg 104706f2543Smrg ZeroMemory( &si, sizeof(si) ); 105706f2543Smrg si.cb = sizeof(si); 106706f2543Smrg ZeroMemory( &pi, sizeof(pi) ); 107706f2543Smrg 108706f2543Smrg if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) 109706f2543Smrg { 110706f2543Smrg LPVOID buffer; 111706f2543Smrg if (!FormatMessage( 112706f2543Smrg FORMAT_MESSAGE_ALLOCATE_BUFFER | 113706f2543Smrg FORMAT_MESSAGE_FROM_SYSTEM | 114706f2543Smrg FORMAT_MESSAGE_IGNORE_INSERTS, 115706f2543Smrg NULL, 116706f2543Smrg GetLastError(), 117706f2543Smrg MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 118706f2543Smrg (LPTSTR) &buffer, 119706f2543Smrg 0, 120706f2543Smrg NULL )) 121706f2543Smrg { 122706f2543Smrg ErrorF("[xkb] Starting '%s' failed!\n", cmdline); 123706f2543Smrg } 124706f2543Smrg else 125706f2543Smrg { 126706f2543Smrg ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *)buffer); 127706f2543Smrg LocalFree(buffer); 128706f2543Smrg } 129706f2543Smrg 130706f2543Smrg free(cmd); 131706f2543Smrg return -1; 132706f2543Smrg } 133706f2543Smrg /* Wait until child process exits. */ 134706f2543Smrg WaitForSingleObject( pi.hProcess, INFINITE ); 135706f2543Smrg 136706f2543Smrg GetExitCodeProcess( pi.hProcess, &dwExitCode); 137706f2543Smrg 138706f2543Smrg /* Close process and thread handles. */ 139706f2543Smrg CloseHandle( pi.hProcess ); 140706f2543Smrg CloseHandle( pi.hThread ); 141706f2543Smrg free(cmd); 142706f2543Smrg 143706f2543Smrg return dwExitCode; 144706f2543Smrg} 145706f2543Smrg#undef System 146706f2543Smrg#define System(x) Win32System(x) 147706f2543Smrg#endif 148706f2543Smrg 149706f2543Smrgstatic void 150706f2543SmrgOutputDirectory( 151706f2543Smrg char* outdir, 152706f2543Smrg size_t size) 153706f2543Smrg{ 154706f2543Smrg#ifndef WIN32 155706f2543Smrg /* Can we write an xkm and then open it too? */ 156706f2543Smrg if (access(XKM_OUTPUT_DIR, W_OK | X_OK) == 0 && (strlen(XKM_OUTPUT_DIR) < size)) 157706f2543Smrg { 158706f2543Smrg (void) strcpy (outdir, XKM_OUTPUT_DIR); 159706f2543Smrg } else 160706f2543Smrg#else 161706f2543Smrg if (strlen(Win32TempDir()) + 1 < size) 162706f2543Smrg { 163706f2543Smrg (void) strcpy(outdir, Win32TempDir()); 164706f2543Smrg (void) strcat(outdir, "\\"); 165706f2543Smrg } else 166706f2543Smrg#endif 167706f2543Smrg if (strlen("/tmp/") < size) 168706f2543Smrg { 169706f2543Smrg (void) strcpy (outdir, "/tmp/"); 170706f2543Smrg } 171706f2543Smrg} 172706f2543Smrg 173706f2543Smrgstatic Bool 174706f2543SmrgXkbDDXCompileKeymapByNames( XkbDescPtr xkb, 175706f2543Smrg XkbComponentNamesPtr names, 176706f2543Smrg unsigned want, 177706f2543Smrg unsigned need, 178706f2543Smrg char * nameRtrn, 179706f2543Smrg int nameRtrnLen) 180706f2543Smrg{ 181706f2543Smrg FILE * out; 182706f2543Smrg char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX]; 183706f2543Smrg 184706f2543Smrg const char *emptystring = ""; 185706f2543Smrg char *xkbbasedirflag = NULL; 186706f2543Smrg const char *xkbbindir = emptystring; 187706f2543Smrg const char *xkbbindirsep = emptystring; 188706f2543Smrg 189706f2543Smrg#ifdef WIN32 190706f2543Smrg /* WIN32 has no popen. The input must be stored in a file which is 191706f2543Smrg used as input for xkbcomp. xkbcomp does not read from stdin. */ 192706f2543Smrg char tmpname[PATH_MAX]; 193706f2543Smrg const char *xkmfile = tmpname; 194706f2543Smrg#else 195706f2543Smrg const char *xkmfile = "-"; 196706f2543Smrg#endif 197706f2543Smrg 198706f2543Smrg snprintf(keymap, sizeof(keymap), "server-%s", display); 199706f2543Smrg 200706f2543Smrg OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); 201706f2543Smrg 202706f2543Smrg#ifdef WIN32 203706f2543Smrg strcpy(tmpname, Win32TempDir()); 204706f2543Smrg strcat(tmpname, "\\xkb_XXXXXX"); 205706f2543Smrg (void) mktemp(tmpname); 206706f2543Smrg#endif 207706f2543Smrg 208706f2543Smrg if (XkbBaseDirectory != NULL) { 209706f2543Smrg if (asprintf(&xkbbasedirflag, "\"-R%s\"", XkbBaseDirectory) == -1) 210706f2543Smrg xkbbasedirflag = NULL; 211706f2543Smrg } 212706f2543Smrg 213706f2543Smrg if (XkbBinDirectory != NULL) { 214706f2543Smrg int ld = strlen(XkbBinDirectory); 215706f2543Smrg int lps = strlen(PATHSEPARATOR); 216706f2543Smrg 217706f2543Smrg xkbbindir = XkbBinDirectory; 218706f2543Smrg 219706f2543Smrg if ((ld >= lps) && 220706f2543Smrg (strcmp(xkbbindir + ld - lps, PATHSEPARATOR) != 0)) { 221706f2543Smrg xkbbindirsep = PATHSEPARATOR; 222706f2543Smrg } 223706f2543Smrg } 224706f2543Smrg 225706f2543Smrg if (asprintf(&buf, 226706f2543Smrg "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" " 227706f2543Smrg "-em1 %s -emp %s -eml %s \"%s%s.xkm\"", 228706f2543Smrg xkbbindir, xkbbindirsep, 229706f2543Smrg ((xkbDebugFlags < 2) ? 1 : 230706f2543Smrg ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)), 231706f2543Smrg xkbbasedirflag ? xkbbasedirflag : "", xkmfile, 232706f2543Smrg PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1, 233706f2543Smrg xkm_output_dir, keymap) == -1) 234706f2543Smrg buf = NULL; 235706f2543Smrg 236706f2543Smrg free(xkbbasedirflag); 237706f2543Smrg 238706f2543Smrg if (!buf) { 239706f2543Smrg LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp: not enough memory\n"); 240706f2543Smrg return FALSE; 241706f2543Smrg } 242706f2543Smrg 243706f2543Smrg#ifndef WIN32 244706f2543Smrg out= Popen(buf,"w"); 245706f2543Smrg#else 246706f2543Smrg out= fopen(tmpname, "w"); 247706f2543Smrg#endif 248706f2543Smrg 249706f2543Smrg if (out!=NULL) { 250706f2543Smrg#ifdef DEBUG 251706f2543Smrg if (xkbDebugFlags) { 252706f2543Smrg ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n"); 253706f2543Smrg XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need); 254706f2543Smrg } 255706f2543Smrg#endif 256706f2543Smrg XkbWriteXKBKeymapForNames(out,names,xkb,want,need); 257706f2543Smrg#ifndef WIN32 258706f2543Smrg if (Pclose(out)==0) 259706f2543Smrg#else 260706f2543Smrg if (fclose(out)==0 && System(buf) >= 0) 261706f2543Smrg#endif 262706f2543Smrg { 263706f2543Smrg if (xkbDebugFlags) 264706f2543Smrg DebugF("[xkb] xkb executes: %s\n",buf); 265706f2543Smrg if (nameRtrn) { 266706f2543Smrg strncpy(nameRtrn,keymap,nameRtrnLen); 267706f2543Smrg nameRtrn[nameRtrnLen-1]= '\0'; 268706f2543Smrg } 269706f2543Smrg free(buf); 270706f2543Smrg return TRUE; 271706f2543Smrg } 272706f2543Smrg else 273706f2543Smrg LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap); 274706f2543Smrg#ifdef WIN32 275706f2543Smrg /* remove the temporary file */ 276706f2543Smrg unlink(tmpname); 277706f2543Smrg#endif 278706f2543Smrg } 279706f2543Smrg else { 280706f2543Smrg#ifndef WIN32 281706f2543Smrg LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n"); 282706f2543Smrg#else 283706f2543Smrg LogMessage(X_ERROR, "Could not open file %s\n", tmpname); 284706f2543Smrg#endif 285706f2543Smrg } 286706f2543Smrg if (nameRtrn) 287706f2543Smrg nameRtrn[0]= '\0'; 288706f2543Smrg free(buf); 289706f2543Smrg return FALSE; 290706f2543Smrg} 291706f2543Smrg 292706f2543Smrgstatic FILE * 293706f2543SmrgXkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen) 294706f2543Smrg{ 295706f2543Smrgchar buf[PATH_MAX],xkm_output_dir[PATH_MAX]; 296706f2543SmrgFILE * file; 297706f2543Smrg 298706f2543Smrg buf[0]= '\0'; 299706f2543Smrg if (mapName!=NULL) { 300706f2543Smrg OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); 301706f2543Smrg if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/') 302706f2543Smrg#ifdef WIN32 303706f2543Smrg &&(!isalpha(xkm_output_dir[0]) || xkm_output_dir[1]!=':') 304706f2543Smrg#endif 305706f2543Smrg ) { 306706f2543Smrg if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir) 307706f2543Smrg +strlen(mapName)+6 <= PATH_MAX) 308706f2543Smrg { 309706f2543Smrg sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory, 310706f2543Smrg xkm_output_dir,mapName); 311706f2543Smrg } 312706f2543Smrg } 313706f2543Smrg else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX) 314706f2543Smrg sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName); 315706f2543Smrg if (buf[0] != '\0') 316706f2543Smrg file= fopen(buf,"rb"); 317706f2543Smrg else file= NULL; 318706f2543Smrg } 319706f2543Smrg else file= NULL; 320706f2543Smrg if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) { 321706f2543Smrg strncpy(fileNameRtrn,buf,fileNameRtrnLen); 322706f2543Smrg buf[fileNameRtrnLen-1]= '\0'; 323706f2543Smrg } 324706f2543Smrg return file; 325706f2543Smrg} 326706f2543Smrg 327706f2543Smrgunsigned 328706f2543SmrgXkbDDXLoadKeymapByNames( DeviceIntPtr keybd, 329706f2543Smrg XkbComponentNamesPtr names, 330706f2543Smrg unsigned want, 331706f2543Smrg unsigned need, 332706f2543Smrg XkbDescPtr * xkbRtrn, 333706f2543Smrg char * nameRtrn, 334706f2543Smrg int nameRtrnLen) 335706f2543Smrg{ 336706f2543SmrgXkbDescPtr xkb; 337706f2543SmrgFILE * file; 338706f2543Smrgchar fileName[PATH_MAX]; 339706f2543Smrgunsigned missing; 340706f2543Smrg 341706f2543Smrg *xkbRtrn = NULL; 342706f2543Smrg if ((keybd==NULL)||(keybd->key==NULL)||(keybd->key->xkbInfo==NULL)) 343706f2543Smrg xkb= NULL; 344706f2543Smrg else xkb= keybd->key->xkbInfo->desc; 345706f2543Smrg if ((names->keycodes==NULL)&&(names->types==NULL)&& 346706f2543Smrg (names->compat==NULL)&&(names->symbols==NULL)&& 347706f2543Smrg (names->geometry==NULL)) { 348706f2543Smrg LogMessage(X_ERROR, "XKB: No components provided for device %s\n", 349706f2543Smrg keybd->name ? keybd->name : "(unnamed keyboard)"); 350706f2543Smrg return 0; 351706f2543Smrg } 352706f2543Smrg else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need, 353706f2543Smrg nameRtrn,nameRtrnLen)){ 354706f2543Smrg LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n"); 355706f2543Smrg return 0; 356706f2543Smrg } 357706f2543Smrg file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX); 358706f2543Smrg if (file==NULL) { 359706f2543Smrg LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",fileName); 360706f2543Smrg return 0; 361706f2543Smrg } 362706f2543Smrg missing= XkmReadFile(file,need,want,xkbRtrn); 363706f2543Smrg if (*xkbRtrn==NULL) { 364706f2543Smrg LogMessage(X_ERROR, "Error loading keymap %s\n",fileName); 365706f2543Smrg fclose(file); 366706f2543Smrg (void) unlink (fileName); 367706f2543Smrg return 0; 368706f2543Smrg } 369706f2543Smrg else { 370706f2543Smrg DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined); 371706f2543Smrg } 372706f2543Smrg fclose(file); 373706f2543Smrg (void) unlink (fileName); 374706f2543Smrg return (need|want)&(~missing); 375706f2543Smrg} 376706f2543Smrg 377706f2543SmrgBool 378706f2543SmrgXkbDDXNamesFromRules( DeviceIntPtr keybd, 379706f2543Smrg char * rules_name, 380706f2543Smrg XkbRF_VarDefsPtr defs, 381706f2543Smrg XkbComponentNamesPtr names) 382706f2543Smrg{ 383706f2543Smrgchar buf[PATH_MAX]; 384706f2543SmrgFILE * file; 385706f2543SmrgBool complete; 386706f2543SmrgXkbRF_RulesPtr rules; 387706f2543Smrg 388706f2543Smrg if (!rules_name) 389706f2543Smrg return FALSE; 390706f2543Smrg 391706f2543Smrg if (strlen(XkbBaseDirectory) + strlen(rules_name) + 8 > PATH_MAX) { 392706f2543Smrg LogMessage(X_ERROR, "XKB: Rules name is too long\n"); 393706f2543Smrg return FALSE; 394706f2543Smrg } 395706f2543Smrg sprintf(buf,"%s/rules/%s", XkbBaseDirectory, rules_name); 396706f2543Smrg 397706f2543Smrg file = fopen(buf, "r"); 398706f2543Smrg if (!file) { 399706f2543Smrg LogMessage(X_ERROR, "XKB: Couldn't open rules file %s\n", buf); 400706f2543Smrg return FALSE; 401706f2543Smrg } 402706f2543Smrg 403706f2543Smrg rules = XkbRF_Create(); 404706f2543Smrg if (!rules) { 405706f2543Smrg LogMessage(X_ERROR, "XKB: Couldn't create rules struct\n"); 406706f2543Smrg fclose(file); 407706f2543Smrg return FALSE; 408706f2543Smrg } 409706f2543Smrg 410706f2543Smrg if (!XkbRF_LoadRules(file, rules)) { 411706f2543Smrg LogMessage(X_ERROR, "XKB: Couldn't parse rules file %s\n", rules_name); 412706f2543Smrg fclose(file); 413706f2543Smrg XkbRF_Free(rules,TRUE); 414706f2543Smrg return FALSE; 415706f2543Smrg } 416706f2543Smrg 417706f2543Smrg memset(names, 0, sizeof(*names)); 418706f2543Smrg complete = XkbRF_GetComponents(rules,defs,names); 419706f2543Smrg fclose(file); 420706f2543Smrg XkbRF_Free(rules, TRUE); 421706f2543Smrg 422706f2543Smrg if (!complete) 423706f2543Smrg LogMessage(X_ERROR, "XKB: Rules returned no components\n"); 424706f2543Smrg 425706f2543Smrg return complete; 426706f2543Smrg} 427706f2543Smrg 428706f2543Smrgstatic Bool 429706f2543SmrgXkbRMLVOtoKcCGST(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, XkbComponentNamesPtr kccgst) 430706f2543Smrg{ 431706f2543Smrg XkbRF_VarDefsRec mlvo; 432706f2543Smrg 433706f2543Smrg mlvo.model = rmlvo->model; 434706f2543Smrg mlvo.layout = rmlvo->layout; 435706f2543Smrg mlvo.variant = rmlvo->variant; 436706f2543Smrg mlvo.options = rmlvo->options; 437706f2543Smrg 438706f2543Smrg return XkbDDXNamesFromRules(dev, rmlvo->rules, &mlvo, kccgst); 439706f2543Smrg} 440706f2543Smrg 441706f2543Smrg/** 442706f2543Smrg * Compile the given RMLVO keymap and return it. Returns the XkbDescPtr on 443706f2543Smrg * success or NULL on failure. If the components compiled are not a superset 444706f2543Smrg * or equal to need, the compiliation is treated as failure. 445706f2543Smrg */ 446706f2543Smrgstatic XkbDescPtr 447706f2543SmrgXkbCompileKeymapForDevice(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, int need) 448706f2543Smrg{ 449706f2543Smrg XkbDescPtr xkb = NULL; 450706f2543Smrg unsigned int provided; 451706f2543Smrg XkbComponentNamesRec kccgst = {0}; 452706f2543Smrg char name[PATH_MAX]; 453706f2543Smrg 454706f2543Smrg if (XkbRMLVOtoKcCGST(dev, rmlvo, &kccgst)) { 455706f2543Smrg provided = XkbDDXLoadKeymapByNames(dev, &kccgst, XkmAllIndicesMask, need, 456706f2543Smrg &xkb, name, PATH_MAX); 457706f2543Smrg if ((need & provided) != need) { 458706f2543Smrg if (xkb) { 459706f2543Smrg XkbFreeKeyboard(xkb, 0, TRUE); 460706f2543Smrg xkb = NULL; 461706f2543Smrg } 462706f2543Smrg } 463706f2543Smrg } 464706f2543Smrg 465706f2543Smrg XkbFreeComponentNames(&kccgst, FALSE); 466706f2543Smrg return xkb; 467706f2543Smrg} 468706f2543Smrg 469706f2543SmrgXkbDescPtr 470706f2543SmrgXkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet *rmlvo) 471706f2543Smrg{ 472706f2543Smrg XkbDescPtr xkb; 473706f2543Smrg unsigned int need; 474706f2543Smrg 475706f2543Smrg if (!dev || !rmlvo) { 476706f2543Smrg LogMessage(X_ERROR, "XKB: No device or RMLVO specified\n"); 477706f2543Smrg return NULL; 478706f2543Smrg } 479706f2543Smrg 480706f2543Smrg /* These are the components we really really need */ 481706f2543Smrg need = XkmSymbolsMask | XkmCompatMapMask | XkmTypesMask | 482706f2543Smrg XkmKeyNamesMask | XkmVirtualModsMask; 483706f2543Smrg 484706f2543Smrg 485706f2543Smrg xkb = XkbCompileKeymapForDevice(dev, rmlvo, need); 486706f2543Smrg 487706f2543Smrg if (!xkb) { 488706f2543Smrg XkbRMLVOSet dflts; 489706f2543Smrg 490706f2543Smrg /* we didn't get what we really needed. And that will likely leave 491706f2543Smrg * us with a keyboard that doesn't work. Use the defaults instead */ 492706f2543Smrg LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default " 493706f2543Smrg "keymap instead.\n"); 494706f2543Smrg 495706f2543Smrg XkbGetRulesDflts(&dflts); 496706f2543Smrg 497706f2543Smrg xkb = XkbCompileKeymapForDevice(dev, &dflts, 0); 498706f2543Smrg 499706f2543Smrg XkbFreeRMLVOSet(&dflts, FALSE); 500706f2543Smrg } 501706f2543Smrg 502706f2543Smrg return xkb; 503706f2543Smrg} 504