From 8a191c08ddda2e66fa26f148d6c21959bb08f923 Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 20 Feb 2011 12:29:25 +0000 Subject: xserver xkeyboard-config libX11 pixman mesa git update 2011 --- xorg-server/xkb/ddxLoad.c | 962 ++-- xorg-server/xkb/xkb.c | 13480 ++++++++++++++++++++++---------------------- 2 files changed, 7243 insertions(+), 7199 deletions(-) (limited to 'xorg-server/xkb') diff --git a/xorg-server/xkb/ddxLoad.c b/xorg-server/xkb/ddxLoad.c index 51b577725..be946d89e 100644 --- a/xorg-server/xkb/ddxLoad.c +++ b/xorg-server/xkb/ddxLoad.c @@ -1,459 +1,503 @@ -/************************************************************ -Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. - -Permission to use, copy, modify, and distribute this -software and its documentation for any purpose and without -fee is hereby granted, provided that the above copyright -notice appear in all copies and that both that copyright -notice and this permission notice appear in supporting -documentation, and that the name of Silicon Graphics not be -used in advertising or publicity pertaining to distribution -of the software without specific prior written permission. -Silicon Graphics makes no representation about the suitability -of this software for any purpose. It is provided "as is" -without any express or implied warranty. - -SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON -GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH -THE USE OR PERFORMANCE OF THIS SOFTWARE. - -********************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include "inputstr.h" -#include "scrnintstr.h" -#include "windowstr.h" -#define XKBSRV_NEED_FILE_FUNCS -#include -#include -#include "xkb.h" - - /* - * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is - * relative to the top-level XKB configuration directory. - * Making the server write to a subdirectory of that directory - * requires some work in the general case (install procedure - * has to create links to /var or somesuch on many machines), - * so we just compile into /usr/tmp for now. - */ -#ifndef XKM_OUTPUT_DIR -#define XKM_OUTPUT_DIR "compiled/" -#endif - -#define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\"" -#define ERROR_PREFIX "\"> \"" -#define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\"" -#define POST_ERROR_MSG2 "\"End of messages from xkbcomp\"" - -#if defined(WIN32) -#define PATHSEPARATOR "\\" -#else -#define PATHSEPARATOR "/" -#endif - -#ifdef WIN32 - -#include -const char* -Win32TempDir() -{ - static char buffer[PATH_MAX]; - if (GetTempPath(sizeof(buffer), buffer)) - { - int len; - buffer[sizeof(buffer)-1] = 0; - len = strlen(buffer); - if (len > 0) - if (buffer[len-1] == '\\') - buffer[len-1] = 0; - return buffer; - } - if (getenv("TEMP") != NULL) - return getenv("TEMP"); - else if (getenv("TMP") != NULL) - return getenv("TEMP"); - else - return "/tmp"; -} - -int -Win32System(const char *cmdline) -{ - STARTUPINFO si; - PROCESS_INFORMATION pi; - DWORD dwExitCode; - char *cmd = strdup(cmdline); - - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); - ZeroMemory( &pi, sizeof(pi) ); - - if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) - { - LPVOID buffer; - if (!FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &buffer, - 0, - NULL )) - { - ErrorF("[xkb] Starting '%s' failed!\n", cmdline); - } - else - { - ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *)buffer); - LocalFree(buffer); - } - - free(cmd); - return -1; - } - /* Wait until child process exits. */ - WaitForSingleObject( pi.hProcess, INFINITE ); - - GetExitCodeProcess( pi.hProcess, &dwExitCode); - - /* Close process and thread handles. */ - CloseHandle( pi.hProcess ); - CloseHandle( pi.hThread ); - free(cmd); - - return dwExitCode; -} -#undef System -#define System(x) Win32System(x) -#endif - -static void -OutputDirectory( - char* outdir, - size_t size) -{ -#ifndef WIN32 - /* Can we write an xkm and then open it too? */ - if (access(XKM_OUTPUT_DIR, W_OK | X_OK) == 0 && (strlen(XKM_OUTPUT_DIR) < size)) - { - (void) strcpy (outdir, XKM_OUTPUT_DIR); - } else -#else - if (strlen(Win32TempDir()) + 1 < size) - { - (void) strcpy(outdir, Win32TempDir()); - (void) strcat(outdir, "\\"); - } else -#endif - if (strlen("/tmp/") < size) - { - (void) strcpy (outdir, "/tmp/"); - } -} - -static Bool -XkbDDXCompileKeymapByNames( XkbDescPtr xkb, - XkbComponentNamesPtr names, - unsigned want, - unsigned need, - char * nameRtrn, - int nameRtrnLen) -{ - FILE * out; - char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX]; - - const char *emptystring = ""; - char *xkbbasedirflag = NULL; - const char *xkbbindir = emptystring; - const char *xkbbindirsep = emptystring; - -#ifdef WIN32 - /* WIN32 has no popen. The input must be stored in a file which is - used as input for xkbcomp. xkbcomp does not read from stdin. */ - char tmpname[PATH_MAX]; - const char *xkmfile = tmpname; -#else - const char *xkmfile = "-"; -#endif - - snprintf(keymap, sizeof(keymap), "server-%s", display); - - OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); - -#ifdef WIN32 - strcpy(tmpname, Win32TempDir()); - strcat(tmpname, "\\xkb_XXXXXX"); - (void) mktemp(tmpname); -#endif - - if (XkbBaseDirectory != NULL) { - if (asprintf(&xkbbasedirflag, "\"-R%s\"", XkbBaseDirectory) == -1) - xkbbasedirflag = NULL; - } - - if (XkbBinDirectory != NULL) { - int ld = strlen(XkbBinDirectory); - int lps = strlen(PATHSEPARATOR); - - xkbbindir = XkbBinDirectory; - - if ((ld >= lps) && - (strcmp(xkbbindir + ld - lps, PATHSEPARATOR) != 0)) { - xkbbindirsep = PATHSEPARATOR; - } - } - - if (asprintf(&buf, - "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" " - "-em1 %s -emp %s -eml %s \"%s%s.xkm\"", - xkbbindir, xkbbindirsep, - ((xkbDebugFlags < 2) ? 1 : - ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)), - xkbbasedirflag ? xkbbasedirflag : "", xkmfile, - PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1, - xkm_output_dir, keymap) == -1) - buf = NULL; - - free(xkbbasedirflag); - - if (!buf) { - LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp: not enough memory\n"); - return FALSE; - } - -#ifndef WIN32 - out= Popen(buf,"w"); -#else - out= fopen(tmpname, "w"); -#endif - - if (out!=NULL) { -#ifdef DEBUG - if (xkbDebugFlags) { - ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n"); - XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need); - } -#endif - XkbWriteXKBKeymapForNames(out,names,xkb,want,need); -#ifndef WIN32 - if (Pclose(out)==0) -#else - if (fclose(out)==0 && System(buf) >= 0) -#endif - { - if (xkbDebugFlags) - DebugF("[xkb] xkb executes: %s\n",buf); - if (nameRtrn) { - strncpy(nameRtrn,keymap,nameRtrnLen); - nameRtrn[nameRtrnLen-1]= '\0'; - } - free(buf); - return TRUE; - } - else - LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap); -#ifdef WIN32 - /* remove the temporary file */ - unlink(tmpname); -#endif - } - else { -#ifndef WIN32 - LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n"); -#else - LogMessage(X_ERROR, "Could not open file %s\n", tmpname); -#endif - } - if (nameRtrn) - nameRtrn[0]= '\0'; - free(buf); - return FALSE; -} - -static FILE * -XkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen) -{ -char buf[PATH_MAX],xkm_output_dir[PATH_MAX]; -FILE * file; - - buf[0]= '\0'; - if (mapName!=NULL) { - OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); - if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/') -#ifdef WIN32 - &&(!isalpha(xkm_output_dir[0]) || xkm_output_dir[1]!=':') -#endif - ) { - if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir) - +strlen(mapName)+6 <= PATH_MAX) - { - sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory, - xkm_output_dir,mapName); - } - } - else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX) - sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName); - if (buf[0] != '\0') - file= fopen(buf,"rb"); - else file= NULL; - } - else file= NULL; - if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) { - strncpy(fileNameRtrn,buf,fileNameRtrnLen); - buf[fileNameRtrnLen-1]= '\0'; - } - return file; -} - -unsigned -XkbDDXLoadKeymapByNames( DeviceIntPtr keybd, - XkbComponentNamesPtr names, - unsigned want, - unsigned need, - XkbDescPtr * xkbRtrn, - char * nameRtrn, - int nameRtrnLen) -{ -XkbDescPtr xkb; -FILE * file; -char fileName[PATH_MAX]; -unsigned missing; - - *xkbRtrn = NULL; - if ((keybd==NULL)||(keybd->key==NULL)||(keybd->key->xkbInfo==NULL)) - xkb= NULL; - else xkb= keybd->key->xkbInfo->desc; - if ((names->keycodes==NULL)&&(names->types==NULL)&& - (names->compat==NULL)&&(names->symbols==NULL)&& - (names->geometry==NULL)) { - LogMessage(X_ERROR, "XKB: No components provided for device %s\n", - keybd->name ? keybd->name : "(unnamed keyboard)"); - return 0; - } - else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need, - nameRtrn,nameRtrnLen)){ - LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n"); - return 0; - } - file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX); - if (file==NULL) { - LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",fileName); - return 0; - } - missing= XkmReadFile(file,need,want,xkbRtrn); - if (*xkbRtrn==NULL) { - LogMessage(X_ERROR, "Error loading keymap %s\n",fileName); - fclose(file); - (void) unlink (fileName); - return 0; - } - else { - DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined); - } - fclose(file); - (void) unlink (fileName); - return (need|want)&(~missing); -} - -Bool -XkbDDXNamesFromRules( DeviceIntPtr keybd, - char * rules_name, - XkbRF_VarDefsPtr defs, - XkbComponentNamesPtr names) -{ -char buf[PATH_MAX]; -FILE * file; -Bool complete; -XkbRF_RulesPtr rules; - - if (!rules_name) - return FALSE; - - if (strlen(XkbBaseDirectory) + strlen(rules_name) + 8 > PATH_MAX) { - LogMessage(X_ERROR, "XKB: Rules name is too long\n"); - return FALSE; - } - sprintf(buf,"%s/rules/%s", XkbBaseDirectory, rules_name); - - file = fopen(buf, "r"); - if (!file) { - LogMessage(X_ERROR, "XKB: Couldn't open rules file %s\n", buf); - return FALSE; - } - - rules = XkbRF_Create(); - if (!rules) { - LogMessage(X_ERROR, "XKB: Couldn't create rules struct\n"); - fclose(file); - return FALSE; - } - - if (!XkbRF_LoadRules(file, rules)) { - LogMessage(X_ERROR, "XKB: Couldn't parse rules file %s\n", rules_name); - fclose(file); - XkbRF_Free(rules,TRUE); - return FALSE; - } - - memset(names, 0, sizeof(*names)); - complete = XkbRF_GetComponents(rules,defs,names); - fclose(file); - XkbRF_Free(rules, TRUE); - - if (!complete) - LogMessage(X_ERROR, "XKB: Rules returned no components\n"); - - return complete; -} - -XkbDescPtr -XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet *rmlvo) -{ - XkbComponentNamesRec kccgst; - XkbRF_VarDefsRec mlvo; - XkbDescPtr xkb; - char name[PATH_MAX]; - - if (!dev || !rmlvo) { - LogMessage(X_ERROR, "XKB: No device or RMLVO specified\n"); - return NULL; - } - - mlvo.model = rmlvo->model; - mlvo.layout = rmlvo->layout; - mlvo.variant = rmlvo->variant; - mlvo.options = rmlvo->options; - - /* XDNFR already logs for us. */ - if (!XkbDDXNamesFromRules(dev, rmlvo->rules, &mlvo, &kccgst)) - return NULL; - - /* XDLKBN too, but it might return 0 as well as allocating. */ - if (!XkbDDXLoadKeymapByNames(dev, &kccgst, XkmAllIndicesMask, 0, &xkb, name, - PATH_MAX)) { - if (xkb) - XkbFreeKeyboard(xkb, 0, TRUE); - return NULL; - } - - return xkb; -} +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include +#include +#include "xkb.h" + + /* + * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is + * relative to the top-level XKB configuration directory. + * Making the server write to a subdirectory of that directory + * requires some work in the general case (install procedure + * has to create links to /var or somesuch on many machines), + * so we just compile into /usr/tmp for now. + */ +#ifndef XKM_OUTPUT_DIR +#define XKM_OUTPUT_DIR "compiled/" +#endif + +#define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\"" +#define ERROR_PREFIX "\"> \"" +#define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\"" +#define POST_ERROR_MSG2 "\"End of messages from xkbcomp\"" + +#if defined(WIN32) +#define PATHSEPARATOR "\\" +#else +#define PATHSEPARATOR "/" +#endif + +#ifdef WIN32 + +#include +const char* +Win32TempDir() +{ + static char buffer[PATH_MAX]; + if (GetTempPath(sizeof(buffer), buffer)) + { + int len; + buffer[sizeof(buffer)-1] = 0; + len = strlen(buffer); + if (len > 0) + if (buffer[len-1] == '\\') + buffer[len-1] = 0; + return buffer; + } + if (getenv("TEMP") != NULL) + return getenv("TEMP"); + else if (getenv("TMP") != NULL) + return getenv("TEMP"); + else + return "/tmp"; +} + +int +Win32System(const char *cmdline) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD dwExitCode; + char *cmd = strdup(cmdline); + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + LPVOID buffer; + if (!FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &buffer, + 0, + NULL )) + { + ErrorF("[xkb] Starting '%s' failed!\n", cmdline); + } + else + { + ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *)buffer); + LocalFree(buffer); + } + + free(cmd); + return -1; + } + /* Wait until child process exits. */ + WaitForSingleObject( pi.hProcess, INFINITE ); + + GetExitCodeProcess( pi.hProcess, &dwExitCode); + + /* Close process and thread handles. */ + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + free(cmd); + + return dwExitCode; +} +#undef System +#define System(x) Win32System(x) +#endif + +static void +OutputDirectory( + char* outdir, + size_t size) +{ +#ifndef WIN32 + /* Can we write an xkm and then open it too? */ + if (access(XKM_OUTPUT_DIR, W_OK | X_OK) == 0 && (strlen(XKM_OUTPUT_DIR) < size)) + { + (void) strcpy (outdir, XKM_OUTPUT_DIR); + } else +#else + if (strlen(Win32TempDir()) + 1 < size) + { + (void) strcpy(outdir, Win32TempDir()); + (void) strcat(outdir, "\\"); + } else +#endif + if (strlen("/tmp/") < size) + { + (void) strcpy (outdir, "/tmp/"); + } +} + +static Bool +XkbDDXCompileKeymapByNames( XkbDescPtr xkb, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + char * nameRtrn, + int nameRtrnLen) +{ + FILE * out; + char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX]; + + const char *emptystring = ""; + char *xkbbasedirflag = NULL; + const char *xkbbindir = emptystring; + const char *xkbbindirsep = emptystring; + +#ifdef WIN32 + /* WIN32 has no popen. The input must be stored in a file which is + used as input for xkbcomp. xkbcomp does not read from stdin. */ + char tmpname[PATH_MAX]; + const char *xkmfile = tmpname; +#else + const char *xkmfile = "-"; +#endif + + snprintf(keymap, sizeof(keymap), "server-%s", display); + + OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); + +#ifdef WIN32 + strcpy(tmpname, Win32TempDir()); + strcat(tmpname, "\\xkb_XXXXXX"); + (void) mktemp(tmpname); +#endif + + if (XkbBaseDirectory != NULL) { + if (asprintf(&xkbbasedirflag, "\"-R%s\"", XkbBaseDirectory) == -1) + xkbbasedirflag = NULL; + } + + if (XkbBinDirectory != NULL) { + int ld = strlen(XkbBinDirectory); + int lps = strlen(PATHSEPARATOR); + + xkbbindir = XkbBinDirectory; + + if ((ld >= lps) && + (strcmp(xkbbindir + ld - lps, PATHSEPARATOR) != 0)) { + xkbbindirsep = PATHSEPARATOR; + } + } + + if (asprintf(&buf, + "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" " + "-em1 %s -emp %s -eml %s \"%s%s.xkm\"", + xkbbindir, xkbbindirsep, + ((xkbDebugFlags < 2) ? 1 : + ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)), + xkbbasedirflag ? xkbbasedirflag : "", xkmfile, + PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1, + xkm_output_dir, keymap) == -1) + buf = NULL; + + free(xkbbasedirflag); + + if (!buf) { + LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp: not enough memory\n"); + return FALSE; + } + +#ifndef WIN32 + out= Popen(buf,"w"); +#else + out= fopen(tmpname, "w"); +#endif + + if (out!=NULL) { +#ifdef DEBUG + if (xkbDebugFlags) { + ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n"); + XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need); + } +#endif + XkbWriteXKBKeymapForNames(out,names,xkb,want,need); +#ifndef WIN32 + if (Pclose(out)==0) +#else + if (fclose(out)==0 && System(buf) >= 0) +#endif + { + if (xkbDebugFlags) + DebugF("[xkb] xkb executes: %s\n",buf); + if (nameRtrn) { + strncpy(nameRtrn,keymap,nameRtrnLen); + nameRtrn[nameRtrnLen-1]= '\0'; + } + free(buf); + return TRUE; + } + else + LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap); +#ifdef WIN32 + /* remove the temporary file */ + unlink(tmpname); +#endif + } + else { +#ifndef WIN32 + LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n"); +#else + LogMessage(X_ERROR, "Could not open file %s\n", tmpname); +#endif + } + if (nameRtrn) + nameRtrn[0]= '\0'; + free(buf); + return FALSE; +} + +static FILE * +XkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen) +{ +char buf[PATH_MAX],xkm_output_dir[PATH_MAX]; +FILE * file; + + buf[0]= '\0'; + if (mapName!=NULL) { + OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); + if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/') +#ifdef WIN32 + &&(!isalpha(xkm_output_dir[0]) || xkm_output_dir[1]!=':') +#endif + ) { + if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir) + +strlen(mapName)+6 <= PATH_MAX) + { + sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory, + xkm_output_dir,mapName); + } + } + else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX) + sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName); + if (buf[0] != '\0') + file= fopen(buf,"rb"); + else file= NULL; + } + else file= NULL; + if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) { + strncpy(fileNameRtrn,buf,fileNameRtrnLen); + buf[fileNameRtrnLen-1]= '\0'; + } + return file; +} + +unsigned +XkbDDXLoadKeymapByNames( DeviceIntPtr keybd, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + XkbDescPtr * xkbRtrn, + char * nameRtrn, + int nameRtrnLen) +{ +XkbDescPtr xkb; +FILE * file; +char fileName[PATH_MAX]; +unsigned missing; + + *xkbRtrn = NULL; + if ((keybd==NULL)||(keybd->key==NULL)||(keybd->key->xkbInfo==NULL)) + xkb= NULL; + else xkb= keybd->key->xkbInfo->desc; + if ((names->keycodes==NULL)&&(names->types==NULL)&& + (names->compat==NULL)&&(names->symbols==NULL)&& + (names->geometry==NULL)) { + LogMessage(X_ERROR, "XKB: No components provided for device %s\n", + keybd->name ? keybd->name : "(unnamed keyboard)"); + return 0; + } + else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need, + nameRtrn,nameRtrnLen)){ + LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n"); + return 0; + } + file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX); + if (file==NULL) { + LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",fileName); + return 0; + } + missing= XkmReadFile(file,need,want,xkbRtrn); + if (*xkbRtrn==NULL) { + LogMessage(X_ERROR, "Error loading keymap %s\n",fileName); + fclose(file); + (void) unlink (fileName); + return 0; + } + else { + DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined); + } + fclose(file); + (void) unlink (fileName); + return (need|want)&(~missing); +} + +Bool +XkbDDXNamesFromRules( DeviceIntPtr keybd, + char * rules_name, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +{ +char buf[PATH_MAX]; +FILE * file; +Bool complete; +XkbRF_RulesPtr rules; + + if (!rules_name) + return FALSE; + + if (strlen(XkbBaseDirectory) + strlen(rules_name) + 8 > PATH_MAX) { + LogMessage(X_ERROR, "XKB: Rules name is too long\n"); + return FALSE; + } + sprintf(buf,"%s/rules/%s", XkbBaseDirectory, rules_name); + + file = fopen(buf, "r"); + if (!file) { + LogMessage(X_ERROR, "XKB: Couldn't open rules file %s\n", buf); + return FALSE; + } + + rules = XkbRF_Create(); + if (!rules) { + LogMessage(X_ERROR, "XKB: Couldn't create rules struct\n"); + fclose(file); + return FALSE; + } + + if (!XkbRF_LoadRules(file, rules)) { + LogMessage(X_ERROR, "XKB: Couldn't parse rules file %s\n", rules_name); + fclose(file); + XkbRF_Free(rules,TRUE); + return FALSE; + } + + memset(names, 0, sizeof(*names)); + complete = XkbRF_GetComponents(rules,defs,names); + fclose(file); + XkbRF_Free(rules, TRUE); + + if (!complete) + LogMessage(X_ERROR, "XKB: Rules returned no components\n"); + + return complete; +} + +static Bool +XkbRMLVOtoKcCGST(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, XkbComponentNamesPtr kccgst) +{ + XkbRF_VarDefsRec mlvo; + + mlvo.model = rmlvo->model; + mlvo.layout = rmlvo->layout; + mlvo.variant = rmlvo->variant; + mlvo.options = rmlvo->options; + + return XkbDDXNamesFromRules(dev, rmlvo->rules, &mlvo, kccgst); +} + +/** + * Compile the given RMLVO keymap and return it. Returns the XkbDescPtr on + * success or NULL on failure. If the components compiled are not a superset + * or equal to need, the compiliation is treated as failure. + */ +static XkbDescPtr +XkbCompileKeymapForDevice(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, int need) +{ + XkbDescPtr xkb; + unsigned int provided; + XkbComponentNamesRec kccgst; + char name[PATH_MAX]; + + if (!XkbRMLVOtoKcCGST(dev, rmlvo, &kccgst)) + return NULL; + + provided = XkbDDXLoadKeymapByNames(dev, &kccgst, XkmAllIndicesMask, need, + &xkb, name, PATH_MAX); + if ((need & provided) != need) { + if (xkb) { + XkbFreeKeyboard(xkb, 0, TRUE); + xkb = NULL; + } + } + + return xkb; +} + +XkbDescPtr +XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet *rmlvo) +{ + XkbDescPtr xkb; + unsigned int need; + + if (!dev || !rmlvo) { + LogMessage(X_ERROR, "XKB: No device or RMLVO specified\n"); + return NULL; + } + + /* These are the components we really really need */ + need = XkmSymbolsMask | XkmCompatMapMask | XkmTypesMask | + XkmKeyNamesMask | XkmVirtualModsMask; + + + xkb = XkbCompileKeymapForDevice(dev, rmlvo, need); + + if (!xkb) { + XkbRMLVOSet dflts; + + /* we didn't get what we really needed. And that will likely leave + * us with a keyboard that doesn't work. Use the defaults instead */ + LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default " + "keymap instead.\n"); + + XkbGetRulesDflts(&dflts); + + xkb = XkbCompileKeymapForDevice(dev, &dflts, 0); + + XkbFreeRMLVOSet(&dflts, FALSE); + } + + return xkb; +} diff --git a/xorg-server/xkb/xkb.c b/xorg-server/xkb/xkb.c index 6fd66c5e5..385c38d7d 100644 --- a/xorg-server/xkb/xkb.c +++ b/xorg-server/xkb/xkb.c @@ -1,6740 +1,6740 @@ -/************************************************************ -Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. - -Permission to use, copy, modify, and distribute this -software and its documentation for any purpose and without -fee is hereby granted, provided that the above copyright -notice appear in all copies and that both that copyright -notice and this permission notice appear in supporting -documentation, and that the name of Silicon Graphics not be -used in advertising or publicity pertaining to distribution -of the software without specific prior written permission. -Silicon Graphics makes no representation about the suitability -of this software for any purpose. It is provided "as is" -without any express or implied warranty. - -SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON -GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH -THE USE OR PERFORMANCE OF THIS SOFTWARE. - -********************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include "misc.h" -#include "inputstr.h" -#define XKBSRV_NEED_FILE_FUNCS -#include -#include "extnsionst.h" -#include "xace.h" -#include "xkb.h" -#include "protocol-versions.h" - -#include -#include - -int XkbEventBase; -static int XkbErrorBase; -int XkbReqCode; -int XkbKeyboardErrorCode; -CARD32 xkbDebugFlags = 0; -static CARD32 xkbDebugCtrls = 0; - -static RESTYPE RT_XKBCLIENT; - -/***====================================================================***/ - -#define CHK_DEVICE(dev, id, client, access_mode, lf) {\ - int why;\ - int rc = lf(&(dev), id, client, access_mode, &why);\ - if (rc != Success) {\ - client->errorValue = _XkbErrCode2(why, id);\ - return rc;\ - }\ -} - -#define CHK_KBD_DEVICE(dev, id, client, mode) \ - CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard) -#define CHK_LED_DEVICE(dev, id, client, mode) \ - CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice) -#define CHK_BELL_DEVICE(dev, id, client, mode) \ - CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice) -#define CHK_ANY_DEVICE(dev, id, client, mode) \ - CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice) - -#define CHK_ATOM_ONLY2(a,ev,er) {\ - if (((a)==None)||(!ValidAtom((a)))) {\ - (ev)= (XID)(a);\ - return er;\ - }\ -} -#define CHK_ATOM_ONLY(a) \ - CHK_ATOM_ONLY2(a,client->errorValue,BadAtom) - -#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\ - if (((a)!=None)&&(!ValidAtom((a)))) {\ - (ev)= (XID)(a);\ - (er)= BadAtom;\ - return ret;\ - }\ -} -#define CHK_ATOM_OR_NONE2(a,ev,er) {\ - if (((a)!=None)&&(!ValidAtom((a)))) {\ - (ev)= (XID)(a);\ - return er;\ - }\ -} -#define CHK_ATOM_OR_NONE(a) \ - CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom) - -#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\ - if ((mask)&(~(legal))) { \ - (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ - (er)= BadValue;\ - return ret;\ - }\ -} -#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\ - if ((mask)&(~(legal))) { \ - (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ - return er;\ - }\ -} -#define CHK_MASK_LEGAL(err,mask,legal) \ - CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue) - -#define CHK_MASK_MATCH(err,affect,value) {\ - if ((value)&(~(affect))) { \ - client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\ - return BadMatch;\ - }\ -} -#define CHK_MASK_OVERLAP(err,m1,m2) {\ - if ((m1)&(m2)) { \ - client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\ - return BadMatch;\ - }\ -} -#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\ - if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\ - (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\ - return er;\ - }\ - else if ( (first)<(x)->min_key_code ) {\ - (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\ - return er;\ - }\ -} -#define CHK_KEY_RANGE(err,first,num,x) \ - CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue) - -#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\ - if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\ - (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\ - return er;\ - }\ - else if ( (first)<(r)->minKeyCode ) {\ - (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\ - return er;\ - }\ -} -#define CHK_REQ_KEY_RANGE(err,first,num,r) \ - CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue) - -/***====================================================================***/ - -int -ProcXkbUseExtension(ClientPtr client) -{ - REQUEST(xkbUseExtensionReq); - xkbUseExtensionReply rep; - register int n; - int supported; - - REQUEST_SIZE_MATCH(xkbUseExtensionReq); - if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) { - /* pre-release version 0.65 is compatible with 1.00 */ - supported= ((SERVER_XKB_MAJOR_VERSION==1)&& - (stuff->wantedMajor==0)&&(stuff->wantedMinor==65)); - } - else supported = 1; - - if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) { - client->xkbClientFlags= _XkbClientInitialized; - client->vMajor= stuff->wantedMajor; - client->vMinor= stuff->wantedMinor; - } - else if (xkbDebugFlags&0x1) { - ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n", - client->index, - (long)client->clientAsMask, - stuff->wantedMajor,stuff->wantedMinor, - SERVER_XKB_MAJOR_VERSION,SERVER_XKB_MINOR_VERSION); - } - memset(&rep, 0, sizeof(xkbUseExtensionReply)); - rep.type = X_Reply; - rep.supported = supported; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.serverMajor = SERVER_XKB_MAJOR_VERSION; - rep.serverMinor = SERVER_XKB_MINOR_VERSION; - if ( client->swapped ) { - swaps(&rep.sequenceNumber, n); - swaps(&rep.serverMajor, n); - swaps(&rep.serverMinor, n); - } - WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep); - return Success; -} - -/***====================================================================***/ - -int -ProcXkbSelectEvents(ClientPtr client) -{ - unsigned legal; - DeviceIntPtr dev; - XkbInterestPtr masks; - REQUEST(xkbSelectEventsReq); - - REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess); - - if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) { - client->mapNotifyMask&= ~stuff->affectMap; - client->mapNotifyMask|= (stuff->affectMap&stuff->map); - } - if ((stuff->affectWhich&(~XkbMapNotifyMask))==0) - return Success; - - masks = XkbFindClientResource((DevicePtr)dev,client); - if (!masks){ - XID id = FakeClientID(client->index); - if (!AddResource(id,RT_XKBCLIENT,dev)) - return BadAlloc; - masks= XkbAddClientResource((DevicePtr)dev,client,id); - } - if (masks) { - union { - CARD8 *c8; - CARD16 *c16; - CARD32 *c32; - } from,to; - register unsigned bit,ndx,maskLeft,dataLeft,size; - - from.c8= (CARD8 *)&stuff[1]; - dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq); - maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask)); - for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) { - if ((bit&maskLeft)==0) - continue; - maskLeft&= ~bit; - switch (ndx) { - case XkbNewKeyboardNotify: - to.c16= &client->newKeyboardNotifyMask; - legal= XkbAllNewKeyboardEventsMask; - size= 2; - break; - case XkbStateNotify: - to.c16= &masks->stateNotifyMask; - legal= XkbAllStateEventsMask; - size= 2; - break; - case XkbControlsNotify: - to.c32= &masks->ctrlsNotifyMask; - legal= XkbAllControlEventsMask; - size= 4; - break; - case XkbIndicatorStateNotify: - to.c32= &masks->iStateNotifyMask; - legal= XkbAllIndicatorEventsMask; - size= 4; - break; - case XkbIndicatorMapNotify: - to.c32= &masks->iMapNotifyMask; - legal= XkbAllIndicatorEventsMask; - size= 4; - break; - case XkbNamesNotify: - to.c16= &masks->namesNotifyMask; - legal= XkbAllNameEventsMask; - size= 2; - break; - case XkbCompatMapNotify: - to.c8= &masks->compatNotifyMask; - legal= XkbAllCompatMapEventsMask; - size= 1; - break; - case XkbBellNotify: - to.c8= &masks->bellNotifyMask; - legal= XkbAllBellEventsMask; - size= 1; - break; - case XkbActionMessage: - to.c8= &masks->actionMessageMask; - legal= XkbAllActionMessagesMask; - size= 1; - break; - case XkbAccessXNotify: - to.c16= &masks->accessXNotifyMask; - legal= XkbAllAccessXEventsMask; - size= 2; - break; - case XkbExtensionDeviceNotify: - to.c16= &masks->extDevNotifyMask; - legal= XkbAllExtensionDeviceEventsMask; - size= 2; - break; - default: - client->errorValue = _XkbErrCode2(33,bit); - return BadValue; - } - - if (stuff->clear&bit) { - if (size==2) to.c16[0]= 0; - else if (size==4) to.c32[0]= 0; - else to.c8[0]= 0; - } - else if (stuff->selectAll&bit) { - if (size==2) to.c16[0]= ~0; - else if (size==4) to.c32[0]= ~0; - else to.c8[0]= ~0; - } - else { - if (dataLeft<(size*2)) - return BadLength; - if (size==2) { - CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]); - CHK_MASK_LEGAL(ndx,from.c16[0],legal); - to.c16[0]&= ~from.c16[0]; - to.c16[0]|= (from.c16[0]&from.c16[1]); - } - else if (size==4) { - CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]); - CHK_MASK_LEGAL(ndx,from.c32[0],legal); - to.c32[0]&= ~from.c32[0]; - to.c32[0]|= (from.c32[0]&from.c32[1]); - } - else { - CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]); - CHK_MASK_LEGAL(ndx,from.c8[0],legal); - to.c8[0]&= ~from.c8[0]; - to.c8[0]|= (from.c8[0]&from.c8[1]); - size= 2; - } - from.c8+= (size*2); - dataLeft-= (size*2); - } - } - if (dataLeft>2) { - ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft); - return BadLength; - } - return Success; - } - return BadAlloc; -} - -/***====================================================================***/ -/** - * Ring a bell on the given device for the given client. - */ -static int -_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin, - int bellClass, int bellID, int pitch, int duration, - int percent, int forceSound, int eventOnly, Atom name) -{ - int base; - pointer ctrl; - int oldPitch, oldDuration; - int newPercent; - - if (bellClass == KbdFeedbackClass) { - KbdFeedbackPtr k; - if (bellID==XkbDfltXIId) - k= dev->kbdfeed; - else { - for (k=dev->kbdfeed; k; k=k->next) { - if (k->ctrl.id == bellID) - break; - } - } - if (!k) { - client->errorValue = _XkbErrCode2(0x5,bellID); - return BadValue; - } - base = k->ctrl.bell; - ctrl = (pointer) &(k->ctrl); - oldPitch= k->ctrl.bell_pitch; - oldDuration= k->ctrl.bell_duration; - if (pitch!=0) { - if (pitch==-1) - k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch; - else k->ctrl.bell_pitch= pitch; - } - if (duration!=0) { - if (duration==-1) - k->ctrl.bell_duration= defaultKeyboardControl.bell_duration; - else k->ctrl.bell_duration= duration; - } - } - else if (bellClass == BellFeedbackClass) { - BellFeedbackPtr b; - if (bellID==XkbDfltXIId) - b= dev->bell; - else { - for (b=dev->bell; b; b=b->next) { - if (b->ctrl.id == bellID) - break; - } - } - if (!b) { - client->errorValue = _XkbErrCode2(0x6,bellID); - return BadValue; - } - base = b->ctrl.percent; - ctrl = (pointer) &(b->ctrl); - oldPitch= b->ctrl.pitch; - oldDuration= b->ctrl.duration; - if (pitch!=0) { - if (pitch==-1) - b->ctrl.pitch= defaultKeyboardControl.bell_pitch; - else b->ctrl.pitch= pitch; - } - if (duration!=0) { - if (duration==-1) - b->ctrl.duration= defaultKeyboardControl.bell_duration; - else b->ctrl.duration= duration; - } - } - else { - client->errorValue = _XkbErrCode2(0x7, bellClass); - return BadValue; - } - - newPercent = (base * percent)/100; - if (percent < 0) - newPercent = base + newPercent; - else newPercent = base - newPercent + percent; - - XkbHandleBell(forceSound, eventOnly, - dev, newPercent, ctrl, bellClass, - name, pWin, client); - if ((pitch!=0)||(duration!=0)) { - if (bellClass == KbdFeedbackClass) { - KbdFeedbackPtr k; - k= (KbdFeedbackPtr)ctrl; - if (pitch!=0) - k->ctrl.bell_pitch= oldPitch; - if (duration!=0) - k->ctrl.bell_duration= oldDuration; - } - else { - BellFeedbackPtr b; - b= (BellFeedbackPtr)ctrl; - if (pitch!=0) - b->ctrl.pitch= oldPitch; - if (duration!=0) - b->ctrl.duration= oldDuration; - } - } - - return Success; -} - -int -ProcXkbBell(ClientPtr client) -{ - REQUEST(xkbBellReq); - DeviceIntPtr dev; - WindowPtr pWin; - int rc; - - REQUEST_SIZE_MATCH(xkbBellReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess); - CHK_ATOM_OR_NONE(stuff->name); - - /* device-independent checks request for sane values */ - if ((stuff->forceSound)&&(stuff->eventOnly)) { - client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly); - return BadMatch; - } - if (stuff->percent < -100 || stuff->percent > 100) { - client->errorValue = _XkbErrCode2(0x2,stuff->percent); - return BadValue; - } - if (stuff->duration<-1) { - client->errorValue = _XkbErrCode2(0x3,stuff->duration); - return BadValue; - } - if (stuff->pitch<-1) { - client->errorValue = _XkbErrCode2(0x4,stuff->pitch); - return BadValue; - } - - if (stuff->bellClass == XkbDfltXIClass) { - if (dev->kbdfeed!=NULL) - stuff->bellClass= KbdFeedbackClass; - else stuff->bellClass= BellFeedbackClass; - } - - if (stuff->window!=None) { - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) { - client->errorValue= stuff->window; - return rc; - } - } - else pWin= NULL; - - /* Client wants to ring a bell on the core keyboard? - Ring the bell on the core keyboard (which does nothing, but if that - fails the client is screwed anyway), and then on all extension devices. - Fail if the core keyboard fails but not the extension devices. this - may cause some keyboards to ding and others to stay silent. Fix - your client to use explicit keyboards to avoid this. - - dev is the device the client requested. - */ - rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID, - stuff->pitch, stuff->duration, stuff->percent, - stuff->forceSound, stuff->eventOnly, stuff->name); - - if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) || - (stuff->deviceSpec == XkbUseCorePtr))) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess); - if (rc == Success) - _XkbBell(client, other, pWin, stuff->bellClass, - stuff->bellID, stuff->pitch, stuff->duration, - stuff->percent, stuff->forceSound, - stuff->eventOnly, stuff->name); - } - } - rc = Success; /* reset to success, that's what we got for the VCK */ - } - - return rc; -} - -/***====================================================================***/ - -int -ProcXkbGetState(ClientPtr client) -{ - REQUEST(xkbGetStateReq); - DeviceIntPtr dev; - xkbGetStateReply rep; - XkbStateRec *xkb; - - REQUEST_SIZE_MATCH(xkbGetStateReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - - xkb= &dev->key->xkbInfo->state; - memset(&rep, 0, sizeof(xkbGetStateReply)); - rep.type= X_Reply; - rep.sequenceNumber= client->sequence; - rep.length = 0; - rep.deviceID = dev->id; - rep.mods = XkbStateFieldFromRec(xkb) & 0xff; - rep.baseMods = xkb->base_mods; - rep.lockedMods = xkb->locked_mods; - rep.latchedMods = xkb->latched_mods; - rep.group = xkb->group; - rep.baseGroup = xkb->base_group; - rep.latchedGroup = xkb->latched_group; - rep.lockedGroup = xkb->locked_group; - rep.compatState = xkb->compat_state; - rep.ptrBtnState = xkb->ptr_buttons; - if (client->swapped) { - register int n; - swaps(&rep.sequenceNumber,n); - swaps(&rep.ptrBtnState,n); - } - WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep); - return Success; -} - -/***====================================================================***/ - -int -ProcXkbLatchLockState(ClientPtr client) -{ - int status; - DeviceIntPtr dev, tmpd; - XkbStateRec oldState,*newState; - CARD16 changed; - xkbStateNotify sn; - XkbEventCauseRec cause; - - REQUEST(xkbLatchLockStateReq); - REQUEST_SIZE_MATCH(xkbLatchLockStateReq); - - if (!(client->xkbClientFlags & _XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); - CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks); - CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches); - - status = Success; - - for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { - if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { - if (!tmpd->key || !tmpd->key->xkbInfo) - continue; - - oldState = tmpd->key->xkbInfo->state; - newState = &tmpd->key->xkbInfo->state; - if (stuff->affectModLocks) { - newState->locked_mods &= ~stuff->affectModLocks; - newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks); - } - if (status == Success && stuff->lockGroup) - newState->locked_group = stuff->groupLock; - if (status == Success && stuff->affectModLatches) - status = XkbLatchModifiers(tmpd, stuff->affectModLatches, - stuff->modLatches); - if (status == Success && stuff->latchGroup) - status = XkbLatchGroup(tmpd, stuff->groupLatch); - - if (status != Success) - return status; - - XkbComputeDerivedState(tmpd->key->xkbInfo); - - changed = XkbStateChangedFlags(&oldState, newState); - if (changed) { - sn.keycode = 0; - sn.eventType = 0; - sn.requestMajor = XkbReqCode; - sn.requestMinor = X_kbLatchLockState; - sn.changed = changed; - XkbSendStateNotify(tmpd, &sn); - changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE); - if (changed) { - XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client); - XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause); - } - } - } - } - - return Success; -} - -/***====================================================================***/ - -int -ProcXkbGetControls(ClientPtr client) -{ - xkbGetControlsReply rep; - XkbControlsPtr xkb; - DeviceIntPtr dev; - register int n; - - REQUEST(xkbGetControlsReq); - REQUEST_SIZE_MATCH(xkbGetControlsReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - - xkb = dev->key->xkbInfo->desc->ctrls; - rep.type = X_Reply; - rep.length = bytes_to_int32(SIZEOF(xkbGetControlsReply)- - SIZEOF(xGenericReply)); - rep.sequenceNumber = client->sequence; - rep.deviceID = ((DeviceIntPtr)dev)->id; - rep.numGroups = xkb->num_groups; - rep.groupsWrap = xkb->groups_wrap; - rep.internalMods = xkb->internal.mask; - rep.ignoreLockMods = xkb->ignore_lock.mask; - rep.internalRealMods = xkb->internal.real_mods; - rep.ignoreLockRealMods = xkb->ignore_lock.real_mods; - rep.internalVMods = xkb->internal.vmods; - rep.ignoreLockVMods = xkb->ignore_lock.vmods; - rep.enabledCtrls = xkb->enabled_ctrls; - rep.repeatDelay = xkb->repeat_delay; - rep.repeatInterval = xkb->repeat_interval; - rep.slowKeysDelay = xkb->slow_keys_delay; - rep.debounceDelay = xkb->debounce_delay; - rep.mkDelay = xkb->mk_delay; - rep.mkInterval = xkb->mk_interval; - rep.mkTimeToMax = xkb->mk_time_to_max; - rep.mkMaxSpeed = xkb->mk_max_speed; - rep.mkCurve = xkb->mk_curve; - rep.mkDfltBtn = xkb->mk_dflt_btn; - rep.axTimeout = xkb->ax_timeout; - rep.axtCtrlsMask = xkb->axt_ctrls_mask; - rep.axtCtrlsValues = xkb->axt_ctrls_values; - rep.axtOptsMask = xkb->axt_opts_mask; - rep.axtOptsValues = xkb->axt_opts_values; - rep.axOptions = xkb->ax_options; - memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize); - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length,n); - swaps(&rep.internalVMods, n); - swaps(&rep.ignoreLockVMods, n); - swapl(&rep.enabledCtrls, n); - swaps(&rep.repeatDelay, n); - swaps(&rep.repeatInterval, n); - swaps(&rep.slowKeysDelay, n); - swaps(&rep.debounceDelay, n); - swaps(&rep.mkDelay, n); - swaps(&rep.mkInterval, n); - swaps(&rep.mkTimeToMax, n); - swaps(&rep.mkMaxSpeed, n); - swaps(&rep.mkCurve, n); - swaps(&rep.axTimeout, n); - swapl(&rep.axtCtrlsMask, n); - swapl(&rep.axtCtrlsValues, n); - swaps(&rep.axtOptsMask, n); - swaps(&rep.axtOptsValues, n); - swaps(&rep.axOptions, n); - } - WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep); - return Success; -} - -int -ProcXkbSetControls(ClientPtr client) -{ - DeviceIntPtr dev, tmpd; - XkbSrvInfoPtr xkbi; - XkbControlsPtr ctrl; - XkbControlsRec new,old; - xkbControlsNotify cn; - XkbEventCauseRec cause; - XkbSrvLedInfoPtr sli; - - REQUEST(xkbSetControlsReq); - REQUEST_SIZE_MATCH(xkbSetControlsReq); - - if (!(client->xkbClientFlags & _XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); - CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask); - - for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { - if (!tmpd->key || !tmpd->key->xkbInfo) - continue; - if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { - xkbi = tmpd->key->xkbInfo; - ctrl = xkbi->desc->ctrls; - new = *ctrl; - XkbSetCauseXkbReq(&cause, X_kbSetControls, client); - - if (stuff->changeCtrls & XkbInternalModsMask) { - CHK_MASK_MATCH(0x02, stuff->affectInternalMods, - stuff->internalMods); - CHK_MASK_MATCH(0x03, stuff->affectInternalVMods, - stuff->internalVMods); - - new.internal.real_mods &= ~(stuff->affectInternalMods); - new.internal.real_mods |= (stuff->affectInternalMods & - stuff->internalMods); - new.internal.vmods &= ~(stuff->affectInternalVMods); - new.internal.vmods |= (stuff->affectInternalVMods & - stuff->internalVMods); - new.internal.mask = new.internal.real_mods | - XkbMaskForVMask(xkbi->desc, - new.internal.vmods); - } - - if (stuff->changeCtrls & XkbIgnoreLockModsMask) { - CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods, - stuff->ignoreLockMods); - CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods, - stuff->ignoreLockVMods); - - new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods); - new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods & - stuff->ignoreLockMods); - new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods); - new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods & - stuff->ignoreLockVMods); - new.ignore_lock.mask = new.ignore_lock.real_mods | - XkbMaskForVMask(xkbi->desc, - new.ignore_lock.vmods); - } - - CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls, - stuff->enabledCtrls); - if (stuff->affectEnabledCtrls) { - CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls, - XkbAllBooleanCtrlsMask); - - new.enabled_ctrls &= ~(stuff->affectEnabledCtrls); - new.enabled_ctrls |= (stuff->affectEnabledCtrls & - stuff->enabledCtrls); - } - - if (stuff->changeCtrls & XkbRepeatKeysMask) { - if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) { - client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay, - stuff->repeatInterval); - return BadValue; - } - - new.repeat_delay = stuff->repeatDelay; - new.repeat_interval = stuff->repeatInterval; - } - - if (stuff->changeCtrls & XkbSlowKeysMask) { - if (stuff->slowKeysDelay < 1) { - client->errorValue = _XkbErrCode2(0x09, - stuff->slowKeysDelay); - return BadValue; - } - - new.slow_keys_delay = stuff->slowKeysDelay; - } - - if (stuff->changeCtrls & XkbBounceKeysMask) { - if (stuff->debounceDelay < 1) { - client->errorValue = _XkbErrCode2(0x0A, - stuff->debounceDelay); - return BadValue; - } - - new.debounce_delay = stuff->debounceDelay; - } - - if (stuff->changeCtrls & XkbMouseKeysMask) { - if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) { - client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn); - return BadValue; - } - - new.mk_dflt_btn = stuff->mkDfltBtn; - } - - if (stuff->changeCtrls & XkbMouseKeysAccelMask) { - if (stuff->mkDelay < 1 || stuff->mkInterval < 1 || - stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 || - stuff->mkCurve < -1000) { - client->errorValue = _XkbErrCode2(0x0C,0); - return BadValue; - } - - new.mk_delay = stuff->mkDelay; - new.mk_interval = stuff->mkInterval; - new.mk_time_to_max = stuff->mkTimeToMax; - new.mk_max_speed = stuff->mkMaxSpeed; - new.mk_curve = stuff->mkCurve; - AccessXComputeCurveFactor(xkbi, &new); - } - - if (stuff->changeCtrls & XkbGroupsWrapMask) { - unsigned act, num; - - act = XkbOutOfRangeGroupAction(stuff->groupsWrap); - switch (act) { - case XkbRedirectIntoRange: - num = XkbOutOfRangeGroupNumber(stuff->groupsWrap); - if (num >= new.num_groups) { - client->errorValue = _XkbErrCode3(0x0D, new.num_groups, - num); - return BadValue; - } - case XkbWrapIntoRange: - case XkbClampIntoRange: - break; - default: - client->errorValue = _XkbErrCode2(0x0E, act); - return BadValue; - } - - new.groups_wrap= stuff->groupsWrap; - } - - CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask); - if (stuff->changeCtrls & XkbAccessXKeysMask) { - new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask; - } - else { - if (stuff->changeCtrls & XkbStickyKeysMask) { - new.ax_options &= ~(XkbAX_SKOptionsMask); - new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask); - } - - if (stuff->changeCtrls & XkbAccessXFeedbackMask) { - new.ax_options &= ~(XkbAX_FBOptionsMask); - new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask); - } - } - - if (stuff->changeCtrls & XkbAccessXTimeoutMask) { - if (stuff->axTimeout < 1) { - client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout); - return BadValue; - } - CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask, - stuff->axtCtrlsValues); - CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask, - XkbAllBooleanCtrlsMask); - CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues); - CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask); - new.ax_timeout = stuff->axTimeout; - new.axt_ctrls_mask = stuff->axtCtrlsMask; - new.axt_ctrls_values = (stuff->axtCtrlsValues & - stuff->axtCtrlsMask); - new.axt_opts_mask = stuff->axtOptsMask; - new.axt_opts_values = (stuff->axtOptsValues & - stuff->axtOptsMask); - } - - if (stuff->changeCtrls & XkbPerKeyRepeatMask) { - memcpy(new.per_key_repeat, stuff->perKeyRepeat, - XkbPerKeyBitArraySize); - if (xkbi->repeatKey && - !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) { - AccessXCancelRepeatKey(xkbi, xkbi->repeatKey); - } - } - - old= *ctrl; - *ctrl= new; - XkbDDXChangeControls(tmpd, &old, ctrl); - - if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) { - cn.keycode = 0; - cn.eventType = 0; - cn.requestMajor = XkbReqCode; - cn.requestMinor = X_kbSetControls; - XkbSendControlsNotify(tmpd, &cn); - } - - sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0); - if (sli) - XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL, - &cause); - - /* If sticky keys were disabled, clear all locks and latches */ - if ((old.enabled_ctrls & XkbStickyKeysMask) && - !(ctrl->enabled_ctrls & XkbStickyKeysMask)) - XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause); - } - } - - return Success; -} - -/***====================================================================***/ - -static int -XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep) -{ - XkbKeyTypeRec *type; - unsigned i,len; - - len= 0; - if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)|| - (!xkb)||(!xkb->map)||(!xkb->map->types)) { - rep->present&= ~XkbKeyTypesMask; - rep->firstType= rep->nTypes= 0; - return 0; - } - type= &xkb->map->types[rep->firstType]; - for (i=0;inTypes;i++,type++){ - len+= SIZEOF(xkbKeyTypeWireDesc); - if (type->map_count>0) { - len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc)); - if (type->preserve) - len+= (type->map_count*SIZEOF(xkbModsWireDesc)); - } - } - return len; -} - -static char * -XkbWriteKeyTypes( XkbDescPtr xkb, - xkbGetMapReply * rep, - char * buf, - ClientPtr client) -{ - XkbKeyTypePtr type; - unsigned i; - xkbKeyTypeWireDesc *wire; - - type= &xkb->map->types[rep->firstType]; - for (i=0;inTypes;i++,type++) { - register unsigned n; - wire= (xkbKeyTypeWireDesc *)buf; - wire->mask = type->mods.mask; - wire->realMods = type->mods.real_mods; - wire->virtualMods = type->mods.vmods; - wire->numLevels = type->num_levels; - wire->nMapEntries = type->map_count; - wire->preserve = (type->preserve!=NULL); - if (client->swapped) { - register int n; - swaps(&wire->virtualMods,n); - } - - buf= (char *)&wire[1]; - if (wire->nMapEntries>0) { - xkbKTMapEntryWireDesc * wire; - XkbKTMapEntryPtr entry; - wire= (xkbKTMapEntryWireDesc *)buf; - entry= type->map; - for (n=0;nmap_count;n++,wire++,entry++) { - wire->active= entry->active; - wire->mask= entry->mods.mask; - wire->level= entry->level; - wire->realMods= entry->mods.real_mods; - wire->virtualMods= entry->mods.vmods; - if (client->swapped) { - register int n; - swaps(&wire->virtualMods,n); - } - } - buf= (char *)wire; - if (type->preserve!=NULL) { - xkbModsWireDesc * pwire; - XkbModsPtr preserve; - pwire= (xkbModsWireDesc *)buf; - preserve= type->preserve; - for (n=0;nmap_count;n++,pwire++,preserve++) { - pwire->mask= preserve->mask; - pwire->realMods= preserve->real_mods; - pwire->virtualMods= preserve->vmods; - if (client->swapped) { - register int n; - swaps(&pwire->virtualMods,n); - } - } - buf= (char *)pwire; - } - } - } - return buf; -} - -static int -XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep) -{ - XkbSymMapPtr symMap; - unsigned i,len; - unsigned nSyms,nSymsThisKey; - - if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)|| - (!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) { - rep->present&= ~XkbKeySymsMask; - rep->firstKeySym= rep->nKeySyms= 0; - rep->totalSyms= 0; - return 0; - } - len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc); - symMap = &xkb->map->key_sym_map[rep->firstKeySym]; - for (i=nSyms=0;inKeySyms;i++,symMap++) { - if (symMap->offset!=0) { - nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width; - nSyms+= nSymsThisKey; - } - } - len+= nSyms*4; - rep->totalSyms= nSyms; - return len; -} - -static int -XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep) -{ -register unsigned i,nMods,bit; - - if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)|| - (!xkb)||(!xkb->server)) { - rep->present&= ~XkbVirtualModsMask; - rep->virtualMods= 0; - return 0; - } - for (i=nMods=0,bit=1;ivirtualMods&bit) - nMods++; - } - return XkbPaddedSize(nMods); -} - -static char * -XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) -{ -register KeySym * pSym; -XkbSymMapPtr symMap; -xkbSymMapWireDesc * outMap; -register unsigned i; - - symMap = &xkb->map->key_sym_map[rep->firstKeySym]; - for (i=0;inKeySyms;i++,symMap++) { - outMap = (xkbSymMapWireDesc *)buf; - outMap->ktIndex[0] = symMap->kt_index[0]; - outMap->ktIndex[1] = symMap->kt_index[1]; - outMap->ktIndex[2] = symMap->kt_index[2]; - outMap->ktIndex[3] = symMap->kt_index[3]; - outMap->groupInfo = symMap->group_info; - outMap->width= symMap->width; - outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info); - buf= (char *)&outMap[1]; - if (outMap->nSyms==0) - continue; - - pSym = &xkb->map->syms[symMap->offset]; - memcpy((char *)buf,(char *)pSym,outMap->nSyms*4); - if (client->swapped) { - register int n,nSyms= outMap->nSyms; - swaps(&outMap->nSyms,n); - while (nSyms-->0) { - swapl(buf,n); - buf+= 4; - } - } - else buf+= outMap->nSyms*4; - } - return buf; -} - -static int -XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep) -{ - unsigned i,len,nActs; - register KeyCode firstKey; - - if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)|| - (!xkb)||(!xkb->server)||(!xkb->server->key_acts)) { - rep->present&= ~XkbKeyActionsMask; - rep->firstKeyAct= rep->nKeyActs= 0; - rep->totalActs= 0; - return 0; - } - firstKey= rep->firstKeyAct; - for (nActs=i=0;inKeyActs;i++) { - if (xkb->server->key_acts[i+firstKey]!=0) - nActs+= XkbKeyNumActions(xkb,i+firstKey); - } - len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc)); - rep->totalActs= nActs; - return len; -} - -static char * -XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, - ClientPtr client) -{ - unsigned i; - CARD8 * numDesc; - XkbAnyAction * actDesc; - - numDesc = (CARD8 *)buf; - for (i=0;inKeyActs;i++) { - if (xkb->server->key_acts[i+rep->firstKeyAct]==0) - numDesc[i] = 0; - else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); - } - buf+= XkbPaddedSize(rep->nKeyActs); - - actDesc = (XkbAnyAction *)buf; - for (i=0;inKeyActs;i++) { - if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) { - unsigned int num; - num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); - memcpy((char *)actDesc, - (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)), - num*SIZEOF(xkbActionWireDesc)); - actDesc+= num; - } - } - buf = (char *)actDesc; - return buf; -} - -static int -XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep) -{ - unsigned i,len,nBhvr; - XkbBehavior * bhv; - - if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)|| - (!xkb)||(!xkb->server)||(!xkb->server->behaviors)) { - rep->present&= ~XkbKeyBehaviorsMask; - rep->firstKeyBehavior= rep->nKeyBehaviors= 0; - rep->totalKeyBehaviors= 0; - return 0; - } - bhv= &xkb->server->behaviors[rep->firstKeyBehavior]; - for (nBhvr=i=0;inKeyBehaviors;i++,bhv++) { - if (bhv->type!=XkbKB_Default) - nBhvr++; - } - len= nBhvr*SIZEOF(xkbBehaviorWireDesc); - rep->totalKeyBehaviors= nBhvr; - return len; -} - -static char * -XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, - ClientPtr client) -{ - unsigned i; - xkbBehaviorWireDesc *wire; - XkbBehavior *pBhvr; - - wire = (xkbBehaviorWireDesc *)buf; - pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior]; - for (i=0;inKeyBehaviors;i++,pBhvr++) { - if (pBhvr->type!=XkbKB_Default) { - wire->key= i+rep->firstKeyBehavior; - wire->type= pBhvr->type; - wire->data= pBhvr->data; - wire++; - } - } - buf = (char *)wire; - return buf; -} - -static int -XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep) -{ - unsigned i,len,nRtrn; - - if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)|| - (!xkb)||(!xkb->server)||(!xkb->server->explicit)) { - rep->present&= ~XkbExplicitComponentsMask; - rep->firstKeyExplicit= rep->nKeyExplicit= 0; - rep->totalKeyExplicit= 0; - return 0; - } - for (nRtrn=i=0;inKeyExplicit;i++) { - if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0) - nRtrn++; - } - rep->totalKeyExplicit= nRtrn; - len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */ - return len; -} - -static char * -XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) -{ -unsigned i; -char * start; -unsigned char * pExp; - - start= buf; - pExp= &xkb->server->explicit[rep->firstKeyExplicit]; - for (i=0;inKeyExplicit;i++,pExp++) { - if (*pExp!=0) { - *buf++= i+rep->firstKeyExplicit; - *buf++= *pExp; - } - } - i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ - return buf+i; -} - -static int -XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep) -{ - unsigned i,len,nRtrn; - - if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)|| - (!xkb)||(!xkb->map)||(!xkb->map->modmap)) { - rep->present&= ~XkbModifierMapMask; - rep->firstModMapKey= rep->nModMapKeys= 0; - rep->totalModMapKeys= 0; - return 0; - } - for (nRtrn=i=0;inModMapKeys;i++) { - if (xkb->map->modmap[i+rep->firstModMapKey]!=0) - nRtrn++; - } - rep->totalModMapKeys= nRtrn; - len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */ - return len; -} - -static char * -XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, - ClientPtr client) -{ -unsigned i; -char * start; -unsigned char * pMap; - - start= buf; - pMap= &xkb->map->modmap[rep->firstModMapKey]; - for (i=0;inModMapKeys;i++,pMap++) { - if (*pMap!=0) { - *buf++= i+rep->firstModMapKey; - *buf++= *pMap; - } - } - i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ - return buf+i; -} - -static int -XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep) -{ - unsigned i,len,nRtrn; - - if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)|| - (!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) { - rep->present&= ~XkbVirtualModMapMask; - rep->firstVModMapKey= rep->nVModMapKeys= 0; - rep->totalVModMapKeys= 0; - return 0; - } - for (nRtrn=i=0;inVModMapKeys;i++) { - if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0) - nRtrn++; - } - rep->totalVModMapKeys= nRtrn; - len= nRtrn*SIZEOF(xkbVModMapWireDesc); - return len; -} - -static char * -XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, - ClientPtr client) -{ -unsigned i; -xkbVModMapWireDesc * wire; -unsigned short * pMap; - - wire= (xkbVModMapWireDesc *)buf; - pMap= &xkb->server->vmodmap[rep->firstVModMapKey]; - for (i=0;inVModMapKeys;i++,pMap++) { - if (*pMap!=0) { - wire->key= i+rep->firstVModMapKey; - wire->vmods= *pMap; - wire++; - } - } - return (char *)wire; -} - -static Status -XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep) -{ -int len; - - rep->minKeyCode= xkb->min_key_code; - rep->maxKeyCode= xkb->max_key_code; - len= XkbSizeKeyTypes(xkb,rep); - len+= XkbSizeKeySyms(xkb,rep); - len+= XkbSizeKeyActions(xkb,rep); - len+= XkbSizeKeyBehaviors(xkb,rep); - len+= XkbSizeVirtualMods(xkb,rep); - len+= XkbSizeExplicit(xkb,rep); - len+= XkbSizeModifierMap(xkb,rep); - len+= XkbSizeVirtualModMap(xkb,rep); - rep->length+= (len/4); - return Success; -} - -static int -XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep) -{ -unsigned i,len; -char *desc,*start; - - len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply)); - start= desc= calloc(1, len); - if (!start) - return BadAlloc; - if ( rep->nTypes>0 ) - desc = XkbWriteKeyTypes(xkb,rep,desc,client); - if ( rep->nKeySyms>0 ) - desc = XkbWriteKeySyms(xkb,rep,desc,client); - if ( rep->nKeyActs>0 ) - desc = XkbWriteKeyActions(xkb,rep,desc,client); - if ( rep->totalKeyBehaviors>0 ) - desc = XkbWriteKeyBehaviors(xkb,rep,desc,client); - if ( rep->virtualMods ) { - register int sz,bit; - for (i=sz=0,bit=1;ivirtualMods&bit) { - desc[sz++]= xkb->server->vmods[i]; - } - } - desc+= XkbPaddedSize(sz); - } - if ( rep->totalKeyExplicit>0 ) - desc= XkbWriteExplicit(xkb,rep,desc,client); - if ( rep->totalModMapKeys>0 ) - desc= XkbWriteModifierMap(xkb,rep,desc,client); - if ( rep->totalVModMapKeys>0 ) - desc= XkbWriteVirtualModMap(xkb,rep,desc,client); - if ((desc-start)!=(len)) { - ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n", - len, (unsigned long)(desc-start)); - } - if (client->swapped) { - register int n; - swaps(&rep->sequenceNumber,n); - swapl(&rep->length,n); - swaps(&rep->present,n); - swaps(&rep->totalSyms,n); - swaps(&rep->totalActs,n); - } - WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep); - WriteToClient(client, len, start); - free((char *)start); - return Success; -} - -int -ProcXkbGetMap(ClientPtr client) -{ - DeviceIntPtr dev; - xkbGetMapReply rep; - XkbDescRec *xkb; - int n,status; - - REQUEST(xkbGetMapReq); - REQUEST_SIZE_MATCH(xkbGetMapReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial); - CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask); - CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask); - - xkb= dev->key->xkbInfo->desc; - memset(&rep, 0, sizeof(xkbGetMapReply)); - rep.type= X_Reply; - rep.sequenceNumber= client->sequence; - rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2; - rep.deviceID = dev->id; - rep.present = stuff->partial|stuff->full; - rep.minKeyCode = xkb->min_key_code; - rep.maxKeyCode = xkb->max_key_code; - if ( stuff->full&XkbKeyTypesMask ) { - rep.firstType = 0; - rep.nTypes = xkb->map->num_types; - } - else if (stuff->partial&XkbKeyTypesMask) { - if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) { - client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types, - stuff->firstType,stuff->nTypes); - return BadValue; - } - rep.firstType = stuff->firstType; - rep.nTypes = stuff->nTypes; - } - else rep.nTypes = 0; - rep.totalTypes = xkb->map->num_types; - - n= XkbNumKeys(xkb); - if ( stuff->full&XkbKeySymsMask ) { - rep.firstKeySym = xkb->min_key_code; - rep.nKeySyms = n; - } - else if (stuff->partial&XkbKeySymsMask) { - CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb); - rep.firstKeySym = stuff->firstKeySym; - rep.nKeySyms = stuff->nKeySyms; - } - else rep.nKeySyms = 0; - rep.totalSyms= 0; - - if ( stuff->full&XkbKeyActionsMask ) { - rep.firstKeyAct= xkb->min_key_code; - rep.nKeyActs= n; - } - else if (stuff->partial&XkbKeyActionsMask) { - CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb); - rep.firstKeyAct= stuff->firstKeyAct; - rep.nKeyActs= stuff->nKeyActs; - } - else rep.nKeyActs= 0; - rep.totalActs= 0; - - if ( stuff->full&XkbKeyBehaviorsMask ) { - rep.firstKeyBehavior = xkb->min_key_code; - rep.nKeyBehaviors = n; - } - else if (stuff->partial&XkbKeyBehaviorsMask) { - CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb); - rep.firstKeyBehavior= stuff->firstKeyBehavior; - rep.nKeyBehaviors= stuff->nKeyBehaviors; - } - else rep.nKeyBehaviors = 0; - rep.totalKeyBehaviors= 0; - - if (stuff->full&XkbVirtualModsMask) - rep.virtualMods= ~0; - else if (stuff->partial&XkbVirtualModsMask) - rep.virtualMods= stuff->virtualMods; - - if (stuff->full&XkbExplicitComponentsMask) { - rep.firstKeyExplicit= xkb->min_key_code; - rep.nKeyExplicit= n; - } - else if (stuff->partial&XkbExplicitComponentsMask) { - CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb); - rep.firstKeyExplicit= stuff->firstKeyExplicit; - rep.nKeyExplicit= stuff->nKeyExplicit; - } - else rep.nKeyExplicit = 0; - rep.totalKeyExplicit= 0; - - if (stuff->full&XkbModifierMapMask) { - rep.firstModMapKey= xkb->min_key_code; - rep.nModMapKeys= n; - } - else if (stuff->partial&XkbModifierMapMask) { - CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb); - rep.firstModMapKey= stuff->firstModMapKey; - rep.nModMapKeys= stuff->nModMapKeys; - } - else rep.nModMapKeys = 0; - rep.totalModMapKeys= 0; - - if (stuff->full&XkbVirtualModMapMask) { - rep.firstVModMapKey= xkb->min_key_code; - rep.nVModMapKeys= n; - } - else if (stuff->partial&XkbVirtualModMapMask) { - CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb); - rep.firstVModMapKey= stuff->firstVModMapKey; - rep.nVModMapKeys= stuff->nVModMapKeys; - } - else rep.nVModMapKeys = 0; - rep.totalVModMapKeys= 0; - - if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success) - return status; - return XkbSendMap(client,xkb,&rep); -} - -/***====================================================================***/ - -static int -CheckKeyTypes( ClientPtr client, - XkbDescPtr xkb, - xkbSetMapReq * req, - xkbKeyTypeWireDesc **wireRtrn, - int * nMapsRtrn, - CARD8 * mapWidthRtrn) -{ -unsigned nMaps; -register unsigned i,n; -register CARD8 * map; -register xkbKeyTypeWireDesc *wire = *wireRtrn; - - if (req->firstType>((unsigned)xkb->map->num_types)) { - *nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types); - return 0; - } - if (req->flags&XkbSetMapResizeTypes) { - nMaps = req->firstType+req->nTypes; - if (nMapsfirstType,req->nTypes,4); - return 0; - } - } - else if (req->present&XkbKeyTypesMask) { - nMaps = xkb->map->num_types; - if ((req->firstType+req->nTypes)>nMaps) { - *nMapsRtrn = req->firstType+req->nTypes; - return 0; - } - } - else { - *nMapsRtrn = xkb->map->num_types; - for (i=0;imap->num_types;i++) { - mapWidthRtrn[i] = xkb->map->types[i].num_levels; - } - return 1; - } - - for (i=0;ifirstType;i++) { - mapWidthRtrn[i] = xkb->map->types[i].num_levels; - } - for (i=0;inTypes;i++) { - unsigned width; - if (client->swapped) { - register int s; - swaps(&wire->virtualMods,s); - } - n= i+req->firstType; - width= wire->numLevels; - if (width<1) { - *nMapsRtrn= _XkbErrCode3(0x04,n,width); - return 0; - } - else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */ - *nMapsRtrn= _XkbErrCode3(0x05,n,width); - return 0; - } - else if ((width!=2)&& - ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)|| - (n==XkbAlphabeticIndex))) { - /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */ - *nMapsRtrn= _XkbErrCode3(0x05,n,width); - return 0; - } - if (wire->nMapEntries>0) { - xkbKTSetMapEntryWireDesc * mapWire; - xkbModsWireDesc * preWire; - mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1]; - preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; - for (n=0;nnMapEntries;n++) { - if (client->swapped) { - register int s; - swaps(&mapWire[n].virtualMods,s); - } - if (mapWire[n].realMods&(~wire->realMods)) { - *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods, - wire->realMods); - return 0; - } - if (mapWire[n].virtualMods&(~wire->virtualMods)) { - *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods); - return 0; - } - if (mapWire[n].level>=wire->numLevels) { - *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels, - mapWire[n].level); - return 0; - } - if (wire->preserve) { - if (client->swapped) { - register int s; - swaps(&preWire[n].virtualMods,s); - } - if (preWire[n].realMods&(~mapWire[n].realMods)) { - *nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods, - mapWire[n].realMods); - return 0; - } - if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) { - *nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods); - return 0; - } - } - } - if (wire->preserve) - map= (CARD8 *)&preWire[wire->nMapEntries]; - else map= (CARD8 *)&mapWire[wire->nMapEntries]; - } - else map= (CARD8 *)&wire[1]; - mapWidthRtrn[i+req->firstType] = wire->numLevels; - wire= (xkbKeyTypeWireDesc *)map; - } - for (i=req->firstType+req->nTypes;imap->types[i].num_levels; - } - *nMapsRtrn = nMaps; - *wireRtrn = wire; - return 1; -} - -static int -CheckKeySyms( ClientPtr client, - XkbDescPtr xkb, - xkbSetMapReq * req, - int nTypes, - CARD8 * mapWidths, - CARD16 * symsPerKey, - xkbSymMapWireDesc ** wireRtrn, - int * errorRtrn) -{ -register unsigned i; -XkbSymMapPtr map; -xkbSymMapWireDesc* wire = *wireRtrn; - - if (!(XkbKeySymsMask&req->present)) - return 1; - CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0); - for (i=0;inKeySyms;i++) { - KeySym *pSyms; - register unsigned nG; - if (client->swapped) { - swaps(&wire->nSyms,nG); - } - nG = XkbNumGroups(wire->groupInfo); - if (nG>XkbNumKbdGroups) { - *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG); - return 0; - } - if (nG>0) { - register int g,w; - for (g=w=0;gktIndex[g]>=(unsigned)nTypes) { - *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g, - wire->ktIndex[g]); - return 0; - } - if (mapWidths[wire->ktIndex[g]]>w) - w= mapWidths[wire->ktIndex[g]]; - } - if (wire->width!=w) { - *errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width); - return 0; - } - w*= nG; - symsPerKey[i+req->firstKeySym] = w; - if (w!=wire->nSyms) { - *errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w); - return 0; - } - } - else if (wire->nSyms!=0) { - *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms); - return 0; - } - pSyms = (KeySym *)&wire[1]; - wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; - } - - map = &xkb->map->key_sym_map[i]; - for (;i<=(unsigned)xkb->max_key_code;i++,map++) { - register int g,nG,w; - nG= XkbKeyNumGroups(xkb,i); - for (w=g=0;gkt_index[g]>=(unsigned)nTypes) { - *errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]); - return 0; - } - if (mapWidths[map->kt_index[g]]>w) - w= mapWidths[map->kt_index[g]]; - } - symsPerKey[i] = w*nG; - } - *wireRtrn = wire; - return 1; -} - -static int -CheckKeyActions( XkbDescPtr xkb, - xkbSetMapReq * req, - int nTypes, - CARD8 * mapWidths, - CARD16 * symsPerKey, - CARD8 ** wireRtrn, - int * nActsRtrn) -{ -int nActs; -CARD8 * wire = *wireRtrn; -register unsigned i; - - if (!(XkbKeyActionsMask&req->present)) - return 1; - CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0); - for (nActs=i=0;inKeyActs;i++) { - if (wire[0]!=0) { - if (wire[0]==symsPerKey[i+req->firstKeyAct]) - nActs+= wire[0]; - else { - *nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]); - return 0; - } - } - wire++; - } - if (req->nKeyActs%4) - wire+= 4-(req->nKeyActs%4); - *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs); - *nActsRtrn = nActs; - return 1; -} - -static int -CheckKeyBehaviors( XkbDescPtr xkb, - xkbSetMapReq * req, - xkbBehaviorWireDesc ** wireRtrn, - int * errorRtrn) -{ -register xkbBehaviorWireDesc * wire = *wireRtrn; -register XkbServerMapPtr server = xkb->server; -register unsigned i; -unsigned first,last; - - if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) { - req->present&= ~XkbKeyBehaviorsMask; - req->nKeyBehaviors= 0; - return 1; - } - first= req->firstKeyBehavior; - last= req->firstKeyBehavior+req->nKeyBehaviors-1; - if (firstminKeyCode) { - *errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode); - return 0; - } - if (last>req->maxKeyCode) { - *errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode); - return 0; - } - - for (i=0;itotalKeyBehaviors;i++,wire++) { - if ((wire->keykey>last)) { - *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key); - return 0; - } - if ((wire->type&XkbKB_Permanent)&& - ((server->behaviors[wire->key].type!=wire->type)|| - (server->behaviors[wire->key].data!=wire->data))) { - *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type); - return 0; - } - if ((wire->type==XkbKB_RadioGroup)&& - ((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) { - *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data, - XkbMaxRadioGroups); - return 0; - } - if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) { - CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0); - } - } - *wireRtrn = wire; - return 1; -} - -static int -CheckVirtualMods( XkbDescRec * xkb, - xkbSetMapReq * req, - CARD8 ** wireRtrn, - int * errorRtrn) -{ -register CARD8 *wire = *wireRtrn; -register unsigned i,nMods,bit; - - if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) - return 1; - for (i=nMods=0,bit=1;ivirtualMods&bit) - nMods++; - } - *wireRtrn= (wire+XkbPaddedSize(nMods)); - return 1; -} - -static int -CheckKeyExplicit( XkbDescPtr xkb, - xkbSetMapReq * req, - CARD8 ** wireRtrn, - int * errorRtrn) -{ -register CARD8 * wire = *wireRtrn; -CARD8 * start; -register unsigned i; -int first,last; - - if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) { - req->present&= ~XkbExplicitComponentsMask; - req->nKeyExplicit= 0; - return 1; - } - first= req->firstKeyExplicit; - last= first+req->nKeyExplicit-1; - if (firstminKeyCode) { - *errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode); - return 0; - } - if (last>req->maxKeyCode) { - *errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode); - return 0; - } - start= wire; - for (i=0;itotalKeyExplicit;i++,wire+=2) { - if ((wire[0]last)) { - *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]); - return 0; - } - if (wire[1]&(~XkbAllExplicitMask)) { - *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]); - return 0; - } - } - wire+= XkbPaddedSize(wire-start)-(wire-start); - *wireRtrn= wire; - return 1; -} - -static int -CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn) -{ -register CARD8 * wire = *wireRtrn; -CARD8 * start; -register unsigned i; -int first,last; - - if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) { - req->present&= ~XkbModifierMapMask; - req->nModMapKeys= 0; - return 1; - } - first= req->firstModMapKey; - last= first+req->nModMapKeys-1; - if (firstminKeyCode) { - *errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode); - return 0; - } - if (last>req->maxKeyCode) { - *errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode); - return 0; - } - start= wire; - for (i=0;itotalModMapKeys;i++,wire+=2) { - if ((wire[0]last)) { - *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]); - return 0; - } - } - wire+= XkbPaddedSize(wire-start)-(wire-start); - *wireRtrn= wire; - return 1; -} - -static int -CheckVirtualModMap( XkbDescPtr xkb, - xkbSetMapReq *req, - xkbVModMapWireDesc **wireRtrn, - int *errRtrn) -{ -register xkbVModMapWireDesc * wire = *wireRtrn; -register unsigned i; -int first,last; - - if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) { - req->present&= ~XkbVirtualModMapMask; - req->nVModMapKeys= 0; - return 1; - } - first= req->firstVModMapKey; - last= first+req->nVModMapKeys-1; - if (firstminKeyCode) { - *errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode); - return 0; - } - if (last>req->maxKeyCode) { - *errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode); - return 0; - } - for (i=0;itotalVModMapKeys;i++,wire++) { - if ((wire->keykey>last)) { - *errRtrn = _XkbErrCode4(0x73,first,last,wire->key); - return 0; - } - } - *wireRtrn= wire; - return 1; -} - -static char * -SetKeyTypes( XkbDescPtr xkb, - xkbSetMapReq * req, - xkbKeyTypeWireDesc * wire, - XkbChangesPtr changes) -{ -register unsigned i; -unsigned first,last; -CARD8 *map; - - if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) { - i= req->firstType+req->nTypes; - if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) { - return NULL; - } - } - if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types) - xkb->map->num_types= req->firstType+req->nTypes; - - for (i=0;inTypes;i++) { - XkbKeyTypePtr pOld; - register unsigned n; - - if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries, - wire->preserve,wire->numLevels)!=Success) { - return NULL; - } - pOld = &xkb->map->types[i+req->firstType]; - map = (CARD8 *)&wire[1]; - - pOld->mods.real_mods = wire->realMods; - pOld->mods.vmods= wire->virtualMods; - pOld->num_levels = wire->numLevels; - pOld->map_count= wire->nMapEntries; - - pOld->mods.mask= pOld->mods.real_mods| - XkbMaskForVMask(xkb,pOld->mods.vmods); - - if (wire->nMapEntries) { - xkbKTSetMapEntryWireDesc *mapWire; - xkbModsWireDesc *preWire; - unsigned tmp; - mapWire= (xkbKTSetMapEntryWireDesc *)map; - preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; - for (n=0;nnMapEntries;n++) { - pOld->map[n].active= 1; - pOld->map[n].mods.mask= mapWire[n].realMods; - pOld->map[n].mods.real_mods= mapWire[n].realMods; - pOld->map[n].mods.vmods= mapWire[n].virtualMods; - pOld->map[n].level= mapWire[n].level; - if (mapWire[n].virtualMods!=0) { - tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods); - pOld->map[n].active= (tmp!=0); - pOld->map[n].mods.mask|= tmp; - } - if (wire->preserve) { - pOld->preserve[n].real_mods= preWire[n].realMods; - pOld->preserve[n].vmods= preWire[n].virtualMods; - tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods); - pOld->preserve[n].mask= preWire[n].realMods|tmp; - } - } - if (wire->preserve) - map= (CARD8 *)&preWire[wire->nMapEntries]; - else map= (CARD8 *)&mapWire[wire->nMapEntries]; - } - else map= (CARD8 *)&wire[1]; - wire = (xkbKeyTypeWireDesc *)map; - } - first= req->firstType; - last= first+req->nTypes-1; /* last changed type */ - if (changes->map.changed&XkbKeyTypesMask) { - int oldLast; - oldLast= changes->map.first_type+changes->map.num_types-1; - if (changes->map.first_typemap.first_type; - if (oldLast>last) - last= oldLast; - } - changes->map.changed|= XkbKeyTypesMask; - changes->map.first_type = first; - changes->map.num_types = (last-first)+1; - return (char *)wire; -} - -static char * -SetKeySyms( ClientPtr client, - XkbDescPtr xkb, - xkbSetMapReq * req, - xkbSymMapWireDesc * wire, - XkbChangesPtr changes, - DeviceIntPtr dev) -{ -register unsigned i,s; -XkbSymMapPtr oldMap; -KeySym * newSyms; -KeySym * pSyms; -unsigned first,last; - - oldMap = &xkb->map->key_sym_map[req->firstKeySym]; - for (i=0;inKeySyms;i++,oldMap++) { - pSyms = (KeySym *)&wire[1]; - if (wire->nSyms>0) { - newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms); - for (s=0;snSyms;s++) { - newSyms[s]= pSyms[s]; - } - if (client->swapped) { - int n; - for (s=0;snSyms;s++) { - swapl(&newSyms[s],n); - } - } - } - oldMap->kt_index[0] = wire->ktIndex[0]; - oldMap->kt_index[1] = wire->ktIndex[1]; - oldMap->kt_index[2] = wire->ktIndex[2]; - oldMap->kt_index[3] = wire->ktIndex[3]; - oldMap->group_info = wire->groupInfo; - oldMap->width = wire->width; - wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; - } - first= req->firstKeySym; - last= first+req->nKeySyms-1; - if (changes->map.changed&XkbKeySymsMask) { - int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1); - if (changes->map.first_key_symmap.first_key_sym; - if (oldLast>last) - last= oldLast; - } - changes->map.changed|= XkbKeySymsMask; - changes->map.first_key_sym = first; - changes->map.num_key_syms = (last-first+1); - - s= 0; - for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { - if (XkbKeyNumGroups(xkb,i)>s) - s= XkbKeyNumGroups(xkb,i); - } - if (s!=xkb->ctrls->num_groups) { - xkbControlsNotify cn; - XkbControlsRec old; - cn.keycode= 0; - cn.eventType= 0; - cn.requestMajor= XkbReqCode; - cn.requestMinor= X_kbSetMap; - old= *xkb->ctrls; - xkb->ctrls->num_groups= s; - if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,FALSE)) - XkbSendControlsNotify(dev,&cn); - } - return (char *)wire; -} - -static char * -SetKeyActions( XkbDescPtr xkb, - xkbSetMapReq * req, - CARD8 * wire, - XkbChangesPtr changes) -{ -register unsigned i,first,last; -CARD8 * nActs = wire; -XkbAction * newActs; - - wire+= XkbPaddedSize(req->nKeyActs); - for (i=0;inKeyActs;i++) { - if (nActs[i]==0) - xkb->server->key_acts[i+req->firstKeyAct]= 0; - else { - newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]); - memcpy((char *)newActs,(char *)wire, - nActs[i]*SIZEOF(xkbActionWireDesc)); - wire+= nActs[i]*SIZEOF(xkbActionWireDesc); - } - } - first= req->firstKeyAct; - last= (first+req->nKeyActs-1); - if (changes->map.changed&XkbKeyActionsMask) { - int oldLast; - oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; - if (changes->map.first_key_actmap.first_key_act; - if (oldLast>last) - last= oldLast; - } - changes->map.changed|= XkbKeyActionsMask; - changes->map.first_key_act= first; - changes->map.num_key_acts= (last-first+1); - return (char *)wire; -} - -static char * -SetKeyBehaviors( XkbSrvInfoPtr xkbi, - xkbSetMapReq *req, - xkbBehaviorWireDesc *wire, - XkbChangesPtr changes) -{ -register unsigned i; -int maxRG = -1; -XkbDescPtr xkb = xkbi->desc; -XkbServerMapPtr server = xkb->server; -unsigned first,last; - - first= req->firstKeyBehavior; - last= req->firstKeyBehavior+req->nKeyBehaviors-1; - memset(&server->behaviors[first], 0, req->nKeyBehaviors*sizeof(XkbBehavior)); - for (i=0;itotalKeyBehaviors;i++) { - if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) { - server->behaviors[wire->key].type= wire->type; - server->behaviors[wire->key].data= wire->data; - if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG)) - maxRG= wire->data + 1; - } - wire++; - } - - if (maxRG>(int)xkbi->nRadioGroups) { - int sz = maxRG*sizeof(XkbRadioGroupRec); - if (xkbi->radioGroups) - xkbi->radioGroups= realloc(xkbi->radioGroups,sz); - else xkbi->radioGroups= calloc(1, sz); - if (xkbi->radioGroups) { - if (xkbi->nRadioGroups) - memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0, - (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec)); - xkbi->nRadioGroups= maxRG; - } - else xkbi->nRadioGroups= 0; - /* should compute members here */ - } - if (changes->map.changed&XkbKeyBehaviorsMask) { - unsigned oldLast; - oldLast= changes->map.first_key_behavior+ - changes->map.num_key_behaviors-1; - if (changes->map.first_key_behaviorfirstKeyBehavior) - first= changes->map.first_key_behavior; - if (oldLast>last) - last= oldLast; - } - changes->map.changed|= XkbKeyBehaviorsMask; - changes->map.first_key_behavior = first; - changes->map.num_key_behaviors = (last-first+1); - return (char *)wire; -} - -static char * -SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, - XkbChangesPtr changes) -{ -register int i,bit,nMods; -XkbServerMapPtr srv = xkbi->desc->server; - - if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) - return (char *)wire; - for (i=nMods=0,bit=1;ivirtualMods&bit) { - if (srv->vmods[i]!=wire[nMods]) { - changes->map.changed|= XkbVirtualModsMask; - changes->map.vmods|= bit; - srv->vmods[i]= wire[nMods]; - } - nMods++; - } - } - return (char *)(wire+XkbPaddedSize(nMods)); -} - -static char * -SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, - XkbChangesPtr changes) -{ -register unsigned i,first,last; -XkbServerMapPtr xkb = xkbi->desc->server; -CARD8 * start; - - start= wire; - first= req->firstKeyExplicit; - last= req->firstKeyExplicit+req->nKeyExplicit-1; - memset(&xkb->explicit[first], 0, req->nKeyExplicit); - for (i=0;itotalKeyExplicit;i++,wire+= 2) { - xkb->explicit[wire[0]]= wire[1]; - } - if (first>0) { - if (changes->map.changed&XkbExplicitComponentsMask) { - int oldLast; - oldLast= changes->map.first_key_explicit+ - changes->map.num_key_explicit-1; - if (changes->map.first_key_explicitmap.first_key_explicit; - if (oldLast>last) - last= oldLast; - } - changes->map.first_key_explicit= first; - changes->map.num_key_explicit= (last-first)+1; - } - wire+= XkbPaddedSize(wire-start)-(wire-start); - return (char *)wire; -} - -static char * -SetModifierMap( XkbSrvInfoPtr xkbi, - xkbSetMapReq * req, - CARD8 * wire, - XkbChangesPtr changes) -{ -register unsigned i,first,last; -XkbClientMapPtr xkb = xkbi->desc->map; -CARD8 * start; - - start= wire; - first= req->firstModMapKey; - last= req->firstModMapKey+req->nModMapKeys-1; - memset(&xkb->modmap[first], 0, req->nModMapKeys); - for (i=0;itotalModMapKeys;i++,wire+= 2) { - xkb->modmap[wire[0]]= wire[1]; - } - if (first>0) { - if (changes->map.changed&XkbModifierMapMask) { - int oldLast; - oldLast= changes->map.first_modmap_key+ - changes->map.num_modmap_keys-1; - if (changes->map.first_modmap_keymap.first_modmap_key; - if (oldLast>last) - last= oldLast; - } - changes->map.first_modmap_key= first; - changes->map.num_modmap_keys= (last-first)+1; - } - wire+= XkbPaddedSize(wire-start)-(wire-start); - return (char *)wire; -} - -static char * -SetVirtualModMap( XkbSrvInfoPtr xkbi, - xkbSetMapReq * req, - xkbVModMapWireDesc * wire, - XkbChangesPtr changes) -{ -register unsigned i,first,last; -XkbServerMapPtr srv = xkbi->desc->server; - - first= req->firstVModMapKey; - last= req->firstVModMapKey+req->nVModMapKeys-1; - memset(&srv->vmodmap[first], 0, req->nVModMapKeys*sizeof(unsigned short)); - for (i=0;itotalVModMapKeys;i++,wire++) { - srv->vmodmap[wire->key]= wire->vmods; - } - if (first>0) { - if (changes->map.changed&XkbVirtualModMapMask) { - int oldLast; - oldLast= changes->map.first_vmodmap_key+ - changes->map.num_vmodmap_keys-1; - if (changes->map.first_vmodmap_keymap.first_vmodmap_key; - if (oldLast>last) - last= oldLast; - } - changes->map.first_vmodmap_key= first; - changes->map.num_vmodmap_keys= (last-first)+1; - } - return (char *)wire; -} - -/** - * Check if the given request can be applied to the given device but don't - * actually do anything.. - */ -static int -_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values) -{ - XkbSrvInfoPtr xkbi; - XkbDescPtr xkb; - int error; - int nTypes = 0, nActions; - CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = {0}; - CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = {0}; - XkbSymMapPtr map; - int i; - - xkbi= dev->key->xkbInfo; - xkb = xkbi->desc; - - if ((xkb->min_key_code != req->minKeyCode)|| - (xkb->max_key_code != req->maxKeyCode)) { - if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */ - req->minKeyCode= xkb->min_key_code; - req->maxKeyCode= xkb->max_key_code; - } - else { - if (!XkbIsLegalKeycode(req->minKeyCode)) { - client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode); - return BadValue; - } - if (req->minKeyCode > req->maxKeyCode) { - client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode); - return BadMatch; - } - } - } - - if ((req->present & XkbKeyTypesMask) && - (!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values, - &nTypes,mapWidths))) { - client->errorValue = nTypes; - return BadValue; - } - - /* symsPerKey/mapWidths must be filled regardless of client-side flags */ - map = &xkb->map->key_sym_map[xkb->min_key_code]; - for (i=xkb->min_key_code;imax_key_code;i++,map++) { - register int g,ng,w; - ng= XkbNumGroups(map->group_info); - for (w=g=0;gkt_index[g]>=(unsigned)nTypes) { - client->errorValue = _XkbErrCode4(0x13,i,g,map->kt_index[g]); - return 0; - } - if (mapWidths[map->kt_index[g]]>w) - w= mapWidths[map->kt_index[g]]; - } - symsPerKey[i] = w*ng; - } - - if ((req->present & XkbKeySymsMask) && - (!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey, - (xkbSymMapWireDesc **)&values,&error))) { - client->errorValue = error; - return BadValue; - } - - if ((req->present & XkbKeyActionsMask) && - (!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey, - (CARD8 **)&values,&nActions))) { - client->errorValue = nActions; - return BadValue; - } - - if ((req->present & XkbKeyBehaviorsMask) && - (!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) { - client->errorValue = error; - return BadValue; - } - - if ((req->present & XkbVirtualModsMask) && - (!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) { - client->errorValue= error; - return BadValue; - } - if ((req->present&XkbExplicitComponentsMask) && - (!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) { - client->errorValue= error; - return BadValue; - } - if ((req->present&XkbModifierMapMask) && - (!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) { - client->errorValue= error; - return BadValue; - } - if ((req->present&XkbVirtualModMapMask) && - (!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) { - client->errorValue= error; - return BadValue; - } - - if (((values-((char *)req))/4)!= req->length) { - ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n"); - client->errorValue = values-((char *)&req[1]); - return BadLength; - } - - return Success; -} - -/** - * Apply the given request on the given device. - */ -static int -_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char *values) -{ - XkbEventCauseRec cause; - XkbChangesRec change; - Bool sentNKN; - XkbSrvInfoPtr xkbi; - XkbDescPtr xkb; - - xkbi= dev->key->xkbInfo; - xkb = xkbi->desc; - - XkbSetCauseXkbReq(&cause,X_kbSetMap,client); - memset(&change, 0, sizeof(change)); - sentNKN = FALSE; - if ((xkb->min_key_code!=req->minKeyCode)|| - (xkb->max_key_code!=req->maxKeyCode)) { - Status status; - xkbNewKeyboardNotify nkn; - nkn.deviceID = nkn.oldDeviceID = dev->id; - nkn.oldMinKeyCode = xkb->min_key_code; - nkn.oldMaxKeyCode = xkb->max_key_code; - status= XkbChangeKeycodeRange(xkb, req->minKeyCode, - req->maxKeyCode, &change); - if (status != Success) - return status; /* oh-oh. what about the other keyboards? */ - nkn.minKeyCode = xkb->min_key_code; - nkn.maxKeyCode = xkb->max_key_code; - nkn.requestMajor = XkbReqCode; - nkn.requestMinor = X_kbSetMap; - nkn.changed = XkbNKN_KeycodesMask; - XkbSendNewKeyboardNotify(dev,&nkn); - sentNKN = TRUE; - } - - if (req->present&XkbKeyTypesMask) { - values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change); - if (!values) goto allocFailure; - } - if (req->present&XkbKeySymsMask) { - values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev); - if (!values) goto allocFailure; - } - if (req->present&XkbKeyActionsMask) { - values = SetKeyActions(xkb,req,(CARD8 *)values,&change); - if (!values) goto allocFailure; - } - if (req->present&XkbKeyBehaviorsMask) { - values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change); - if (!values) goto allocFailure; - } - if (req->present&XkbVirtualModsMask) - values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change); - if (req->present&XkbExplicitComponentsMask) - values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change); - if (req->present&XkbModifierMapMask) - values= SetModifierMap(xkbi,req,(CARD8 *)values,&change); - if (req->present&XkbVirtualModMapMask) - values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change); - if (((values-((char *)req))/4)!=req->length) { - ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n"); - client->errorValue = values-((char *)&req[1]); - return BadLength; - } - if (req->flags&XkbSetMapRecomputeActions) { - KeyCode first,last,firstMM,lastMM; - if (change.map.num_key_syms>0) { - first= change.map.first_key_sym; - last= first+change.map.num_key_syms-1; - } - else first= last= 0; - if (change.map.num_modmap_keys>0) { - firstMM= change.map.first_modmap_key; - lastMM= first+change.map.num_modmap_keys-1; - } - else firstMM= lastMM= 0; - if ((last>0) && (lastMM>0)) { - if (firstMMlast) - last= lastMM; - } - else if (lastMM>0) { - first= firstMM; - last= lastMM; - } - if (last>0) { - unsigned check= 0; - XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause); - if (check) - XkbCheckSecondaryEffects(xkbi,check,&change,&cause); - } - } - if (!sentNKN) - XkbSendNotification(dev,&change,&cause); - - return Success; -allocFailure: - return BadAlloc; -} - - -int -ProcXkbSetMap(ClientPtr client) -{ - DeviceIntPtr dev; - char * tmp; - int rc; - - REQUEST(xkbSetMapReq); - REQUEST_AT_LEAST_SIZE(xkbSetMapReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); - CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask); - - tmp = (char *)&stuff[1]; - - /* Check if we can to the SetMap on the requested device. If this - succeeds, do the same thing for all extension devices (if needed). - If any of them fails, fail. */ - rc = _XkbSetMapChecks(client, dev, stuff, tmp); - - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - { - rc = _XkbSetMapChecks(client, other, stuff, tmp); - if (rc != Success) - return rc; - } - } - } - } - - /* We know now that we will succed with the SetMap. In theory anyway. */ - rc = _XkbSetMap(client, dev, stuff, tmp); - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - _XkbSetMap(client, other, stuff, tmp); - /* ignore rc. if the SetMap failed although the check above - reported true there isn't much we can do. we still need to - set all other devices, hoping that at least they stay in - sync. */ - } - } - } - - return Success; -} - -/***====================================================================***/ - -static Status -XkbComputeGetCompatMapReplySize( XkbCompatMapPtr compat, - xkbGetCompatMapReply * rep) -{ -unsigned size,nGroups; - - nGroups= 0; - if (rep->groups!=0) { - register int i,bit; - for (i=0,bit=1;igroups&bit) - nGroups++; - } - } - size= nGroups*SIZEOF(xkbModsWireDesc); - size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc)); - rep->length= size/4; - return Success; -} - -static int -XkbSendCompatMap( ClientPtr client, - XkbCompatMapPtr compat, - xkbGetCompatMapReply * rep) -{ -char * data; -int size; - - size= rep->length*4; - if (size>0) { - data = malloc(size); - if (data) { - register unsigned i,bit; - xkbModsWireDesc * grp; - XkbSymInterpretPtr sym= &compat->sym_interpret[rep->firstSI]; - xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; - for (i=0;inSI;i++,sym++,wire++) { - wire->sym= sym->sym; - wire->mods= sym->mods; - wire->match= sym->match; - wire->virtualMod= sym->virtual_mod; - wire->flags= sym->flags; - memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc); - if (client->swapped) { - register int n; - swapl(&wire->sym,n); - } - } - if (rep->groups) { - grp = (xkbModsWireDesc *)wire; - for (i=0,bit=1;igroups&bit) { - grp->mask= compat->groups[i].mask; - grp->realMods= compat->groups[i].real_mods; - grp->virtualMods= compat->groups[i].vmods; - if (client->swapped) { - register int n; - swaps(&grp->virtualMods,n); - } - grp++; - } - } - wire= (xkbSymInterpretWireDesc*)grp; - } - } - else return BadAlloc; - } - else data= NULL; - - if (client->swapped) { - register int n; - swaps(&rep->sequenceNumber,n); - swapl(&rep->length,n); - swaps(&rep->firstSI,n); - swaps(&rep->nSI,n); - swaps(&rep->nTotalSI,n); - } - - WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep); - if (data) { - WriteToClient(client, size, data); - free((char *)data); - } - return Success; -} - -int -ProcXkbGetCompatMap(ClientPtr client) -{ - xkbGetCompatMapReply rep; - DeviceIntPtr dev; - XkbDescPtr xkb; - XkbCompatMapPtr compat; - - REQUEST(xkbGetCompatMapReq); - REQUEST_SIZE_MATCH(xkbGetCompatMapReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - - xkb = dev->key->xkbInfo->desc; - compat= xkb->compat; - - rep.type = X_Reply; - rep.deviceID = dev->id; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.firstSI = stuff->firstSI; - rep.nSI = stuff->nSI; - if (stuff->getAllSI) { - rep.firstSI = 0; - rep.nSI = compat->num_si; - } - else if ((((unsigned)stuff->nSI)>0)&& - ((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) { - client->errorValue = _XkbErrCode2(0x05,compat->num_si); - return BadValue; - } - rep.nTotalSI = compat->num_si; - rep.groups= stuff->groups; - XkbComputeGetCompatMapReplySize(compat,&rep); - return XkbSendCompatMap(client,compat,&rep); -} - -/** - * Apply the given request on the given device. - * If dryRun is TRUE, then value checks are performed, but the device isn't - * modified. - */ -static int -_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev, - xkbSetCompatMapReq *req, char* data, BOOL dryRun) -{ - XkbSrvInfoPtr xkbi; - XkbDescPtr xkb; - XkbCompatMapPtr compat; - int nGroups; - unsigned i,bit; - - xkbi = dev->key->xkbInfo; - xkb = xkbi->desc; - compat = xkb->compat; - - if ((req->nSI>0)||(req->truncateSI)) { - xkbSymInterpretWireDesc *wire; - if (req->firstSI>compat->num_si) { - client->errorValue = _XkbErrCode2(0x02,compat->num_si); - return BadValue; - } - wire= (xkbSymInterpretWireDesc *)data; - wire+= req->nSI; - data = (char *)wire; - } - - nGroups= 0; - if (req->groups!=0) { - for (i=0,bit=1;igroups&bit ) - nGroups++; - } - } - data+= nGroups*SIZEOF(xkbModsWireDesc); - if (((data-((char *)req))/4)!=req->length) { - return BadLength; - } - - /* Done all the checks we can do */ - if (dryRun) - return Success; - - data = (char *)&req[1]; - if (req->nSI>0) { - xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; - XkbSymInterpretPtr sym; - if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) { - compat->num_si= req->firstSI+req->nSI; - compat->sym_interpret= realloc(compat->sym_interpret, - compat->num_si * sizeof(XkbSymInterpretRec)); - if (!compat->sym_interpret) { - compat->num_si= 0; - return BadAlloc; - } - } - else if (req->truncateSI) { - compat->num_si = req->firstSI+req->nSI; - } - sym = &compat->sym_interpret[req->firstSI]; - for (i=0;inSI;i++,wire++,sym++) { - if (client->swapped) { - int n; - swapl(&wire->sym,n); - } - sym->sym= wire->sym; - sym->mods= wire->mods; - sym->match= wire->match; - sym->flags= wire->flags; - sym->virtual_mod= wire->virtualMod; - memcpy((char *)&sym->act,(char *)&wire->act, - SIZEOF(xkbActionWireDesc)); - } - data = (char *)wire; - } - else if (req->truncateSI) { - compat->num_si = req->firstSI; - } - - if (req->groups!=0) { - unsigned i, bit; - xkbModsWireDesc *wire = (xkbModsWireDesc *)data; - for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { - if (req->groups & bit) { - if (client->swapped) { - int n; - swaps(&wire->virtualMods,n); - } - compat->groups[i].mask= wire->realMods; - compat->groups[i].real_mods= wire->realMods; - compat->groups[i].vmods= wire->virtualMods; - if (wire->virtualMods!=0) { - unsigned tmp; - tmp= XkbMaskForVMask(xkb,wire->virtualMods); - compat->groups[i].mask|= tmp; - } - data+= SIZEOF(xkbModsWireDesc); - wire= (xkbModsWireDesc *)data; - } - } - } - i= XkbPaddedSize((data-((char *)req))); - if ((i/4)!=req->length) { - ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n"); - return BadLength; - } - - if (dev->xkb_interest) { - xkbCompatMapNotify ev; - ev.deviceID = dev->id; - ev.changedGroups = req->groups; - ev.firstSI = req->firstSI; - ev.nSI = req->nSI; - ev.nTotalSI = compat->num_si; - XkbSendCompatMapNotify(dev,&ev); - } - - if (req->recomputeActions) { - XkbChangesRec change; - unsigned check; - XkbEventCauseRec cause; - - XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client); - memset(&change, 0, sizeof(XkbChangesRec)); - XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check, - &cause); - if (check) - XkbCheckSecondaryEffects(xkbi,check,&change,&cause); - XkbSendNotification(dev,&change,&cause); - } - return Success; -} - -int -ProcXkbSetCompatMap(ClientPtr client) -{ - DeviceIntPtr dev; - char *data; - int rc; - - REQUEST(xkbSetCompatMapReq); - REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); - - data = (char *)&stuff[1]; - - /* check first using a dry-run */ - rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE); - if (rc != Success) - return rc; - if (stuff->deviceSpec == XkbUseCoreKbd) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - { - /* dry-run */ - rc = _XkbSetCompatMap(client, other, stuff, data, TRUE); - if (rc != Success) - return rc; - } - } - } - } - - /* Yay, the dry-runs succeed. Let's apply */ - rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE); - if (rc != Success) - return rc; - if (stuff->deviceSpec == XkbUseCoreKbd) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - { - rc = _XkbSetCompatMap(client, other, stuff, data, FALSE); - if (rc != Success) - return rc; - } - } - } - } - - return Success; -} - -/***====================================================================***/ - -int -ProcXkbGetIndicatorState(ClientPtr client) -{ - xkbGetIndicatorStateReply rep; - XkbSrvLedInfoPtr sli; - DeviceIntPtr dev; - register int i; - - REQUEST(xkbGetIndicatorStateReq); - REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); - - sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, - XkbXI_IndicatorStateMask); - if (!sli) - return BadAlloc; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.deviceID = dev->id; - rep.state = sli->effectiveState; - - if (client->swapped) { - swaps(&rep.sequenceNumber,i); - swapl(&rep.state,i); - } - WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep); - return Success; -} - -/***====================================================================***/ - -static Status -XkbComputeGetIndicatorMapReplySize( - XkbIndicatorPtr indicators, - xkbGetIndicatorMapReply *rep) -{ -register int i,bit; -int nIndicators; - - rep->realIndicators = indicators->phys_indicators; - for (i=nIndicators=0,bit=1;iwhich&bit) - nIndicators++; - } - rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4; - return Success; -} - -static int -XkbSendIndicatorMap( ClientPtr client, - XkbIndicatorPtr indicators, - xkbGetIndicatorMapReply * rep) -{ -int length; -CARD8 * map; -register int i; -register unsigned bit; - - length = rep->length*4; - if (length>0) { - CARD8 *to; - to= map= malloc(length); - if (map) { - xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *)to; - for (i=0,bit=1;iwhich&bit) { - wire->flags= indicators->maps[i].flags; - wire->whichGroups= indicators->maps[i].which_groups; - wire->groups= indicators->maps[i].groups; - wire->whichMods= indicators->maps[i].which_mods; - wire->mods= indicators->maps[i].mods.mask; - wire->realMods= indicators->maps[i].mods.real_mods; - wire->virtualMods= indicators->maps[i].mods.vmods; - wire->ctrls= indicators->maps[i].ctrls; - if (client->swapped) { - register int n; - swaps(&wire->virtualMods,n); - swapl(&wire->ctrls,n); - } - wire++; - } - } - to = (CARD8 *)wire; - if ((to-map)!=length) { - client->errorValue = _XkbErrCode2(0xff,length); - free(map); - return BadLength; - } - } - else return BadAlloc; - } - else map = NULL; - if (client->swapped) { - swaps(&rep->sequenceNumber,i); - swapl(&rep->length,i); - swapl(&rep->which,i); - swapl(&rep->realIndicators,i); - } - WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep); - if (map) { - WriteToClient(client, length, (char *)map); - free((char *)map); - } - return Success; -} - -int -ProcXkbGetIndicatorMap(ClientPtr client) -{ -xkbGetIndicatorMapReply rep; -DeviceIntPtr dev; -XkbDescPtr xkb; -XkbIndicatorPtr leds; - - REQUEST(xkbGetIndicatorMapReq); - REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - - xkb= dev->key->xkbInfo->desc; - leds= xkb->indicators; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.deviceID = dev->id; - rep.which = stuff->which; - XkbComputeGetIndicatorMapReplySize(leds,&rep); - return XkbSendIndicatorMap(client,leds,&rep); -} - -/** - * Apply the given map to the given device. Which specifies which components - * to apply. - */ -static int -_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev, - int which, xkbIndicatorMapWireDesc *desc) -{ - XkbSrvInfoPtr xkbi; - XkbSrvLedInfoPtr sli; - XkbEventCauseRec cause; - int i, bit; - - xkbi = dev->key->xkbInfo; - - sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, - XkbXI_IndicatorMapsMask); - if (!sli) - return BadAlloc; - - for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { - if (which & bit) { - sli->maps[i].flags = desc->flags; - sli->maps[i].which_groups = desc->whichGroups; - sli->maps[i].groups = desc->groups; - sli->maps[i].which_mods = desc->whichMods; - sli->maps[i].mods.mask = desc->mods; - sli->maps[i].mods.real_mods = desc->mods; - sli->maps[i].mods.vmods= desc->virtualMods; - sli->maps[i].ctrls = desc->ctrls; - if (desc->virtualMods!=0) { - unsigned tmp; - tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods); - sli->maps[i].mods.mask= desc->mods|tmp; - } - desc++; - } - } - - XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client); - XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause); - - return Success; -} - -int -ProcXkbSetIndicatorMap(ClientPtr client) -{ - int i, bit; - int nIndicators; - DeviceIntPtr dev; - xkbIndicatorMapWireDesc *from; - int rc; - - REQUEST(xkbSetIndicatorMapReq); - REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); - - if (stuff->which==0) - return Success; - - for (nIndicators=i=0,bit=1;iwhich&bit) - nIndicators++; - } - if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+ - (nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) { - return BadLength; - } - - from = (xkbIndicatorMapWireDesc *)&stuff[1]; - for (i=0,bit=1;iwhich&bit) { - if (client->swapped) { - int n; - swaps(&from->virtualMods,n); - swapl(&from->ctrls,n); - } - CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup); - CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods); - from++; - } - } - - from = (xkbIndicatorMapWireDesc *)&stuff[1]; - rc = _XkbSetIndicatorMap(client, dev, stuff->which, from); - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess); - if (rc == Success) - _XkbSetIndicatorMap(client, other, stuff->which, from); - } - } - } - - return Success; -} - -/***====================================================================***/ - -int -ProcXkbGetNamedIndicator(ClientPtr client) -{ - DeviceIntPtr dev; - xkbGetNamedIndicatorReply rep; - register int i = 0; - XkbSrvLedInfoPtr sli; - XkbIndicatorMapPtr map = NULL; - - REQUEST(xkbGetNamedIndicatorReq); - REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); - CHK_ATOM_ONLY(stuff->indicator); - - sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0); - if (!sli) - return BadAlloc; - - i= 0; - map= NULL; - if ((sli->names)&&(sli->maps)) { - for (i=0;iindicator==sli->names[i]) { - map= &sli->maps[i]; - break; - } - } - } - - rep.type= X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.deviceID = dev->id; - rep.indicator= stuff->indicator; - if (map!=NULL) { - rep.found= TRUE; - rep.on= ((sli->effectiveState&(1<physIndicators&(1<flags; - rep.whichGroups= map->which_groups; - rep.groups= map->groups; - rep.whichMods= map->which_mods; - rep.mods= map->mods.mask; - rep.realMods= map->mods.real_mods; - rep.virtualMods= map->mods.vmods; - rep.ctrls= map->ctrls; - rep.supported= TRUE; - } - else { - rep.found= FALSE; - rep.on= FALSE; - rep.realIndicator= FALSE; - rep.ndx= XkbNoIndicator; - rep.flags= 0; - rep.whichGroups= 0; - rep.groups= 0; - rep.whichMods= 0; - rep.mods= 0; - rep.realMods= 0; - rep.virtualMods= 0; - rep.ctrls= 0; - rep.supported= TRUE; - } - if ( client->swapped ) { - register int n; - swapl(&rep.length,n); - swaps(&rep.sequenceNumber,n); - swapl(&rep.indicator,n); - swaps(&rep.virtualMods,n); - swapl(&rep.ctrls,n); - } - - WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep); - return Success; -} - - -/** - * Find the IM on the device. - * Returns the map, or NULL if the map doesn't exist. - * If the return value is NULL, led_return is undefined. Otherwise, led_return - * is set to the led index of the map. - */ -static XkbIndicatorMapPtr -_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, - int *led_return) -{ - XkbIndicatorMapPtr map; - - /* search for the right indicator */ - map = NULL; - if (sli->names && sli->maps) { - int led; - - for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { - if (sli->names[led] == indicator) { - map= &sli->maps[led]; - *led_return = led; - break; - } - } - } - - return map; -} - -/** - * Creates an indicator map on the device. If dryRun is TRUE, it only checks - * if creation is possible, but doesn't actually create it. - */ -static int -_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator, - int ledClass, int ledID, - XkbIndicatorMapPtr *map_return, int *led_return, - Bool dryRun) -{ - XkbSrvLedInfoPtr sli; - XkbIndicatorMapPtr map; - int led; - - sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask); - if (!sli) - return BadAlloc; - - map = _XkbFindNamedIndicatorMap(sli, indicator, &led); - - if (!map) - { - /* find first unused indicator maps and assign the name to it */ - for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) { - if ((sli->names) && (sli->maps) && (sli->names[led] == None) && - (!XkbIM_InUse(&sli->maps[led]))) - { - map = &sli->maps[led]; - if (!dryRun) - sli->names[led] = indicator; - break; - } - } - } - - if (!map) - return BadAlloc; - - *led_return = led; - *map_return = map; - return Success; -} - -static int -_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev, - xkbSetNamedIndicatorReq *stuff) -{ - unsigned int extDevReason; - unsigned int statec, namec, mapc; - XkbSrvLedInfoPtr sli; - int led = 0; - XkbIndicatorMapPtr map; - DeviceIntPtr kbd; - XkbEventCauseRec cause; - xkbExtensionDeviceNotify ed; - XkbChangesRec changes; - int rc; - - rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass, - stuff->ledID, &map, &led, FALSE); - if (rc != Success || !map) /* oh-oh */ - return rc; - - sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, - XkbXI_IndicatorsMask); - if (!sli) - return BadAlloc; - - namec = mapc = statec = 0; - extDevReason = 0; - - namec |= (1<namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0); - extDevReason |= XkbXI_IndicatorNamesMask; - - if (stuff->setMap) { - map->flags = stuff->flags; - map->which_groups = stuff->whichGroups; - map->groups = stuff->groups; - map->which_mods = stuff->whichMods; - map->mods.mask = stuff->realMods; - map->mods.real_mods = stuff->realMods; - map->mods.vmods= stuff->virtualMods; - map->ctrls = stuff->ctrls; - mapc|= (1<setState) && ((map->flags & XkbIM_NoExplicit) == 0)) - { - if (stuff->on) sli->explicitState |= (1<explicitState &= ~(1<effectiveState ^ sli->explicitState) & (1 << led)); - } - - memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify)); - memset((char *)&changes, 0, sizeof(XkbChangesRec)); - XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client); - if (namec) - XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); - if (mapc) - XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); - if (statec) - XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); - - kbd = dev; - if ((sli->flags&XkbSLI_HasOwnState)==0) - kbd = inputInfo.keyboard; - XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); - - return Success; -} - -int -ProcXkbSetNamedIndicator(ClientPtr client) -{ - int rc; - DeviceIntPtr dev; - int led = 0; - XkbIndicatorMapPtr map; - - REQUEST(xkbSetNamedIndicatorReq); - REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); - CHK_ATOM_ONLY(stuff->indicator); - CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup); - CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods); - - /* Dry-run for checks */ - rc = _XkbCreateIndicatorMap(dev, stuff->indicator, - stuff->ledClass, stuff->ledID, - &map, &led, TRUE); - if (rc != Success || !map) /* couldn't be created or didn't exist */ - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd || - stuff->deviceSpec == XkbUseCorePtr) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev && - (other->kbdfeed || other->leds) && - (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) - { - rc = _XkbCreateIndicatorMap(other, stuff->indicator, - stuff->ledClass, stuff->ledID, - &map, &led, TRUE); - if (rc != Success || !map) - return rc; - } - } - } - - /* All checks passed, let's do it */ - rc = _XkbSetNamedIndicator(client, dev, stuff); - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd || - stuff->deviceSpec == XkbUseCorePtr) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev && - (other->kbdfeed || other->leds) && - (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) - { - _XkbSetNamedIndicator(client, other, stuff); - } - } - } - - return Success; -} - -/***====================================================================***/ - -static CARD32 -_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count) -{ -register unsigned int i,bit,nAtoms; -register CARD32 atomsPresent; - - for (i=nAtoms=atomsPresent=0,bit=1;iminKeyCode= xkb->min_key_code; - rep->maxKeyCode= xkb->max_key_code; - which= rep->which; - length= 0; - if (xkb->names!=NULL) { - if (which&XkbKeycodesNameMask) length++; - if (which&XkbGeometryNameMask) length++; - if (which&XkbSymbolsNameMask) length++; - if (which&XkbPhysSymbolsNameMask) length++; - if (which&XkbTypesNameMask) length++; - if (which&XkbCompatNameMask) length++; - } - else which&= ~XkbComponentNamesMask; - - if (xkb->map!=NULL) { - if (which&XkbKeyTypeNamesMask) - length+= xkb->map->num_types; - rep->nTypes= xkb->map->num_types; - if (which&XkbKTLevelNamesMask) { - XkbKeyTypePtr pType = xkb->map->types; - int nKTLevels = 0; - - length+= XkbPaddedSize(xkb->map->num_types)/4; - for (i=0;imap->num_types;i++,pType++) { - if (pType->level_names!=NULL) - nKTLevels+= pType->num_levels; - } - rep->nKTLevels= nKTLevels; - length+= nKTLevels; - } - } - else { - rep->nTypes= 0; - rep->nKTLevels= 0; - which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask); - } - - rep->minKeyCode= xkb->min_key_code; - rep->maxKeyCode= xkb->max_key_code; - rep->indicators= 0; - rep->virtualMods= 0; - rep->groupNames= 0; - if (xkb->names!=NULL) { - if (which&XkbIndicatorNamesMask) { - int nLeds; - rep->indicators= - _XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds); - length+= nLeds; - if (nLeds==0) - which&= ~XkbIndicatorNamesMask; - } - - if (which&XkbVirtualModNamesMask) { - int nVMods; - rep->virtualMods= - _XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods); - length+= nVMods; - if (nVMods==0) - which&= ~XkbVirtualModNamesMask; - } - - if (which&XkbGroupNamesMask) { - int nGroups; - rep->groupNames= - _XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups); - length+= nGroups; - if (nGroups==0) - which&= ~XkbGroupNamesMask; - } - - if ((which&XkbKeyNamesMask)&&(xkb->names->keys)) - length+= rep->nKeys; - else which&= ~XkbKeyNamesMask; - - if ((which&XkbKeyAliasesMask)&& - (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) { - rep->nKeyAliases= xkb->names->num_key_aliases; - length+= rep->nKeyAliases*2; - } - else { - which&= ~XkbKeyAliasesMask; - rep->nKeyAliases= 0; - } - - if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0)) - length+= xkb->names->num_rg; - else which&= ~XkbRGNamesMask; - } - else { - which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask); - which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask); - which&= ~XkbRGNamesMask; - } - - rep->length= length; - rep->which= which; - return Success; -} - -static int -XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep) -{ -register unsigned i,length,which; -char * start; -char * desc; -register int n; - - length= rep->length*4; - which= rep->which; - if (client->swapped) { - swaps(&rep->sequenceNumber,n); - swapl(&rep->length,n); - swapl(&rep->which,n); - swaps(&rep->virtualMods,n); - swapl(&rep->indicators,n); - } - - start = desc = malloc(length); - if ( !start ) - return BadAlloc; - if (xkb->names) { - if (which&XkbKeycodesNameMask) { - *((CARD32 *)desc)= xkb->names->keycodes; - if (client->swapped) { - swapl(desc,n); - } - desc+= 4; - } - if (which&XkbGeometryNameMask) { - *((CARD32 *)desc)= xkb->names->geometry; - if (client->swapped) { - swapl(desc,n); - } - desc+= 4; - } - if (which&XkbSymbolsNameMask) { - *((CARD32 *)desc)= xkb->names->symbols; - if (client->swapped) { - swapl(desc,n); - } - desc+= 4; - } - if (which&XkbPhysSymbolsNameMask) { - register CARD32 *atm= (CARD32 *)desc; - atm[0]= (CARD32)xkb->names->phys_symbols; - if (client->swapped) { - swapl(&atm[0],n); - } - desc+= 4; - } - if (which&XkbTypesNameMask) { - *((CARD32 *)desc)= (CARD32)xkb->names->types; - if (client->swapped) { - swapl(desc,n); - } - desc+= 4; - } - if (which&XkbCompatNameMask) { - *((CARD32 *)desc)= (CARD32)xkb->names->compat; - if (client->swapped) { - swapl(desc,n); - } - desc+= 4; - } - if (which&XkbKeyTypeNamesMask) { - register CARD32 *atm= (CARD32 *)desc; - register XkbKeyTypePtr type= xkb->map->types; - - for (i=0;imap->num_types;i++,atm++,type++) { - *atm= (CARD32)type->name; - if (client->swapped) { - swapl(atm,n); - } - } - desc= (char *)atm; - } - if (which&XkbKTLevelNamesMask && xkb->map) { - XkbKeyTypePtr type = xkb->map->types; - register CARD32 *atm; - for (i=0;inTypes;i++,type++) { - *desc++ = type->num_levels; - } - desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes; - - atm= (CARD32 *)desc; - type = xkb->map->types; - for (i=0;imap->num_types;i++,type++) { - register unsigned l; - if (type->level_names) { - for (l=0;lnum_levels;l++,atm++) { - *atm= type->level_names[l]; - if (client->swapped) { - swapl(atm,n); - } - } - desc+= type->num_levels*4; - } - } - } - if (which&XkbIndicatorNamesMask) { - desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators, - client->swapped); - } - if (which&XkbVirtualModNamesMask) { - desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods, - client->swapped); - } - if (which&XkbGroupNamesMask) { - desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups, - client->swapped); - } - if (which&XkbKeyNamesMask) { - for (i=0;inKeys;i++,desc+= sizeof(XkbKeyNameRec)) { - *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey]; - } - } - if (which&XkbKeyAliasesMask) { - XkbKeyAliasPtr pAl; - pAl= xkb->names->key_aliases; - for (i=0;inKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) { - *((XkbKeyAliasPtr)desc)= *pAl; - } - } - if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) { - register CARD32 *atm= (CARD32 *)desc; - for (i=0;inRadioGroups;i++,atm++) { - *atm= (CARD32)xkb->names->radio_groups[i]; - if (client->swapped) { - swapl(atm,n); - } - } - desc+= rep->nRadioGroups*4; - } - } - - if ((desc-start)!=(length)) { - ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n", - length, (unsigned long)(desc-start)); - } - WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep); - WriteToClient(client, length, start); - free((char *)start); - return Success; -} - -int -ProcXkbGetNames(ClientPtr client) -{ - DeviceIntPtr dev; - XkbDescPtr xkb; - xkbGetNamesReply rep; - - REQUEST(xkbGetNamesReq); - REQUEST_SIZE_MATCH(xkbGetNamesReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); - - xkb = dev->key->xkbInfo->desc; - memset(&rep, 0, sizeof(xkbGetNamesReply)); - rep.type= X_Reply; - rep.sequenceNumber= client->sequence; - rep.length = 0; - rep.deviceID = dev->id; - rep.which = stuff->which; - rep.nTypes = xkb->map->num_types; - rep.firstKey = xkb->min_key_code; - rep.nKeys = XkbNumKeys(xkb); - if (xkb->names!=NULL) { - rep.nKeyAliases= xkb->names->num_key_aliases; - rep.nRadioGroups = xkb->names->num_rg; - } - else { - rep.nKeyAliases= rep.nRadioGroups= 0; - } - XkbComputeGetNamesReplySize(xkb,&rep); - return XkbSendNames(client,xkb,&rep); -} - -/***====================================================================***/ - -static CARD32 * -_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError) -{ -register int i; - - for (i=0;ikey->xkbInfo->desc; - names = xkb->names; - - - if (stuff->which & XkbKeyTypeNamesMask) { - int i; - CARD32 *old; - if ( stuff->nTypes<1 ) { - client->errorValue = _XkbErrCode2(0x02,stuff->nTypes); - return BadValue; - } - if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) { - client->errorValue = _XkbErrCode4(0x03,stuff->firstType, - stuff->nTypes, - xkb->map->num_types); - return BadValue; - } - if (((unsigned)stuff->firstType)<=XkbLastRequiredType) { - client->errorValue = _XkbErrCode2(0x04,stuff->firstType); - return BadAccess; - } - old= tmp; - tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad); - if (!tmp) { - client->errorValue= bad; - return BadAtom; - } - for (i=0;inTypes;i++,old++) { - if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i)) - client->errorValue= _XkbErrCode2(0x05,i); - } - } - if (stuff->which&XkbKTLevelNamesMask) { - unsigned i; - XkbKeyTypePtr type; - CARD8 * width; - if ( stuff->nKTLevels<1 ) { - client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels); - return BadValue; - } - if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>= - xkb->map->num_types) { - client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel, - stuff->nKTLevels,xkb->map->num_types); - return BadValue; - } - width = (CARD8 *)tmp; - tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); - type = &xkb->map->types[stuff->firstKTLevel]; - for (i=0;inKTLevels;i++,type++) { - if (width[i]==0) - continue; - else if (width[i]!=type->num_levels) { - client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel, - type->num_levels,width[i]); - return BadMatch; - } - tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad); - if (!tmp) { - client->errorValue= bad; - return BadAtom; - } - } - } - if (stuff->which&XkbIndicatorNamesMask) { - if (stuff->indicators==0) { - client->errorValue= 0x08; - return BadMatch; - } - tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators, - client->swapped,&bad); - if (!tmp) { - client->errorValue= bad; - return BadAtom; - } - } - if (stuff->which&XkbVirtualModNamesMask) { - if (stuff->virtualMods==0) { - client->errorValue= 0x09; - return BadMatch; - } - tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods, - (CARD32)stuff->virtualMods, - client->swapped,&bad); - if (!tmp) { - client->errorValue = bad; - return BadAtom; - } - } - if (stuff->which&XkbGroupNamesMask) { - if (stuff->groupNames==0) { - client->errorValue= 0x0a; - return BadMatch; - } - tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups, - (CARD32)stuff->groupNames, - client->swapped,&bad); - if (!tmp) { - client->errorValue = bad; - return BadAtom; - } - } - if (stuff->which&XkbKeyNamesMask) { - if (stuff->firstKey<(unsigned)xkb->min_key_code) { - client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code, - stuff->firstKey); - return BadValue; - } - if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)|| - (stuff->nKeys<1)) { - client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code, - stuff->firstKey,stuff->nKeys); - return BadValue; - } - tmp+= stuff->nKeys; - } - if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) { - tmp+= stuff->nKeyAliases*2; - } - if (stuff->which&XkbRGNamesMask) { - if ( stuff->nRadioGroups<1 ) { - client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups); - return BadValue; - } - tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad); - if (!tmp) { - client->errorValue= bad; - return BadAtom; - } - } - if ((tmp-((CARD32 *)stuff))!=stuff->length) { - client->errorValue = stuff->length; - return BadLength; - } - - - - return Success; -} - -static int -_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff) -{ - XkbDescRec *xkb; - XkbNamesRec *names; - CARD32 *tmp; - xkbNamesNotify nn; - - tmp = (CARD32 *)&stuff[1]; - xkb = dev->key->xkbInfo->desc; - names = xkb->names; - - if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups, - stuff->nKeyAliases)!=Success) { - return BadAlloc; - } - - memset(&nn, 0, sizeof(xkbNamesNotify)); - nn.changed= stuff->which; - tmp = (CARD32 *)&stuff[1]; - if (stuff->which&XkbKeycodesNameMask) - names->keycodes= *tmp++; - if (stuff->which&XkbGeometryNameMask) - names->geometry= *tmp++; - if (stuff->which&XkbSymbolsNameMask) - names->symbols= *tmp++; - if (stuff->which&XkbPhysSymbolsNameMask) - names->phys_symbols= *tmp++; - if (stuff->which&XkbTypesNameMask) - names->types= *tmp++; - if (stuff->which&XkbCompatNameMask) - names->compat= *tmp++; - if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) { - register unsigned i; - register XkbKeyTypePtr type; - - type= &xkb->map->types[stuff->firstType]; - for (i=0;inTypes;i++,type++) { - type->name= *tmp++; - } - nn.firstType= stuff->firstType; - nn.nTypes= stuff->nTypes; - } - if (stuff->which&XkbKTLevelNamesMask) { - register XkbKeyTypePtr type; - register unsigned i; - CARD8 *width; - - width = (CARD8 *)tmp; - tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); - type= &xkb->map->types[stuff->firstKTLevel]; - for (i=0;inKTLevels;i++,type++) { - if (width[i]>0) { - if (type->level_names) { - register unsigned n; - for (n=0;nlevel_names[n]= tmp[n]; - } - } - tmp+= width[i]; - } - } - nn.firstLevelName= 0; - nn.nLevelNames= stuff->nTypes; - } - if (stuff->which&XkbIndicatorNamesMask) { - tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators, - stuff->indicators); - nn.changedIndicators= stuff->indicators; - } - if (stuff->which&XkbVirtualModNamesMask) { - tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods, - stuff->virtualMods); - nn.changedVirtualMods= stuff->virtualMods; - } - if (stuff->which&XkbGroupNamesMask) { - tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups, - stuff->groupNames); - nn.changedVirtualMods= stuff->groupNames; - } - if (stuff->which&XkbKeyNamesMask) { - memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp, - stuff->nKeys*XkbKeyNameLength); - tmp+= stuff->nKeys; - nn.firstKey= stuff->firstKey; - nn.nKeys= stuff->nKeys; - } - if (stuff->which&XkbKeyAliasesMask) { - if (stuff->nKeyAliases>0) { - register int na= stuff->nKeyAliases; - if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success) - return BadAlloc; - memcpy((char *)names->key_aliases,(char *)tmp, - stuff->nKeyAliases*sizeof(XkbKeyAliasRec)); - tmp+= stuff->nKeyAliases*2; - } - else if (names->key_aliases!=NULL) { - free(names->key_aliases); - names->key_aliases= NULL; - names->num_key_aliases= 0; - } - nn.nAliases= names->num_key_aliases; - } - if (stuff->which&XkbRGNamesMask) { - if (stuff->nRadioGroups>0) { - register unsigned i,nrg; - nrg= stuff->nRadioGroups; - if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success) - return BadAlloc; - - for (i=0;inRadioGroups;i++) { - names->radio_groups[i]= tmp[i]; - } - tmp+= stuff->nRadioGroups; - } - else if (names->radio_groups) { - free(names->radio_groups); - names->radio_groups= NULL; - names->num_rg= 0; - } - nn.nRadioGroups= names->num_rg; - } - if (nn.changed) { - Bool needExtEvent; - needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0; - XkbSendNamesNotify(dev,&nn); - if (needExtEvent) { - XkbSrvLedInfoPtr sli; - xkbExtensionDeviceNotify edev; - register int i; - register unsigned bit; - - sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, - XkbXI_IndicatorsMask); - sli->namesPresent= 0; - for (i=0,bit=1;iindicators[i]!=None) - sli->namesPresent|= bit; - } - memset(&edev, 0, sizeof(xkbExtensionDeviceNotify)); - edev.reason= XkbXI_IndicatorNamesMask; - edev.ledClass= KbdFeedbackClass; - edev.ledID= dev->kbdfeed->ctrl.id; - edev.ledsDefined= sli->namesPresent|sli->mapsPresent; - edev.ledState= sli->effectiveState; - edev.firstBtn= 0; - edev.nBtns= 0; - edev.supported= XkbXI_AllFeaturesMask; - edev.unsupported= 0; - XkbSendExtensionDeviceNotify(dev,client,&edev); - } - } - return Success; -} - -int -ProcXkbSetNames(ClientPtr client) -{ - DeviceIntPtr dev; - CARD32 *tmp; - Atom bad; - int rc; - - REQUEST(xkbSetNamesReq); - REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); - CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); - - /* check device-independent stuff */ - tmp = (CARD32 *)&stuff[1]; - - if (stuff->which&XkbKeycodesNameMask) { - tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); - if (!tmp) { - client->errorValue = bad; - return BadAtom; - } - } - if (stuff->which&XkbGeometryNameMask) { - tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); - if (!tmp) { - client->errorValue = bad; - return BadAtom; - } - } - if (stuff->which&XkbSymbolsNameMask) { - tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); - if (!tmp) { - client->errorValue = bad; - return BadAtom; - } - } - if (stuff->which&XkbPhysSymbolsNameMask) { - tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); - if (!tmp) { - client->errorValue= bad; - return BadAtom; - } - } - if (stuff->which&XkbTypesNameMask) { - tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); - if (!tmp) { - client->errorValue = bad; - return BadAtom; - } - } - if (stuff->which&XkbCompatNameMask) { - tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); - if (!tmp) { - client->errorValue = bad; - return BadAtom; - } - } - - /* start of device-dependent tests */ - rc = _XkbSetNamesCheck(client, dev, stuff, tmp); - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - { - rc = _XkbSetNamesCheck(client, other, stuff, tmp); - if (rc != Success) - return rc; - } - } - } - } - - /* everything is okay -- update names */ - - rc = _XkbSetNames(client, dev, stuff); - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - _XkbSetNames(client, other, stuff); - } - } - } - - /* everything is okay -- update names */ - - return Success; -} - -/***====================================================================***/ - -#include "xkbgeom.h" - -#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4) - -static char * -XkbWriteCountedString(char *wire,char *str,Bool swap) -{ - CARD16 len,*pLen; - - if (!str) - return wire; - - len= strlen(str); - pLen= (CARD16 *)wire; - *pLen= len; - if (swap) { - register int n; - swaps(pLen,n); - } - memcpy(&wire[2],str,len); - wire+= ((2+len+3)/4)*4; - return wire; -} - -static int -XkbSizeGeomProperties(XkbGeometryPtr geom) -{ -register int i,size; -XkbPropertyPtr prop; - - for (size=i=0,prop=geom->properties;inum_properties;i++,prop++) { - size+= XkbSizeCountedString(prop->name); - size+= XkbSizeCountedString(prop->value); - } - return size; -} - -static char * -XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap) -{ -register int i; -register XkbPropertyPtr prop; - - for (i=0,prop=geom->properties;inum_properties;i++,prop++) { - wire= XkbWriteCountedString(wire,prop->name,swap); - wire= XkbWriteCountedString(wire,prop->value,swap); - } - return wire; -} - -static int -XkbSizeGeomKeyAliases(XkbGeometryPtr geom) -{ - return geom->num_key_aliases*(2*XkbKeyNameLength); -} - -static char * -XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap) -{ -register int sz; - - sz= geom->num_key_aliases*(XkbKeyNameLength*2); - if (sz>0) { - memcpy(wire,(char *)geom->key_aliases,sz); - wire+= sz; - } - return wire; -} - -static int -XkbSizeGeomColors(XkbGeometryPtr geom) -{ -register int i,size; -register XkbColorPtr color; - - for (i=size=0,color=geom->colors;inum_colors;i++,color++) { - size+= XkbSizeCountedString(color->spec); - } - return size; -} - -static char * -XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap) -{ -register int i; -register XkbColorPtr color; - - for (i=0,color=geom->colors;inum_colors;i++,color++) { - wire= XkbWriteCountedString(wire,color->spec,swap); - } - return wire; -} - -static int -XkbSizeGeomShapes(XkbGeometryPtr geom) -{ -register int i,size; -register XkbShapePtr shape; - - for (i=size=0,shape=geom->shapes;inum_shapes;i++,shape++) { - register int n; - register XkbOutlinePtr ol; - size+= SIZEOF(xkbShapeWireDesc); - for (n=0,ol=shape->outlines;nnum_outlines;n++,ol++) { - size+= SIZEOF(xkbOutlineWireDesc); - size+= ol->num_points*SIZEOF(xkbPointWireDesc); - } - } - return size; -} - -static char * -XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap) -{ -int i; -XkbShapePtr shape; -xkbShapeWireDesc * shapeWire; - - for (i=0,shape=geom->shapes;inum_shapes;i++,shape++) { - register int o; - XkbOutlinePtr ol; - xkbOutlineWireDesc * olWire; - shapeWire= (xkbShapeWireDesc *)wire; - shapeWire->name= shape->name; - shapeWire->nOutlines= shape->num_outlines; - if (shape->primary!=NULL) - shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary); - else shapeWire->primaryNdx= XkbNoShape; - if (shape->approx!=NULL) - shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx); - else shapeWire->approxNdx= XkbNoShape; - if (swap) { - register int n; - swapl(&shapeWire->name,n); - } - wire= (char *)&shapeWire[1]; - for (o=0,ol=shape->outlines;onum_outlines;o++,ol++) { - register int p; - XkbPointPtr pt; - xkbPointWireDesc * ptWire; - olWire= (xkbOutlineWireDesc *)wire; - olWire->nPoints= ol->num_points; - olWire->cornerRadius= ol->corner_radius; - wire= (char *)&olWire[1]; - ptWire= (xkbPointWireDesc *)wire; - for (p=0,pt=ol->points;pnum_points;p++,pt++) { - ptWire[p].x= pt->x; - ptWire[p].y= pt->y; - if (swap) { - register int n; - swaps(&ptWire[p].x,n); - swaps(&ptWire[p].y,n); - } - } - wire= (char *)&ptWire[ol->num_points]; - } - } - return wire; -} - -static int -XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad) -{ -register int i,size; - - for (i=size=0;iany.type==XkbTextDoodad) { - size+= XkbSizeCountedString(doodad->text.text); - size+= XkbSizeCountedString(doodad->text.font); - } - else if (doodad->any.type==XkbLogoDoodad) { - size+= XkbSizeCountedString(doodad->logo.logo_name); - } - } - return size; -} - -static char * -XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap) -{ -register int i; -xkbDoodadWireDesc * doodadWire; - - for (i=0;iany.name= doodad->any.name; - doodadWire->any.type= doodad->any.type; - doodadWire->any.priority= doodad->any.priority; - doodadWire->any.top= doodad->any.top; - doodadWire->any.left= doodad->any.left; - if (swap) { - register int n; - swapl(&doodadWire->any.name,n); - swaps(&doodadWire->any.top,n); - swaps(&doodadWire->any.left,n); - } - switch (doodad->any.type) { - case XkbOutlineDoodad: - case XkbSolidDoodad: - doodadWire->shape.angle= doodad->shape.angle; - doodadWire->shape.colorNdx= doodad->shape.color_ndx; - doodadWire->shape.shapeNdx= doodad->shape.shape_ndx; - if (swap) { - register int n; - swaps(&doodadWire->shape.angle,n); - } - break; - case XkbTextDoodad: - doodadWire->text.angle= doodad->text.angle; - doodadWire->text.width= doodad->text.width; - doodadWire->text.height= doodad->text.height; - doodadWire->text.colorNdx= doodad->text.color_ndx; - if (swap) { - register int n; - swaps(&doodadWire->text.angle,n); - swaps(&doodadWire->text.width,n); - swaps(&doodadWire->text.height,n); - } - wire= XkbWriteCountedString(wire,doodad->text.text,swap); - wire= XkbWriteCountedString(wire,doodad->text.font,swap); - break; - case XkbIndicatorDoodad: - doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx; - doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx; - doodadWire->indicator.offColorNdx= - doodad->indicator.off_color_ndx; - break; - case XkbLogoDoodad: - doodadWire->logo.angle= doodad->logo.angle; - doodadWire->logo.colorNdx= doodad->logo.color_ndx; - doodadWire->logo.shapeNdx= doodad->logo.shape_ndx; - wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap); - break; - default: - ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n", - doodad->any.type); - ErrorF("[xkb] Ignored\n"); - break; - } - } - return wire; -} - -static char * -XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap) -{ -register int r; -XkbOverlayRowPtr row; -xkbOverlayWireDesc * olWire; - - olWire= (xkbOverlayWireDesc *)wire; - olWire->name= ol->name; - olWire->nRows= ol->num_rows; - if (swap) { - register int n; - swapl(&olWire->name,n); - } - wire= (char *)&olWire[1]; - for (r=0,row=ol->rows;rnum_rows;r++,row++) { - unsigned int k; - XkbOverlayKeyPtr key; - xkbOverlayRowWireDesc * rowWire; - rowWire= (xkbOverlayRowWireDesc *)wire; - rowWire->rowUnder= row->row_under; - rowWire->nKeys= row->num_keys; - wire= (char *)&rowWire[1]; - for (k=0,key=row->keys;knum_keys;k++,key++) { - xkbOverlayKeyWireDesc * keyWire; - keyWire= (xkbOverlayKeyWireDesc *)wire; - memcpy(keyWire->over,key->over.name,XkbKeyNameLength); - memcpy(keyWire->under,key->under.name,XkbKeyNameLength); - wire= (char *)&keyWire[1]; - } - } - return wire; -} - -static int -XkbSizeGeomSections(XkbGeometryPtr geom) -{ -register int i,size; -XkbSectionPtr section; - - for (i=size=0,section=geom->sections;inum_sections;i++,section++) { - size+= SIZEOF(xkbSectionWireDesc); - if (section->rows) { - int r; - XkbRowPtr row; - for (r=0,row=section->rows;rnum_rows;row++,r++) { - size+= SIZEOF(xkbRowWireDesc); - size+= row->num_keys*SIZEOF(xkbKeyWireDesc); - } - } - if (section->doodads) - size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads); - if (section->overlays) { - int o; - XkbOverlayPtr ol; - for (o=0,ol=section->overlays;onum_overlays;o++,ol++) { - int r; - XkbOverlayRowPtr row; - size+= SIZEOF(xkbOverlayWireDesc); - for (r=0,row=ol->rows;rnum_rows;r++,row++) { - size+= SIZEOF(xkbOverlayRowWireDesc); - size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc); - } - } - } - } - return size; -} - -static char * -XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap) -{ -register int i; -XkbSectionPtr section; -xkbSectionWireDesc * sectionWire; - - for (i=0,section=geom->sections;inum_sections;i++,section++) { - sectionWire= (xkbSectionWireDesc *)wire; - sectionWire->name= section->name; - sectionWire->top= section->top; - sectionWire->left= section->left; - sectionWire->width= section->width; - sectionWire->height= section->height; - sectionWire->angle= section->angle; - sectionWire->priority= section->priority; - sectionWire->nRows= section->num_rows; - sectionWire->nDoodads= section->num_doodads; - sectionWire->nOverlays= section->num_overlays; - sectionWire->pad= 0; - if (swap) { - register int n; - swapl(§ionWire->name,n); - swaps(§ionWire->top,n); - swaps(§ionWire->left,n); - swaps(§ionWire->width,n); - swaps(§ionWire->height,n); - swaps(§ionWire->angle,n); - } - wire= (char *)§ionWire[1]; - if (section->rows) { - int r; - XkbRowPtr row; - xkbRowWireDesc * rowWire; - for (r=0,row=section->rows;rnum_rows;r++,row++) { - rowWire= (xkbRowWireDesc *)wire; - rowWire->top= row->top; - rowWire->left= row->left; - rowWire->nKeys= row->num_keys; - rowWire->vertical= row->vertical; - rowWire->pad= 0; - if (swap) { - register int n; - swaps(&rowWire->top,n); - swaps(&rowWire->left,n); - } - wire= (char *)&rowWire[1]; - if (row->keys) { - int k; - XkbKeyPtr key; - xkbKeyWireDesc * keyWire; - keyWire= (xkbKeyWireDesc *)wire; - for (k=0,key=row->keys;knum_keys;k++,key++) { - memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength); - keyWire[k].gap= key->gap; - keyWire[k].shapeNdx= key->shape_ndx; - keyWire[k].colorNdx= key->color_ndx; - if (swap) { - register int n; - swaps(&keyWire[k].gap,n); - } - } - wire= (char *)&keyWire[row->num_keys]; - } - } - } - if (section->doodads) { - wire= XkbWriteGeomDoodads(wire, - section->num_doodads,section->doodads, - swap); - } - if (section->overlays) { - register int o; - for (o=0;onum_overlays;o++) { - wire= XkbWriteGeomOverlay(wire,§ion->overlays[o],swap); - } - } - } - return wire; -} - -static Status -XkbComputeGetGeometryReplySize( XkbGeometryPtr geom, - xkbGetGeometryReply * rep, - Atom name) -{ -int len; - - if (geom!=NULL) { - len= XkbSizeCountedString(geom->label_font); - len+= XkbSizeGeomProperties(geom); - len+= XkbSizeGeomColors(geom); - len+= XkbSizeGeomShapes(geom); - len+= XkbSizeGeomSections(geom); - len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads); - len+= XkbSizeGeomKeyAliases(geom); - rep->length= len/4; - rep->found= TRUE; - rep->name= geom->name; - rep->widthMM= geom->width_mm; - rep->heightMM= geom->height_mm; - rep->nProperties= geom->num_properties; - rep->nColors= geom->num_colors; - rep->nShapes= geom->num_shapes; - rep->nSections= geom->num_sections; - rep->nDoodads= geom->num_doodads; - rep->nKeyAliases= geom->num_key_aliases; - rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color); - rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color); - } - else { - rep->length= 0; - rep->found= FALSE; - rep->name= name; - rep->widthMM= rep->heightMM= 0; - rep->nProperties= rep->nColors= rep->nShapes= 0; - rep->nSections= rep->nDoodads= 0; - rep->nKeyAliases= 0; - rep->labelColorNdx= rep->baseColorNdx= 0; - } - return Success; -} - -static int -XkbSendGeometry( ClientPtr client, - XkbGeometryPtr geom, - xkbGetGeometryReply * rep, - Bool freeGeom) -{ - char *desc,*start; - int len; - - if (geom!=NULL) { - len= rep->length*4; - start= desc= malloc(len); - if (!start) - return BadAlloc; - desc= XkbWriteCountedString(desc,geom->label_font,client->swapped); - if ( rep->nProperties>0 ) - desc = XkbWriteGeomProperties(desc,geom,client->swapped); - if ( rep->nColors>0 ) - desc = XkbWriteGeomColors(desc,geom,client->swapped); - if ( rep->nShapes>0 ) - desc = XkbWriteGeomShapes(desc,geom,client->swapped); - if ( rep->nSections>0 ) - desc = XkbWriteGeomSections(desc,geom,client->swapped); - if ( rep->nDoodads>0 ) - desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads, - client->swapped); - if ( rep->nKeyAliases>0 ) - desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped); - if ((desc-start)!=(len)) { - ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n", - len, (unsigned long)(desc-start)); - } - } - else { - len= 0; - start= NULL; - } - if (client->swapped) { - register int n; - swaps(&rep->sequenceNumber,n); - swapl(&rep->length,n); - swapl(&rep->name,n); - swaps(&rep->widthMM,n); - swaps(&rep->heightMM,n); - swaps(&rep->nProperties,n); - swaps(&rep->nColors,n); - swaps(&rep->nShapes,n); - swaps(&rep->nSections,n); - swaps(&rep->nDoodads,n); - swaps(&rep->nKeyAliases,n); - } - WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep); - if (len>0) - WriteToClient(client, len, start); - if (start!=NULL) - free((char *)start); - if (freeGeom) - XkbFreeGeometry(geom,XkbGeomAllMask,TRUE); - return Success; -} - -int -ProcXkbGetGeometry(ClientPtr client) -{ - DeviceIntPtr dev; - xkbGetGeometryReply rep; - XkbGeometryPtr geom; - Bool shouldFree; - Status status; - - REQUEST(xkbGetGeometryReq); - REQUEST_SIZE_MATCH(xkbGetGeometryReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - CHK_ATOM_OR_NONE(stuff->name); - - geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree); - rep.type= X_Reply; - rep.deviceID= dev->id; - rep.sequenceNumber= client->sequence; - rep.length= 0; - status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name); - if (status!=Success) - return status; - else return XkbSendGeometry(client,geom,&rep,shouldFree); -} - -/***====================================================================***/ - -static char * -_GetCountedString(char **wire_inout,Bool swap) -{ -char * wire,*str; -CARD16 len,*plen; - - wire= *wire_inout; - plen= (CARD16 *)wire; - if (swap) { - register int n; - swaps(plen,n); - } - len= *plen; - str= malloc(len+1); - if (str) { - memcpy(str,&wire[2],len); - str[len]= '\0'; - } - wire+= XkbPaddedSize(len+2); - *wire_inout= wire; - return str; -} - -static Status -_CheckSetDoodad( char ** wire_inout, - XkbGeometryPtr geom, - XkbSectionPtr section, - ClientPtr client) -{ -char * wire; -xkbDoodadWireDesc * dWire; -XkbDoodadPtr doodad; - - dWire= (xkbDoodadWireDesc *)(*wire_inout); - wire= (char *)&dWire[1]; - if (client->swapped) { - register int n; - swapl(&dWire->any.name,n); - swaps(&dWire->any.top,n); - swaps(&dWire->any.left,n); - swaps(&dWire->any.angle,n); - } - CHK_ATOM_ONLY(dWire->any.name); - doodad= XkbAddGeomDoodad(geom,section,dWire->any.name); - if (!doodad) - return BadAlloc; - doodad->any.type= dWire->any.type; - doodad->any.priority= dWire->any.priority; - doodad->any.top= dWire->any.top; - doodad->any.left= dWire->any.left; - doodad->any.angle= dWire->any.angle; - switch (doodad->any.type) { - case XkbOutlineDoodad: - case XkbSolidDoodad: - if (dWire->shape.colorNdx>=geom->num_colors) { - client->errorValue= _XkbErrCode3(0x40,geom->num_colors, - dWire->shape.colorNdx); - return BadMatch; - } - if (dWire->shape.shapeNdx>=geom->num_shapes) { - client->errorValue= _XkbErrCode3(0x41,geom->num_shapes, - dWire->shape.shapeNdx); - return BadMatch; - } - doodad->shape.color_ndx= dWire->shape.colorNdx; - doodad->shape.shape_ndx= dWire->shape.shapeNdx; - break; - case XkbTextDoodad: - if (dWire->text.colorNdx>=geom->num_colors) { - client->errorValue= _XkbErrCode3(0x42,geom->num_colors, - dWire->text.colorNdx); - return BadMatch; - } - if (client->swapped) { - register int n; - swaps(&dWire->text.width,n); - swaps(&dWire->text.height,n); - } - doodad->text.width= dWire->text.width; - doodad->text.height= dWire->text.height; - doodad->text.color_ndx= dWire->text.colorNdx; - doodad->text.text= _GetCountedString(&wire,client->swapped); - doodad->text.font= _GetCountedString(&wire,client->swapped); - break; - case XkbIndicatorDoodad: - if (dWire->indicator.onColorNdx>=geom->num_colors) { - client->errorValue= _XkbErrCode3(0x43,geom->num_colors, - dWire->indicator.onColorNdx); - return BadMatch; - } - if (dWire->indicator.offColorNdx>=geom->num_colors) { - client->errorValue= _XkbErrCode3(0x44,geom->num_colors, - dWire->indicator.offColorNdx); - return BadMatch; - } - if (dWire->indicator.shapeNdx>=geom->num_shapes) { - client->errorValue= _XkbErrCode3(0x45,geom->num_shapes, - dWire->indicator.shapeNdx); - return BadMatch; - } - doodad->indicator.shape_ndx= dWire->indicator.shapeNdx; - doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx; - doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx; - break; - case XkbLogoDoodad: - if (dWire->logo.colorNdx>=geom->num_colors) { - client->errorValue= _XkbErrCode3(0x46,geom->num_colors, - dWire->logo.colorNdx); - return BadMatch; - } - if (dWire->logo.shapeNdx>=geom->num_shapes) { - client->errorValue= _XkbErrCode3(0x47,geom->num_shapes, - dWire->logo.shapeNdx); - return BadMatch; - } - doodad->logo.color_ndx= dWire->logo.colorNdx; - doodad->logo.shape_ndx= dWire->logo.shapeNdx; - doodad->logo.logo_name= _GetCountedString(&wire,client->swapped); - break; - default: - client->errorValue= _XkbErrCode2(0x4F,dWire->any.type); - return BadValue; - } - *wire_inout= wire; - return Success; -} - -static Status -_CheckSetOverlay( char ** wire_inout, - XkbGeometryPtr geom, - XkbSectionPtr section, - ClientPtr client) -{ -register int r; -char * wire; -XkbOverlayPtr ol; -xkbOverlayWireDesc * olWire; -xkbOverlayRowWireDesc * rWire; - - wire= *wire_inout; - olWire= (xkbOverlayWireDesc *)wire; - if (client->swapped) { - register int n; - swapl(&olWire->name,n); - } - CHK_ATOM_ONLY(olWire->name); - ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows); - rWire= (xkbOverlayRowWireDesc *)&olWire[1]; - for (r=0;rnRows;r++) { - register int k; - xkbOverlayKeyWireDesc * kWire; - XkbOverlayRowPtr row; - - if (rWire->rowUnder>section->num_rows) { - client->errorValue= _XkbErrCode4(0x20,r,section->num_rows, - rWire->rowUnder); - return BadMatch; - } - row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys); - kWire= (xkbOverlayKeyWireDesc *)&rWire[1]; - for (k=0;knKeys;k++,kWire++) { - if (XkbAddGeomOverlayKey(ol,row, - (char *)kWire->over,(char *)kWire->under)==NULL) { - client->errorValue= _XkbErrCode3(0x21,r,k); - return BadMatch; - } - } - rWire= (xkbOverlayRowWireDesc *)kWire; - } - olWire= (xkbOverlayWireDesc *)rWire; - wire= (char *)olWire; - *wire_inout= wire; - return Success; -} - -static Status -_CheckSetSections( XkbGeometryPtr geom, - xkbSetGeometryReq * req, - char ** wire_inout, - ClientPtr client) -{ -Status status; -register int s; -char * wire; -xkbSectionWireDesc * sWire; -XkbSectionPtr section; - - wire= *wire_inout; - if (req->nSections<1) - return Success; - sWire= (xkbSectionWireDesc *)wire; - for (s=0;snSections;s++) { - register int r; - xkbRowWireDesc * rWire; - if (client->swapped) { - register int n; - swapl(&sWire->name,n); - swaps(&sWire->top,n); - swaps(&sWire->left,n); - swaps(&sWire->width,n); - swaps(&sWire->height,n); - swaps(&sWire->angle,n); - } - CHK_ATOM_ONLY(sWire->name); - section= XkbAddGeomSection(geom,sWire->name,sWire->nRows, - sWire->nDoodads,sWire->nOverlays); - if (!section) - return BadAlloc; - section->priority= sWire->priority; - section->top= sWire->top; - section->left= sWire->left; - section->width= sWire->width; - section->height= sWire->height; - section->angle= sWire->angle; - rWire= (xkbRowWireDesc *)&sWire[1]; - for (r=0;rnRows;r++) { - register int k; - XkbRowPtr row; - xkbKeyWireDesc * kWire; - if (client->swapped) { - register int n; - swaps(&rWire->top,n); - swaps(&rWire->left,n); - } - row= XkbAddGeomRow(section,rWire->nKeys); - if (!row) - return BadAlloc; - row->top= rWire->top; - row->left= rWire->left; - row->vertical= rWire->vertical; - kWire= (xkbKeyWireDesc *)&rWire[1]; - for (k=0;knKeys;k++) { - XkbKeyPtr key; - key= XkbAddGeomKey(row); - if (!key) - return BadAlloc; - memcpy(key->name.name,kWire[k].name,XkbKeyNameLength); - key->gap= kWire[k].gap; - key->shape_ndx= kWire[k].shapeNdx; - key->color_ndx= kWire[k].colorNdx; - if (key->shape_ndx>=geom->num_shapes) { - client->errorValue= _XkbErrCode3(0x10,key->shape_ndx, - geom->num_shapes); - return BadMatch; - } - if (key->color_ndx>=geom->num_colors) { - client->errorValue= _XkbErrCode3(0x11,key->color_ndx, - geom->num_colors); - return BadMatch; - } - } - rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys]; - } - wire= (char *)rWire; - if (sWire->nDoodads>0) { - register int d; - for (d=0;dnDoodads;d++) { - status=_CheckSetDoodad(&wire,geom,section,client); - if (status!=Success) - return status; - } - } - if (sWire->nOverlays>0) { - register int o; - for (o=0;onOverlays;o++) { - status= _CheckSetOverlay(&wire,geom,section,client); - if (status!=Success) - return status; - } - } - sWire= (xkbSectionWireDesc *)wire; - } - wire= (char *)sWire; - *wire_inout= wire; - return Success; -} - -static Status -_CheckSetShapes( XkbGeometryPtr geom, - xkbSetGeometryReq * req, - char ** wire_inout, - ClientPtr client) -{ -register int i; -char * wire; - - wire= *wire_inout; - if (req->nShapes<1) { - client->errorValue= _XkbErrCode2(0x06,req->nShapes); - return BadValue; - } - else { - xkbShapeWireDesc * shapeWire; - XkbShapePtr shape; - register int o; - shapeWire= (xkbShapeWireDesc *)wire; - for (i=0;inShapes;i++) { - xkbOutlineWireDesc * olWire; - XkbOutlinePtr ol; - shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines); - if (!shape) - return BadAlloc; - olWire= (xkbOutlineWireDesc *)(&shapeWire[1]); - for (o=0;onOutlines;o++) { - register int p; - XkbPointPtr pt; - xkbPointWireDesc * ptWire; - - ol= XkbAddGeomOutline(shape,olWire->nPoints); - if (!ol) - return BadAlloc; - ol->corner_radius= olWire->cornerRadius; - ptWire= (xkbPointWireDesc *)&olWire[1]; - for (p=0,pt=ol->points;pnPoints;p++,pt++) { - pt->x= ptWire[p].x; - pt->y= ptWire[p].y; - if (client->swapped) { - register int n; - swaps(&pt->x,n); - swaps(&pt->y,n); - } - } - ol->num_points= olWire->nPoints; - olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]); - } - if (shapeWire->primaryNdx!=XkbNoShape) - shape->primary= &shape->outlines[shapeWire->primaryNdx]; - if (shapeWire->approxNdx!=XkbNoShape) - shape->approx= &shape->outlines[shapeWire->approxNdx]; - shapeWire= (xkbShapeWireDesc *)olWire; - } - wire= (char *)shapeWire; - } - if (geom->num_shapes!=req->nShapes) { - client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes); - return BadMatch; - } - - *wire_inout= wire; - return Success; -} - -static Status -_CheckSetGeom( XkbGeometryPtr geom, - xkbSetGeometryReq * req, - ClientPtr client) -{ -register int i; -Status status; -char * wire; - - wire= (char *)&req[1]; - geom->label_font= _GetCountedString(&wire,client->swapped); - - for (i=0;inProperties;i++) { - char *name,*val; - name= _GetCountedString(&wire,client->swapped); - if (!name) - return BadAlloc; - val= _GetCountedString(&wire,client->swapped); - if (!val) { - free(name); - return BadAlloc; - } - if (XkbAddGeomProperty(geom,name,val)==NULL) { - free(name); - free(val); - return BadAlloc; - } - free(name); - free(val); - } - - if (req->nColors<2) { - client->errorValue= _XkbErrCode3(0x01,2,req->nColors); - return BadValue; - } - if (req->baseColorNdx>req->nColors) { - client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx); - return BadMatch; - } - if (req->labelColorNdx>req->nColors) { - client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx); - return BadMatch; - } - if (req->labelColorNdx==req->baseColorNdx) { - client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx, - req->labelColorNdx); - return BadMatch; - } - - for (i=0;inColors;i++) { - char *name; - name= _GetCountedString(&wire,client->swapped); - if (!name) - return BadAlloc; - if (!XkbAddGeomColor(geom,name,geom->num_colors)) { - free(name); - return BadAlloc; - } - free(name); - } - if (req->nColors!=geom->num_colors) { - client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors); - return BadMatch; - } - geom->label_color= &geom->colors[req->labelColorNdx]; - geom->base_color= &geom->colors[req->baseColorNdx]; - - if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success) - return status; - - if ((status=_CheckSetSections(geom,req,&wire,client))!=Success) - return status; - - for (i=0;inDoodads;i++) { - status=_CheckSetDoodad(&wire,geom,NULL,client); - if (status!=Success) - return status; - } - - for (i=0;inKeyAliases;i++) { - if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL) - return BadAlloc; - wire+= 2*XkbKeyNameLength; - } - return Success; -} - -static int -_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff) -{ - XkbDescPtr xkb; - Bool new_name; - xkbNewKeyboardNotify nkn; - XkbGeometryPtr geom,old; - XkbGeometrySizesRec sizes; - Status status; - - xkb= dev->key->xkbInfo->desc; - old= xkb->geom; - xkb->geom= NULL; - - sizes.which= XkbGeomAllMask; - sizes.num_properties= stuff->nProperties; - sizes.num_colors= stuff->nColors; - sizes.num_shapes= stuff->nShapes; - sizes.num_sections= stuff->nSections; - sizes.num_doodads= stuff->nDoodads; - sizes.num_key_aliases= stuff->nKeyAliases; - if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) { - xkb->geom= old; - return status; - } - geom= xkb->geom; - geom->name= stuff->name; - geom->width_mm= stuff->widthMM; - geom->height_mm= stuff->heightMM; - if ((status= _CheckSetGeom(geom,stuff,client))!=Success) { - XkbFreeGeometry(geom,XkbGeomAllMask,TRUE); - xkb->geom= old; - return status; - } - new_name= (xkb->names->geometry!=geom->name); - xkb->names->geometry= geom->name; - if (old) - XkbFreeGeometry(old,XkbGeomAllMask,TRUE); - if (new_name) { - xkbNamesNotify nn; - memset(&nn, 0, sizeof(xkbNamesNotify)); - nn.changed= XkbGeometryNameMask; - XkbSendNamesNotify(dev,&nn); - } - nkn.deviceID= nkn.oldDeviceID= dev->id; - nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code; - nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code; - nkn.requestMajor= XkbReqCode; - nkn.requestMinor= X_kbSetGeometry; - nkn.changed= XkbNKN_GeometryMask; - XkbSendNewKeyboardNotify(dev,&nkn); - return Success; -} - -int -ProcXkbSetGeometry(ClientPtr client) -{ - DeviceIntPtr dev; - int rc; - - REQUEST(xkbSetGeometryReq); - REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); - CHK_ATOM_OR_NONE(stuff->name); - - rc = _XkbSetGeometry(client, dev, stuff); - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - _XkbSetGeometry(client, other, stuff); - } - } - } - - return Success; -} - -/***====================================================================***/ - -int -ProcXkbPerClientFlags(ClientPtr client) -{ - DeviceIntPtr dev; - xkbPerClientFlagsReply rep; - XkbInterestPtr interest; - Mask access_mode = DixGetAttrAccess | DixSetAttrAccess; - - REQUEST(xkbPerClientFlagsReq); - REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); - CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask); - CHK_MASK_MATCH(0x02,stuff->change,stuff->value); - - interest = XkbFindClientResource((DevicePtr)dev,client); - memset(&rep, 0, sizeof(xkbPerClientFlagsReply)); - rep.type= X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - if (stuff->change) { - client->xkbClientFlags&= ~stuff->change; - client->xkbClientFlags|= stuff->value; - } - if (stuff->change&XkbPCF_AutoResetControlsMask) { - Bool want; - want= stuff->value&XkbPCF_AutoResetControlsMask; - if (interest && !want) { - interest->autoCtrls= interest->autoCtrlValues= 0; - } - else if (want && (!interest)) { - XID id = FakeClientID(client->index); - if (!AddResource(id,RT_XKBCLIENT,dev)) - return BadAlloc; - interest= XkbAddClientResource((DevicePtr)dev,client,id); - if (!interest) - return BadAlloc; - } - if (interest && want ) { - register unsigned affect; - affect= stuff->ctrlsToChange; - - CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask); - CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls); - CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues); - - interest->autoCtrls&= ~affect; - interest->autoCtrlValues&= ~affect; - interest->autoCtrls|= stuff->autoCtrls&affect; - interest->autoCtrlValues|= stuff->autoCtrlValues&affect; - } - } - rep.supported = XkbPCF_AllFlagsMask; - rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask; - if (interest) { - rep.autoCtrls= interest->autoCtrls; - rep.autoCtrlValues= interest->autoCtrlValues; - } - else { - rep.autoCtrls= rep.autoCtrlValues= 0; - } - if ( client->swapped ) { - register int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.supported,n); - swapl(&rep.value,n); - swapl(&rep.autoCtrls,n); - swapl(&rep.autoCtrlValues,n); - } - WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep); - return Success; -} - -/***====================================================================***/ - -/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */ -/* and wildcards */ -static unsigned char componentSpecLegal[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87, - 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff -}; - -/* same as above but accepts percent, plus and bar too */ -static unsigned char componentExprLegal[] = { - 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87, - 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff -}; - -static char * -GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn) -{ -int len; -register int i; -unsigned char *wire,*str,*tmp,*legal; - - if (allowExpr) legal= &componentExprLegal[0]; - else legal= &componentSpecLegal[0]; - - wire= *pWire; - len= (*(unsigned char *)wire++); - if (len>0) { - str= calloc(1, len+1); - if (str) { - tmp= str; - for (i=0;ixkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - - status= Success; - str= (unsigned char *)&stuff[1]; - memset(&list, 0, sizeof(XkbSrvListInfoRec)); - list.maxRtrn= stuff->maxNames; - list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,FALSE,&status); - list.pattern[_XkbListTypes]= GetComponentSpec(&str,FALSE,&status); - list.pattern[_XkbListCompat]= GetComponentSpec(&str,FALSE,&status); - list.pattern[_XkbListSymbols]= GetComponentSpec(&str,FALSE,&status); - list.pattern[_XkbListGeometry]= GetComponentSpec(&str,FALSE,&status); - if (status!=Success) - return status; - len= str-((unsigned char *)stuff); - if ((XkbPaddedSize(len)/4)!=stuff->length) - return BadLength; - if ((status=XkbDDXList(dev,&list,client))!=Success) { - free(list.pool); - list.pool = NULL; - return status; - } - memset(&rep, 0, sizeof(xkbListComponentsReply)); - rep.type= X_Reply; - rep.deviceID = dev->id; - rep.sequenceNumber = client->sequence; - rep.length = XkbPaddedSize(list.nPool)/4; - rep.nKeymaps = 0; - rep.nKeycodes = list.nFound[_XkbListKeycodes]; - rep.nTypes = list.nFound[_XkbListTypes]; - rep.nCompatMaps = list.nFound[_XkbListCompat]; - rep.nSymbols = list.nFound[_XkbListSymbols]; - rep.nGeometries = list.nFound[_XkbListGeometry]; - rep.extra= 0; - if (list.nTotal>list.maxRtrn) - rep.extra = (list.nTotal-list.maxRtrn); - if (client->swapped) { - register int n; - swaps(&rep.sequenceNumber,n); - swapl(&rep.length,n); - swaps(&rep.nKeymaps,n); - swaps(&rep.nKeycodes,n); - swaps(&rep.nTypes,n); - swaps(&rep.nCompatMaps,n); - swaps(&rep.nSymbols,n); - swaps(&rep.nGeometries,n); - swaps(&rep.extra,n); - } - WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep); - if (list.nPool && list.pool) { - WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool); - free(list.pool); - list.pool= NULL; - } - return Success; -} - -/***====================================================================***/ - -int -ProcXkbGetKbdByName(ClientPtr client) -{ - DeviceIntPtr dev; - DeviceIntPtr tmpd; - xkbGetKbdByNameReply rep; - xkbGetMapReply mrep; - xkbGetCompatMapReply crep; - xkbGetIndicatorMapReply irep; - xkbGetNamesReply nrep; - xkbGetGeometryReply grep; - XkbComponentNamesRec names; - XkbDescPtr xkb, new; - unsigned char * str; - char mapFile[PATH_MAX]; - unsigned len; - unsigned fwant,fneed,reported; - int status; - Bool geom_changed; - XkbSrvLedInfoPtr old_sli; - XkbSrvLedInfoPtr sli; - Mask access_mode = DixGetAttrAccess | DixManageAccess; - - REQUEST(xkbGetKbdByNameReq); - REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); - - xkb = dev->key->xkbInfo->desc; - status= Success; - str= (unsigned char *)&stuff[1]; - if (GetComponentSpec(&str,TRUE,&status)) /* keymap, unsupported */ - return BadMatch; - names.keycodes= GetComponentSpec(&str,TRUE,&status); - names.types= GetComponentSpec(&str,TRUE,&status); - names.compat= GetComponentSpec(&str,TRUE,&status); - names.symbols= GetComponentSpec(&str,TRUE,&status); - names.geometry= GetComponentSpec(&str,TRUE,&status); - if (status!=Success) - return status; - len= str-((unsigned char *)stuff); - if ((XkbPaddedSize(len)/4)!=stuff->length) - return BadLength; - - CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask); - CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask); - - if (stuff->load) - fwant= XkbGBN_AllComponentsMask; - else fwant= stuff->want|stuff->need; - if ((!names.compat)&& - (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) { - names.compat= _XkbDupString("%"); - } - if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) { - names.types= _XkbDupString("%"); - } - if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) { - names.symbols= _XkbDupString("%"); - } - geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0)); - if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) { - names.geometry= _XkbDupString("%"); - geom_changed= FALSE; - } - - memset(mapFile, 0, PATH_MAX); - rep.type= X_Reply; - rep.deviceID = dev->id; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.minKeyCode = xkb->min_key_code; - rep.maxKeyCode = xkb->max_key_code; - rep.loaded= FALSE; - fwant= XkbConvertGetByNameComponents(TRUE,stuff->want)|XkmVirtualModsMask; - fneed= XkbConvertGetByNameComponents(TRUE,stuff->need); - rep.reported= XkbConvertGetByNameComponents(FALSE,fwant|fneed); - if (stuff->load) { - fneed|= XkmKeymapRequired; - fwant|= XkmKeymapLegal; - } - if ((fwant|fneed)&XkmSymbolsMask) { - fneed|= XkmKeyNamesIndex|XkmTypesIndex; - fwant|= XkmIndicatorsIndex; - } - - /* We pass dev in here so we can get the old names out if needed. */ - rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new, - mapFile,PATH_MAX); - rep.newKeyboard= FALSE; - rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0; - - stuff->want|= stuff->need; - if (new==NULL) - rep.reported= 0; - else { - if (stuff->load) - rep.loaded= TRUE; - if (stuff->load || - ((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) { - XkbChangesRec changes; - memset(&changes, 0, sizeof(changes)); - XkbUpdateDescActions(new, - new->min_key_code,XkbNumKeys(new), - &changes); - } - - if (new->map==NULL) - rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask); - else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) { - mrep.type= X_Reply; - mrep.deviceID = dev->id; - mrep.sequenceNumber= client->sequence; - mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2); - mrep.minKeyCode = new->min_key_code; - mrep.maxKeyCode = new->max_key_code; - mrep.present = 0; - mrep.totalSyms = mrep.totalActs = - mrep.totalKeyBehaviors= mrep.totalKeyExplicit= - mrep.totalModMapKeys= mrep.totalVModMapKeys= 0; - if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) { - mrep.present|= XkbKeyTypesMask; - mrep.firstType = 0; - mrep.nTypes = mrep.totalTypes= new->map->num_types; - } - else { - mrep.firstType = mrep.nTypes= 0; - mrep.totalTypes= 0; - } - if (rep.reported&XkbGBN_ClientSymbolsMask) { - mrep.present|= (XkbKeySymsMask|XkbModifierMapMask); - mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code; - mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new); - } - else { - mrep.firstKeySym= mrep.firstModMapKey= 0; - mrep.nKeySyms= mrep.nModMapKeys= 0; - } - if (rep.reported&XkbGBN_ServerSymbolsMask) { - mrep.present|= XkbAllServerInfoMask; - mrep.virtualMods= ~0; - mrep.firstKeyAct = mrep.firstKeyBehavior = - mrep.firstKeyExplicit = new->min_key_code; - mrep.nKeyActs = mrep.nKeyBehaviors = - mrep.nKeyExplicit = XkbNumKeys(new); - mrep.firstVModMapKey= new->min_key_code; - mrep.nVModMapKeys= XkbNumKeys(new); - } - else { - mrep.virtualMods= 0; - mrep.firstKeyAct= mrep.firstKeyBehavior= - mrep.firstKeyExplicit = 0; - mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0; - } - XkbComputeGetMapReplySize(new,&mrep); - rep.length+= SIZEOF(xGenericReply)/4+mrep.length; - } - if (new->compat==NULL) - rep.reported&= ~XkbGBN_CompatMapMask; - else if (rep.reported&XkbGBN_CompatMapMask) { - crep.type= X_Reply; - crep.deviceID= dev->id; - crep.sequenceNumber= client->sequence; - crep.length= 0; - crep.groups= XkbAllGroupsMask; - crep.firstSI= 0; - crep.nSI= crep.nTotalSI= new->compat->num_si; - XkbComputeGetCompatMapReplySize(new->compat,&crep); - rep.length+= SIZEOF(xGenericReply)/4+crep.length; - } - if (new->indicators==NULL) - rep.reported&= ~XkbGBN_IndicatorMapMask; - else if (rep.reported&XkbGBN_IndicatorMapMask) { - irep.type= X_Reply; - irep.deviceID= dev->id; - irep.sequenceNumber= client->sequence; - irep.length= 0; - irep.which= XkbAllIndicatorsMask; - XkbComputeGetIndicatorMapReplySize(new->indicators,&irep); - rep.length+= SIZEOF(xGenericReply)/4+irep.length; - } - if (new->names==NULL) - rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask); - else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) { - nrep.type= X_Reply; - nrep.deviceID= dev->id; - nrep.sequenceNumber= client->sequence; - nrep.length= 0; - nrep.minKeyCode= new->min_key_code; - nrep.maxKeyCode= new->max_key_code; - if (rep.reported&XkbGBN_OtherNamesMask) { - nrep.which= XkbAllNamesMask; - if (new->map!=NULL) - nrep.nTypes= new->map->num_types; - else nrep.nTypes= 0; - nrep.nKTLevels= 0; - nrep.groupNames= XkbAllGroupsMask; - nrep.virtualMods= XkbAllVirtualModsMask; - nrep.indicators= XkbAllIndicatorsMask; - nrep.nRadioGroups= new->names->num_rg; - } - else { - nrep.which= 0; - nrep.nTypes= 0; - nrep.nKTLevels= 0; - nrep.groupNames= 0; - nrep.virtualMods= 0; - nrep.indicators= 0; - nrep.nRadioGroups= 0; - } - if (rep.reported&XkbGBN_KeyNamesMask) { - nrep.which|= XkbKeyNamesMask; - nrep.firstKey= new->min_key_code; - nrep.nKeys= XkbNumKeys(new); - nrep.nKeyAliases= new->names->num_key_aliases; - if (nrep.nKeyAliases) - nrep.which|= XkbKeyAliasesMask; - } - else { - nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask); - nrep.firstKey= nrep.nKeys= 0; - nrep.nKeyAliases= 0; - } - XkbComputeGetNamesReplySize(new,&nrep); - rep.length+= SIZEOF(xGenericReply)/4+nrep.length; - } - if (new->geom==NULL) - rep.reported&= ~XkbGBN_GeometryMask; - else if (rep.reported&XkbGBN_GeometryMask) { - grep.type= X_Reply; - grep.deviceID= dev->id; - grep.sequenceNumber= client->sequence; - grep.length= 0; - grep.found= TRUE; - grep.pad= 0; - grep.widthMM= grep.heightMM= 0; - grep.nProperties= grep.nColors= grep.nShapes= 0; - grep.nSections= grep.nDoodads= 0; - grep.baseColorNdx= grep.labelColorNdx= 0; - XkbComputeGetGeometryReplySize(new->geom,&grep,None); - rep.length+= SIZEOF(xGenericReply)/4+grep.length; - } - } - - reported= rep.reported; - if ( client->swapped ) { - register int n; - swaps(&rep.sequenceNumber,n); - swapl(&rep.length,n); - swaps(&rep.found,n); - swaps(&rep.reported,n); - } - WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep); - if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) - XkbSendMap(client,new,&mrep); - if (reported&XkbGBN_CompatMapMask) - XkbSendCompatMap(client,new->compat,&crep); - if (reported&XkbGBN_IndicatorMapMask) - XkbSendIndicatorMap(client,new->indicators,&irep); - if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask)) - XkbSendNames(client,new,&nrep); - if (reported&XkbGBN_GeometryMask) - XkbSendGeometry(client,new->geom,&grep,FALSE); - if (rep.loaded) { - XkbDescPtr old_xkb; - xkbNewKeyboardNotify nkn; - int i,nG,nTG; - old_xkb= xkb; - xkb= new; - dev->key->xkbInfo->desc= xkb; - new= old_xkb; /* so it'll get freed automatically */ - - *xkb->ctrls= *old_xkb->ctrls; - for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { - nG= XkbKeyNumGroups(xkb,i); - if (nG>=XkbNumKbdGroups) { - nTG= XkbNumKbdGroups; - break; - } - if (nG>nTG) { - nTG= nG; - } - } - xkb->ctrls->num_groups= nTG; - - for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { - if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { - if (tmpd != dev) - XkbCopyDeviceKeymap(tmpd, dev); - - if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { - old_sli = tmpd->kbdfeed->xkb_sli; - tmpd->kbdfeed->xkb_sli = NULL; - sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0); - if (sli) { - sli->explicitState = old_sli->explicitState; - sli->effectiveState = old_sli->effectiveState; - } - tmpd->kbdfeed->xkb_sli = sli; - XkbFreeSrvLedInfo(old_sli); - } - } - } - - nkn.deviceID= nkn.oldDeviceID= dev->id; - nkn.minKeyCode= new->min_key_code; - nkn.maxKeyCode= new->max_key_code; - nkn.oldMinKeyCode= xkb->min_key_code; - nkn.oldMaxKeyCode= xkb->max_key_code; - nkn.requestMajor= XkbReqCode; - nkn.requestMinor= X_kbGetKbdByName; - nkn.changed= XkbNKN_KeycodesMask; - if (geom_changed) - nkn.changed|= XkbNKN_GeometryMask; - XkbSendNewKeyboardNotify(dev,&nkn); - - if (!IsMaster(dev) && dev->u.master) - { - DeviceIntPtr master = dev->u.master; - if (master->u.lastSlave == dev) - { - XkbCopyDeviceKeymap(dev->u.master, dev); - XkbSendNewKeyboardNotify(dev,&nkn); - } - } - } - if ((new!=NULL)&&(new!=xkb)) { - XkbFreeKeyboard(new,XkbAllComponentsMask,TRUE); - new= NULL; - } - free(names.keycodes); - names.keycodes = NULL; - free(names.types); - names.types = NULL; - free(names.compat); - names.compat = NULL; - free(names.symbols); - names.symbols = NULL; - free(names.geometry); - names.geometry = NULL; - return Success; -} - -/***====================================================================***/ - -static int -ComputeDeviceLedInfoSize( DeviceIntPtr dev, - unsigned int what, - XkbSrvLedInfoPtr sli) -{ -int nNames,nMaps; -register unsigned n,bit; - - if (sli==NULL) - return 0; - nNames= nMaps= 0; - if ((what&XkbXI_IndicatorNamesMask)==0) - sli->namesPresent= 0; - if ((what&XkbXI_IndicatorMapsMask)==0) - sli->mapsPresent= 0; - - for (n=0,bit=1;nnames && sli->names[n]!=None) { - sli->namesPresent|= bit; - nNames++; - } - if (sli->maps && XkbIM_InUse(&sli->maps[n])) { - sli->mapsPresent|= bit; - nMaps++; - } - } - return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc)); -} - -static int -CheckDeviceLedFBs( DeviceIntPtr dev, - int class, - int id, - xkbGetDeviceInfoReply * rep, - ClientPtr client) -{ -int nFBs= 0; -int length= 0; -Bool classOk; - - if (class==XkbDfltXIClass) { - if (dev->kbdfeed) class= KbdFeedbackClass; - else if (dev->leds) class= LedFeedbackClass; - else { - client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); - return XkbKeyboardErrorCode; - } - } - classOk= FALSE; - if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { - KbdFeedbackPtr kf; - classOk= TRUE; - for (kf= dev->kbdfeed;(kf);kf=kf->next) { - if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id)) - continue; - nFBs++; - length+= SIZEOF(xkbDeviceLedsWireDesc); - if (!kf->xkb_sli) - kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0); - length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli); - if (id!=XkbAllXIIds) - break; - } - } - if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { - LedFeedbackPtr lf; - classOk= TRUE; - for (lf= dev->leds;(lf);lf=lf->next) { - if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id)) - continue; - nFBs++; - length+= SIZEOF(xkbDeviceLedsWireDesc); - if (!lf->xkb_sli) - lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0); - length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli); - if (id!=XkbAllXIIds) - break; - } - } - if (nFBs>0) { - rep->nDeviceLedFBs= nFBs; - rep->length+= (length/4); - return Success; - } - if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id); - else client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); - return XkbKeyboardErrorCode; -} - -static int -SendDeviceLedInfo( XkbSrvLedInfoPtr sli, - ClientPtr client) -{ -xkbDeviceLedsWireDesc wire; -int length; - - length= 0; - wire.ledClass= sli->class; - wire.ledID= sli->id; - wire.namesPresent= sli->namesPresent; - wire.mapsPresent= sli->mapsPresent; - wire.physIndicators= sli->physIndicators; - wire.state= sli->effectiveState; - if (client->swapped) { - register int n; - swaps(&wire.ledClass,n); - swaps(&wire.ledID,n); - swapl(&wire.namesPresent,n); - swapl(&wire.mapsPresent,n); - swapl(&wire.physIndicators,n); - swapl(&wire.state,n); - } - WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire); - length+= SIZEOF(xkbDeviceLedsWireDesc); - if (sli->namesPresent|sli->mapsPresent) { - register unsigned i,bit; - if (sli->namesPresent) { - CARD32 awire; - for (i=0,bit=1;inamesPresent&bit) { - awire= (CARD32)sli->names[i]; - if (client->swapped) { - register int n; - swapl(&awire,n); - } - WriteToClient(client,4,(char *)&awire); - length+= 4; - } - } - } - if (sli->mapsPresent) { - for (i=0,bit=1;imapsPresent&bit) { - iwire.flags= sli->maps[i].flags; - iwire.whichGroups= sli->maps[i].which_groups; - iwire.groups= sli->maps[i].groups; - iwire.whichMods= sli->maps[i].which_mods; - iwire.mods= sli->maps[i].mods.mask; - iwire.realMods= sli->maps[i].mods.real_mods; - iwire.virtualMods= sli->maps[i].mods.vmods; - iwire.ctrls= sli->maps[i].ctrls; - if (client->swapped) { - register int n; - swaps(&iwire.virtualMods,n); - swapl(&iwire.ctrls,n); - } - WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc), - (char *)&iwire); - length+= SIZEOF(xkbIndicatorMapWireDesc); - } - } - } - } - return length; -} - -static int -SendDeviceLedFBs( DeviceIntPtr dev, - int class, - int id, - unsigned wantLength, - ClientPtr client) -{ -int length= 0; - - if (class==XkbDfltXIClass) { - if (dev->kbdfeed) class= KbdFeedbackClass; - else if (dev->leds) class= LedFeedbackClass; - } - if ((dev->kbdfeed)&& - ((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { - KbdFeedbackPtr kf; - for (kf= dev->kbdfeed;(kf);kf=kf->next) { - if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) { - length+= SendDeviceLedInfo(kf->xkb_sli,client); - if (id!=XkbAllXIIds) - break; - } - } - } - if ((dev->leds)&& - ((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { - LedFeedbackPtr lf; - for (lf= dev->leds;(lf);lf=lf->next) { - if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) { - length+= SendDeviceLedInfo(lf->xkb_sli,client); - if (id!=XkbAllXIIds) - break; - } - } - } - if (length==wantLength) - return Success; - else return BadLength; -} - -int -ProcXkbGetDeviceInfo(ClientPtr client) -{ -DeviceIntPtr dev; -xkbGetDeviceInfoReply rep; -int status,nDeviceLedFBs; -unsigned length,nameLen; -CARD16 ledClass,ledID; -unsigned wanted; -char * str; - - REQUEST(xkbGetDeviceInfoReq); - REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - wanted= stuff->wanted; - - CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); - CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask); - - if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns))) - wanted&= ~XkbXI_ButtonActionsMask; - if ((!dev->kbdfeed)&&(!dev->leds)) - wanted&= ~XkbXI_IndicatorsMask; - - nameLen= XkbSizeCountedString(dev->name); - memset((char *)&rep, 0, SIZEOF(xkbGetDeviceInfoReply)); - rep.type = X_Reply; - rep.deviceID= dev->id; - rep.sequenceNumber = client->sequence; - rep.length = nameLen/4; - rep.present = wanted; - rep.supported = XkbXI_AllDeviceFeaturesMask; - rep.unsupported = 0; - rep.firstBtnWanted = rep.nBtnsWanted = 0; - rep.firstBtnRtrn = rep.nBtnsRtrn = 0; - if (dev->button) - rep.totalBtns= dev->button->numButtons; - else rep.totalBtns= 0; - rep.devType= dev->xinput_type; - rep.hasOwnState= (dev->key && dev->key->xkbInfo); - rep.nDeviceLedFBs = 0; - if (dev->kbdfeed) rep.dfltKbdFB= dev->kbdfeed->ctrl.id; - else rep.dfltKbdFB= XkbXINone; - if (dev->leds) rep.dfltLedFB= dev->leds->ctrl.id; - else rep.dfltLedFB= XkbXINone; - - ledClass= stuff->ledClass; - ledID= stuff->ledID; - - rep.firstBtnWanted= rep.nBtnsWanted= 0; - rep.firstBtnRtrn= rep.nBtnsRtrn= 0; - if (wanted&XkbXI_ButtonActionsMask) { - if (stuff->allBtns) { - stuff->firstBtn= 0; - stuff->nBtns= dev->button->numButtons; - } - - if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { - client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons, - stuff->firstBtn, - stuff->nBtns); - return BadValue; - } - else { - rep.firstBtnWanted= stuff->firstBtn; - rep.nBtnsWanted= stuff->nBtns; - if (dev->button->xkb_acts!=NULL) { - XkbAction *act; - register int i; - - rep.firstBtnRtrn= stuff->firstBtn; - rep.nBtnsRtrn= stuff->nBtns; - act= &dev->button->xkb_acts[rep.firstBtnWanted]; - for (i=0;itype!=XkbSA_NoAction) - break; - } - rep.firstBtnRtrn+= i; - rep.nBtnsRtrn-= i; - act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1]; - for (i=0;itype!=XkbSA_NoAction) - break; - } - rep.nBtnsRtrn-= i; - } - rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4; - } - } - - if (wanted&XkbXI_IndicatorsMask) { - status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client); - if (status!=Success) - return status; - } - length= rep.length*4; - nDeviceLedFBs = rep.nDeviceLedFBs; - if (client->swapped) { - register int n; - swaps(&rep.sequenceNumber,n); - swapl(&rep.length,n); - swaps(&rep.present,n); - swaps(&rep.supported,n); - swaps(&rep.unsupported,n); - swaps(&rep.nDeviceLedFBs,n); - swapl(&rep.type,n); - } - WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep); - - str= malloc(nameLen); - if (!str) - return BadAlloc; - XkbWriteCountedString(str,dev->name,client->swapped); - WriteToClient(client,nameLen,str); - free(str); - length-= nameLen; - - if (rep.nBtnsRtrn>0) { - int sz; - xkbActionWireDesc * awire; - sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc); - awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn]; - WriteToClient(client,sz,(char *)awire); - length-= sz; - } - if (nDeviceLedFBs>0) { - status= SendDeviceLedFBs(dev,ledClass,ledID,length,client); - if (status!=Success) - return status; - } - else if (length!=0) { - ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); - ErrorF("[xkb] Wrote %d fewer bytes than expected\n",length); - return BadLength; - } - return Success; -} - -static char * -CheckSetDeviceIndicators( char * wire, - DeviceIntPtr dev, - int num, - int * status_rtrn, - ClientPtr client) -{ -xkbDeviceLedsWireDesc * ledWire; -int i; -XkbSrvLedInfoPtr sli; - - ledWire= (xkbDeviceLedsWireDesc *)wire; - for (i=0;iswapped) { - register int n; - swaps(&ledWire->ledClass,n); - swaps(&ledWire->ledID,n); - swapl(&ledWire->namesPresent,n); - swapl(&ledWire->mapsPresent,n); - swapl(&ledWire->physIndicators,n); - } - - sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID, - XkbXI_IndicatorsMask); - if (sli!=NULL) { - register int n; - register unsigned bit; - int nMaps,nNames; - CARD32 *atomWire; - xkbIndicatorMapWireDesc *mapWire; - - nMaps= nNames= 0; - for (n=0,bit=1;nnamesPresent&bit) - nNames++; - if (ledWire->mapsPresent&bit) - nMaps++; - } - atomWire= (CARD32 *)&ledWire[1]; - if (nNames>0) { - for (n=0;nswapped) { - register int t; - swapl(atomWire,t); - } - CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue, - *status_rtrn,NULL); - atomWire++; - } - } - mapWire= (xkbIndicatorMapWireDesc *)atomWire; - if (nMaps>0) { - for (n=0;nswapped) { - register int t; - swaps(&mapWire->virtualMods,t); - swapl(&mapWire->ctrls,t); - } - CHK_MASK_LEGAL3(0x21,mapWire->whichGroups, - XkbIM_UseAnyGroup, - client->errorValue, - *status_rtrn,NULL); - CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods, - client->errorValue, - *status_rtrn,NULL); - mapWire++; - } - } - ledWire= (xkbDeviceLedsWireDesc *)mapWire; - } - else { - /* SHOULD NEVER HAPPEN */ - return (char *)ledWire; - } - } - return (char *)ledWire; -} - -static char * -SetDeviceIndicators( char * wire, - DeviceIntPtr dev, - unsigned changed, - int num, - int * status_rtrn, - ClientPtr client, - xkbExtensionDeviceNotify *ev) -{ -xkbDeviceLedsWireDesc * ledWire; -int i; -XkbEventCauseRec cause; -unsigned namec,mapc,statec; -xkbExtensionDeviceNotify ed; -XkbChangesRec changes; -DeviceIntPtr kbd; - - memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify)); - memset((char *)&changes, 0, sizeof(XkbChangesRec)); - XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client); - ledWire= (xkbDeviceLedsWireDesc *)wire; - for (i=0;iledClass,ledWire->ledID, - XkbXI_IndicatorMapsMask); - if (!sli) { - /* SHOULD NEVER HAPPEN!! */ - return (char *)ledWire; - } - - atomWire= (CARD32 *)&ledWire[1]; - if (changed&XkbXI_IndicatorNamesMask) { - namec= sli->namesPresent|ledWire->namesPresent; - memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom)); - } - if (ledWire->namesPresent) { - sli->namesPresent= ledWire->namesPresent; - memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom)); - for (n=0,bit=1;nnamesPresent&bit) { - sli->names[n]= (Atom)*atomWire; - if (sli->names[n]==None) - ledWire->namesPresent&= ~bit; - atomWire++; - } - } - } - mapWire= (xkbIndicatorMapWireDesc *)atomWire; - if (changed&XkbXI_IndicatorMapsMask) { - mapc= sli->mapsPresent|ledWire->mapsPresent; - sli->mapsPresent= ledWire->mapsPresent; - memset((char*)sli->maps, 0, XkbNumIndicators*sizeof(XkbIndicatorMapRec)); - } - if (ledWire->mapsPresent) { - for (n=0,bit=1;nmapsPresent&bit) { - sli->maps[n].flags= mapWire->flags; - sli->maps[n].which_groups= mapWire->whichGroups; - sli->maps[n].groups= mapWire->groups; - sli->maps[n].which_mods= mapWire->whichMods; - sli->maps[n].mods.mask= mapWire->mods; - sli->maps[n].mods.real_mods=mapWire->realMods; - sli->maps[n].mods.vmods= mapWire->virtualMods; - sli->maps[n].ctrls= mapWire->ctrls; - mapWire++; - } - } - } - if (changed&XkbXI_IndicatorStateMask) { - statec= sli->effectiveState^ledWire->state; - sli->explicitState&= ~statec; - sli->explicitState|= (ledWire->state&statec); - } - if (namec) - XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); - if (mapc) - XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); - if (statec) - XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); - - kbd= dev; - if ((sli->flags&XkbSLI_HasOwnState)==0) - kbd = inputInfo.keyboard; - - XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause); - ledWire= (xkbDeviceLedsWireDesc *)mapWire; - } - return (char *)ledWire; -} - - -static int -_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, - xkbSetDeviceInfoReq *stuff) -{ - char *wire; - - wire= (char *)&stuff[1]; - if (stuff->change&XkbXI_ButtonActionsMask) { - if (!dev->button) { - client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass); - return XkbKeyboardErrorCode; - } - if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { - client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns, - dev->button->numButtons); - return BadMatch; - } - wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc)); - } - if (stuff->change&XkbXI_IndicatorsMask) { - int status= Success; - wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs, - &status,client); - if (status!=Success) - return status; - } - if (((wire-((char *)stuff))/4)!=stuff->length) - return BadLength; - - return Success; -} - -static int -_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, - xkbSetDeviceInfoReq *stuff) -{ - char *wire; - xkbExtensionDeviceNotify ed; - - memset((char *)&ed, 0, SIZEOF(xkbExtensionDeviceNotify)); - ed.deviceID= dev->id; - wire= (char *)&stuff[1]; - if (stuff->change&XkbXI_ButtonActionsMask) { - int nBtns,sz,i; - XkbAction * acts; - DeviceIntPtr kbd; - - nBtns= dev->button->numButtons; - acts= dev->button->xkb_acts; - if (acts==NULL) { - acts= calloc(nBtns, sizeof(XkbAction)); - if (!acts) - return BadAlloc; - dev->button->xkb_acts= acts; - } - sz= stuff->nBtns*SIZEOF(xkbActionWireDesc); - memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz); - wire+= sz; - ed.reason|= XkbXI_ButtonActionsMask; - ed.firstBtn= stuff->firstBtn; - ed.nBtns= stuff->nBtns; - - if (dev->key) kbd= dev; - else kbd= inputInfo.keyboard; - acts= &dev->button->xkb_acts[stuff->firstBtn]; - for (i=0;inBtns;i++,acts++) { - if (acts->type!=XkbSA_NoAction) - XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0); - } - } - if (stuff->change&XkbXI_IndicatorsMask) { - int status= Success; - wire= SetDeviceIndicators(wire,dev,stuff->change, - stuff->nDeviceLedFBs, &status,client,&ed); - if (status!=Success) - return status; - } - if ((stuff->change)&&(ed.reason)) - XkbSendExtensionDeviceNotify(dev,client,&ed); - return Success; -} - -int -ProcXkbSetDeviceInfo(ClientPtr client) -{ - DeviceIntPtr dev; - int rc; - - REQUEST(xkbSetDeviceInfoReq); - REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); - CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask); - - rc = _XkbSetDeviceInfoCheck(client, dev, stuff); - - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) && - ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || - (stuff->deviceSpec == XkbUseCorePtr && other->button))) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - { - rc = _XkbSetDeviceInfoCheck(client, other, stuff); - if (rc != Success) - return rc; - } - } - } - } - - /* checks done, apply */ - rc = _XkbSetDeviceInfo(client, dev, stuff); - if (rc != Success) - return rc; - - if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr) - { - DeviceIntPtr other; - for (other = inputInfo.devices; other; other = other->next) - { - if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) && - ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || - (stuff->deviceSpec == XkbUseCorePtr && other->button))) - { - rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); - if (rc == Success) - { - rc = _XkbSetDeviceInfo(client, other, stuff); - if (rc != Success) - return rc; - } - } - } - } - - return Success; -} - -/***====================================================================***/ - -int -ProcXkbSetDebuggingFlags(ClientPtr client) -{ -CARD32 newFlags,newCtrls,extraLength; -xkbSetDebuggingFlagsReply rep; -int rc; - - REQUEST(xkbSetDebuggingFlagsReq); - REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); - - rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess); - if (rc != Success) - return rc; - - newFlags= xkbDebugFlags&(~stuff->affectFlags); - newFlags|= (stuff->flags&stuff->affectFlags); - newCtrls= xkbDebugCtrls&(~stuff->affectCtrls); - newCtrls|= (stuff->ctrls&stuff->affectCtrls); - if (xkbDebugFlags || newFlags || stuff->msgLength) { - ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags); - if (newCtrls!=xkbDebugCtrls) - ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls); - } - extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq; - if (stuff->msgLength>0) { - char *msg; - if (extraLengthmsgLength)) { - ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n", - stuff->msgLength,(long)extraLength, - XkbPaddedSize(stuff->msgLength)); - return BadLength; - } - msg= (char *)&stuff[1]; - if (msg[stuff->msgLength-1]!='\0') { - ErrorF("[xkb] XkbDebug: message not null-terminated\n"); - return BadValue; - } - ErrorF("[xkb] XkbDebug: %s\n",msg); - } - xkbDebugFlags = newFlags; - xkbDebugCtrls = newCtrls; - - rep.type= X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.currentFlags = newFlags; - rep.currentCtrls = newCtrls; - rep.supportedFlags = ~0; - rep.supportedCtrls = ~0; - if ( client->swapped ) { - register int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.currentFlags, n); - swapl(&rep.currentCtrls, n); - swapl(&rep.supportedFlags, n); - swapl(&rep.supportedCtrls, n); - } - WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep); - return Success; -} - -/***====================================================================***/ - -static int -ProcXkbDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_kbUseExtension: - return ProcXkbUseExtension(client); - case X_kbSelectEvents: - return ProcXkbSelectEvents(client); - case X_kbBell: - return ProcXkbBell(client); - case X_kbGetState: - return ProcXkbGetState(client); - case X_kbLatchLockState: - return ProcXkbLatchLockState(client); - case X_kbGetControls: - return ProcXkbGetControls(client); - case X_kbSetControls: - return ProcXkbSetControls(client); - case X_kbGetMap: - return ProcXkbGetMap(client); - case X_kbSetMap: - return ProcXkbSetMap(client); - case X_kbGetCompatMap: - return ProcXkbGetCompatMap(client); - case X_kbSetCompatMap: - return ProcXkbSetCompatMap(client); - case X_kbGetIndicatorState: - return ProcXkbGetIndicatorState(client); - case X_kbGetIndicatorMap: - return ProcXkbGetIndicatorMap(client); - case X_kbSetIndicatorMap: - return ProcXkbSetIndicatorMap(client); - case X_kbGetNamedIndicator: - return ProcXkbGetNamedIndicator(client); - case X_kbSetNamedIndicator: - return ProcXkbSetNamedIndicator(client); - case X_kbGetNames: - return ProcXkbGetNames(client); - case X_kbSetNames: - return ProcXkbSetNames(client); - case X_kbGetGeometry: - return ProcXkbGetGeometry(client); - case X_kbSetGeometry: - return ProcXkbSetGeometry(client); - case X_kbPerClientFlags: - return ProcXkbPerClientFlags(client); - case X_kbListComponents: - return ProcXkbListComponents(client); - case X_kbGetKbdByName: - return ProcXkbGetKbdByName(client); - case X_kbGetDeviceInfo: - return ProcXkbGetDeviceInfo(client); - case X_kbSetDeviceInfo: - return ProcXkbSetDeviceInfo(client); - case X_kbSetDebuggingFlags: - return ProcXkbSetDebuggingFlags(client); - default: - return BadRequest; - } -} - -static int -XkbClientGone(pointer data,XID id) -{ - DevicePtr pXDev = (DevicePtr)data; - - if (!XkbRemoveResourceClient(pXDev,id)) { - ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n"); - } - return 1; -} - -void -XkbExtensionInit(void) -{ - ExtensionEntry *extEntry; - - RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient"); - if (!RT_XKBCLIENT) - return; - - if (!XkbInitPrivates()) - return; - - if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, - ProcXkbDispatch, SProcXkbDispatch, - NULL, StandardMinorOpcode))) { - XkbReqCode = (unsigned char)extEntry->base; - XkbEventBase = (unsigned char)extEntry->eventBase; - XkbErrorBase = (unsigned char)extEntry->errorBase; - XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard; - } - return; -} - - +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include "misc.h" +#include "inputstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include +#include "extnsionst.h" +#include "xace.h" +#include "xkb.h" +#include "protocol-versions.h" + +#include +#include + +int XkbEventBase; +static int XkbErrorBase; +int XkbReqCode; +int XkbKeyboardErrorCode; +CARD32 xkbDebugFlags = 0; +static CARD32 xkbDebugCtrls = 0; + +static RESTYPE RT_XKBCLIENT; + +/***====================================================================***/ + +#define CHK_DEVICE(dev, id, client, access_mode, lf) {\ + int why;\ + int rc = lf(&(dev), id, client, access_mode, &why);\ + if (rc != Success) {\ + client->errorValue = _XkbErrCode2(why, id);\ + return rc;\ + }\ +} + +#define CHK_KBD_DEVICE(dev, id, client, mode) \ + CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard) +#define CHK_LED_DEVICE(dev, id, client, mode) \ + CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice) +#define CHK_BELL_DEVICE(dev, id, client, mode) \ + CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice) +#define CHK_ANY_DEVICE(dev, id, client, mode) \ + CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice) + +#define CHK_ATOM_ONLY2(a,ev,er) {\ + if (((a)==None)||(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + return er;\ + }\ +} +#define CHK_ATOM_ONLY(a) \ + CHK_ATOM_ONLY2(a,client->errorValue,BadAtom) + +#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\ + if (((a)!=None)&&(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + (er)= BadAtom;\ + return ret;\ + }\ +} +#define CHK_ATOM_OR_NONE2(a,ev,er) {\ + if (((a)!=None)&&(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + return er;\ + }\ +} +#define CHK_ATOM_OR_NONE(a) \ + CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom) + +#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\ + if ((mask)&(~(legal))) { \ + (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ + (er)= BadValue;\ + return ret;\ + }\ +} +#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\ + if ((mask)&(~(legal))) { \ + (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ + return er;\ + }\ +} +#define CHK_MASK_LEGAL(err,mask,legal) \ + CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue) + +#define CHK_MASK_MATCH(err,affect,value) {\ + if ((value)&(~(affect))) { \ + client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\ + return BadMatch;\ + }\ +} +#define CHK_MASK_OVERLAP(err,m1,m2) {\ + if ((m1)&(m2)) { \ + client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\ + return BadMatch;\ + }\ +} +#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\ + if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\ + (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\ + return er;\ + }\ + else if ( (first)<(x)->min_key_code ) {\ + (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\ + return er;\ + }\ +} +#define CHK_KEY_RANGE(err,first,num,x) \ + CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue) + +#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\ + if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\ + (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\ + return er;\ + }\ + else if ( (first)<(r)->minKeyCode ) {\ + (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\ + return er;\ + }\ +} +#define CHK_REQ_KEY_RANGE(err,first,num,r) \ + CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue) + +/***====================================================================***/ + +int +ProcXkbUseExtension(ClientPtr client) +{ + REQUEST(xkbUseExtensionReq); + xkbUseExtensionReply rep; + register int n; + int supported; + + REQUEST_SIZE_MATCH(xkbUseExtensionReq); + if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) { + /* pre-release version 0.65 is compatible with 1.00 */ + supported= ((SERVER_XKB_MAJOR_VERSION==1)&& + (stuff->wantedMajor==0)&&(stuff->wantedMinor==65)); + } + else supported = 1; + + if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) { + client->xkbClientFlags= _XkbClientInitialized; + client->vMajor= stuff->wantedMajor; + client->vMinor= stuff->wantedMinor; + } + else if (xkbDebugFlags&0x1) { + ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n", + client->index, + (long)client->clientAsMask, + stuff->wantedMajor,stuff->wantedMinor, + SERVER_XKB_MAJOR_VERSION,SERVER_XKB_MINOR_VERSION); + } + memset(&rep, 0, sizeof(xkbUseExtensionReply)); + rep.type = X_Reply; + rep.supported = supported; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.serverMajor = SERVER_XKB_MAJOR_VERSION; + rep.serverMinor = SERVER_XKB_MINOR_VERSION; + if ( client->swapped ) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.serverMajor, n); + swaps(&rep.serverMinor, n); + } + WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +int +ProcXkbSelectEvents(ClientPtr client) +{ + unsigned legal; + DeviceIntPtr dev; + XkbInterestPtr masks; + REQUEST(xkbSelectEventsReq); + + REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess); + + if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) { + client->mapNotifyMask&= ~stuff->affectMap; + client->mapNotifyMask|= (stuff->affectMap&stuff->map); + } + if ((stuff->affectWhich&(~XkbMapNotifyMask))==0) + return Success; + + masks = XkbFindClientResource((DevicePtr)dev,client); + if (!masks){ + XID id = FakeClientID(client->index); + if (!AddResource(id,RT_XKBCLIENT,dev)) + return BadAlloc; + masks= XkbAddClientResource((DevicePtr)dev,client,id); + } + if (masks) { + union { + CARD8 *c8; + CARD16 *c16; + CARD32 *c32; + } from,to; + register unsigned bit,ndx,maskLeft,dataLeft,size; + + from.c8= (CARD8 *)&stuff[1]; + dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq); + maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask)); + for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) { + if ((bit&maskLeft)==0) + continue; + maskLeft&= ~bit; + switch (ndx) { + case XkbNewKeyboardNotify: + to.c16= &client->newKeyboardNotifyMask; + legal= XkbAllNewKeyboardEventsMask; + size= 2; + break; + case XkbStateNotify: + to.c16= &masks->stateNotifyMask; + legal= XkbAllStateEventsMask; + size= 2; + break; + case XkbControlsNotify: + to.c32= &masks->ctrlsNotifyMask; + legal= XkbAllControlEventsMask; + size= 4; + break; + case XkbIndicatorStateNotify: + to.c32= &masks->iStateNotifyMask; + legal= XkbAllIndicatorEventsMask; + size= 4; + break; + case XkbIndicatorMapNotify: + to.c32= &masks->iMapNotifyMask; + legal= XkbAllIndicatorEventsMask; + size= 4; + break; + case XkbNamesNotify: + to.c16= &masks->namesNotifyMask; + legal= XkbAllNameEventsMask; + size= 2; + break; + case XkbCompatMapNotify: + to.c8= &masks->compatNotifyMask; + legal= XkbAllCompatMapEventsMask; + size= 1; + break; + case XkbBellNotify: + to.c8= &masks->bellNotifyMask; + legal= XkbAllBellEventsMask; + size= 1; + break; + case XkbActionMessage: + to.c8= &masks->actionMessageMask; + legal= XkbAllActionMessagesMask; + size= 1; + break; + case XkbAccessXNotify: + to.c16= &masks->accessXNotifyMask; + legal= XkbAllAccessXEventsMask; + size= 2; + break; + case XkbExtensionDeviceNotify: + to.c16= &masks->extDevNotifyMask; + legal= XkbAllExtensionDeviceEventsMask; + size= 2; + break; + default: + client->errorValue = _XkbErrCode2(33,bit); + return BadValue; + } + + if (stuff->clear&bit) { + if (size==2) to.c16[0]= 0; + else if (size==4) to.c32[0]= 0; + else to.c8[0]= 0; + } + else if (stuff->selectAll&bit) { + if (size==2) to.c16[0]= ~0; + else if (size==4) to.c32[0]= ~0; + else to.c8[0]= ~0; + } + else { + if (dataLeft<(size*2)) + return BadLength; + if (size==2) { + CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]); + CHK_MASK_LEGAL(ndx,from.c16[0],legal); + to.c16[0]&= ~from.c16[0]; + to.c16[0]|= (from.c16[0]&from.c16[1]); + } + else if (size==4) { + CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]); + CHK_MASK_LEGAL(ndx,from.c32[0],legal); + to.c32[0]&= ~from.c32[0]; + to.c32[0]|= (from.c32[0]&from.c32[1]); + } + else { + CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]); + CHK_MASK_LEGAL(ndx,from.c8[0],legal); + to.c8[0]&= ~from.c8[0]; + to.c8[0]|= (from.c8[0]&from.c8[1]); + size= 2; + } + from.c8+= (size*2); + dataLeft-= (size*2); + } + } + if (dataLeft>2) { + ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft); + return BadLength; + } + return Success; + } + return BadAlloc; +} + +/***====================================================================***/ +/** + * Ring a bell on the given device for the given client. + */ +static int +_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin, + int bellClass, int bellID, int pitch, int duration, + int percent, int forceSound, int eventOnly, Atom name) +{ + int base; + pointer ctrl; + int oldPitch, oldDuration; + int newPercent; + + if (bellClass == KbdFeedbackClass) { + KbdFeedbackPtr k; + if (bellID==XkbDfltXIId) + k= dev->kbdfeed; + else { + for (k=dev->kbdfeed; k; k=k->next) { + if (k->ctrl.id == bellID) + break; + } + } + if (!k) { + client->errorValue = _XkbErrCode2(0x5,bellID); + return BadValue; + } + base = k->ctrl.bell; + ctrl = (pointer) &(k->ctrl); + oldPitch= k->ctrl.bell_pitch; + oldDuration= k->ctrl.bell_duration; + if (pitch!=0) { + if (pitch==-1) + k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch; + else k->ctrl.bell_pitch= pitch; + } + if (duration!=0) { + if (duration==-1) + k->ctrl.bell_duration= defaultKeyboardControl.bell_duration; + else k->ctrl.bell_duration= duration; + } + } + else if (bellClass == BellFeedbackClass) { + BellFeedbackPtr b; + if (bellID==XkbDfltXIId) + b= dev->bell; + else { + for (b=dev->bell; b; b=b->next) { + if (b->ctrl.id == bellID) + break; + } + } + if (!b) { + client->errorValue = _XkbErrCode2(0x6,bellID); + return BadValue; + } + base = b->ctrl.percent; + ctrl = (pointer) &(b->ctrl); + oldPitch= b->ctrl.pitch; + oldDuration= b->ctrl.duration; + if (pitch!=0) { + if (pitch==-1) + b->ctrl.pitch= defaultKeyboardControl.bell_pitch; + else b->ctrl.pitch= pitch; + } + if (duration!=0) { + if (duration==-1) + b->ctrl.duration= defaultKeyboardControl.bell_duration; + else b->ctrl.duration= duration; + } + } + else { + client->errorValue = _XkbErrCode2(0x7, bellClass); + return BadValue; + } + + newPercent = (base * percent)/100; + if (percent < 0) + newPercent = base + newPercent; + else newPercent = base - newPercent + percent; + + XkbHandleBell(forceSound, eventOnly, + dev, newPercent, ctrl, bellClass, + name, pWin, client); + if ((pitch!=0)||(duration!=0)) { + if (bellClass == KbdFeedbackClass) { + KbdFeedbackPtr k; + k= (KbdFeedbackPtr)ctrl; + if (pitch!=0) + k->ctrl.bell_pitch= oldPitch; + if (duration!=0) + k->ctrl.bell_duration= oldDuration; + } + else { + BellFeedbackPtr b; + b= (BellFeedbackPtr)ctrl; + if (pitch!=0) + b->ctrl.pitch= oldPitch; + if (duration!=0) + b->ctrl.duration= oldDuration; + } + } + + return Success; +} + +int +ProcXkbBell(ClientPtr client) +{ + REQUEST(xkbBellReq); + DeviceIntPtr dev; + WindowPtr pWin; + int rc; + + REQUEST_SIZE_MATCH(xkbBellReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess); + CHK_ATOM_OR_NONE(stuff->name); + + /* device-independent checks request for sane values */ + if ((stuff->forceSound)&&(stuff->eventOnly)) { + client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly); + return BadMatch; + } + if (stuff->percent < -100 || stuff->percent > 100) { + client->errorValue = _XkbErrCode2(0x2,stuff->percent); + return BadValue; + } + if (stuff->duration<-1) { + client->errorValue = _XkbErrCode2(0x3,stuff->duration); + return BadValue; + } + if (stuff->pitch<-1) { + client->errorValue = _XkbErrCode2(0x4,stuff->pitch); + return BadValue; + } + + if (stuff->bellClass == XkbDfltXIClass) { + if (dev->kbdfeed!=NULL) + stuff->bellClass= KbdFeedbackClass; + else stuff->bellClass= BellFeedbackClass; + } + + if (stuff->window!=None) { + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) { + client->errorValue= stuff->window; + return rc; + } + } + else pWin= NULL; + + /* Client wants to ring a bell on the core keyboard? + Ring the bell on the core keyboard (which does nothing, but if that + fails the client is screwed anyway), and then on all extension devices. + Fail if the core keyboard fails but not the extension devices. this + may cause some keyboards to ding and others to stay silent. Fix + your client to use explicit keyboards to avoid this. + + dev is the device the client requested. + */ + rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID, + stuff->pitch, stuff->duration, stuff->percent, + stuff->forceSound, stuff->eventOnly, stuff->name); + + if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) || + (stuff->deviceSpec == XkbUseCorePtr))) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess); + if (rc == Success) + _XkbBell(client, other, pWin, stuff->bellClass, + stuff->bellID, stuff->pitch, stuff->duration, + stuff->percent, stuff->forceSound, + stuff->eventOnly, stuff->name); + } + } + rc = Success; /* reset to success, that's what we got for the VCK */ + } + + return rc; +} + +/***====================================================================***/ + +int +ProcXkbGetState(ClientPtr client) +{ + REQUEST(xkbGetStateReq); + DeviceIntPtr dev; + xkbGetStateReply rep; + XkbStateRec *xkb; + + REQUEST_SIZE_MATCH(xkbGetStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + xkb= &dev->key->xkbInfo->state; + memset(&rep, 0, sizeof(xkbGetStateReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.mods = XkbStateFieldFromRec(xkb) & 0xff; + rep.baseMods = xkb->base_mods; + rep.lockedMods = xkb->locked_mods; + rep.latchedMods = xkb->latched_mods; + rep.group = xkb->group; + rep.baseGroup = xkb->base_group; + rep.latchedGroup = xkb->latched_group; + rep.lockedGroup = xkb->locked_group; + rep.compatState = xkb->compat_state; + rep.ptrBtnState = xkb->ptr_buttons; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swaps(&rep.ptrBtnState,n); + } + WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +int +ProcXkbLatchLockState(ClientPtr client) +{ + int status; + DeviceIntPtr dev, tmpd; + XkbStateRec oldState,*newState; + CARD16 changed; + xkbStateNotify sn; + XkbEventCauseRec cause; + + REQUEST(xkbLatchLockStateReq); + REQUEST_SIZE_MATCH(xkbLatchLockStateReq); + + if (!(client->xkbClientFlags & _XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); + CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks); + CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches); + + status = Success; + + for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { + if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { + if (!tmpd->key || !tmpd->key->xkbInfo) + continue; + + oldState = tmpd->key->xkbInfo->state; + newState = &tmpd->key->xkbInfo->state; + if (stuff->affectModLocks) { + newState->locked_mods &= ~stuff->affectModLocks; + newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks); + } + if (status == Success && stuff->lockGroup) + newState->locked_group = stuff->groupLock; + if (status == Success && stuff->affectModLatches) + status = XkbLatchModifiers(tmpd, stuff->affectModLatches, + stuff->modLatches); + if (status == Success && stuff->latchGroup) + status = XkbLatchGroup(tmpd, stuff->groupLatch); + + if (status != Success) + return status; + + XkbComputeDerivedState(tmpd->key->xkbInfo); + + changed = XkbStateChangedFlags(&oldState, newState); + if (changed) { + sn.keycode = 0; + sn.eventType = 0; + sn.requestMajor = XkbReqCode; + sn.requestMinor = X_kbLatchLockState; + sn.changed = changed; + XkbSendStateNotify(tmpd, &sn); + changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE); + if (changed) { + XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client); + XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause); + } + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbGetControls(ClientPtr client) +{ + xkbGetControlsReply rep; + XkbControlsPtr xkb; + DeviceIntPtr dev; + register int n; + + REQUEST(xkbGetControlsReq); + REQUEST_SIZE_MATCH(xkbGetControlsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + xkb = dev->key->xkbInfo->desc->ctrls; + rep.type = X_Reply; + rep.length = bytes_to_int32(SIZEOF(xkbGetControlsReply)- + SIZEOF(xGenericReply)); + rep.sequenceNumber = client->sequence; + rep.deviceID = ((DeviceIntPtr)dev)->id; + rep.numGroups = xkb->num_groups; + rep.groupsWrap = xkb->groups_wrap; + rep.internalMods = xkb->internal.mask; + rep.ignoreLockMods = xkb->ignore_lock.mask; + rep.internalRealMods = xkb->internal.real_mods; + rep.ignoreLockRealMods = xkb->ignore_lock.real_mods; + rep.internalVMods = xkb->internal.vmods; + rep.ignoreLockVMods = xkb->ignore_lock.vmods; + rep.enabledCtrls = xkb->enabled_ctrls; + rep.repeatDelay = xkb->repeat_delay; + rep.repeatInterval = xkb->repeat_interval; + rep.slowKeysDelay = xkb->slow_keys_delay; + rep.debounceDelay = xkb->debounce_delay; + rep.mkDelay = xkb->mk_delay; + rep.mkInterval = xkb->mk_interval; + rep.mkTimeToMax = xkb->mk_time_to_max; + rep.mkMaxSpeed = xkb->mk_max_speed; + rep.mkCurve = xkb->mk_curve; + rep.mkDfltBtn = xkb->mk_dflt_btn; + rep.axTimeout = xkb->ax_timeout; + rep.axtCtrlsMask = xkb->axt_ctrls_mask; + rep.axtCtrlsValues = xkb->axt_ctrls_values; + rep.axtOptsMask = xkb->axt_opts_mask; + rep.axtOptsValues = xkb->axt_opts_values; + rep.axOptions = xkb->ax_options; + memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length,n); + swaps(&rep.internalVMods, n); + swaps(&rep.ignoreLockVMods, n); + swapl(&rep.enabledCtrls, n); + swaps(&rep.repeatDelay, n); + swaps(&rep.repeatInterval, n); + swaps(&rep.slowKeysDelay, n); + swaps(&rep.debounceDelay, n); + swaps(&rep.mkDelay, n); + swaps(&rep.mkInterval, n); + swaps(&rep.mkTimeToMax, n); + swaps(&rep.mkMaxSpeed, n); + swaps(&rep.mkCurve, n); + swaps(&rep.axTimeout, n); + swapl(&rep.axtCtrlsMask, n); + swapl(&rep.axtCtrlsValues, n); + swaps(&rep.axtOptsMask, n); + swaps(&rep.axtOptsValues, n); + swaps(&rep.axOptions, n); + } + WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep); + return Success; +} + +int +ProcXkbSetControls(ClientPtr client) +{ + DeviceIntPtr dev, tmpd; + XkbSrvInfoPtr xkbi; + XkbControlsPtr ctrl; + XkbControlsRec new,old; + xkbControlsNotify cn; + XkbEventCauseRec cause; + XkbSrvLedInfoPtr sli; + + REQUEST(xkbSetControlsReq); + REQUEST_SIZE_MATCH(xkbSetControlsReq); + + if (!(client->xkbClientFlags & _XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask); + + for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { + if (!tmpd->key || !tmpd->key->xkbInfo) + continue; + if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { + xkbi = tmpd->key->xkbInfo; + ctrl = xkbi->desc->ctrls; + new = *ctrl; + XkbSetCauseXkbReq(&cause, X_kbSetControls, client); + + if (stuff->changeCtrls & XkbInternalModsMask) { + CHK_MASK_MATCH(0x02, stuff->affectInternalMods, + stuff->internalMods); + CHK_MASK_MATCH(0x03, stuff->affectInternalVMods, + stuff->internalVMods); + + new.internal.real_mods &= ~(stuff->affectInternalMods); + new.internal.real_mods |= (stuff->affectInternalMods & + stuff->internalMods); + new.internal.vmods &= ~(stuff->affectInternalVMods); + new.internal.vmods |= (stuff->affectInternalVMods & + stuff->internalVMods); + new.internal.mask = new.internal.real_mods | + XkbMaskForVMask(xkbi->desc, + new.internal.vmods); + } + + if (stuff->changeCtrls & XkbIgnoreLockModsMask) { + CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods, + stuff->ignoreLockMods); + CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods, + stuff->ignoreLockVMods); + + new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods); + new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods & + stuff->ignoreLockMods); + new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods); + new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods & + stuff->ignoreLockVMods); + new.ignore_lock.mask = new.ignore_lock.real_mods | + XkbMaskForVMask(xkbi->desc, + new.ignore_lock.vmods); + } + + CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls, + stuff->enabledCtrls); + if (stuff->affectEnabledCtrls) { + CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls, + XkbAllBooleanCtrlsMask); + + new.enabled_ctrls &= ~(stuff->affectEnabledCtrls); + new.enabled_ctrls |= (stuff->affectEnabledCtrls & + stuff->enabledCtrls); + } + + if (stuff->changeCtrls & XkbRepeatKeysMask) { + if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) { + client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay, + stuff->repeatInterval); + return BadValue; + } + + new.repeat_delay = stuff->repeatDelay; + new.repeat_interval = stuff->repeatInterval; + } + + if (stuff->changeCtrls & XkbSlowKeysMask) { + if (stuff->slowKeysDelay < 1) { + client->errorValue = _XkbErrCode2(0x09, + stuff->slowKeysDelay); + return BadValue; + } + + new.slow_keys_delay = stuff->slowKeysDelay; + } + + if (stuff->changeCtrls & XkbBounceKeysMask) { + if (stuff->debounceDelay < 1) { + client->errorValue = _XkbErrCode2(0x0A, + stuff->debounceDelay); + return BadValue; + } + + new.debounce_delay = stuff->debounceDelay; + } + + if (stuff->changeCtrls & XkbMouseKeysMask) { + if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) { + client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn); + return BadValue; + } + + new.mk_dflt_btn = stuff->mkDfltBtn; + } + + if (stuff->changeCtrls & XkbMouseKeysAccelMask) { + if (stuff->mkDelay < 1 || stuff->mkInterval < 1 || + stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 || + stuff->mkCurve < -1000) { + client->errorValue = _XkbErrCode2(0x0C,0); + return BadValue; + } + + new.mk_delay = stuff->mkDelay; + new.mk_interval = stuff->mkInterval; + new.mk_time_to_max = stuff->mkTimeToMax; + new.mk_max_speed = stuff->mkMaxSpeed; + new.mk_curve = stuff->mkCurve; + AccessXComputeCurveFactor(xkbi, &new); + } + + if (stuff->changeCtrls & XkbGroupsWrapMask) { + unsigned act, num; + + act = XkbOutOfRangeGroupAction(stuff->groupsWrap); + switch (act) { + case XkbRedirectIntoRange: + num = XkbOutOfRangeGroupNumber(stuff->groupsWrap); + if (num >= new.num_groups) { + client->errorValue = _XkbErrCode3(0x0D, new.num_groups, + num); + return BadValue; + } + case XkbWrapIntoRange: + case XkbClampIntoRange: + break; + default: + client->errorValue = _XkbErrCode2(0x0E, act); + return BadValue; + } + + new.groups_wrap= stuff->groupsWrap; + } + + CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask); + if (stuff->changeCtrls & XkbAccessXKeysMask) { + new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask; + } + else { + if (stuff->changeCtrls & XkbStickyKeysMask) { + new.ax_options &= ~(XkbAX_SKOptionsMask); + new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask); + } + + if (stuff->changeCtrls & XkbAccessXFeedbackMask) { + new.ax_options &= ~(XkbAX_FBOptionsMask); + new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask); + } + } + + if (stuff->changeCtrls & XkbAccessXTimeoutMask) { + if (stuff->axTimeout < 1) { + client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout); + return BadValue; + } + CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask, + stuff->axtCtrlsValues); + CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask, + XkbAllBooleanCtrlsMask); + CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues); + CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask); + new.ax_timeout = stuff->axTimeout; + new.axt_ctrls_mask = stuff->axtCtrlsMask; + new.axt_ctrls_values = (stuff->axtCtrlsValues & + stuff->axtCtrlsMask); + new.axt_opts_mask = stuff->axtOptsMask; + new.axt_opts_values = (stuff->axtOptsValues & + stuff->axtOptsMask); + } + + if (stuff->changeCtrls & XkbPerKeyRepeatMask) { + memcpy(new.per_key_repeat, stuff->perKeyRepeat, + XkbPerKeyBitArraySize); + if (xkbi->repeatKey && + !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) { + AccessXCancelRepeatKey(xkbi, xkbi->repeatKey); + } + } + + old= *ctrl; + *ctrl= new; + XkbDDXChangeControls(tmpd, &old, ctrl); + + if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) { + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = XkbReqCode; + cn.requestMinor = X_kbSetControls; + XkbSendControlsNotify(tmpd, &cn); + } + + sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0); + if (sli) + XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL, + &cause); + + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls & XkbStickyKeysMask) && + !(ctrl->enabled_ctrls & XkbStickyKeysMask)) + XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause); + } + } + + return Success; +} + +/***====================================================================***/ + +static int +XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + XkbKeyTypeRec *type; + unsigned i,len; + + len= 0; + if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->types)) { + rep->present&= ~XkbKeyTypesMask; + rep->firstType= rep->nTypes= 0; + return 0; + } + type= &xkb->map->types[rep->firstType]; + for (i=0;inTypes;i++,type++){ + len+= SIZEOF(xkbKeyTypeWireDesc); + if (type->map_count>0) { + len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc)); + if (type->preserve) + len+= (type->map_count*SIZEOF(xkbModsWireDesc)); + } + } + return len; +} + +static char * +XkbWriteKeyTypes( XkbDescPtr xkb, + xkbGetMapReply * rep, + char * buf, + ClientPtr client) +{ + XkbKeyTypePtr type; + unsigned i; + xkbKeyTypeWireDesc *wire; + + type= &xkb->map->types[rep->firstType]; + for (i=0;inTypes;i++,type++) { + register unsigned n; + wire= (xkbKeyTypeWireDesc *)buf; + wire->mask = type->mods.mask; + wire->realMods = type->mods.real_mods; + wire->virtualMods = type->mods.vmods; + wire->numLevels = type->num_levels; + wire->nMapEntries = type->map_count; + wire->preserve = (type->preserve!=NULL); + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + + buf= (char *)&wire[1]; + if (wire->nMapEntries>0) { + xkbKTMapEntryWireDesc * wire; + XkbKTMapEntryPtr entry; + wire= (xkbKTMapEntryWireDesc *)buf; + entry= type->map; + for (n=0;nmap_count;n++,wire++,entry++) { + wire->active= entry->active; + wire->mask= entry->mods.mask; + wire->level= entry->level; + wire->realMods= entry->mods.real_mods; + wire->virtualMods= entry->mods.vmods; + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + } + buf= (char *)wire; + if (type->preserve!=NULL) { + xkbModsWireDesc * pwire; + XkbModsPtr preserve; + pwire= (xkbModsWireDesc *)buf; + preserve= type->preserve; + for (n=0;nmap_count;n++,pwire++,preserve++) { + pwire->mask= preserve->mask; + pwire->realMods= preserve->real_mods; + pwire->virtualMods= preserve->vmods; + if (client->swapped) { + register int n; + swaps(&pwire->virtualMods,n); + } + } + buf= (char *)pwire; + } + } + } + return buf; +} + +static int +XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + XkbSymMapPtr symMap; + unsigned i,len; + unsigned nSyms,nSymsThisKey; + + if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) { + rep->present&= ~XkbKeySymsMask; + rep->firstKeySym= rep->nKeySyms= 0; + rep->totalSyms= 0; + return 0; + } + len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc); + symMap = &xkb->map->key_sym_map[rep->firstKeySym]; + for (i=nSyms=0;inKeySyms;i++,symMap++) { + if (symMap->offset!=0) { + nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width; + nSyms+= nSymsThisKey; + } + } + len+= nSyms*4; + rep->totalSyms= nSyms; + return len; +} + +static int +XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep) +{ +register unsigned i,nMods,bit; + + if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)|| + (!xkb)||(!xkb->server)) { + rep->present&= ~XkbVirtualModsMask; + rep->virtualMods= 0; + return 0; + } + for (i=nMods=0,bit=1;ivirtualMods&bit) + nMods++; + } + return XkbPaddedSize(nMods); +} + +static char * +XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) +{ +register KeySym * pSym; +XkbSymMapPtr symMap; +xkbSymMapWireDesc * outMap; +register unsigned i; + + symMap = &xkb->map->key_sym_map[rep->firstKeySym]; + for (i=0;inKeySyms;i++,symMap++) { + outMap = (xkbSymMapWireDesc *)buf; + outMap->ktIndex[0] = symMap->kt_index[0]; + outMap->ktIndex[1] = symMap->kt_index[1]; + outMap->ktIndex[2] = symMap->kt_index[2]; + outMap->ktIndex[3] = symMap->kt_index[3]; + outMap->groupInfo = symMap->group_info; + outMap->width= symMap->width; + outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info); + buf= (char *)&outMap[1]; + if (outMap->nSyms==0) + continue; + + pSym = &xkb->map->syms[symMap->offset]; + memcpy((char *)buf,(char *)pSym,outMap->nSyms*4); + if (client->swapped) { + register int n,nSyms= outMap->nSyms; + swaps(&outMap->nSyms,n); + while (nSyms-->0) { + swapl(buf,n); + buf+= 4; + } + } + else buf+= outMap->nSyms*4; + } + return buf; +} + +static int +XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nActs; + register KeyCode firstKey; + + if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->key_acts)) { + rep->present&= ~XkbKeyActionsMask; + rep->firstKeyAct= rep->nKeyActs= 0; + rep->totalActs= 0; + return 0; + } + firstKey= rep->firstKeyAct; + for (nActs=i=0;inKeyActs;i++) { + if (xkb->server->key_acts[i+firstKey]!=0) + nActs+= XkbKeyNumActions(xkb,i+firstKey); + } + len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc)); + rep->totalActs= nActs; + return len; +} + +static char * +XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +{ + unsigned i; + CARD8 * numDesc; + XkbAnyAction * actDesc; + + numDesc = (CARD8 *)buf; + for (i=0;inKeyActs;i++) { + if (xkb->server->key_acts[i+rep->firstKeyAct]==0) + numDesc[i] = 0; + else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); + } + buf+= XkbPaddedSize(rep->nKeyActs); + + actDesc = (XkbAnyAction *)buf; + for (i=0;inKeyActs;i++) { + if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) { + unsigned int num; + num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); + memcpy((char *)actDesc, + (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)), + num*SIZEOF(xkbActionWireDesc)); + actDesc+= num; + } + } + buf = (char *)actDesc; + return buf; +} + +static int +XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nBhvr; + XkbBehavior * bhv; + + if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->behaviors)) { + rep->present&= ~XkbKeyBehaviorsMask; + rep->firstKeyBehavior= rep->nKeyBehaviors= 0; + rep->totalKeyBehaviors= 0; + return 0; + } + bhv= &xkb->server->behaviors[rep->firstKeyBehavior]; + for (nBhvr=i=0;inKeyBehaviors;i++,bhv++) { + if (bhv->type!=XkbKB_Default) + nBhvr++; + } + len= nBhvr*SIZEOF(xkbBehaviorWireDesc); + rep->totalKeyBehaviors= nBhvr; + return len; +} + +static char * +XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +{ + unsigned i; + xkbBehaviorWireDesc *wire; + XkbBehavior *pBhvr; + + wire = (xkbBehaviorWireDesc *)buf; + pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior]; + for (i=0;inKeyBehaviors;i++,pBhvr++) { + if (pBhvr->type!=XkbKB_Default) { + wire->key= i+rep->firstKeyBehavior; + wire->type= pBhvr->type; + wire->data= pBhvr->data; + wire++; + } + } + buf = (char *)wire; + return buf; +} + +static int +XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->explicit)) { + rep->present&= ~XkbExplicitComponentsMask; + rep->firstKeyExplicit= rep->nKeyExplicit= 0; + rep->totalKeyExplicit= 0; + return 0; + } + for (nRtrn=i=0;inKeyExplicit;i++) { + if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0) + nRtrn++; + } + rep->totalKeyExplicit= nRtrn; + len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */ + return len; +} + +static char * +XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) +{ +unsigned i; +char * start; +unsigned char * pExp; + + start= buf; + pExp= &xkb->server->explicit[rep->firstKeyExplicit]; + for (i=0;inKeyExplicit;i++,pExp++) { + if (*pExp!=0) { + *buf++= i+rep->firstKeyExplicit; + *buf++= *pExp; + } + } + i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ + return buf+i; +} + +static int +XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->modmap)) { + rep->present&= ~XkbModifierMapMask; + rep->firstModMapKey= rep->nModMapKeys= 0; + rep->totalModMapKeys= 0; + return 0; + } + for (nRtrn=i=0;inModMapKeys;i++) { + if (xkb->map->modmap[i+rep->firstModMapKey]!=0) + nRtrn++; + } + rep->totalModMapKeys= nRtrn; + len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */ + return len; +} + +static char * +XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +{ +unsigned i; +char * start; +unsigned char * pMap; + + start= buf; + pMap= &xkb->map->modmap[rep->firstModMapKey]; + for (i=0;inModMapKeys;i++,pMap++) { + if (*pMap!=0) { + *buf++= i+rep->firstModMapKey; + *buf++= *pMap; + } + } + i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ + return buf+i; +} + +static int +XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) { + rep->present&= ~XkbVirtualModMapMask; + rep->firstVModMapKey= rep->nVModMapKeys= 0; + rep->totalVModMapKeys= 0; + return 0; + } + for (nRtrn=i=0;inVModMapKeys;i++) { + if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0) + nRtrn++; + } + rep->totalVModMapKeys= nRtrn; + len= nRtrn*SIZEOF(xkbVModMapWireDesc); + return len; +} + +static char * +XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +{ +unsigned i; +xkbVModMapWireDesc * wire; +unsigned short * pMap; + + wire= (xkbVModMapWireDesc *)buf; + pMap= &xkb->server->vmodmap[rep->firstVModMapKey]; + for (i=0;inVModMapKeys;i++,pMap++) { + if (*pMap!=0) { + wire->key= i+rep->firstVModMapKey; + wire->vmods= *pMap; + wire++; + } + } + return (char *)wire; +} + +static Status +XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep) +{ +int len; + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + len= XkbSizeKeyTypes(xkb,rep); + len+= XkbSizeKeySyms(xkb,rep); + len+= XkbSizeKeyActions(xkb,rep); + len+= XkbSizeKeyBehaviors(xkb,rep); + len+= XkbSizeVirtualMods(xkb,rep); + len+= XkbSizeExplicit(xkb,rep); + len+= XkbSizeModifierMap(xkb,rep); + len+= XkbSizeVirtualModMap(xkb,rep); + rep->length+= (len/4); + return Success; +} + +static int +XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep) +{ +unsigned i,len; +char *desc,*start; + + len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply)); + start= desc= calloc(1, len); + if (!start) + return BadAlloc; + if ( rep->nTypes>0 ) + desc = XkbWriteKeyTypes(xkb,rep,desc,client); + if ( rep->nKeySyms>0 ) + desc = XkbWriteKeySyms(xkb,rep,desc,client); + if ( rep->nKeyActs>0 ) + desc = XkbWriteKeyActions(xkb,rep,desc,client); + if ( rep->totalKeyBehaviors>0 ) + desc = XkbWriteKeyBehaviors(xkb,rep,desc,client); + if ( rep->virtualMods ) { + register int sz,bit; + for (i=sz=0,bit=1;ivirtualMods&bit) { + desc[sz++]= xkb->server->vmods[i]; + } + } + desc+= XkbPaddedSize(sz); + } + if ( rep->totalKeyExplicit>0 ) + desc= XkbWriteExplicit(xkb,rep,desc,client); + if ( rep->totalModMapKeys>0 ) + desc= XkbWriteModifierMap(xkb,rep,desc,client); + if ( rep->totalVModMapKeys>0 ) + desc= XkbWriteVirtualModMap(xkb,rep,desc,client); + if ((desc-start)!=(len)) { + ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n", + len, (unsigned long)(desc-start)); + } + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swaps(&rep->present,n); + swaps(&rep->totalSyms,n); + swaps(&rep->totalActs,n); + } + WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep); + WriteToClient(client, len, start); + free((char *)start); + return Success; +} + +int +ProcXkbGetMap(ClientPtr client) +{ + DeviceIntPtr dev; + xkbGetMapReply rep; + XkbDescRec *xkb; + int n,status; + + REQUEST(xkbGetMapReq); + REQUEST_SIZE_MATCH(xkbGetMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial); + CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask); + CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask); + + xkb= dev->key->xkbInfo->desc; + memset(&rep, 0, sizeof(xkbGetMapReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2; + rep.deviceID = dev->id; + rep.present = stuff->partial|stuff->full; + rep.minKeyCode = xkb->min_key_code; + rep.maxKeyCode = xkb->max_key_code; + if ( stuff->full&XkbKeyTypesMask ) { + rep.firstType = 0; + rep.nTypes = xkb->map->num_types; + } + else if (stuff->partial&XkbKeyTypesMask) { + if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types, + stuff->firstType,stuff->nTypes); + return BadValue; + } + rep.firstType = stuff->firstType; + rep.nTypes = stuff->nTypes; + } + else rep.nTypes = 0; + rep.totalTypes = xkb->map->num_types; + + n= XkbNumKeys(xkb); + if ( stuff->full&XkbKeySymsMask ) { + rep.firstKeySym = xkb->min_key_code; + rep.nKeySyms = n; + } + else if (stuff->partial&XkbKeySymsMask) { + CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb); + rep.firstKeySym = stuff->firstKeySym; + rep.nKeySyms = stuff->nKeySyms; + } + else rep.nKeySyms = 0; + rep.totalSyms= 0; + + if ( stuff->full&XkbKeyActionsMask ) { + rep.firstKeyAct= xkb->min_key_code; + rep.nKeyActs= n; + } + else if (stuff->partial&XkbKeyActionsMask) { + CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb); + rep.firstKeyAct= stuff->firstKeyAct; + rep.nKeyActs= stuff->nKeyActs; + } + else rep.nKeyActs= 0; + rep.totalActs= 0; + + if ( stuff->full&XkbKeyBehaviorsMask ) { + rep.firstKeyBehavior = xkb->min_key_code; + rep.nKeyBehaviors = n; + } + else if (stuff->partial&XkbKeyBehaviorsMask) { + CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb); + rep.firstKeyBehavior= stuff->firstKeyBehavior; + rep.nKeyBehaviors= stuff->nKeyBehaviors; + } + else rep.nKeyBehaviors = 0; + rep.totalKeyBehaviors= 0; + + if (stuff->full&XkbVirtualModsMask) + rep.virtualMods= ~0; + else if (stuff->partial&XkbVirtualModsMask) + rep.virtualMods= stuff->virtualMods; + + if (stuff->full&XkbExplicitComponentsMask) { + rep.firstKeyExplicit= xkb->min_key_code; + rep.nKeyExplicit= n; + } + else if (stuff->partial&XkbExplicitComponentsMask) { + CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb); + rep.firstKeyExplicit= stuff->firstKeyExplicit; + rep.nKeyExplicit= stuff->nKeyExplicit; + } + else rep.nKeyExplicit = 0; + rep.totalKeyExplicit= 0; + + if (stuff->full&XkbModifierMapMask) { + rep.firstModMapKey= xkb->min_key_code; + rep.nModMapKeys= n; + } + else if (stuff->partial&XkbModifierMapMask) { + CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb); + rep.firstModMapKey= stuff->firstModMapKey; + rep.nModMapKeys= stuff->nModMapKeys; + } + else rep.nModMapKeys = 0; + rep.totalModMapKeys= 0; + + if (stuff->full&XkbVirtualModMapMask) { + rep.firstVModMapKey= xkb->min_key_code; + rep.nVModMapKeys= n; + } + else if (stuff->partial&XkbVirtualModMapMask) { + CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb); + rep.firstVModMapKey= stuff->firstVModMapKey; + rep.nVModMapKeys= stuff->nVModMapKeys; + } + else rep.nVModMapKeys = 0; + rep.totalVModMapKeys= 0; + + if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success) + return status; + return XkbSendMap(client,xkb,&rep); +} + +/***====================================================================***/ + +static int +CheckKeyTypes( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + xkbKeyTypeWireDesc **wireRtrn, + int * nMapsRtrn, + CARD8 * mapWidthRtrn) +{ +unsigned nMaps; +register unsigned i,n; +register CARD8 * map; +register xkbKeyTypeWireDesc *wire = *wireRtrn; + + if (req->firstType>((unsigned)xkb->map->num_types)) { + *nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types); + return 0; + } + if (req->flags&XkbSetMapResizeTypes) { + nMaps = req->firstType+req->nTypes; + if (nMapsfirstType,req->nTypes,4); + return 0; + } + } + else if (req->present&XkbKeyTypesMask) { + nMaps = xkb->map->num_types; + if ((req->firstType+req->nTypes)>nMaps) { + *nMapsRtrn = req->firstType+req->nTypes; + return 0; + } + } + else { + *nMapsRtrn = xkb->map->num_types; + for (i=0;imap->num_types;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + return 1; + } + + for (i=0;ifirstType;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + for (i=0;inTypes;i++) { + unsigned width; + if (client->swapped) { + register int s; + swaps(&wire->virtualMods,s); + } + n= i+req->firstType; + width= wire->numLevels; + if (width<1) { + *nMapsRtrn= _XkbErrCode3(0x04,n,width); + return 0; + } + else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */ + *nMapsRtrn= _XkbErrCode3(0x05,n,width); + return 0; + } + else if ((width!=2)&& + ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)|| + (n==XkbAlphabeticIndex))) { + /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */ + *nMapsRtrn= _XkbErrCode3(0x05,n,width); + return 0; + } + if (wire->nMapEntries>0) { + xkbKTSetMapEntryWireDesc * mapWire; + xkbModsWireDesc * preWire; + mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1]; + preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; + for (n=0;nnMapEntries;n++) { + if (client->swapped) { + register int s; + swaps(&mapWire[n].virtualMods,s); + } + if (mapWire[n].realMods&(~wire->realMods)) { + *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods, + wire->realMods); + return 0; + } + if (mapWire[n].virtualMods&(~wire->virtualMods)) { + *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods); + return 0; + } + if (mapWire[n].level>=wire->numLevels) { + *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels, + mapWire[n].level); + return 0; + } + if (wire->preserve) { + if (client->swapped) { + register int s; + swaps(&preWire[n].virtualMods,s); + } + if (preWire[n].realMods&(~mapWire[n].realMods)) { + *nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods, + mapWire[n].realMods); + return 0; + } + if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) { + *nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods); + return 0; + } + } + } + if (wire->preserve) + map= (CARD8 *)&preWire[wire->nMapEntries]; + else map= (CARD8 *)&mapWire[wire->nMapEntries]; + } + else map= (CARD8 *)&wire[1]; + mapWidthRtrn[i+req->firstType] = wire->numLevels; + wire= (xkbKeyTypeWireDesc *)map; + } + for (i=req->firstType+req->nTypes;imap->types[i].num_levels; + } + *nMapsRtrn = nMaps; + *wireRtrn = wire; + return 1; +} + +static int +CheckKeySyms( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + int nTypes, + CARD8 * mapWidths, + CARD16 * symsPerKey, + xkbSymMapWireDesc ** wireRtrn, + int * errorRtrn) +{ +register unsigned i; +XkbSymMapPtr map; +xkbSymMapWireDesc* wire = *wireRtrn; + + if (!(XkbKeySymsMask&req->present)) + return 1; + CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0); + for (i=0;inKeySyms;i++) { + KeySym *pSyms; + register unsigned nG; + if (client->swapped) { + swaps(&wire->nSyms,nG); + } + nG = XkbNumGroups(wire->groupInfo); + if (nG>XkbNumKbdGroups) { + *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG); + return 0; + } + if (nG>0) { + register int g,w; + for (g=w=0;gktIndex[g]>=(unsigned)nTypes) { + *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g, + wire->ktIndex[g]); + return 0; + } + if (mapWidths[wire->ktIndex[g]]>w) + w= mapWidths[wire->ktIndex[g]]; + } + if (wire->width!=w) { + *errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width); + return 0; + } + w*= nG; + symsPerKey[i+req->firstKeySym] = w; + if (w!=wire->nSyms) { + *errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w); + return 0; + } + } + else if (wire->nSyms!=0) { + *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms); + return 0; + } + pSyms = (KeySym *)&wire[1]; + wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; + } + + map = &xkb->map->key_sym_map[i]; + for (;i<=(unsigned)xkb->max_key_code;i++,map++) { + register int g,nG,w; + nG= XkbKeyNumGroups(xkb,i); + for (w=g=0;gkt_index[g]>=(unsigned)nTypes) { + *errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]); + return 0; + } + if (mapWidths[map->kt_index[g]]>w) + w= mapWidths[map->kt_index[g]]; + } + symsPerKey[i] = w*nG; + } + *wireRtrn = wire; + return 1; +} + +static int +CheckKeyActions( XkbDescPtr xkb, + xkbSetMapReq * req, + int nTypes, + CARD8 * mapWidths, + CARD16 * symsPerKey, + CARD8 ** wireRtrn, + int * nActsRtrn) +{ +int nActs; +CARD8 * wire = *wireRtrn; +register unsigned i; + + if (!(XkbKeyActionsMask&req->present)) + return 1; + CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0); + for (nActs=i=0;inKeyActs;i++) { + if (wire[0]!=0) { + if (wire[0]==symsPerKey[i+req->firstKeyAct]) + nActs+= wire[0]; + else { + *nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]); + return 0; + } + } + wire++; + } + if (req->nKeyActs%4) + wire+= 4-(req->nKeyActs%4); + *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs); + *nActsRtrn = nActs; + return 1; +} + +static int +CheckKeyBehaviors( XkbDescPtr xkb, + xkbSetMapReq * req, + xkbBehaviorWireDesc ** wireRtrn, + int * errorRtrn) +{ +register xkbBehaviorWireDesc * wire = *wireRtrn; +register XkbServerMapPtr server = xkb->server; +register unsigned i; +unsigned first,last; + + if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) { + req->present&= ~XkbKeyBehaviorsMask; + req->nKeyBehaviors= 0; + return 1; + } + first= req->firstKeyBehavior; + last= req->firstKeyBehavior+req->nKeyBehaviors-1; + if (firstminKeyCode) { + *errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode); + return 0; + } + + for (i=0;itotalKeyBehaviors;i++,wire++) { + if ((wire->keykey>last)) { + *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key); + return 0; + } + if ((wire->type&XkbKB_Permanent)&& + ((server->behaviors[wire->key].type!=wire->type)|| + (server->behaviors[wire->key].data!=wire->data))) { + *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type); + return 0; + } + if ((wire->type==XkbKB_RadioGroup)&& + ((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) { + *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data, + XkbMaxRadioGroups); + return 0; + } + if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) { + CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0); + } + } + *wireRtrn = wire; + return 1; +} + +static int +CheckVirtualMods( XkbDescRec * xkb, + xkbSetMapReq * req, + CARD8 ** wireRtrn, + int * errorRtrn) +{ +register CARD8 *wire = *wireRtrn; +register unsigned i,nMods,bit; + + if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) + return 1; + for (i=nMods=0,bit=1;ivirtualMods&bit) + nMods++; + } + *wireRtrn= (wire+XkbPaddedSize(nMods)); + return 1; +} + +static int +CheckKeyExplicit( XkbDescPtr xkb, + xkbSetMapReq * req, + CARD8 ** wireRtrn, + int * errorRtrn) +{ +register CARD8 * wire = *wireRtrn; +CARD8 * start; +register unsigned i; +int first,last; + + if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) { + req->present&= ~XkbExplicitComponentsMask; + req->nKeyExplicit= 0; + return 1; + } + first= req->firstKeyExplicit; + last= first+req->nKeyExplicit-1; + if (firstminKeyCode) { + *errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode); + return 0; + } + start= wire; + for (i=0;itotalKeyExplicit;i++,wire+=2) { + if ((wire[0]last)) { + *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]); + return 0; + } + if (wire[1]&(~XkbAllExplicitMask)) { + *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]); + return 0; + } + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + *wireRtrn= wire; + return 1; +} + +static int +CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn) +{ +register CARD8 * wire = *wireRtrn; +CARD8 * start; +register unsigned i; +int first,last; + + if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) { + req->present&= ~XkbModifierMapMask; + req->nModMapKeys= 0; + return 1; + } + first= req->firstModMapKey; + last= first+req->nModMapKeys-1; + if (firstminKeyCode) { + *errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode); + return 0; + } + start= wire; + for (i=0;itotalModMapKeys;i++,wire+=2) { + if ((wire[0]last)) { + *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]); + return 0; + } + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + *wireRtrn= wire; + return 1; +} + +static int +CheckVirtualModMap( XkbDescPtr xkb, + xkbSetMapReq *req, + xkbVModMapWireDesc **wireRtrn, + int *errRtrn) +{ +register xkbVModMapWireDesc * wire = *wireRtrn; +register unsigned i; +int first,last; + + if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) { + req->present&= ~XkbVirtualModMapMask; + req->nVModMapKeys= 0; + return 1; + } + first= req->firstVModMapKey; + last= first+req->nVModMapKeys-1; + if (firstminKeyCode) { + *errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode); + return 0; + } + for (i=0;itotalVModMapKeys;i++,wire++) { + if ((wire->keykey>last)) { + *errRtrn = _XkbErrCode4(0x73,first,last,wire->key); + return 0; + } + } + *wireRtrn= wire; + return 1; +} + +static char * +SetKeyTypes( XkbDescPtr xkb, + xkbSetMapReq * req, + xkbKeyTypeWireDesc * wire, + XkbChangesPtr changes) +{ +register unsigned i; +unsigned first,last; +CARD8 *map; + + if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) { + i= req->firstType+req->nTypes; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) { + return NULL; + } + } + if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types) + xkb->map->num_types= req->firstType+req->nTypes; + + for (i=0;inTypes;i++) { + XkbKeyTypePtr pOld; + register unsigned n; + + if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries, + wire->preserve,wire->numLevels)!=Success) { + return NULL; + } + pOld = &xkb->map->types[i+req->firstType]; + map = (CARD8 *)&wire[1]; + + pOld->mods.real_mods = wire->realMods; + pOld->mods.vmods= wire->virtualMods; + pOld->num_levels = wire->numLevels; + pOld->map_count= wire->nMapEntries; + + pOld->mods.mask= pOld->mods.real_mods| + XkbMaskForVMask(xkb,pOld->mods.vmods); + + if (wire->nMapEntries) { + xkbKTSetMapEntryWireDesc *mapWire; + xkbModsWireDesc *preWire; + unsigned tmp; + mapWire= (xkbKTSetMapEntryWireDesc *)map; + preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; + for (n=0;nnMapEntries;n++) { + pOld->map[n].active= 1; + pOld->map[n].mods.mask= mapWire[n].realMods; + pOld->map[n].mods.real_mods= mapWire[n].realMods; + pOld->map[n].mods.vmods= mapWire[n].virtualMods; + pOld->map[n].level= mapWire[n].level; + if (mapWire[n].virtualMods!=0) { + tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods); + pOld->map[n].active= (tmp!=0); + pOld->map[n].mods.mask|= tmp; + } + if (wire->preserve) { + pOld->preserve[n].real_mods= preWire[n].realMods; + pOld->preserve[n].vmods= preWire[n].virtualMods; + tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods); + pOld->preserve[n].mask= preWire[n].realMods|tmp; + } + } + if (wire->preserve) + map= (CARD8 *)&preWire[wire->nMapEntries]; + else map= (CARD8 *)&mapWire[wire->nMapEntries]; + } + else map= (CARD8 *)&wire[1]; + wire = (xkbKeyTypeWireDesc *)map; + } + first= req->firstType; + last= first+req->nTypes-1; /* last changed type */ + if (changes->map.changed&XkbKeyTypesMask) { + int oldLast; + oldLast= changes->map.first_type+changes->map.num_types-1; + if (changes->map.first_typemap.first_type; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type = first; + changes->map.num_types = (last-first)+1; + return (char *)wire; +} + +static char * +SetKeySyms( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + xkbSymMapWireDesc * wire, + XkbChangesPtr changes, + DeviceIntPtr dev) +{ +register unsigned i,s; +XkbSymMapPtr oldMap; +KeySym * newSyms; +KeySym * pSyms; +unsigned first,last; + + oldMap = &xkb->map->key_sym_map[req->firstKeySym]; + for (i=0;inKeySyms;i++,oldMap++) { + pSyms = (KeySym *)&wire[1]; + if (wire->nSyms>0) { + newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms); + for (s=0;snSyms;s++) { + newSyms[s]= pSyms[s]; + } + if (client->swapped) { + int n; + for (s=0;snSyms;s++) { + swapl(&newSyms[s],n); + } + } + } + oldMap->kt_index[0] = wire->ktIndex[0]; + oldMap->kt_index[1] = wire->ktIndex[1]; + oldMap->kt_index[2] = wire->ktIndex[2]; + oldMap->kt_index[3] = wire->ktIndex[3]; + oldMap->group_info = wire->groupInfo; + oldMap->width = wire->width; + wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; + } + first= req->firstKeySym; + last= first+req->nKeySyms-1; + if (changes->map.changed&XkbKeySymsMask) { + int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1); + if (changes->map.first_key_symmap.first_key_sym; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym = first; + changes->map.num_key_syms = (last-first+1); + + s= 0; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (XkbKeyNumGroups(xkb,i)>s) + s= XkbKeyNumGroups(xkb,i); + } + if (s!=xkb->ctrls->num_groups) { + xkbControlsNotify cn; + XkbControlsRec old; + cn.keycode= 0; + cn.eventType= 0; + cn.requestMajor= XkbReqCode; + cn.requestMinor= X_kbSetMap; + old= *xkb->ctrls; + xkb->ctrls->num_groups= s; + if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,FALSE)) + XkbSendControlsNotify(dev,&cn); + } + return (char *)wire; +} + +static char * +SetKeyActions( XkbDescPtr xkb, + xkbSetMapReq * req, + CARD8 * wire, + XkbChangesPtr changes) +{ +register unsigned i,first,last; +CARD8 * nActs = wire; +XkbAction * newActs; + + wire+= XkbPaddedSize(req->nKeyActs); + for (i=0;inKeyActs;i++) { + if (nActs[i]==0) + xkb->server->key_acts[i+req->firstKeyAct]= 0; + else { + newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]); + memcpy((char *)newActs,(char *)wire, + nActs[i]*SIZEOF(xkbActionWireDesc)); + wire+= nActs[i]*SIZEOF(xkbActionWireDesc); + } + } + first= req->firstKeyAct; + last= (first+req->nKeyActs-1); + if (changes->map.changed&XkbKeyActionsMask) { + int oldLast; + oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; + if (changes->map.first_key_actmap.first_key_act; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act= first; + changes->map.num_key_acts= (last-first+1); + return (char *)wire; +} + +static char * +SetKeyBehaviors( XkbSrvInfoPtr xkbi, + xkbSetMapReq *req, + xkbBehaviorWireDesc *wire, + XkbChangesPtr changes) +{ +register unsigned i; +int maxRG = -1; +XkbDescPtr xkb = xkbi->desc; +XkbServerMapPtr server = xkb->server; +unsigned first,last; + + first= req->firstKeyBehavior; + last= req->firstKeyBehavior+req->nKeyBehaviors-1; + memset(&server->behaviors[first], 0, req->nKeyBehaviors*sizeof(XkbBehavior)); + for (i=0;itotalKeyBehaviors;i++) { + if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) { + server->behaviors[wire->key].type= wire->type; + server->behaviors[wire->key].data= wire->data; + if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG)) + maxRG= wire->data + 1; + } + wire++; + } + + if (maxRG>(int)xkbi->nRadioGroups) { + int sz = maxRG*sizeof(XkbRadioGroupRec); + if (xkbi->radioGroups) + xkbi->radioGroups= realloc(xkbi->radioGroups,sz); + else xkbi->radioGroups= calloc(1, sz); + if (xkbi->radioGroups) { + if (xkbi->nRadioGroups) + memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0, + (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec)); + xkbi->nRadioGroups= maxRG; + } + else xkbi->nRadioGroups= 0; + /* should compute members here */ + } + if (changes->map.changed&XkbKeyBehaviorsMask) { + unsigned oldLast; + oldLast= changes->map.first_key_behavior+ + changes->map.num_key_behaviors-1; + if (changes->map.first_key_behaviorfirstKeyBehavior) + first= changes->map.first_key_behavior; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyBehaviorsMask; + changes->map.first_key_behavior = first; + changes->map.num_key_behaviors = (last-first+1); + return (char *)wire; +} + +static char * +SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, + XkbChangesPtr changes) +{ +register int i,bit,nMods; +XkbServerMapPtr srv = xkbi->desc->server; + + if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) + return (char *)wire; + for (i=nMods=0,bit=1;ivirtualMods&bit) { + if (srv->vmods[i]!=wire[nMods]) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + srv->vmods[i]= wire[nMods]; + } + nMods++; + } + } + return (char *)(wire+XkbPaddedSize(nMods)); +} + +static char * +SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, + XkbChangesPtr changes) +{ +register unsigned i,first,last; +XkbServerMapPtr xkb = xkbi->desc->server; +CARD8 * start; + + start= wire; + first= req->firstKeyExplicit; + last= req->firstKeyExplicit+req->nKeyExplicit-1; + memset(&xkb->explicit[first], 0, req->nKeyExplicit); + for (i=0;itotalKeyExplicit;i++,wire+= 2) { + xkb->explicit[wire[0]]= wire[1]; + } + if (first>0) { + if (changes->map.changed&XkbExplicitComponentsMask) { + int oldLast; + oldLast= changes->map.first_key_explicit+ + changes->map.num_key_explicit-1; + if (changes->map.first_key_explicitmap.first_key_explicit; + if (oldLast>last) + last= oldLast; + } + changes->map.first_key_explicit= first; + changes->map.num_key_explicit= (last-first)+1; + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + return (char *)wire; +} + +static char * +SetModifierMap( XkbSrvInfoPtr xkbi, + xkbSetMapReq * req, + CARD8 * wire, + XkbChangesPtr changes) +{ +register unsigned i,first,last; +XkbClientMapPtr xkb = xkbi->desc->map; +CARD8 * start; + + start= wire; + first= req->firstModMapKey; + last= req->firstModMapKey+req->nModMapKeys-1; + memset(&xkb->modmap[first], 0, req->nModMapKeys); + for (i=0;itotalModMapKeys;i++,wire+= 2) { + xkb->modmap[wire[0]]= wire[1]; + } + if (first>0) { + if (changes->map.changed&XkbModifierMapMask) { + int oldLast; + oldLast= changes->map.first_modmap_key+ + changes->map.num_modmap_keys-1; + if (changes->map.first_modmap_keymap.first_modmap_key; + if (oldLast>last) + last= oldLast; + } + changes->map.first_modmap_key= first; + changes->map.num_modmap_keys= (last-first)+1; + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + return (char *)wire; +} + +static char * +SetVirtualModMap( XkbSrvInfoPtr xkbi, + xkbSetMapReq * req, + xkbVModMapWireDesc * wire, + XkbChangesPtr changes) +{ +register unsigned i,first,last; +XkbServerMapPtr srv = xkbi->desc->server; + + first= req->firstVModMapKey; + last= req->firstVModMapKey+req->nVModMapKeys-1; + memset(&srv->vmodmap[first], 0, req->nVModMapKeys*sizeof(unsigned short)); + for (i=0;itotalVModMapKeys;i++,wire++) { + srv->vmodmap[wire->key]= wire->vmods; + } + if (first>0) { + if (changes->map.changed&XkbVirtualModMapMask) { + int oldLast; + oldLast= changes->map.first_vmodmap_key+ + changes->map.num_vmodmap_keys-1; + if (changes->map.first_vmodmap_keymap.first_vmodmap_key; + if (oldLast>last) + last= oldLast; + } + changes->map.first_vmodmap_key= first; + changes->map.num_vmodmap_keys= (last-first)+1; + } + return (char *)wire; +} + +/** + * Check if the given request can be applied to the given device but don't + * actually do anything.. + */ +static int +_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values) +{ + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + int error; + int nTypes = 0, nActions; + CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = {0}; + CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = {0}; + XkbSymMapPtr map; + int i; + + xkbi= dev->key->xkbInfo; + xkb = xkbi->desc; + + if ((xkb->min_key_code != req->minKeyCode)|| + (xkb->max_key_code != req->maxKeyCode)) { + if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */ + req->minKeyCode= xkb->min_key_code; + req->maxKeyCode= xkb->max_key_code; + } + else { + if (!XkbIsLegalKeycode(req->minKeyCode)) { + client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode); + return BadValue; + } + if (req->minKeyCode > req->maxKeyCode) { + client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode); + return BadMatch; + } + } + } + + if ((req->present & XkbKeyTypesMask) && + (!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values, + &nTypes,mapWidths))) { + client->errorValue = nTypes; + return BadValue; + } + + /* symsPerKey/mapWidths must be filled regardless of client-side flags */ + map = &xkb->map->key_sym_map[xkb->min_key_code]; + for (i=xkb->min_key_code;imax_key_code;i++,map++) { + register int g,ng,w; + ng= XkbNumGroups(map->group_info); + for (w=g=0;gkt_index[g]>=(unsigned)nTypes) { + client->errorValue = _XkbErrCode4(0x13,i,g,map->kt_index[g]); + return 0; + } + if (mapWidths[map->kt_index[g]]>w) + w= mapWidths[map->kt_index[g]]; + } + symsPerKey[i] = w*ng; + } + + if ((req->present & XkbKeySymsMask) && + (!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey, + (xkbSymMapWireDesc **)&values,&error))) { + client->errorValue = error; + return BadValue; + } + + if ((req->present & XkbKeyActionsMask) && + (!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey, + (CARD8 **)&values,&nActions))) { + client->errorValue = nActions; + return BadValue; + } + + if ((req->present & XkbKeyBehaviorsMask) && + (!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) { + client->errorValue = error; + return BadValue; + } + + if ((req->present & XkbVirtualModsMask) && + (!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } + if ((req->present&XkbExplicitComponentsMask) && + (!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } + if ((req->present&XkbModifierMapMask) && + (!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } + if ((req->present&XkbVirtualModMapMask) && + (!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) { + client->errorValue= error; + return BadValue; + } + + if (((values-((char *)req))/4)!= req->length) { + ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n"); + client->errorValue = values-((char *)&req[1]); + return BadLength; + } + + return Success; +} + +/** + * Apply the given request on the given device. + */ +static int +_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char *values) +{ + XkbEventCauseRec cause; + XkbChangesRec change; + Bool sentNKN; + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + + xkbi= dev->key->xkbInfo; + xkb = xkbi->desc; + + XkbSetCauseXkbReq(&cause,X_kbSetMap,client); + memset(&change, 0, sizeof(change)); + sentNKN = FALSE; + if ((xkb->min_key_code!=req->minKeyCode)|| + (xkb->max_key_code!=req->maxKeyCode)) { + Status status; + xkbNewKeyboardNotify nkn; + nkn.deviceID = nkn.oldDeviceID = dev->id; + nkn.oldMinKeyCode = xkb->min_key_code; + nkn.oldMaxKeyCode = xkb->max_key_code; + status= XkbChangeKeycodeRange(xkb, req->minKeyCode, + req->maxKeyCode, &change); + if (status != Success) + return status; /* oh-oh. what about the other keyboards? */ + nkn.minKeyCode = xkb->min_key_code; + nkn.maxKeyCode = xkb->max_key_code; + nkn.requestMajor = XkbReqCode; + nkn.requestMinor = X_kbSetMap; + nkn.changed = XkbNKN_KeycodesMask; + XkbSendNewKeyboardNotify(dev,&nkn); + sentNKN = TRUE; + } + + if (req->present&XkbKeyTypesMask) { + values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change); + if (!values) goto allocFailure; + } + if (req->present&XkbKeySymsMask) { + values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev); + if (!values) goto allocFailure; + } + if (req->present&XkbKeyActionsMask) { + values = SetKeyActions(xkb,req,(CARD8 *)values,&change); + if (!values) goto allocFailure; + } + if (req->present&XkbKeyBehaviorsMask) { + values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change); + if (!values) goto allocFailure; + } + if (req->present&XkbVirtualModsMask) + values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change); + if (req->present&XkbExplicitComponentsMask) + values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change); + if (req->present&XkbModifierMapMask) + values= SetModifierMap(xkbi,req,(CARD8 *)values,&change); + if (req->present&XkbVirtualModMapMask) + values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change); + if (((values-((char *)req))/4)!=req->length) { + ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n"); + client->errorValue = values-((char *)&req[1]); + return BadLength; + } + if (req->flags&XkbSetMapRecomputeActions) { + KeyCode first,last,firstMM,lastMM; + if (change.map.num_key_syms>0) { + first= change.map.first_key_sym; + last= first+change.map.num_key_syms-1; + } + else first= last= 0; + if (change.map.num_modmap_keys>0) { + firstMM= change.map.first_modmap_key; + lastMM= first+change.map.num_modmap_keys-1; + } + else firstMM= lastMM= 0; + if ((last>0) && (lastMM>0)) { + if (firstMMlast) + last= lastMM; + } + else if (lastMM>0) { + first= firstMM; + last= lastMM; + } + if (last>0) { + unsigned check= 0; + XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + } + } + if (!sentNKN) + XkbSendNotification(dev,&change,&cause); + + return Success; +allocFailure: + return BadAlloc; +} + + +int +ProcXkbSetMap(ClientPtr client) +{ + DeviceIntPtr dev; + char * tmp; + int rc; + + REQUEST(xkbSetMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask); + + tmp = (char *)&stuff[1]; + + /* Check if we can to the SetMap on the requested device. If this + succeeds, do the same thing for all extension devices (if needed). + If any of them fails, fail. */ + rc = _XkbSetMapChecks(client, dev, stuff, tmp); + + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetMapChecks(client, other, stuff, tmp); + if (rc != Success) + return rc; + } + } + } + } + + /* We know now that we will succed with the SetMap. In theory anyway. */ + rc = _XkbSetMap(client, dev, stuff, tmp); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + _XkbSetMap(client, other, stuff, tmp); + /* ignore rc. if the SetMap failed although the check above + reported true there isn't much we can do. we still need to + set all other devices, hoping that at least they stay in + sync. */ + } + } + } + + return Success; +} + +/***====================================================================***/ + +static Status +XkbComputeGetCompatMapReplySize( XkbCompatMapPtr compat, + xkbGetCompatMapReply * rep) +{ +unsigned size,nGroups; + + nGroups= 0; + if (rep->groups!=0) { + register int i,bit; + for (i=0,bit=1;igroups&bit) + nGroups++; + } + } + size= nGroups*SIZEOF(xkbModsWireDesc); + size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc)); + rep->length= size/4; + return Success; +} + +static int +XkbSendCompatMap( ClientPtr client, + XkbCompatMapPtr compat, + xkbGetCompatMapReply * rep) +{ +char * data; +int size; + + size= rep->length*4; + if (size>0) { + data = malloc(size); + if (data) { + register unsigned i,bit; + xkbModsWireDesc * grp; + XkbSymInterpretPtr sym= &compat->sym_interpret[rep->firstSI]; + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + for (i=0;inSI;i++,sym++,wire++) { + wire->sym= sym->sym; + wire->mods= sym->mods; + wire->match= sym->match; + wire->virtualMod= sym->virtual_mod; + wire->flags= sym->flags; + memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc); + if (client->swapped) { + register int n; + swapl(&wire->sym,n); + } + } + if (rep->groups) { + grp = (xkbModsWireDesc *)wire; + for (i=0,bit=1;igroups&bit) { + grp->mask= compat->groups[i].mask; + grp->realMods= compat->groups[i].real_mods; + grp->virtualMods= compat->groups[i].vmods; + if (client->swapped) { + register int n; + swaps(&grp->virtualMods,n); + } + grp++; + } + } + wire= (xkbSymInterpretWireDesc*)grp; + } + } + else return BadAlloc; + } + else data= NULL; + + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swaps(&rep->firstSI,n); + swaps(&rep->nSI,n); + swaps(&rep->nTotalSI,n); + } + + WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep); + if (data) { + WriteToClient(client, size, data); + free((char *)data); + } + return Success; +} + +int +ProcXkbGetCompatMap(ClientPtr client) +{ + xkbGetCompatMapReply rep; + DeviceIntPtr dev; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + + REQUEST(xkbGetCompatMapReq); + REQUEST_SIZE_MATCH(xkbGetCompatMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + xkb = dev->key->xkbInfo->desc; + compat= xkb->compat; + + rep.type = X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.firstSI = stuff->firstSI; + rep.nSI = stuff->nSI; + if (stuff->getAllSI) { + rep.firstSI = 0; + rep.nSI = compat->num_si; + } + else if ((((unsigned)stuff->nSI)>0)&& + ((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) { + client->errorValue = _XkbErrCode2(0x05,compat->num_si); + return BadValue; + } + rep.nTotalSI = compat->num_si; + rep.groups= stuff->groups; + XkbComputeGetCompatMapReplySize(compat,&rep); + return XkbSendCompatMap(client,compat,&rep); +} + +/** + * Apply the given request on the given device. + * If dryRun is TRUE, then value checks are performed, but the device isn't + * modified. + */ +static int +_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev, + xkbSetCompatMapReq *req, char* data, BOOL dryRun) +{ + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + int nGroups; + unsigned i,bit; + + xkbi = dev->key->xkbInfo; + xkb = xkbi->desc; + compat = xkb->compat; + + if ((req->nSI>0)||(req->truncateSI)) { + xkbSymInterpretWireDesc *wire; + if (req->firstSI>compat->num_si) { + client->errorValue = _XkbErrCode2(0x02,compat->num_si); + return BadValue; + } + wire= (xkbSymInterpretWireDesc *)data; + wire+= req->nSI; + data = (char *)wire; + } + + nGroups= 0; + if (req->groups!=0) { + for (i=0,bit=1;igroups&bit ) + nGroups++; + } + } + data+= nGroups*SIZEOF(xkbModsWireDesc); + if (((data-((char *)req))/4)!=req->length) { + return BadLength; + } + + /* Done all the checks we can do */ + if (dryRun) + return Success; + + data = (char *)&req[1]; + if (req->nSI>0) { + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + XkbSymInterpretPtr sym; + if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) { + compat->num_si= req->firstSI+req->nSI; + compat->sym_interpret= realloc(compat->sym_interpret, + compat->num_si * sizeof(XkbSymInterpretRec)); + if (!compat->sym_interpret) { + compat->num_si= 0; + return BadAlloc; + } + } + else if (req->truncateSI) { + compat->num_si = req->firstSI+req->nSI; + } + sym = &compat->sym_interpret[req->firstSI]; + for (i=0;inSI;i++,wire++,sym++) { + if (client->swapped) { + int n; + swapl(&wire->sym,n); + } + sym->sym= wire->sym; + sym->mods= wire->mods; + sym->match= wire->match; + sym->flags= wire->flags; + sym->virtual_mod= wire->virtualMod; + memcpy((char *)&sym->act,(char *)&wire->act, + SIZEOF(xkbActionWireDesc)); + } + data = (char *)wire; + } + else if (req->truncateSI) { + compat->num_si = req->firstSI; + } + + if (req->groups!=0) { + unsigned i, bit; + xkbModsWireDesc *wire = (xkbModsWireDesc *)data; + for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { + if (req->groups & bit) { + if (client->swapped) { + int n; + swaps(&wire->virtualMods,n); + } + compat->groups[i].mask= wire->realMods; + compat->groups[i].real_mods= wire->realMods; + compat->groups[i].vmods= wire->virtualMods; + if (wire->virtualMods!=0) { + unsigned tmp; + tmp= XkbMaskForVMask(xkb,wire->virtualMods); + compat->groups[i].mask|= tmp; + } + data+= SIZEOF(xkbModsWireDesc); + wire= (xkbModsWireDesc *)data; + } + } + } + i= XkbPaddedSize((data-((char *)req))); + if ((i/4)!=req->length) { + ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n"); + return BadLength; + } + + if (dev->xkb_interest) { + xkbCompatMapNotify ev; + ev.deviceID = dev->id; + ev.changedGroups = req->groups; + ev.firstSI = req->firstSI; + ev.nSI = req->nSI; + ev.nTotalSI = compat->num_si; + XkbSendCompatMapNotify(dev,&ev); + } + + if (req->recomputeActions) { + XkbChangesRec change; + unsigned check; + XkbEventCauseRec cause; + + XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client); + memset(&change, 0, sizeof(XkbChangesRec)); + XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check, + &cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + XkbSendNotification(dev,&change,&cause); + } + return Success; +} + +int +ProcXkbSetCompatMap(ClientPtr client) +{ + DeviceIntPtr dev; + char *data; + int rc; + + REQUEST(xkbSetCompatMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + + data = (char *)&stuff[1]; + + /* check first using a dry-run */ + rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE); + if (rc != Success) + return rc; + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + /* dry-run */ + rc = _XkbSetCompatMap(client, other, stuff, data, TRUE); + if (rc != Success) + return rc; + } + } + } + } + + /* Yay, the dry-runs succeed. Let's apply */ + rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE); + if (rc != Success) + return rc; + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetCompatMap(client, other, stuff, data, FALSE); + if (rc != Success) + return rc; + } + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbGetIndicatorState(ClientPtr client) +{ + xkbGetIndicatorStateReply rep; + XkbSrvLedInfoPtr sli; + DeviceIntPtr dev; + register int i; + + REQUEST(xkbGetIndicatorStateReq); + REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorStateMask); + if (!sli) + return BadAlloc; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.state = sli->effectiveState; + + if (client->swapped) { + swaps(&rep.sequenceNumber,i); + swapl(&rep.state,i); + } + WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +static Status +XkbComputeGetIndicatorMapReplySize( + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply *rep) +{ +register int i,bit; +int nIndicators; + + rep->realIndicators = indicators->phys_indicators; + for (i=nIndicators=0,bit=1;iwhich&bit) + nIndicators++; + } + rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4; + return Success; +} + +static int +XkbSendIndicatorMap( ClientPtr client, + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply * rep) +{ +int length; +CARD8 * map; +register int i; +register unsigned bit; + + length = rep->length*4; + if (length>0) { + CARD8 *to; + to= map= malloc(length); + if (map) { + xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *)to; + for (i=0,bit=1;iwhich&bit) { + wire->flags= indicators->maps[i].flags; + wire->whichGroups= indicators->maps[i].which_groups; + wire->groups= indicators->maps[i].groups; + wire->whichMods= indicators->maps[i].which_mods; + wire->mods= indicators->maps[i].mods.mask; + wire->realMods= indicators->maps[i].mods.real_mods; + wire->virtualMods= indicators->maps[i].mods.vmods; + wire->ctrls= indicators->maps[i].ctrls; + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + swapl(&wire->ctrls,n); + } + wire++; + } + } + to = (CARD8 *)wire; + if ((to-map)!=length) { + client->errorValue = _XkbErrCode2(0xff,length); + free(map); + return BadLength; + } + } + else return BadAlloc; + } + else map = NULL; + if (client->swapped) { + swaps(&rep->sequenceNumber,i); + swapl(&rep->length,i); + swapl(&rep->which,i); + swapl(&rep->realIndicators,i); + } + WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep); + if (map) { + WriteToClient(client, length, (char *)map); + free((char *)map); + } + return Success; +} + +int +ProcXkbGetIndicatorMap(ClientPtr client) +{ +xkbGetIndicatorMapReply rep; +DeviceIntPtr dev; +XkbDescPtr xkb; +XkbIndicatorPtr leds; + + REQUEST(xkbGetIndicatorMapReq); + REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + xkb= dev->key->xkbInfo->desc; + leds= xkb->indicators; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.which = stuff->which; + XkbComputeGetIndicatorMapReplySize(leds,&rep); + return XkbSendIndicatorMap(client,leds,&rep); +} + +/** + * Apply the given map to the given device. Which specifies which components + * to apply. + */ +static int +_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev, + int which, xkbIndicatorMapWireDesc *desc) +{ + XkbSrvInfoPtr xkbi; + XkbSrvLedInfoPtr sli; + XkbEventCauseRec cause; + int i, bit; + + xkbi = dev->key->xkbInfo; + + sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, + XkbXI_IndicatorMapsMask); + if (!sli) + return BadAlloc; + + for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { + if (which & bit) { + sli->maps[i].flags = desc->flags; + sli->maps[i].which_groups = desc->whichGroups; + sli->maps[i].groups = desc->groups; + sli->maps[i].which_mods = desc->whichMods; + sli->maps[i].mods.mask = desc->mods; + sli->maps[i].mods.real_mods = desc->mods; + sli->maps[i].mods.vmods= desc->virtualMods; + sli->maps[i].ctrls = desc->ctrls; + if (desc->virtualMods!=0) { + unsigned tmp; + tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods); + sli->maps[i].mods.mask= desc->mods|tmp; + } + desc++; + } + } + + XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client); + XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause); + + return Success; +} + +int +ProcXkbSetIndicatorMap(ClientPtr client) +{ + int i, bit; + int nIndicators; + DeviceIntPtr dev; + xkbIndicatorMapWireDesc *from; + int rc; + + REQUEST(xkbSetIndicatorMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); + + if (stuff->which==0) + return Success; + + for (nIndicators=i=0,bit=1;iwhich&bit) + nIndicators++; + } + if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+ + (nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) { + return BadLength; + } + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + for (i=0,bit=1;iwhich&bit) { + if (client->swapped) { + int n; + swaps(&from->virtualMods,n); + swapl(&from->ctrls,n); + } + CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup); + CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods); + from++; + } + } + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + rc = _XkbSetIndicatorMap(client, dev, stuff->which, from); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess); + if (rc == Success) + _XkbSetIndicatorMap(client, other, stuff->which, from); + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbGetNamedIndicator(ClientPtr client) +{ + DeviceIntPtr dev; + xkbGetNamedIndicatorReply rep; + register int i = 0; + XkbSrvLedInfoPtr sli; + XkbIndicatorMapPtr map = NULL; + + REQUEST(xkbGetNamedIndicatorReq); + REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); + CHK_ATOM_ONLY(stuff->indicator); + + sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0); + if (!sli) + return BadAlloc; + + i= 0; + map= NULL; + if ((sli->names)&&(sli->maps)) { + for (i=0;iindicator==sli->names[i]) { + map= &sli->maps[i]; + break; + } + } + } + + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.deviceID = dev->id; + rep.indicator= stuff->indicator; + if (map!=NULL) { + rep.found= TRUE; + rep.on= ((sli->effectiveState&(1<physIndicators&(1<flags; + rep.whichGroups= map->which_groups; + rep.groups= map->groups; + rep.whichMods= map->which_mods; + rep.mods= map->mods.mask; + rep.realMods= map->mods.real_mods; + rep.virtualMods= map->mods.vmods; + rep.ctrls= map->ctrls; + rep.supported= TRUE; + } + else { + rep.found= FALSE; + rep.on= FALSE; + rep.realIndicator= FALSE; + rep.ndx= XkbNoIndicator; + rep.flags= 0; + rep.whichGroups= 0; + rep.groups= 0; + rep.whichMods= 0; + rep.mods= 0; + rep.realMods= 0; + rep.virtualMods= 0; + rep.ctrls= 0; + rep.supported= TRUE; + } + if ( client->swapped ) { + register int n; + swapl(&rep.length,n); + swaps(&rep.sequenceNumber,n); + swapl(&rep.indicator,n); + swaps(&rep.virtualMods,n); + swapl(&rep.ctrls,n); + } + + WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep); + return Success; +} + + +/** + * Find the IM on the device. + * Returns the map, or NULL if the map doesn't exist. + * If the return value is NULL, led_return is undefined. Otherwise, led_return + * is set to the led index of the map. + */ +static XkbIndicatorMapPtr +_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, + int *led_return) +{ + XkbIndicatorMapPtr map; + + /* search for the right indicator */ + map = NULL; + if (sli->names && sli->maps) { + int led; + + for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { + if (sli->names[led] == indicator) { + map= &sli->maps[led]; + *led_return = led; + break; + } + } + } + + return map; +} + +/** + * Creates an indicator map on the device. If dryRun is TRUE, it only checks + * if creation is possible, but doesn't actually create it. + */ +static int +_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator, + int ledClass, int ledID, + XkbIndicatorMapPtr *map_return, int *led_return, + Bool dryRun) +{ + XkbSrvLedInfoPtr sli; + XkbIndicatorMapPtr map; + int led; + + sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask); + if (!sli) + return BadAlloc; + + map = _XkbFindNamedIndicatorMap(sli, indicator, &led); + + if (!map) + { + /* find first unused indicator maps and assign the name to it */ + for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) { + if ((sli->names) && (sli->maps) && (sli->names[led] == None) && + (!XkbIM_InUse(&sli->maps[led]))) + { + map = &sli->maps[led]; + if (!dryRun) + sli->names[led] = indicator; + break; + } + } + } + + if (!map) + return BadAlloc; + + *led_return = led; + *map_return = map; + return Success; +} + +static int +_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev, + xkbSetNamedIndicatorReq *stuff) +{ + unsigned int extDevReason; + unsigned int statec, namec, mapc; + XkbSrvLedInfoPtr sli; + int led = 0; + XkbIndicatorMapPtr map; + DeviceIntPtr kbd; + XkbEventCauseRec cause; + xkbExtensionDeviceNotify ed; + XkbChangesRec changes; + int rc; + + rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass, + stuff->ledID, &map, &led, FALSE); + if (rc != Success || !map) /* oh-oh */ + return rc; + + sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, + XkbXI_IndicatorsMask); + if (!sli) + return BadAlloc; + + namec = mapc = statec = 0; + extDevReason = 0; + + namec |= (1<namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0); + extDevReason |= XkbXI_IndicatorNamesMask; + + if (stuff->setMap) { + map->flags = stuff->flags; + map->which_groups = stuff->whichGroups; + map->groups = stuff->groups; + map->which_mods = stuff->whichMods; + map->mods.mask = stuff->realMods; + map->mods.real_mods = stuff->realMods; + map->mods.vmods= stuff->virtualMods; + map->ctrls = stuff->ctrls; + mapc|= (1<setState) && ((map->flags & XkbIM_NoExplicit) == 0)) + { + if (stuff->on) sli->explicitState |= (1<explicitState &= ~(1<effectiveState ^ sli->explicitState) & (1 << led)); + } + + memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify)); + memset((char *)&changes, 0, sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client); + if (namec) + XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); + if (mapc) + XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); + if (statec) + XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); + + kbd = dev; + if ((sli->flags&XkbSLI_HasOwnState)==0) + kbd = inputInfo.keyboard; + XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); + + return Success; +} + +int +ProcXkbSetNamedIndicator(ClientPtr client) +{ + int rc; + DeviceIntPtr dev; + int led = 0; + XkbIndicatorMapPtr map; + + REQUEST(xkbSetNamedIndicatorReq); + REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); + CHK_ATOM_ONLY(stuff->indicator); + CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup); + CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods); + + /* Dry-run for checks */ + rc = _XkbCreateIndicatorMap(dev, stuff->indicator, + stuff->ledClass, stuff->ledID, + &map, &led, TRUE); + if (rc != Success || !map) /* couldn't be created or didn't exist */ + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd || + stuff->deviceSpec == XkbUseCorePtr) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev && + (other->kbdfeed || other->leds) && + (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) + { + rc = _XkbCreateIndicatorMap(other, stuff->indicator, + stuff->ledClass, stuff->ledID, + &map, &led, TRUE); + if (rc != Success || !map) + return rc; + } + } + } + + /* All checks passed, let's do it */ + rc = _XkbSetNamedIndicator(client, dev, stuff); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd || + stuff->deviceSpec == XkbUseCorePtr) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev && + (other->kbdfeed || other->leds) && + (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) + { + _XkbSetNamedIndicator(client, other, stuff); + } + } + } + + return Success; +} + +/***====================================================================***/ + +static CARD32 +_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count) +{ +register unsigned int i,bit,nAtoms; +register CARD32 atomsPresent; + + for (i=nAtoms=atomsPresent=0,bit=1;iminKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + which= rep->which; + length= 0; + if (xkb->names!=NULL) { + if (which&XkbKeycodesNameMask) length++; + if (which&XkbGeometryNameMask) length++; + if (which&XkbSymbolsNameMask) length++; + if (which&XkbPhysSymbolsNameMask) length++; + if (which&XkbTypesNameMask) length++; + if (which&XkbCompatNameMask) length++; + } + else which&= ~XkbComponentNamesMask; + + if (xkb->map!=NULL) { + if (which&XkbKeyTypeNamesMask) + length+= xkb->map->num_types; + rep->nTypes= xkb->map->num_types; + if (which&XkbKTLevelNamesMask) { + XkbKeyTypePtr pType = xkb->map->types; + int nKTLevels = 0; + + length+= XkbPaddedSize(xkb->map->num_types)/4; + for (i=0;imap->num_types;i++,pType++) { + if (pType->level_names!=NULL) + nKTLevels+= pType->num_levels; + } + rep->nKTLevels= nKTLevels; + length+= nKTLevels; + } + } + else { + rep->nTypes= 0; + rep->nKTLevels= 0; + which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask); + } + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + rep->indicators= 0; + rep->virtualMods= 0; + rep->groupNames= 0; + if (xkb->names!=NULL) { + if (which&XkbIndicatorNamesMask) { + int nLeds; + rep->indicators= + _XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds); + length+= nLeds; + if (nLeds==0) + which&= ~XkbIndicatorNamesMask; + } + + if (which&XkbVirtualModNamesMask) { + int nVMods; + rep->virtualMods= + _XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods); + length+= nVMods; + if (nVMods==0) + which&= ~XkbVirtualModNamesMask; + } + + if (which&XkbGroupNamesMask) { + int nGroups; + rep->groupNames= + _XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups); + length+= nGroups; + if (nGroups==0) + which&= ~XkbGroupNamesMask; + } + + if ((which&XkbKeyNamesMask)&&(xkb->names->keys)) + length+= rep->nKeys; + else which&= ~XkbKeyNamesMask; + + if ((which&XkbKeyAliasesMask)&& + (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) { + rep->nKeyAliases= xkb->names->num_key_aliases; + length+= rep->nKeyAliases*2; + } + else { + which&= ~XkbKeyAliasesMask; + rep->nKeyAliases= 0; + } + + if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0)) + length+= xkb->names->num_rg; + else which&= ~XkbRGNamesMask; + } + else { + which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask); + which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask); + which&= ~XkbRGNamesMask; + } + + rep->length= length; + rep->which= which; + return Success; +} + +static int +XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep) +{ +register unsigned i,length,which; +char * start; +char * desc; +register int n; + + length= rep->length*4; + which= rep->which; + if (client->swapped) { + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swapl(&rep->which,n); + swaps(&rep->virtualMods,n); + swapl(&rep->indicators,n); + } + + start = desc = calloc(1, length); + if ( !start ) + return BadAlloc; + if (xkb->names) { + if (which&XkbKeycodesNameMask) { + *((CARD32 *)desc)= xkb->names->keycodes; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbGeometryNameMask) { + *((CARD32 *)desc)= xkb->names->geometry; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbSymbolsNameMask) { + *((CARD32 *)desc)= xkb->names->symbols; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbPhysSymbolsNameMask) { + register CARD32 *atm= (CARD32 *)desc; + atm[0]= (CARD32)xkb->names->phys_symbols; + if (client->swapped) { + swapl(&atm[0],n); + } + desc+= 4; + } + if (which&XkbTypesNameMask) { + *((CARD32 *)desc)= (CARD32)xkb->names->types; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbCompatNameMask) { + *((CARD32 *)desc)= (CARD32)xkb->names->compat; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbKeyTypeNamesMask) { + register CARD32 *atm= (CARD32 *)desc; + register XkbKeyTypePtr type= xkb->map->types; + + for (i=0;imap->num_types;i++,atm++,type++) { + *atm= (CARD32)type->name; + if (client->swapped) { + swapl(atm,n); + } + } + desc= (char *)atm; + } + if (which&XkbKTLevelNamesMask && xkb->map) { + XkbKeyTypePtr type = xkb->map->types; + register CARD32 *atm; + for (i=0;inTypes;i++,type++) { + *desc++ = type->num_levels; + } + desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes; + + atm= (CARD32 *)desc; + type = xkb->map->types; + for (i=0;imap->num_types;i++,type++) { + register unsigned l; + if (type->level_names) { + for (l=0;lnum_levels;l++,atm++) { + *atm= type->level_names[l]; + if (client->swapped) { + swapl(atm,n); + } + } + desc+= type->num_levels*4; + } + } + } + if (which&XkbIndicatorNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators, + client->swapped); + } + if (which&XkbVirtualModNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods, + client->swapped); + } + if (which&XkbGroupNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups, + client->swapped); + } + if (which&XkbKeyNamesMask) { + for (i=0;inKeys;i++,desc+= sizeof(XkbKeyNameRec)) { + *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey]; + } + } + if (which&XkbKeyAliasesMask) { + XkbKeyAliasPtr pAl; + pAl= xkb->names->key_aliases; + for (i=0;inKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) { + *((XkbKeyAliasPtr)desc)= *pAl; + } + } + if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) { + register CARD32 *atm= (CARD32 *)desc; + for (i=0;inRadioGroups;i++,atm++) { + *atm= (CARD32)xkb->names->radio_groups[i]; + if (client->swapped) { + swapl(atm,n); + } + } + desc+= rep->nRadioGroups*4; + } + } + + if ((desc-start)!=(length)) { + ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n", + length, (unsigned long)(desc-start)); + } + WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep); + WriteToClient(client, length, start); + free((char *)start); + return Success; +} + +int +ProcXkbGetNames(ClientPtr client) +{ + DeviceIntPtr dev; + XkbDescPtr xkb; + xkbGetNamesReply rep; + + REQUEST(xkbGetNamesReq); + REQUEST_SIZE_MATCH(xkbGetNamesReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + + xkb = dev->key->xkbInfo->desc; + memset(&rep, 0, sizeof(xkbGetNamesReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.which = stuff->which; + rep.nTypes = xkb->map->num_types; + rep.firstKey = xkb->min_key_code; + rep.nKeys = XkbNumKeys(xkb); + if (xkb->names!=NULL) { + rep.nKeyAliases= xkb->names->num_key_aliases; + rep.nRadioGroups = xkb->names->num_rg; + } + else { + rep.nKeyAliases= rep.nRadioGroups= 0; + } + XkbComputeGetNamesReplySize(xkb,&rep); + return XkbSendNames(client,xkb,&rep); +} + +/***====================================================================***/ + +static CARD32 * +_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError) +{ +register int i; + + for (i=0;ikey->xkbInfo->desc; + names = xkb->names; + + + if (stuff->which & XkbKeyTypeNamesMask) { + int i; + CARD32 *old; + if ( stuff->nTypes<1 ) { + client->errorValue = _XkbErrCode2(0x02,stuff->nTypes); + return BadValue; + } + if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x03,stuff->firstType, + stuff->nTypes, + xkb->map->num_types); + return BadValue; + } + if (((unsigned)stuff->firstType)<=XkbLastRequiredType) { + client->errorValue = _XkbErrCode2(0x04,stuff->firstType); + return BadAccess; + } + old= tmp; + tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + for (i=0;inTypes;i++,old++) { + if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i)) + client->errorValue= _XkbErrCode2(0x05,i); + } + } + if (stuff->which&XkbKTLevelNamesMask) { + unsigned i; + XkbKeyTypePtr type; + CARD8 * width; + if ( stuff->nKTLevels<1 ) { + client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels); + return BadValue; + } + if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>= + xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel, + stuff->nKTLevels,xkb->map->num_types); + return BadValue; + } + width = (CARD8 *)tmp; + tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); + type = &xkb->map->types[stuff->firstKTLevel]; + for (i=0;inKTLevels;i++,type++) { + if (width[i]==0) + continue; + else if (width[i]!=type->num_levels) { + client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel, + type->num_levels,width[i]); + return BadMatch; + } + tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + } + if (stuff->which&XkbIndicatorNamesMask) { + if (stuff->indicators==0) { + client->errorValue= 0x08; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators, + client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if (stuff->which&XkbVirtualModNamesMask) { + if (stuff->virtualMods==0) { + client->errorValue= 0x09; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods, + (CARD32)stuff->virtualMods, + client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbGroupNamesMask) { + if (stuff->groupNames==0) { + client->errorValue= 0x0a; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups, + (CARD32)stuff->groupNames, + client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbKeyNamesMask) { + if (stuff->firstKey<(unsigned)xkb->min_key_code) { + client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code, + stuff->firstKey); + return BadValue; + } + if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)|| + (stuff->nKeys<1)) { + client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code, + stuff->firstKey,stuff->nKeys); + return BadValue; + } + tmp+= stuff->nKeys; + } + if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) { + tmp+= stuff->nKeyAliases*2; + } + if (stuff->which&XkbRGNamesMask) { + if ( stuff->nRadioGroups<1 ) { + client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups); + return BadValue; + } + tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if ((tmp-((CARD32 *)stuff))!=stuff->length) { + client->errorValue = stuff->length; + return BadLength; + } + + + + return Success; +} + +static int +_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff) +{ + XkbDescRec *xkb; + XkbNamesRec *names; + CARD32 *tmp; + xkbNamesNotify nn; + + tmp = (CARD32 *)&stuff[1]; + xkb = dev->key->xkbInfo->desc; + names = xkb->names; + + if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups, + stuff->nKeyAliases)!=Success) { + return BadAlloc; + } + + memset(&nn, 0, sizeof(xkbNamesNotify)); + nn.changed= stuff->which; + tmp = (CARD32 *)&stuff[1]; + if (stuff->which&XkbKeycodesNameMask) + names->keycodes= *tmp++; + if (stuff->which&XkbGeometryNameMask) + names->geometry= *tmp++; + if (stuff->which&XkbSymbolsNameMask) + names->symbols= *tmp++; + if (stuff->which&XkbPhysSymbolsNameMask) + names->phys_symbols= *tmp++; + if (stuff->which&XkbTypesNameMask) + names->types= *tmp++; + if (stuff->which&XkbCompatNameMask) + names->compat= *tmp++; + if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) { + register unsigned i; + register XkbKeyTypePtr type; + + type= &xkb->map->types[stuff->firstType]; + for (i=0;inTypes;i++,type++) { + type->name= *tmp++; + } + nn.firstType= stuff->firstType; + nn.nTypes= stuff->nTypes; + } + if (stuff->which&XkbKTLevelNamesMask) { + register XkbKeyTypePtr type; + register unsigned i; + CARD8 *width; + + width = (CARD8 *)tmp; + tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); + type= &xkb->map->types[stuff->firstKTLevel]; + for (i=0;inKTLevels;i++,type++) { + if (width[i]>0) { + if (type->level_names) { + register unsigned n; + for (n=0;nlevel_names[n]= tmp[n]; + } + } + tmp+= width[i]; + } + } + nn.firstLevelName= 0; + nn.nLevelNames= stuff->nTypes; + } + if (stuff->which&XkbIndicatorNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators, + stuff->indicators); + nn.changedIndicators= stuff->indicators; + } + if (stuff->which&XkbVirtualModNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods, + stuff->virtualMods); + nn.changedVirtualMods= stuff->virtualMods; + } + if (stuff->which&XkbGroupNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups, + stuff->groupNames); + nn.changedVirtualMods= stuff->groupNames; + } + if (stuff->which&XkbKeyNamesMask) { + memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp, + stuff->nKeys*XkbKeyNameLength); + tmp+= stuff->nKeys; + nn.firstKey= stuff->firstKey; + nn.nKeys= stuff->nKeys; + } + if (stuff->which&XkbKeyAliasesMask) { + if (stuff->nKeyAliases>0) { + register int na= stuff->nKeyAliases; + if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success) + return BadAlloc; + memcpy((char *)names->key_aliases,(char *)tmp, + stuff->nKeyAliases*sizeof(XkbKeyAliasRec)); + tmp+= stuff->nKeyAliases*2; + } + else if (names->key_aliases!=NULL) { + free(names->key_aliases); + names->key_aliases= NULL; + names->num_key_aliases= 0; + } + nn.nAliases= names->num_key_aliases; + } + if (stuff->which&XkbRGNamesMask) { + if (stuff->nRadioGroups>0) { + register unsigned i,nrg; + nrg= stuff->nRadioGroups; + if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success) + return BadAlloc; + + for (i=0;inRadioGroups;i++) { + names->radio_groups[i]= tmp[i]; + } + tmp+= stuff->nRadioGroups; + } + else if (names->radio_groups) { + free(names->radio_groups); + names->radio_groups= NULL; + names->num_rg= 0; + } + nn.nRadioGroups= names->num_rg; + } + if (nn.changed) { + Bool needExtEvent; + needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0; + XkbSendNamesNotify(dev,&nn); + if (needExtEvent) { + XkbSrvLedInfoPtr sli; + xkbExtensionDeviceNotify edev; + register int i; + register unsigned bit; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorsMask); + sli->namesPresent= 0; + for (i=0,bit=1;iindicators[i]!=None) + sli->namesPresent|= bit; + } + memset(&edev, 0, sizeof(xkbExtensionDeviceNotify)); + edev.reason= XkbXI_IndicatorNamesMask; + edev.ledClass= KbdFeedbackClass; + edev.ledID= dev->kbdfeed->ctrl.id; + edev.ledsDefined= sli->namesPresent|sli->mapsPresent; + edev.ledState= sli->effectiveState; + edev.firstBtn= 0; + edev.nBtns= 0; + edev.supported= XkbXI_AllFeaturesMask; + edev.unsupported= 0; + XkbSendExtensionDeviceNotify(dev,client,&edev); + } + } + return Success; +} + +int +ProcXkbSetNames(ClientPtr client) +{ + DeviceIntPtr dev; + CARD32 *tmp; + Atom bad; + int rc; + + REQUEST(xkbSetNamesReq); + REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + + /* check device-independent stuff */ + tmp = (CARD32 *)&stuff[1]; + + if (stuff->which&XkbKeycodesNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbGeometryNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbSymbolsNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbPhysSymbolsNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if (stuff->which&XkbTypesNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbCompatNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + + /* start of device-dependent tests */ + rc = _XkbSetNamesCheck(client, dev, stuff, tmp); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetNamesCheck(client, other, stuff, tmp); + if (rc != Success) + return rc; + } + } + } + } + + /* everything is okay -- update names */ + + rc = _XkbSetNames(client, dev, stuff); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + _XkbSetNames(client, other, stuff); + } + } + } + + /* everything is okay -- update names */ + + return Success; +} + +/***====================================================================***/ + +#include "xkbgeom.h" + +#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4) + +static char * +XkbWriteCountedString(char *wire,char *str,Bool swap) +{ + CARD16 len,*pLen; + + if (!str) + return wire; + + len= strlen(str); + pLen= (CARD16 *)wire; + *pLen= len; + if (swap) { + register int n; + swaps(pLen,n); + } + memcpy(&wire[2],str,len); + wire+= ((2+len+3)/4)*4; + return wire; +} + +static int +XkbSizeGeomProperties(XkbGeometryPtr geom) +{ +register int i,size; +XkbPropertyPtr prop; + + for (size=i=0,prop=geom->properties;inum_properties;i++,prop++) { + size+= XkbSizeCountedString(prop->name); + size+= XkbSizeCountedString(prop->value); + } + return size; +} + +static char * +XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap) +{ +register int i; +register XkbPropertyPtr prop; + + for (i=0,prop=geom->properties;inum_properties;i++,prop++) { + wire= XkbWriteCountedString(wire,prop->name,swap); + wire= XkbWriteCountedString(wire,prop->value,swap); + } + return wire; +} + +static int +XkbSizeGeomKeyAliases(XkbGeometryPtr geom) +{ + return geom->num_key_aliases*(2*XkbKeyNameLength); +} + +static char * +XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap) +{ +register int sz; + + sz= geom->num_key_aliases*(XkbKeyNameLength*2); + if (sz>0) { + memcpy(wire,(char *)geom->key_aliases,sz); + wire+= sz; + } + return wire; +} + +static int +XkbSizeGeomColors(XkbGeometryPtr geom) +{ +register int i,size; +register XkbColorPtr color; + + for (i=size=0,color=geom->colors;inum_colors;i++,color++) { + size+= XkbSizeCountedString(color->spec); + } + return size; +} + +static char * +XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap) +{ +register int i; +register XkbColorPtr color; + + for (i=0,color=geom->colors;inum_colors;i++,color++) { + wire= XkbWriteCountedString(wire,color->spec,swap); + } + return wire; +} + +static int +XkbSizeGeomShapes(XkbGeometryPtr geom) +{ +register int i,size; +register XkbShapePtr shape; + + for (i=size=0,shape=geom->shapes;inum_shapes;i++,shape++) { + register int n; + register XkbOutlinePtr ol; + size+= SIZEOF(xkbShapeWireDesc); + for (n=0,ol=shape->outlines;nnum_outlines;n++,ol++) { + size+= SIZEOF(xkbOutlineWireDesc); + size+= ol->num_points*SIZEOF(xkbPointWireDesc); + } + } + return size; +} + +static char * +XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap) +{ +int i; +XkbShapePtr shape; +xkbShapeWireDesc * shapeWire; + + for (i=0,shape=geom->shapes;inum_shapes;i++,shape++) { + register int o; + XkbOutlinePtr ol; + xkbOutlineWireDesc * olWire; + shapeWire= (xkbShapeWireDesc *)wire; + shapeWire->name= shape->name; + shapeWire->nOutlines= shape->num_outlines; + if (shape->primary!=NULL) + shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary); + else shapeWire->primaryNdx= XkbNoShape; + if (shape->approx!=NULL) + shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx); + else shapeWire->approxNdx= XkbNoShape; + if (swap) { + register int n; + swapl(&shapeWire->name,n); + } + wire= (char *)&shapeWire[1]; + for (o=0,ol=shape->outlines;onum_outlines;o++,ol++) { + register int p; + XkbPointPtr pt; + xkbPointWireDesc * ptWire; + olWire= (xkbOutlineWireDesc *)wire; + olWire->nPoints= ol->num_points; + olWire->cornerRadius= ol->corner_radius; + wire= (char *)&olWire[1]; + ptWire= (xkbPointWireDesc *)wire; + for (p=0,pt=ol->points;pnum_points;p++,pt++) { + ptWire[p].x= pt->x; + ptWire[p].y= pt->y; + if (swap) { + register int n; + swaps(&ptWire[p].x,n); + swaps(&ptWire[p].y,n); + } + } + wire= (char *)&ptWire[ol->num_points]; + } + } + return wire; +} + +static int +XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad) +{ +register int i,size; + + for (i=size=0;iany.type==XkbTextDoodad) { + size+= XkbSizeCountedString(doodad->text.text); + size+= XkbSizeCountedString(doodad->text.font); + } + else if (doodad->any.type==XkbLogoDoodad) { + size+= XkbSizeCountedString(doodad->logo.logo_name); + } + } + return size; +} + +static char * +XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap) +{ +register int i; +xkbDoodadWireDesc * doodadWire; + + for (i=0;iany.name= doodad->any.name; + doodadWire->any.type= doodad->any.type; + doodadWire->any.priority= doodad->any.priority; + doodadWire->any.top= doodad->any.top; + doodadWire->any.left= doodad->any.left; + if (swap) { + register int n; + swapl(&doodadWire->any.name,n); + swaps(&doodadWire->any.top,n); + swaps(&doodadWire->any.left,n); + } + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodadWire->shape.angle= doodad->shape.angle; + doodadWire->shape.colorNdx= doodad->shape.color_ndx; + doodadWire->shape.shapeNdx= doodad->shape.shape_ndx; + if (swap) { + register int n; + swaps(&doodadWire->shape.angle,n); + } + break; + case XkbTextDoodad: + doodadWire->text.angle= doodad->text.angle; + doodadWire->text.width= doodad->text.width; + doodadWire->text.height= doodad->text.height; + doodadWire->text.colorNdx= doodad->text.color_ndx; + if (swap) { + register int n; + swaps(&doodadWire->text.angle,n); + swaps(&doodadWire->text.width,n); + swaps(&doodadWire->text.height,n); + } + wire= XkbWriteCountedString(wire,doodad->text.text,swap); + wire= XkbWriteCountedString(wire,doodad->text.font,swap); + break; + case XkbIndicatorDoodad: + doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx; + doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx; + doodadWire->indicator.offColorNdx= + doodad->indicator.off_color_ndx; + break; + case XkbLogoDoodad: + doodadWire->logo.angle= doodad->logo.angle; + doodadWire->logo.colorNdx= doodad->logo.color_ndx; + doodadWire->logo.shapeNdx= doodad->logo.shape_ndx; + wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap); + break; + default: + ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n", + doodad->any.type); + ErrorF("[xkb] Ignored\n"); + break; + } + } + return wire; +} + +static char * +XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap) +{ +register int r; +XkbOverlayRowPtr row; +xkbOverlayWireDesc * olWire; + + olWire= (xkbOverlayWireDesc *)wire; + olWire->name= ol->name; + olWire->nRows= ol->num_rows; + if (swap) { + register int n; + swapl(&olWire->name,n); + } + wire= (char *)&olWire[1]; + for (r=0,row=ol->rows;rnum_rows;r++,row++) { + unsigned int k; + XkbOverlayKeyPtr key; + xkbOverlayRowWireDesc * rowWire; + rowWire= (xkbOverlayRowWireDesc *)wire; + rowWire->rowUnder= row->row_under; + rowWire->nKeys= row->num_keys; + wire= (char *)&rowWire[1]; + for (k=0,key=row->keys;knum_keys;k++,key++) { + xkbOverlayKeyWireDesc * keyWire; + keyWire= (xkbOverlayKeyWireDesc *)wire; + memcpy(keyWire->over,key->over.name,XkbKeyNameLength); + memcpy(keyWire->under,key->under.name,XkbKeyNameLength); + wire= (char *)&keyWire[1]; + } + } + return wire; +} + +static int +XkbSizeGeomSections(XkbGeometryPtr geom) +{ +register int i,size; +XkbSectionPtr section; + + for (i=size=0,section=geom->sections;inum_sections;i++,section++) { + size+= SIZEOF(xkbSectionWireDesc); + if (section->rows) { + int r; + XkbRowPtr row; + for (r=0,row=section->rows;rnum_rows;row++,r++) { + size+= SIZEOF(xkbRowWireDesc); + size+= row->num_keys*SIZEOF(xkbKeyWireDesc); + } + } + if (section->doodads) + size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads); + if (section->overlays) { + int o; + XkbOverlayPtr ol; + for (o=0,ol=section->overlays;onum_overlays;o++,ol++) { + int r; + XkbOverlayRowPtr row; + size+= SIZEOF(xkbOverlayWireDesc); + for (r=0,row=ol->rows;rnum_rows;r++,row++) { + size+= SIZEOF(xkbOverlayRowWireDesc); + size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc); + } + } + } + } + return size; +} + +static char * +XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap) +{ +register int i; +XkbSectionPtr section; +xkbSectionWireDesc * sectionWire; + + for (i=0,section=geom->sections;inum_sections;i++,section++) { + sectionWire= (xkbSectionWireDesc *)wire; + sectionWire->name= section->name; + sectionWire->top= section->top; + sectionWire->left= section->left; + sectionWire->width= section->width; + sectionWire->height= section->height; + sectionWire->angle= section->angle; + sectionWire->priority= section->priority; + sectionWire->nRows= section->num_rows; + sectionWire->nDoodads= section->num_doodads; + sectionWire->nOverlays= section->num_overlays; + sectionWire->pad= 0; + if (swap) { + register int n; + swapl(§ionWire->name,n); + swaps(§ionWire->top,n); + swaps(§ionWire->left,n); + swaps(§ionWire->width,n); + swaps(§ionWire->height,n); + swaps(§ionWire->angle,n); + } + wire= (char *)§ionWire[1]; + if (section->rows) { + int r; + XkbRowPtr row; + xkbRowWireDesc * rowWire; + for (r=0,row=section->rows;rnum_rows;r++,row++) { + rowWire= (xkbRowWireDesc *)wire; + rowWire->top= row->top; + rowWire->left= row->left; + rowWire->nKeys= row->num_keys; + rowWire->vertical= row->vertical; + rowWire->pad= 0; + if (swap) { + register int n; + swaps(&rowWire->top,n); + swaps(&rowWire->left,n); + } + wire= (char *)&rowWire[1]; + if (row->keys) { + int k; + XkbKeyPtr key; + xkbKeyWireDesc * keyWire; + keyWire= (xkbKeyWireDesc *)wire; + for (k=0,key=row->keys;knum_keys;k++,key++) { + memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength); + keyWire[k].gap= key->gap; + keyWire[k].shapeNdx= key->shape_ndx; + keyWire[k].colorNdx= key->color_ndx; + if (swap) { + register int n; + swaps(&keyWire[k].gap,n); + } + } + wire= (char *)&keyWire[row->num_keys]; + } + } + } + if (section->doodads) { + wire= XkbWriteGeomDoodads(wire, + section->num_doodads,section->doodads, + swap); + } + if (section->overlays) { + register int o; + for (o=0;onum_overlays;o++) { + wire= XkbWriteGeomOverlay(wire,§ion->overlays[o],swap); + } + } + } + return wire; +} + +static Status +XkbComputeGetGeometryReplySize( XkbGeometryPtr geom, + xkbGetGeometryReply * rep, + Atom name) +{ +int len; + + if (geom!=NULL) { + len= XkbSizeCountedString(geom->label_font); + len+= XkbSizeGeomProperties(geom); + len+= XkbSizeGeomColors(geom); + len+= XkbSizeGeomShapes(geom); + len+= XkbSizeGeomSections(geom); + len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads); + len+= XkbSizeGeomKeyAliases(geom); + rep->length= len/4; + rep->found= TRUE; + rep->name= geom->name; + rep->widthMM= geom->width_mm; + rep->heightMM= geom->height_mm; + rep->nProperties= geom->num_properties; + rep->nColors= geom->num_colors; + rep->nShapes= geom->num_shapes; + rep->nSections= geom->num_sections; + rep->nDoodads= geom->num_doodads; + rep->nKeyAliases= geom->num_key_aliases; + rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color); + rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color); + } + else { + rep->length= 0; + rep->found= FALSE; + rep->name= name; + rep->widthMM= rep->heightMM= 0; + rep->nProperties= rep->nColors= rep->nShapes= 0; + rep->nSections= rep->nDoodads= 0; + rep->nKeyAliases= 0; + rep->labelColorNdx= rep->baseColorNdx= 0; + } + return Success; +} + +static int +XkbSendGeometry( ClientPtr client, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep, + Bool freeGeom) +{ + char *desc,*start; + int len; + + if (geom!=NULL) { + len= rep->length*4; + start= desc= malloc(len); + if (!start) + return BadAlloc; + desc= XkbWriteCountedString(desc,geom->label_font,client->swapped); + if ( rep->nProperties>0 ) + desc = XkbWriteGeomProperties(desc,geom,client->swapped); + if ( rep->nColors>0 ) + desc = XkbWriteGeomColors(desc,geom,client->swapped); + if ( rep->nShapes>0 ) + desc = XkbWriteGeomShapes(desc,geom,client->swapped); + if ( rep->nSections>0 ) + desc = XkbWriteGeomSections(desc,geom,client->swapped); + if ( rep->nDoodads>0 ) + desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads, + client->swapped); + if ( rep->nKeyAliases>0 ) + desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped); + if ((desc-start)!=(len)) { + ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n", + len, (unsigned long)(desc-start)); + } + } + else { + len= 0; + start= NULL; + } + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swapl(&rep->name,n); + swaps(&rep->widthMM,n); + swaps(&rep->heightMM,n); + swaps(&rep->nProperties,n); + swaps(&rep->nColors,n); + swaps(&rep->nShapes,n); + swaps(&rep->nSections,n); + swaps(&rep->nDoodads,n); + swaps(&rep->nKeyAliases,n); + } + WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep); + if (len>0) + WriteToClient(client, len, start); + if (start!=NULL) + free((char *)start); + if (freeGeom) + XkbFreeGeometry(geom,XkbGeomAllMask,TRUE); + return Success; +} + +int +ProcXkbGetGeometry(ClientPtr client) +{ + DeviceIntPtr dev; + xkbGetGeometryReply rep; + XkbGeometryPtr geom; + Bool shouldFree; + Status status; + + REQUEST(xkbGetGeometryReq); + REQUEST_SIZE_MATCH(xkbGetGeometryReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + CHK_ATOM_OR_NONE(stuff->name); + + geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree); + rep.type= X_Reply; + rep.deviceID= dev->id; + rep.sequenceNumber= client->sequence; + rep.length= 0; + status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name); + if (status!=Success) + return status; + else return XkbSendGeometry(client,geom,&rep,shouldFree); +} + +/***====================================================================***/ + +static char * +_GetCountedString(char **wire_inout,Bool swap) +{ +char * wire,*str; +CARD16 len,*plen; + + wire= *wire_inout; + plen= (CARD16 *)wire; + if (swap) { + register int n; + swaps(plen,n); + } + len= *plen; + str= malloc(len+1); + if (str) { + memcpy(str,&wire[2],len); + str[len]= '\0'; + } + wire+= XkbPaddedSize(len+2); + *wire_inout= wire; + return str; +} + +static Status +_CheckSetDoodad( char ** wire_inout, + XkbGeometryPtr geom, + XkbSectionPtr section, + ClientPtr client) +{ +char * wire; +xkbDoodadWireDesc * dWire; +XkbDoodadPtr doodad; + + dWire= (xkbDoodadWireDesc *)(*wire_inout); + wire= (char *)&dWire[1]; + if (client->swapped) { + register int n; + swapl(&dWire->any.name,n); + swaps(&dWire->any.top,n); + swaps(&dWire->any.left,n); + swaps(&dWire->any.angle,n); + } + CHK_ATOM_ONLY(dWire->any.name); + doodad= XkbAddGeomDoodad(geom,section,dWire->any.name); + if (!doodad) + return BadAlloc; + doodad->any.type= dWire->any.type; + doodad->any.priority= dWire->any.priority; + doodad->any.top= dWire->any.top; + doodad->any.left= dWire->any.left; + doodad->any.angle= dWire->any.angle; + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + if (dWire->shape.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x40,geom->num_colors, + dWire->shape.colorNdx); + return BadMatch; + } + if (dWire->shape.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x41,geom->num_shapes, + dWire->shape.shapeNdx); + return BadMatch; + } + doodad->shape.color_ndx= dWire->shape.colorNdx; + doodad->shape.shape_ndx= dWire->shape.shapeNdx; + break; + case XkbTextDoodad: + if (dWire->text.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x42,geom->num_colors, + dWire->text.colorNdx); + return BadMatch; + } + if (client->swapped) { + register int n; + swaps(&dWire->text.width,n); + swaps(&dWire->text.height,n); + } + doodad->text.width= dWire->text.width; + doodad->text.height= dWire->text.height; + doodad->text.color_ndx= dWire->text.colorNdx; + doodad->text.text= _GetCountedString(&wire,client->swapped); + doodad->text.font= _GetCountedString(&wire,client->swapped); + break; + case XkbIndicatorDoodad: + if (dWire->indicator.onColorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x43,geom->num_colors, + dWire->indicator.onColorNdx); + return BadMatch; + } + if (dWire->indicator.offColorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x44,geom->num_colors, + dWire->indicator.offColorNdx); + return BadMatch; + } + if (dWire->indicator.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x45,geom->num_shapes, + dWire->indicator.shapeNdx); + return BadMatch; + } + doodad->indicator.shape_ndx= dWire->indicator.shapeNdx; + doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx; + doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx; + break; + case XkbLogoDoodad: + if (dWire->logo.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x46,geom->num_colors, + dWire->logo.colorNdx); + return BadMatch; + } + if (dWire->logo.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x47,geom->num_shapes, + dWire->logo.shapeNdx); + return BadMatch; + } + doodad->logo.color_ndx= dWire->logo.colorNdx; + doodad->logo.shape_ndx= dWire->logo.shapeNdx; + doodad->logo.logo_name= _GetCountedString(&wire,client->swapped); + break; + default: + client->errorValue= _XkbErrCode2(0x4F,dWire->any.type); + return BadValue; + } + *wire_inout= wire; + return Success; +} + +static Status +_CheckSetOverlay( char ** wire_inout, + XkbGeometryPtr geom, + XkbSectionPtr section, + ClientPtr client) +{ +register int r; +char * wire; +XkbOverlayPtr ol; +xkbOverlayWireDesc * olWire; +xkbOverlayRowWireDesc * rWire; + + wire= *wire_inout; + olWire= (xkbOverlayWireDesc *)wire; + if (client->swapped) { + register int n; + swapl(&olWire->name,n); + } + CHK_ATOM_ONLY(olWire->name); + ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows); + rWire= (xkbOverlayRowWireDesc *)&olWire[1]; + for (r=0;rnRows;r++) { + register int k; + xkbOverlayKeyWireDesc * kWire; + XkbOverlayRowPtr row; + + if (rWire->rowUnder>section->num_rows) { + client->errorValue= _XkbErrCode4(0x20,r,section->num_rows, + rWire->rowUnder); + return BadMatch; + } + row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys); + kWire= (xkbOverlayKeyWireDesc *)&rWire[1]; + for (k=0;knKeys;k++,kWire++) { + if (XkbAddGeomOverlayKey(ol,row, + (char *)kWire->over,(char *)kWire->under)==NULL) { + client->errorValue= _XkbErrCode3(0x21,r,k); + return BadMatch; + } + } + rWire= (xkbOverlayRowWireDesc *)kWire; + } + olWire= (xkbOverlayWireDesc *)rWire; + wire= (char *)olWire; + *wire_inout= wire; + return Success; +} + +static Status +_CheckSetSections( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + char ** wire_inout, + ClientPtr client) +{ +Status status; +register int s; +char * wire; +xkbSectionWireDesc * sWire; +XkbSectionPtr section; + + wire= *wire_inout; + if (req->nSections<1) + return Success; + sWire= (xkbSectionWireDesc *)wire; + for (s=0;snSections;s++) { + register int r; + xkbRowWireDesc * rWire; + if (client->swapped) { + register int n; + swapl(&sWire->name,n); + swaps(&sWire->top,n); + swaps(&sWire->left,n); + swaps(&sWire->width,n); + swaps(&sWire->height,n); + swaps(&sWire->angle,n); + } + CHK_ATOM_ONLY(sWire->name); + section= XkbAddGeomSection(geom,sWire->name,sWire->nRows, + sWire->nDoodads,sWire->nOverlays); + if (!section) + return BadAlloc; + section->priority= sWire->priority; + section->top= sWire->top; + section->left= sWire->left; + section->width= sWire->width; + section->height= sWire->height; + section->angle= sWire->angle; + rWire= (xkbRowWireDesc *)&sWire[1]; + for (r=0;rnRows;r++) { + register int k; + XkbRowPtr row; + xkbKeyWireDesc * kWire; + if (client->swapped) { + register int n; + swaps(&rWire->top,n); + swaps(&rWire->left,n); + } + row= XkbAddGeomRow(section,rWire->nKeys); + if (!row) + return BadAlloc; + row->top= rWire->top; + row->left= rWire->left; + row->vertical= rWire->vertical; + kWire= (xkbKeyWireDesc *)&rWire[1]; + for (k=0;knKeys;k++) { + XkbKeyPtr key; + key= XkbAddGeomKey(row); + if (!key) + return BadAlloc; + memcpy(key->name.name,kWire[k].name,XkbKeyNameLength); + key->gap= kWire[k].gap; + key->shape_ndx= kWire[k].shapeNdx; + key->color_ndx= kWire[k].colorNdx; + if (key->shape_ndx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x10,key->shape_ndx, + geom->num_shapes); + return BadMatch; + } + if (key->color_ndx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x11,key->color_ndx, + geom->num_colors); + return BadMatch; + } + } + rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys]; + } + wire= (char *)rWire; + if (sWire->nDoodads>0) { + register int d; + for (d=0;dnDoodads;d++) { + status=_CheckSetDoodad(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + if (sWire->nOverlays>0) { + register int o; + for (o=0;onOverlays;o++) { + status= _CheckSetOverlay(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + sWire= (xkbSectionWireDesc *)wire; + } + wire= (char *)sWire; + *wire_inout= wire; + return Success; +} + +static Status +_CheckSetShapes( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + char ** wire_inout, + ClientPtr client) +{ +register int i; +char * wire; + + wire= *wire_inout; + if (req->nShapes<1) { + client->errorValue= _XkbErrCode2(0x06,req->nShapes); + return BadValue; + } + else { + xkbShapeWireDesc * shapeWire; + XkbShapePtr shape; + register int o; + shapeWire= (xkbShapeWireDesc *)wire; + for (i=0;inShapes;i++) { + xkbOutlineWireDesc * olWire; + XkbOutlinePtr ol; + shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines); + if (!shape) + return BadAlloc; + olWire= (xkbOutlineWireDesc *)(&shapeWire[1]); + for (o=0;onOutlines;o++) { + register int p; + XkbPointPtr pt; + xkbPointWireDesc * ptWire; + + ol= XkbAddGeomOutline(shape,olWire->nPoints); + if (!ol) + return BadAlloc; + ol->corner_radius= olWire->cornerRadius; + ptWire= (xkbPointWireDesc *)&olWire[1]; + for (p=0,pt=ol->points;pnPoints;p++,pt++) { + pt->x= ptWire[p].x; + pt->y= ptWire[p].y; + if (client->swapped) { + register int n; + swaps(&pt->x,n); + swaps(&pt->y,n); + } + } + ol->num_points= olWire->nPoints; + olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]); + } + if (shapeWire->primaryNdx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire->primaryNdx]; + if (shapeWire->approxNdx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire->approxNdx]; + shapeWire= (xkbShapeWireDesc *)olWire; + } + wire= (char *)shapeWire; + } + if (geom->num_shapes!=req->nShapes) { + client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes); + return BadMatch; + } + + *wire_inout= wire; + return Success; +} + +static Status +_CheckSetGeom( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + ClientPtr client) +{ +register int i; +Status status; +char * wire; + + wire= (char *)&req[1]; + geom->label_font= _GetCountedString(&wire,client->swapped); + + for (i=0;inProperties;i++) { + char *name,*val; + name= _GetCountedString(&wire,client->swapped); + if (!name) + return BadAlloc; + val= _GetCountedString(&wire,client->swapped); + if (!val) { + free(name); + return BadAlloc; + } + if (XkbAddGeomProperty(geom,name,val)==NULL) { + free(name); + free(val); + return BadAlloc; + } + free(name); + free(val); + } + + if (req->nColors<2) { + client->errorValue= _XkbErrCode3(0x01,2,req->nColors); + return BadValue; + } + if (req->baseColorNdx>req->nColors) { + client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx); + return BadMatch; + } + if (req->labelColorNdx>req->nColors) { + client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx); + return BadMatch; + } + if (req->labelColorNdx==req->baseColorNdx) { + client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx, + req->labelColorNdx); + return BadMatch; + } + + for (i=0;inColors;i++) { + char *name; + name= _GetCountedString(&wire,client->swapped); + if (!name) + return BadAlloc; + if (!XkbAddGeomColor(geom,name,geom->num_colors)) { + free(name); + return BadAlloc; + } + free(name); + } + if (req->nColors!=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors); + return BadMatch; + } + geom->label_color= &geom->colors[req->labelColorNdx]; + geom->base_color= &geom->colors[req->baseColorNdx]; + + if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success) + return status; + + if ((status=_CheckSetSections(geom,req,&wire,client))!=Success) + return status; + + for (i=0;inDoodads;i++) { + status=_CheckSetDoodad(&wire,geom,NULL,client); + if (status!=Success) + return status; + } + + for (i=0;inKeyAliases;i++) { + if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL) + return BadAlloc; + wire+= 2*XkbKeyNameLength; + } + return Success; +} + +static int +_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff) +{ + XkbDescPtr xkb; + Bool new_name; + xkbNewKeyboardNotify nkn; + XkbGeometryPtr geom,old; + XkbGeometrySizesRec sizes; + Status status; + + xkb= dev->key->xkbInfo->desc; + old= xkb->geom; + xkb->geom= NULL; + + sizes.which= XkbGeomAllMask; + sizes.num_properties= stuff->nProperties; + sizes.num_colors= stuff->nColors; + sizes.num_shapes= stuff->nShapes; + sizes.num_sections= stuff->nSections; + sizes.num_doodads= stuff->nDoodads; + sizes.num_key_aliases= stuff->nKeyAliases; + if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) { + xkb->geom= old; + return status; + } + geom= xkb->geom; + geom->name= stuff->name; + geom->width_mm= stuff->widthMM; + geom->height_mm= stuff->heightMM; + if ((status= _CheckSetGeom(geom,stuff,client))!=Success) { + XkbFreeGeometry(geom,XkbGeomAllMask,TRUE); + xkb->geom= old; + return status; + } + new_name= (xkb->names->geometry!=geom->name); + xkb->names->geometry= geom->name; + if (old) + XkbFreeGeometry(old,XkbGeomAllMask,TRUE); + if (new_name) { + xkbNamesNotify nn; + memset(&nn, 0, sizeof(xkbNamesNotify)); + nn.changed= XkbGeometryNameMask; + XkbSendNamesNotify(dev,&nn); + } + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code; + nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbSetGeometry; + nkn.changed= XkbNKN_GeometryMask; + XkbSendNewKeyboardNotify(dev,&nkn); + return Success; +} + +int +ProcXkbSetGeometry(ClientPtr client) +{ + DeviceIntPtr dev; + int rc; + + REQUEST(xkbSetGeometryReq); + REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_ATOM_OR_NONE(stuff->name); + + rc = _XkbSetGeometry(client, dev, stuff); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + _XkbSetGeometry(client, other, stuff); + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbPerClientFlags(ClientPtr client) +{ + DeviceIntPtr dev; + xkbPerClientFlagsReply rep; + XkbInterestPtr interest; + Mask access_mode = DixGetAttrAccess | DixSetAttrAccess; + + REQUEST(xkbPerClientFlagsReq); + REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); + CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask); + CHK_MASK_MATCH(0x02,stuff->change,stuff->value); + + interest = XkbFindClientResource((DevicePtr)dev,client); + memset(&rep, 0, sizeof(xkbPerClientFlagsReply)); + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (stuff->change) { + client->xkbClientFlags&= ~stuff->change; + client->xkbClientFlags|= stuff->value; + } + if (stuff->change&XkbPCF_AutoResetControlsMask) { + Bool want; + want= stuff->value&XkbPCF_AutoResetControlsMask; + if (interest && !want) { + interest->autoCtrls= interest->autoCtrlValues= 0; + } + else if (want && (!interest)) { + XID id = FakeClientID(client->index); + if (!AddResource(id,RT_XKBCLIENT,dev)) + return BadAlloc; + interest= XkbAddClientResource((DevicePtr)dev,client,id); + if (!interest) + return BadAlloc; + } + if (interest && want ) { + register unsigned affect; + affect= stuff->ctrlsToChange; + + CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask); + CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls); + CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues); + + interest->autoCtrls&= ~affect; + interest->autoCtrlValues&= ~affect; + interest->autoCtrls|= stuff->autoCtrls&affect; + interest->autoCtrlValues|= stuff->autoCtrlValues&affect; + } + } + rep.supported = XkbPCF_AllFlagsMask; + rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask; + if (interest) { + rep.autoCtrls= interest->autoCtrls; + rep.autoCtrlValues= interest->autoCtrlValues; + } + else { + rep.autoCtrls= rep.autoCtrlValues= 0; + } + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.supported,n); + swapl(&rep.value,n); + swapl(&rep.autoCtrls,n); + swapl(&rep.autoCtrlValues,n); + } + WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */ +/* and wildcards */ +static unsigned char componentSpecLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +/* same as above but accepts percent, plus and bar too */ +static unsigned char componentExprLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +static char * +GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn) +{ +int len; +register int i; +unsigned char *wire,*str,*tmp,*legal; + + if (allowExpr) legal= &componentExprLegal[0]; + else legal= &componentSpecLegal[0]; + + wire= *pWire; + len= (*(unsigned char *)wire++); + if (len>0) { + str= calloc(1, len+1); + if (str) { + tmp= str; + for (i=0;ixkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + status= Success; + str= (unsigned char *)&stuff[1]; + memset(&list, 0, sizeof(XkbSrvListInfoRec)); + list.maxRtrn= stuff->maxNames; + list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,FALSE,&status); + list.pattern[_XkbListTypes]= GetComponentSpec(&str,FALSE,&status); + list.pattern[_XkbListCompat]= GetComponentSpec(&str,FALSE,&status); + list.pattern[_XkbListSymbols]= GetComponentSpec(&str,FALSE,&status); + list.pattern[_XkbListGeometry]= GetComponentSpec(&str,FALSE,&status); + if (status!=Success) + return status; + len= str-((unsigned char *)stuff); + if ((XkbPaddedSize(len)/4)!=stuff->length) + return BadLength; + if ((status=XkbDDXList(dev,&list,client))!=Success) { + free(list.pool); + list.pool = NULL; + return status; + } + memset(&rep, 0, sizeof(xkbListComponentsReply)); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = XkbPaddedSize(list.nPool)/4; + rep.nKeymaps = 0; + rep.nKeycodes = list.nFound[_XkbListKeycodes]; + rep.nTypes = list.nFound[_XkbListTypes]; + rep.nCompatMaps = list.nFound[_XkbListCompat]; + rep.nSymbols = list.nFound[_XkbListSymbols]; + rep.nGeometries = list.nFound[_XkbListGeometry]; + rep.extra= 0; + if (list.nTotal>list.maxRtrn) + rep.extra = (list.nTotal-list.maxRtrn); + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.nKeymaps,n); + swaps(&rep.nKeycodes,n); + swaps(&rep.nTypes,n); + swaps(&rep.nCompatMaps,n); + swaps(&rep.nSymbols,n); + swaps(&rep.nGeometries,n); + swaps(&rep.extra,n); + } + WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep); + if (list.nPool && list.pool) { + WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool); + free(list.pool); + list.pool= NULL; + } + return Success; +} + +/***====================================================================***/ + +int +ProcXkbGetKbdByName(ClientPtr client) +{ + DeviceIntPtr dev; + DeviceIntPtr tmpd; + xkbGetKbdByNameReply rep = {0}; + xkbGetMapReply mrep = {0}; + xkbGetCompatMapReply crep = {0}; + xkbGetIndicatorMapReply irep = {0}; + xkbGetNamesReply nrep = {0}; + xkbGetGeometryReply grep = {0}; + XkbComponentNamesRec names = {0}; + XkbDescPtr xkb, new; + unsigned char * str; + char mapFile[PATH_MAX]; + unsigned len; + unsigned fwant,fneed,reported; + int status; + Bool geom_changed; + XkbSrvLedInfoPtr old_sli; + XkbSrvLedInfoPtr sli; + Mask access_mode = DixGetAttrAccess | DixManageAccess; + + REQUEST(xkbGetKbdByNameReq); + REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); + + xkb = dev->key->xkbInfo->desc; + status= Success; + str= (unsigned char *)&stuff[1]; + if (GetComponentSpec(&str,TRUE,&status)) /* keymap, unsupported */ + return BadMatch; + names.keycodes= GetComponentSpec(&str,TRUE,&status); + names.types= GetComponentSpec(&str,TRUE,&status); + names.compat= GetComponentSpec(&str,TRUE,&status); + names.symbols= GetComponentSpec(&str,TRUE,&status); + names.geometry= GetComponentSpec(&str,TRUE,&status); + if (status!=Success) + return status; + len= str-((unsigned char *)stuff); + if ((XkbPaddedSize(len)/4)!=stuff->length) + return BadLength; + + CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask); + CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask); + + if (stuff->load) + fwant= XkbGBN_AllComponentsMask; + else fwant= stuff->want|stuff->need; + if ((!names.compat)&& + (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) { + names.compat= _XkbDupString("%"); + } + if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) { + names.types= _XkbDupString("%"); + } + if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) { + names.symbols= _XkbDupString("%"); + } + geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0)); + if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) { + names.geometry= _XkbDupString("%"); + geom_changed= FALSE; + } + + memset(mapFile, 0, PATH_MAX); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.minKeyCode = xkb->min_key_code; + rep.maxKeyCode = xkb->max_key_code; + rep.loaded= FALSE; + fwant= XkbConvertGetByNameComponents(TRUE,stuff->want)|XkmVirtualModsMask; + fneed= XkbConvertGetByNameComponents(TRUE,stuff->need); + rep.reported= XkbConvertGetByNameComponents(FALSE,fwant|fneed); + if (stuff->load) { + fneed|= XkmKeymapRequired; + fwant|= XkmKeymapLegal; + } + if ((fwant|fneed)&XkmSymbolsMask) { + fneed|= XkmKeyNamesIndex|XkmTypesIndex; + fwant|= XkmIndicatorsIndex; + } + + /* We pass dev in here so we can get the old names out if needed. */ + rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new, + mapFile,PATH_MAX); + rep.newKeyboard= FALSE; + rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0; + + stuff->want|= stuff->need; + if (new==NULL) + rep.reported= 0; + else { + if (stuff->load) + rep.loaded= TRUE; + if (stuff->load || + ((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) { + XkbChangesRec changes; + memset(&changes, 0, sizeof(changes)); + XkbUpdateDescActions(new, + new->min_key_code,XkbNumKeys(new), + &changes); + } + + if (new->map==NULL) + rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask); + else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) { + mrep.type= X_Reply; + mrep.deviceID = dev->id; + mrep.sequenceNumber= client->sequence; + mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2); + mrep.minKeyCode = new->min_key_code; + mrep.maxKeyCode = new->max_key_code; + mrep.present = 0; + mrep.totalSyms = mrep.totalActs = + mrep.totalKeyBehaviors= mrep.totalKeyExplicit= + mrep.totalModMapKeys= mrep.totalVModMapKeys= 0; + if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) { + mrep.present|= XkbKeyTypesMask; + mrep.firstType = 0; + mrep.nTypes = mrep.totalTypes= new->map->num_types; + } + else { + mrep.firstType = mrep.nTypes= 0; + mrep.totalTypes= 0; + } + if (rep.reported&XkbGBN_ClientSymbolsMask) { + mrep.present|= (XkbKeySymsMask|XkbModifierMapMask); + mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code; + mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new); + } + else { + mrep.firstKeySym= mrep.firstModMapKey= 0; + mrep.nKeySyms= mrep.nModMapKeys= 0; + } + if (rep.reported&XkbGBN_ServerSymbolsMask) { + mrep.present|= XkbAllServerInfoMask; + mrep.virtualMods= ~0; + mrep.firstKeyAct = mrep.firstKeyBehavior = + mrep.firstKeyExplicit = new->min_key_code; + mrep.nKeyActs = mrep.nKeyBehaviors = + mrep.nKeyExplicit = XkbNumKeys(new); + mrep.firstVModMapKey= new->min_key_code; + mrep.nVModMapKeys= XkbNumKeys(new); + } + else { + mrep.virtualMods= 0; + mrep.firstKeyAct= mrep.firstKeyBehavior= + mrep.firstKeyExplicit = 0; + mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0; + } + XkbComputeGetMapReplySize(new,&mrep); + rep.length+= SIZEOF(xGenericReply)/4+mrep.length; + } + if (new->compat==NULL) + rep.reported&= ~XkbGBN_CompatMapMask; + else if (rep.reported&XkbGBN_CompatMapMask) { + crep.type= X_Reply; + crep.deviceID= dev->id; + crep.sequenceNumber= client->sequence; + crep.length= 0; + crep.groups= XkbAllGroupsMask; + crep.firstSI= 0; + crep.nSI= crep.nTotalSI= new->compat->num_si; + XkbComputeGetCompatMapReplySize(new->compat,&crep); + rep.length+= SIZEOF(xGenericReply)/4+crep.length; + } + if (new->indicators==NULL) + rep.reported&= ~XkbGBN_IndicatorMapMask; + else if (rep.reported&XkbGBN_IndicatorMapMask) { + irep.type= X_Reply; + irep.deviceID= dev->id; + irep.sequenceNumber= client->sequence; + irep.length= 0; + irep.which= XkbAllIndicatorsMask; + XkbComputeGetIndicatorMapReplySize(new->indicators,&irep); + rep.length+= SIZEOF(xGenericReply)/4+irep.length; + } + if (new->names==NULL) + rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask); + else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) { + nrep.type= X_Reply; + nrep.deviceID= dev->id; + nrep.sequenceNumber= client->sequence; + nrep.length= 0; + nrep.minKeyCode= new->min_key_code; + nrep.maxKeyCode= new->max_key_code; + if (rep.reported&XkbGBN_OtherNamesMask) { + nrep.which= XkbAllNamesMask; + if (new->map!=NULL) + nrep.nTypes= new->map->num_types; + else nrep.nTypes= 0; + nrep.nKTLevels= 0; + nrep.groupNames= XkbAllGroupsMask; + nrep.virtualMods= XkbAllVirtualModsMask; + nrep.indicators= XkbAllIndicatorsMask; + nrep.nRadioGroups= new->names->num_rg; + } + else { + nrep.which= 0; + nrep.nTypes= 0; + nrep.nKTLevels= 0; + nrep.groupNames= 0; + nrep.virtualMods= 0; + nrep.indicators= 0; + nrep.nRadioGroups= 0; + } + if (rep.reported&XkbGBN_KeyNamesMask) { + nrep.which|= XkbKeyNamesMask; + nrep.firstKey= new->min_key_code; + nrep.nKeys= XkbNumKeys(new); + nrep.nKeyAliases= new->names->num_key_aliases; + if (nrep.nKeyAliases) + nrep.which|= XkbKeyAliasesMask; + } + else { + nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask); + nrep.firstKey= nrep.nKeys= 0; + nrep.nKeyAliases= 0; + } + XkbComputeGetNamesReplySize(new,&nrep); + rep.length+= SIZEOF(xGenericReply)/4+nrep.length; + } + if (new->geom==NULL) + rep.reported&= ~XkbGBN_GeometryMask; + else if (rep.reported&XkbGBN_GeometryMask) { + grep.type= X_Reply; + grep.deviceID= dev->id; + grep.sequenceNumber= client->sequence; + grep.length= 0; + grep.found= TRUE; + grep.pad= 0; + grep.widthMM= grep.heightMM= 0; + grep.nProperties= grep.nColors= grep.nShapes= 0; + grep.nSections= grep.nDoodads= 0; + grep.baseColorNdx= grep.labelColorNdx= 0; + XkbComputeGetGeometryReplySize(new->geom,&grep,None); + rep.length+= SIZEOF(xGenericReply)/4+grep.length; + } + } + + reported= rep.reported; + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.found,n); + swaps(&rep.reported,n); + } + WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep); + if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) + XkbSendMap(client,new,&mrep); + if (reported&XkbGBN_CompatMapMask) + XkbSendCompatMap(client,new->compat,&crep); + if (reported&XkbGBN_IndicatorMapMask) + XkbSendIndicatorMap(client,new->indicators,&irep); + if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask)) + XkbSendNames(client,new,&nrep); + if (reported&XkbGBN_GeometryMask) + XkbSendGeometry(client,new->geom,&grep,FALSE); + if (rep.loaded) { + XkbDescPtr old_xkb; + xkbNewKeyboardNotify nkn; + int i,nG,nTG; + old_xkb= xkb; + xkb= new; + dev->key->xkbInfo->desc= xkb; + new= old_xkb; /* so it'll get freed automatically */ + + *xkb->ctrls= *old_xkb->ctrls; + for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + nG= XkbKeyNumGroups(xkb,i); + if (nG>=XkbNumKbdGroups) { + nTG= XkbNumKbdGroups; + break; + } + if (nG>nTG) { + nTG= nG; + } + } + xkb->ctrls->num_groups= nTG; + + for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { + if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { + if (tmpd != dev) + XkbCopyDeviceKeymap(tmpd, dev); + + if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { + old_sli = tmpd->kbdfeed->xkb_sli; + tmpd->kbdfeed->xkb_sli = NULL; + sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0); + if (sli) { + sli->explicitState = old_sli->explicitState; + sli->effectiveState = old_sli->effectiveState; + } + tmpd->kbdfeed->xkb_sli = sli; + XkbFreeSrvLedInfo(old_sli); + } + } + } + + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= new->min_key_code; + nkn.maxKeyCode= new->max_key_code; + nkn.oldMinKeyCode= xkb->min_key_code; + nkn.oldMaxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbGetKbdByName; + nkn.changed= XkbNKN_KeycodesMask; + if (geom_changed) + nkn.changed|= XkbNKN_GeometryMask; + XkbSendNewKeyboardNotify(dev,&nkn); + + if (!IsMaster(dev) && dev->u.master) + { + DeviceIntPtr master = dev->u.master; + if (master->u.lastSlave == dev) + { + XkbCopyDeviceKeymap(dev->u.master, dev); + XkbSendNewKeyboardNotify(dev,&nkn); + } + } + } + if ((new!=NULL)&&(new!=xkb)) { + XkbFreeKeyboard(new,XkbAllComponentsMask,TRUE); + new= NULL; + } + free(names.keycodes); + names.keycodes = NULL; + free(names.types); + names.types = NULL; + free(names.compat); + names.compat = NULL; + free(names.symbols); + names.symbols = NULL; + free(names.geometry); + names.geometry = NULL; + return Success; +} + +/***====================================================================***/ + +static int +ComputeDeviceLedInfoSize( DeviceIntPtr dev, + unsigned int what, + XkbSrvLedInfoPtr sli) +{ +int nNames,nMaps; +register unsigned n,bit; + + if (sli==NULL) + return 0; + nNames= nMaps= 0; + if ((what&XkbXI_IndicatorNamesMask)==0) + sli->namesPresent= 0; + if ((what&XkbXI_IndicatorMapsMask)==0) + sli->mapsPresent= 0; + + for (n=0,bit=1;nnames && sli->names[n]!=None) { + sli->namesPresent|= bit; + nNames++; + } + if (sli->maps && XkbIM_InUse(&sli->maps[n])) { + sli->mapsPresent|= bit; + nMaps++; + } + } + return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc)); +} + +static int +CheckDeviceLedFBs( DeviceIntPtr dev, + int class, + int id, + xkbGetDeviceInfoReply * rep, + ClientPtr client) +{ +int nFBs= 0; +int length= 0; +Bool classOk; + + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + else { + client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); + return XkbKeyboardErrorCode; + } + } + classOk= FALSE; + if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { + KbdFeedbackPtr kf; + classOk= TRUE; + for (kf= dev->kbdfeed;(kf);kf=kf->next) { + if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id)) + continue; + nFBs++; + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (!kf->xkb_sli) + kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0); + length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli); + if (id!=XkbAllXIIds) + break; + } + } + if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { + LedFeedbackPtr lf; + classOk= TRUE; + for (lf= dev->leds;(lf);lf=lf->next) { + if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id)) + continue; + nFBs++; + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (!lf->xkb_sli) + lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0); + length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli); + if (id!=XkbAllXIIds) + break; + } + } + if (nFBs>0) { + rep->nDeviceLedFBs= nFBs; + rep->length+= (length/4); + return Success; + } + if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id); + else client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); + return XkbKeyboardErrorCode; +} + +static int +SendDeviceLedInfo( XkbSrvLedInfoPtr sli, + ClientPtr client) +{ +xkbDeviceLedsWireDesc wire; +int length; + + length= 0; + wire.ledClass= sli->class; + wire.ledID= sli->id; + wire.namesPresent= sli->namesPresent; + wire.mapsPresent= sli->mapsPresent; + wire.physIndicators= sli->physIndicators; + wire.state= sli->effectiveState; + if (client->swapped) { + register int n; + swaps(&wire.ledClass,n); + swaps(&wire.ledID,n); + swapl(&wire.namesPresent,n); + swapl(&wire.mapsPresent,n); + swapl(&wire.physIndicators,n); + swapl(&wire.state,n); + } + WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire); + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (sli->namesPresent|sli->mapsPresent) { + register unsigned i,bit; + if (sli->namesPresent) { + CARD32 awire; + for (i=0,bit=1;inamesPresent&bit) { + awire= (CARD32)sli->names[i]; + if (client->swapped) { + register int n; + swapl(&awire,n); + } + WriteToClient(client,4,(char *)&awire); + length+= 4; + } + } + } + if (sli->mapsPresent) { + for (i=0,bit=1;imapsPresent&bit) { + iwire.flags= sli->maps[i].flags; + iwire.whichGroups= sli->maps[i].which_groups; + iwire.groups= sli->maps[i].groups; + iwire.whichMods= sli->maps[i].which_mods; + iwire.mods= sli->maps[i].mods.mask; + iwire.realMods= sli->maps[i].mods.real_mods; + iwire.virtualMods= sli->maps[i].mods.vmods; + iwire.ctrls= sli->maps[i].ctrls; + if (client->swapped) { + register int n; + swaps(&iwire.virtualMods,n); + swapl(&iwire.ctrls,n); + } + WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc), + (char *)&iwire); + length+= SIZEOF(xkbIndicatorMapWireDesc); + } + } + } + } + return length; +} + +static int +SendDeviceLedFBs( DeviceIntPtr dev, + int class, + int id, + unsigned wantLength, + ClientPtr client) +{ +int length= 0; + + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + } + if ((dev->kbdfeed)&& + ((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { + KbdFeedbackPtr kf; + for (kf= dev->kbdfeed;(kf);kf=kf->next) { + if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) { + length+= SendDeviceLedInfo(kf->xkb_sli,client); + if (id!=XkbAllXIIds) + break; + } + } + } + if ((dev->leds)&& + ((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { + LedFeedbackPtr lf; + for (lf= dev->leds;(lf);lf=lf->next) { + if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) { + length+= SendDeviceLedInfo(lf->xkb_sli,client); + if (id!=XkbAllXIIds) + break; + } + } + } + if (length==wantLength) + return Success; + else return BadLength; +} + +int +ProcXkbGetDeviceInfo(ClientPtr client) +{ +DeviceIntPtr dev; +xkbGetDeviceInfoReply rep; +int status,nDeviceLedFBs; +unsigned length,nameLen; +CARD16 ledClass,ledID; +unsigned wanted; +char * str; + + REQUEST(xkbGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + wanted= stuff->wanted; + + CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask); + + if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns))) + wanted&= ~XkbXI_ButtonActionsMask; + if ((!dev->kbdfeed)&&(!dev->leds)) + wanted&= ~XkbXI_IndicatorsMask; + + nameLen= XkbSizeCountedString(dev->name); + memset((char *)&rep, 0, SIZEOF(xkbGetDeviceInfoReply)); + rep.type = X_Reply; + rep.deviceID= dev->id; + rep.sequenceNumber = client->sequence; + rep.length = nameLen/4; + rep.present = wanted; + rep.supported = XkbXI_AllDeviceFeaturesMask; + rep.unsupported = 0; + rep.firstBtnWanted = rep.nBtnsWanted = 0; + rep.firstBtnRtrn = rep.nBtnsRtrn = 0; + if (dev->button) + rep.totalBtns= dev->button->numButtons; + else rep.totalBtns= 0; + rep.devType= dev->xinput_type; + rep.hasOwnState= (dev->key && dev->key->xkbInfo); + rep.nDeviceLedFBs = 0; + if (dev->kbdfeed) rep.dfltKbdFB= dev->kbdfeed->ctrl.id; + else rep.dfltKbdFB= XkbXINone; + if (dev->leds) rep.dfltLedFB= dev->leds->ctrl.id; + else rep.dfltLedFB= XkbXINone; + + ledClass= stuff->ledClass; + ledID= stuff->ledID; + + rep.firstBtnWanted= rep.nBtnsWanted= 0; + rep.firstBtnRtrn= rep.nBtnsRtrn= 0; + if (wanted&XkbXI_ButtonActionsMask) { + if (stuff->allBtns) { + stuff->firstBtn= 0; + stuff->nBtns= dev->button->numButtons; + } + + if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { + client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons, + stuff->firstBtn, + stuff->nBtns); + return BadValue; + } + else { + rep.firstBtnWanted= stuff->firstBtn; + rep.nBtnsWanted= stuff->nBtns; + if (dev->button->xkb_acts!=NULL) { + XkbAction *act; + register int i; + + rep.firstBtnRtrn= stuff->firstBtn; + rep.nBtnsRtrn= stuff->nBtns; + act= &dev->button->xkb_acts[rep.firstBtnWanted]; + for (i=0;itype!=XkbSA_NoAction) + break; + } + rep.firstBtnRtrn+= i; + rep.nBtnsRtrn-= i; + act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1]; + for (i=0;itype!=XkbSA_NoAction) + break; + } + rep.nBtnsRtrn-= i; + } + rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4; + } + } + + if (wanted&XkbXI_IndicatorsMask) { + status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client); + if (status!=Success) + return status; + } + length= rep.length*4; + nDeviceLedFBs = rep.nDeviceLedFBs; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.present,n); + swaps(&rep.supported,n); + swaps(&rep.unsupported,n); + swaps(&rep.nDeviceLedFBs,n); + swapl(&rep.type,n); + } + WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep); + + str= malloc(nameLen); + if (!str) + return BadAlloc; + XkbWriteCountedString(str,dev->name,client->swapped); + WriteToClient(client,nameLen,str); + free(str); + length-= nameLen; + + if (rep.nBtnsRtrn>0) { + int sz; + xkbActionWireDesc * awire; + sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc); + awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn]; + WriteToClient(client,sz,(char *)awire); + length-= sz; + } + if (nDeviceLedFBs>0) { + status= SendDeviceLedFBs(dev,ledClass,ledID,length,client); + if (status!=Success) + return status; + } + else if (length!=0) { + ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); + ErrorF("[xkb] Wrote %d fewer bytes than expected\n",length); + return BadLength; + } + return Success; +} + +static char * +CheckSetDeviceIndicators( char * wire, + DeviceIntPtr dev, + int num, + int * status_rtrn, + ClientPtr client) +{ +xkbDeviceLedsWireDesc * ledWire; +int i; +XkbSrvLedInfoPtr sli; + + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;iswapped) { + register int n; + swaps(&ledWire->ledClass,n); + swaps(&ledWire->ledID,n); + swapl(&ledWire->namesPresent,n); + swapl(&ledWire->mapsPresent,n); + swapl(&ledWire->physIndicators,n); + } + + sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID, + XkbXI_IndicatorsMask); + if (sli!=NULL) { + register int n; + register unsigned bit; + int nMaps,nNames; + CARD32 *atomWire; + xkbIndicatorMapWireDesc *mapWire; + + nMaps= nNames= 0; + for (n=0,bit=1;nnamesPresent&bit) + nNames++; + if (ledWire->mapsPresent&bit) + nMaps++; + } + atomWire= (CARD32 *)&ledWire[1]; + if (nNames>0) { + for (n=0;nswapped) { + register int t; + swapl(atomWire,t); + } + CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue, + *status_rtrn,NULL); + atomWire++; + } + } + mapWire= (xkbIndicatorMapWireDesc *)atomWire; + if (nMaps>0) { + for (n=0;nswapped) { + register int t; + swaps(&mapWire->virtualMods,t); + swapl(&mapWire->ctrls,t); + } + CHK_MASK_LEGAL3(0x21,mapWire->whichGroups, + XkbIM_UseAnyGroup, + client->errorValue, + *status_rtrn,NULL); + CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods, + client->errorValue, + *status_rtrn,NULL); + mapWire++; + } + } + ledWire= (xkbDeviceLedsWireDesc *)mapWire; + } + else { + /* SHOULD NEVER HAPPEN */ + return (char *)ledWire; + } + } + return (char *)ledWire; +} + +static char * +SetDeviceIndicators( char * wire, + DeviceIntPtr dev, + unsigned changed, + int num, + int * status_rtrn, + ClientPtr client, + xkbExtensionDeviceNotify *ev) +{ +xkbDeviceLedsWireDesc * ledWire; +int i; +XkbEventCauseRec cause; +unsigned namec,mapc,statec; +xkbExtensionDeviceNotify ed; +XkbChangesRec changes; +DeviceIntPtr kbd; + + memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify)); + memset((char *)&changes, 0, sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client); + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;iledClass,ledWire->ledID, + XkbXI_IndicatorMapsMask); + if (!sli) { + /* SHOULD NEVER HAPPEN!! */ + return (char *)ledWire; + } + + atomWire= (CARD32 *)&ledWire[1]; + if (changed&XkbXI_IndicatorNamesMask) { + namec= sli->namesPresent|ledWire->namesPresent; + memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom)); + } + if (ledWire->namesPresent) { + sli->namesPresent= ledWire->namesPresent; + memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom)); + for (n=0,bit=1;nnamesPresent&bit) { + sli->names[n]= (Atom)*atomWire; + if (sli->names[n]==None) + ledWire->namesPresent&= ~bit; + atomWire++; + } + } + } + mapWire= (xkbIndicatorMapWireDesc *)atomWire; + if (changed&XkbXI_IndicatorMapsMask) { + mapc= sli->mapsPresent|ledWire->mapsPresent; + sli->mapsPresent= ledWire->mapsPresent; + memset((char*)sli->maps, 0, XkbNumIndicators*sizeof(XkbIndicatorMapRec)); + } + if (ledWire->mapsPresent) { + for (n=0,bit=1;nmapsPresent&bit) { + sli->maps[n].flags= mapWire->flags; + sli->maps[n].which_groups= mapWire->whichGroups; + sli->maps[n].groups= mapWire->groups; + sli->maps[n].which_mods= mapWire->whichMods; + sli->maps[n].mods.mask= mapWire->mods; + sli->maps[n].mods.real_mods=mapWire->realMods; + sli->maps[n].mods.vmods= mapWire->virtualMods; + sli->maps[n].ctrls= mapWire->ctrls; + mapWire++; + } + } + } + if (changed&XkbXI_IndicatorStateMask) { + statec= sli->effectiveState^ledWire->state; + sli->explicitState&= ~statec; + sli->explicitState|= (ledWire->state&statec); + } + if (namec) + XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); + if (mapc) + XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); + if (statec) + XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); + + kbd= dev; + if ((sli->flags&XkbSLI_HasOwnState)==0) + kbd = inputInfo.keyboard; + + XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause); + ledWire= (xkbDeviceLedsWireDesc *)mapWire; + } + return (char *)ledWire; +} + + +static int +_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, + xkbSetDeviceInfoReq *stuff) +{ + char *wire; + + wire= (char *)&stuff[1]; + if (stuff->change&XkbXI_ButtonActionsMask) { + if (!dev->button) { + client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass); + return XkbKeyboardErrorCode; + } + if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { + client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns, + dev->button->numButtons); + return BadMatch; + } + wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc)); + } + if (stuff->change&XkbXI_IndicatorsMask) { + int status= Success; + wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs, + &status,client); + if (status!=Success) + return status; + } + if (((wire-((char *)stuff))/4)!=stuff->length) + return BadLength; + + return Success; +} + +static int +_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, + xkbSetDeviceInfoReq *stuff) +{ + char *wire; + xkbExtensionDeviceNotify ed; + + memset((char *)&ed, 0, SIZEOF(xkbExtensionDeviceNotify)); + ed.deviceID= dev->id; + wire= (char *)&stuff[1]; + if (stuff->change&XkbXI_ButtonActionsMask) { + int nBtns,sz,i; + XkbAction * acts; + DeviceIntPtr kbd; + + nBtns= dev->button->numButtons; + acts= dev->button->xkb_acts; + if (acts==NULL) { + acts= calloc(nBtns, sizeof(XkbAction)); + if (!acts) + return BadAlloc; + dev->button->xkb_acts= acts; + } + sz= stuff->nBtns*SIZEOF(xkbActionWireDesc); + memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz); + wire+= sz; + ed.reason|= XkbXI_ButtonActionsMask; + ed.firstBtn= stuff->firstBtn; + ed.nBtns= stuff->nBtns; + + if (dev->key) kbd= dev; + else kbd= inputInfo.keyboard; + acts= &dev->button->xkb_acts[stuff->firstBtn]; + for (i=0;inBtns;i++,acts++) { + if (acts->type!=XkbSA_NoAction) + XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0); + } + } + if (stuff->change&XkbXI_IndicatorsMask) { + int status= Success; + wire= SetDeviceIndicators(wire,dev,stuff->change, + stuff->nDeviceLedFBs, &status,client,&ed); + if (status!=Success) + return status; + } + if ((stuff->change)&&(ed.reason)) + XkbSendExtensionDeviceNotify(dev,client,&ed); + return Success; +} + +int +ProcXkbSetDeviceInfo(ClientPtr client) +{ + DeviceIntPtr dev; + int rc; + + REQUEST(xkbSetDeviceInfoReq); + REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask); + + rc = _XkbSetDeviceInfoCheck(client, dev, stuff); + + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) && + ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || + (stuff->deviceSpec == XkbUseCorePtr && other->button))) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetDeviceInfoCheck(client, other, stuff); + if (rc != Success) + return rc; + } + } + } + } + + /* checks done, apply */ + rc = _XkbSetDeviceInfo(client, dev, stuff); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) && + ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || + (stuff->deviceSpec == XkbUseCorePtr && other->button))) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetDeviceInfo(client, other, stuff); + if (rc != Success) + return rc; + } + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbSetDebuggingFlags(ClientPtr client) +{ +CARD32 newFlags,newCtrls,extraLength; +xkbSetDebuggingFlagsReply rep; +int rc; + + REQUEST(xkbSetDebuggingFlagsReq); + REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); + + rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess); + if (rc != Success) + return rc; + + newFlags= xkbDebugFlags&(~stuff->affectFlags); + newFlags|= (stuff->flags&stuff->affectFlags); + newCtrls= xkbDebugCtrls&(~stuff->affectCtrls); + newCtrls|= (stuff->ctrls&stuff->affectCtrls); + if (xkbDebugFlags || newFlags || stuff->msgLength) { + ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags); + if (newCtrls!=xkbDebugCtrls) + ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls); + } + extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq; + if (stuff->msgLength>0) { + char *msg; + if (extraLengthmsgLength)) { + ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n", + stuff->msgLength,(long)extraLength, + XkbPaddedSize(stuff->msgLength)); + return BadLength; + } + msg= (char *)&stuff[1]; + if (msg[stuff->msgLength-1]!='\0') { + ErrorF("[xkb] XkbDebug: message not null-terminated\n"); + return BadValue; + } + ErrorF("[xkb] XkbDebug: %s\n",msg); + } + xkbDebugFlags = newFlags; + xkbDebugCtrls = newCtrls; + + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.currentFlags = newFlags; + rep.currentCtrls = newCtrls; + rep.supportedFlags = ~0; + rep.supportedCtrls = ~0; + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.currentFlags, n); + swapl(&rep.currentCtrls, n); + swapl(&rep.supportedFlags, n); + swapl(&rep.supportedCtrls, n); + } + WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +static int +ProcXkbDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_kbUseExtension: + return ProcXkbUseExtension(client); + case X_kbSelectEvents: + return ProcXkbSelectEvents(client); + case X_kbBell: + return ProcXkbBell(client); + case X_kbGetState: + return ProcXkbGetState(client); + case X_kbLatchLockState: + return ProcXkbLatchLockState(client); + case X_kbGetControls: + return ProcXkbGetControls(client); + case X_kbSetControls: + return ProcXkbSetControls(client); + case X_kbGetMap: + return ProcXkbGetMap(client); + case X_kbSetMap: + return ProcXkbSetMap(client); + case X_kbGetCompatMap: + return ProcXkbGetCompatMap(client); + case X_kbSetCompatMap: + return ProcXkbSetCompatMap(client); + case X_kbGetIndicatorState: + return ProcXkbGetIndicatorState(client); + case X_kbGetIndicatorMap: + return ProcXkbGetIndicatorMap(client); + case X_kbSetIndicatorMap: + return ProcXkbSetIndicatorMap(client); + case X_kbGetNamedIndicator: + return ProcXkbGetNamedIndicator(client); + case X_kbSetNamedIndicator: + return ProcXkbSetNamedIndicator(client); + case X_kbGetNames: + return ProcXkbGetNames(client); + case X_kbSetNames: + return ProcXkbSetNames(client); + case X_kbGetGeometry: + return ProcXkbGetGeometry(client); + case X_kbSetGeometry: + return ProcXkbSetGeometry(client); + case X_kbPerClientFlags: + return ProcXkbPerClientFlags(client); + case X_kbListComponents: + return ProcXkbListComponents(client); + case X_kbGetKbdByName: + return ProcXkbGetKbdByName(client); + case X_kbGetDeviceInfo: + return ProcXkbGetDeviceInfo(client); + case X_kbSetDeviceInfo: + return ProcXkbSetDeviceInfo(client); + case X_kbSetDebuggingFlags: + return ProcXkbSetDebuggingFlags(client); + default: + return BadRequest; + } +} + +static int +XkbClientGone(pointer data,XID id) +{ + DevicePtr pXDev = (DevicePtr)data; + + if (!XkbRemoveResourceClient(pXDev,id)) { + ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n"); + } + return 1; +} + +void +XkbExtensionInit(void) +{ + ExtensionEntry *extEntry; + + RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient"); + if (!RT_XKBCLIENT) + return; + + if (!XkbInitPrivates()) + return; + + if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, + ProcXkbDispatch, SProcXkbDispatch, + NULL, StandardMinorOpcode))) { + XkbReqCode = (unsigned char)extEntry->base; + XkbEventBase = (unsigned char)extEntry->eventBase; + XkbErrorBase = (unsigned char)extEntry->errorBase; + XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard; + } + return; +} + + -- cgit v1.2.3