diff options
Diffstat (limited to 'xorg-server/xkb')
37 files changed, 26507 insertions, 0 deletions
diff --git a/xorg-server/xkb/Makefile.am b/xorg-server/xkb/Makefile.am new file mode 100644 index 000000000..5b594c130 --- /dev/null +++ b/xorg-server/xkb/Makefile.am @@ -0,0 +1,53 @@ +noinst_LTLIBRARIES = libxkb.la libxkbstubs.la + +AM_CFLAGS = $(DIX_CFLAGS) \ + -DHAVE_XKB_CONFIG_H + +DDX_SRCS = \ + ddxBeep.c \ + ddxCtrls.c \ + ddxFakeBtn.c \ + ddxFakeMtn.c \ + ddxInit.c \ + ddxKeyClick.c \ + ddxLEDs.c \ + ddxLoad.c \ + ddxList.c \ + ddxDevBtn.c + +DIX_SRCS = \ + xkb.c \ + xkbUtils.c \ + xkbEvents.c \ + xkbAccessX.c \ + xkbSwap.c \ + xkbLEDs.c \ + xkbInit.c \ + xkbActions.c \ + xkbPrKeyEv.c + +# this should be replaced by a common library or something, ideally -d +XKBFILE_SRCS = \ + maprules.c \ + xkmread.c \ + xkbtext.c \ + xkbfmisc.c \ + xkbout.c + +X11_SRCS = \ + XKBMisc.c \ + XKBAlloc.c \ + XKBGAlloc.c \ + XKBMAlloc.c + +# ends up unused... +# XI_SRCS = xkbPrOtherEv.c + +libxkb_la_SOURCES = $(DDX_SRCS) $(DIX_SRCS) $(XI_SRCS) $(XKBFILE_SRCS) \ + $(X11_SRCS) +libxkbstubs_la_SOURCES = ddxVT.c ddxPrivate.c ddxKillSrv.c + +EXTRA_DIST = xkbDflts.h xkbgeom.h xkb.h + +xkbcompileddir = $(XKB_COMPILED_DIR) +dist_xkbcompiled_DATA = README.compiled diff --git a/xorg-server/xkb/Makefile.in b/xorg-server/xkb/Makefile.in new file mode 100644 index 000000000..836547dd7 --- /dev/null +++ b/xorg-server/xkb/Makefile.in @@ -0,0 +1,767 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = xkb +DIST_COMMON = $(dist_xkbcompiled_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \ + $(top_builddir)/include/xorg-server.h \ + $(top_builddir)/include/dix-config.h \ + $(top_builddir)/include/xgl-config.h \ + $(top_builddir)/include/xorg-config.h \ + $(top_builddir)/include/xkb-config.h \ + $(top_builddir)/include/xwin-config.h \ + $(top_builddir)/include/kdrive-config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libxkb_la_LIBADD = +am__objects_1 = ddxBeep.lo ddxCtrls.lo ddxFakeBtn.lo ddxFakeMtn.lo \ + ddxInit.lo ddxKeyClick.lo ddxLEDs.lo ddxLoad.lo ddxList.lo \ + ddxDevBtn.lo +am__objects_2 = xkb.lo xkbUtils.lo xkbEvents.lo xkbAccessX.lo \ + xkbSwap.lo xkbLEDs.lo xkbInit.lo xkbActions.lo xkbPrKeyEv.lo +am__objects_3 = maprules.lo xkmread.lo xkbtext.lo xkbfmisc.lo \ + xkbout.lo +am__objects_4 = XKBMisc.lo XKBAlloc.lo XKBGAlloc.lo XKBMAlloc.lo +am_libxkb_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) $(am__objects_4) +libxkb_la_OBJECTS = $(am_libxkb_la_OBJECTS) +libxkbstubs_la_LIBADD = +am_libxkbstubs_la_OBJECTS = ddxVT.lo ddxPrivate.lo ddxKillSrv.lo +libxkbstubs_la_OBJECTS = $(am_libxkbstubs_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libxkb_la_SOURCES) $(libxkbstubs_la_SOURCES) +DIST_SOURCES = $(libxkb_la_SOURCES) $(libxkbstubs_la_SOURCES) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(xkbcompileddir)" +dist_xkbcompiledDATA_INSTALL = $(INSTALL_DATA) +DATA = $(dist_xkbcompiled_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +APPDEFAULTDIR = @APPDEFAULTDIR@ +APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASE_FONT_PATH = @BASE_FONT_PATH@ +BUILD_DATE = @BUILD_DATE@ +BUILD_TIME = @BUILD_TIME@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DARWIN_LIBS = @DARWIN_LIBS@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@ +DEFAULT_LOGPREFIX = @DEFAULT_LOGPREFIX@ +DEFAULT_MODULE_PATH = @DEFAULT_MODULE_PATH@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DGA_CFLAGS = @DGA_CFLAGS@ +DGA_LIBS = @DGA_LIBS@ +DIX_CFLAGS = @DIX_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DMXEXAMPLES_DEP_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@ +DMXEXAMPLES_DEP_LIBS = @DMXEXAMPLES_DEP_LIBS@ +DMXMODULES_CFLAGS = @DMXMODULES_CFLAGS@ +DMXMODULES_LIBS = @DMXMODULES_LIBS@ +DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@ +DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@ +DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@ +DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@ +DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ +DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@ +DRIPROTO_LIBS = @DRIPROTO_LIBS@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DRI_DRIVER_PATH = @DRI_DRIVER_PATH@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@ +GLX_DEFINES = @GLX_DEFINES@ +GL_CFLAGS = @GL_CFLAGS@ +GL_LIBS = @GL_LIBS@ +GREP = @GREP@ +HAL_CFLAGS = @HAL_CFLAGS@ +HAL_LIBS = @HAL_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KDRIVE_CFLAGS = @KDRIVE_CFLAGS@ +KDRIVE_INCS = @KDRIVE_INCS@ +KDRIVE_LIBS = @KDRIVE_LIBS@ +KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@ +KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@ +KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@ +LAUNCHD = @LAUNCHD@ +LDFLAGS = @LDFLAGS@ +LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ +LIBDRM_LIBS = @LIBDRM_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LINUXDOC = @LINUXDOC@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAKE_HTML = @MAKE_HTML@ +MAKE_PDF = @MAKE_PDF@ +MAKE_PS = @MAKE_PS@ +MAKE_TEXT = @MAKE_TEXT@ +MESA_SOURCE = @MESA_SOURCE@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +MKFONTDIR = @MKFONTDIR@ +MKFONTSCALE = @MKFONTSCALE@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCCLD = @OBJCCLD@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCLINK = @OBJCLINK@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ +PCIACCESS_LIBS = @PCIACCESS_LIBS@ +PCI_TXT_IDS_PATH = @PCI_TXT_IDS_PATH@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PROJECTROOT = @PROJECTROOT@ +PS2PDF = @PS2PDF@ +RANLIB = @RANLIB@ +RAWCPP = @RAWCPP@ +RAWCPPFLAGS = @RAWCPPFLAGS@ +SED = @SED@ +SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@ +SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@ +STRIP = @STRIP@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +UTILS_SYS_LIBS = @UTILS_SYS_LIBS@ +VENDOR_MAN_VERSION = @VENDOR_MAN_VERSION@ +VENDOR_NAME = @VENDOR_NAME@ +VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@ +VENDOR_RELEASE = @VENDOR_RELEASE@ +VERSION = @VERSION@ +X11APP_ARCHS = @X11APP_ARCHS@ +X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@ +X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@ +XDMCP_CFLAGS = @XDMCP_CFLAGS@ +XDMCP_LIBS = @XDMCP_LIBS@ +XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@ +XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@ +XDMX_CFLAGS = @XDMX_CFLAGS@ +XDMX_LIBS = @XDMX_LIBS@ +XDMX_SYS_LIBS = @XDMX_SYS_LIBS@ +XEGLMODULES_CFLAGS = @XEGLMODULES_CFLAGS@ +XEGL_LIBS = @XEGL_LIBS@ +XEGL_SYS_LIBS = @XEGL_SYS_LIBS@ +XEPHYR_CFLAGS = @XEPHYR_CFLAGS@ +XEPHYR_DRI_LIBS = @XEPHYR_DRI_LIBS@ +XEPHYR_INCS = @XEPHYR_INCS@ +XEPHYR_LIBS = @XEPHYR_LIBS@ +XF86CONFIGFILE = @XF86CONFIGFILE@ +XF86MISC_CFLAGS = @XF86MISC_CFLAGS@ +XF86MISC_LIBS = @XF86MISC_LIBS@ +XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ +XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ +XGLMODULES_CFLAGS = @XGLMODULES_CFLAGS@ +XGLMODULES_LIBS = @XGLMODULES_LIBS@ +XGLXMODULES_CFLAGS = @XGLXMODULES_CFLAGS@ +XGLXMODULES_LIBS = @XGLXMODULES_LIBS@ +XGLX_LIBS = @XGLX_LIBS@ +XGLX_SYS_LIBS = @XGLX_SYS_LIBS@ +XGL_LIBS = @XGL_LIBS@ +XGL_MODULE_PATH = @XGL_MODULE_PATH@ +XGL_SYS_LIBS = @XGL_SYS_LIBS@ +XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@ +XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@ +XKB_COMPILED_DIR = @XKB_COMPILED_DIR@ +XKM_OUTPUT_DIR = @XKM_OUTPUT_DIR@ +XLIB_CFLAGS = @XLIB_CFLAGS@ +XLIB_LIBS = @XLIB_LIBS@ +XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@ +XNESTMODULES_LIBS = @XNESTMODULES_LIBS@ +XNEST_LIBS = @XNEST_LIBS@ +XNEST_SYS_LIBS = @XNEST_SYS_LIBS@ +XORGCFG_DEP_CFLAGS = @XORGCFG_DEP_CFLAGS@ +XORGCFG_DEP_LIBS = @XORGCFG_DEP_LIBS@ +XORGCONFIG_DEP_CFLAGS = @XORGCONFIG_DEP_CFLAGS@ +XORGCONFIG_DEP_LIBS = @XORGCONFIG_DEP_LIBS@ +XORG_CFLAGS = @XORG_CFLAGS@ +XORG_INCS = @XORG_INCS@ +XORG_LIBS = @XORG_LIBS@ +XORG_MODULES_CFLAGS = @XORG_MODULES_CFLAGS@ +XORG_MODULES_LIBS = @XORG_MODULES_LIBS@ +XORG_OS = @XORG_OS@ +XORG_OS_SUBDIR = @XORG_OS_SUBDIR@ +XORG_SYS_LIBS = @XORG_SYS_LIBS@ +XPRINTMODULES_CFLAGS = @XPRINTMODULES_CFLAGS@ +XPRINTMODULES_LIBS = @XPRINTMODULES_LIBS@ +XPRINTPROTO_CFLAGS = @XPRINTPROTO_CFLAGS@ +XPRINTPROTO_LIBS = @XPRINTPROTO_LIBS@ +XPRINT_CFLAGS = @XPRINT_CFLAGS@ +XPRINT_LIBS = @XPRINT_LIBS@ +XPRINT_SYS_LIBS = @XPRINT_SYS_LIBS@ +XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ +XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ +XSDL_INCS = @XSDL_INCS@ +XSDL_LIBS = @XSDL_LIBS@ +XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@ +XSERVERCFLAGS_LIBS = @XSERVERCFLAGS_LIBS@ +XSERVERLIBS_CFLAGS = @XSERVERLIBS_CFLAGS@ +XSERVERLIBS_LIBS = @XSERVERLIBS_LIBS@ +XSERVER_LIBS = @XSERVER_LIBS@ +XSERVER_SYS_LIBS = @XSERVER_SYS_LIBS@ +XTSTEXAMPLES_DEP_CFLAGS = @XTSTEXAMPLES_DEP_CFLAGS@ +XTSTEXAMPLES_DEP_LIBS = @XTSTEXAMPLES_DEP_LIBS@ +XVFB_LIBS = @XVFB_LIBS@ +XVFB_SYS_LIBS = @XVFB_SYS_LIBS@ +XWINMODULES_CFLAGS = @XWINMODULES_CFLAGS@ +XWINMODULES_LIBS = @XWINMODULES_LIBS@ +XWIN_LIBS = @XWIN_LIBS@ +XWIN_SERVER_NAME = @XWIN_SERVER_NAME@ +XWIN_SYS_LIBS = @XWIN_SYS_LIBS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +__XCONFIGFILE__ = @__XCONFIGFILE__@ +abi_ansic = @abi_ansic@ +abi_extension = @abi_extension@ +abi_font = @abi_font@ +abi_videodrv = @abi_videodrv@ +abi_xinput = @abi_xinput@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +driverdir = @driverdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +extdir = @extdir@ +ft_config = @ft_config@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +launchagentsdir = @launchagentsdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +logdir = @logdir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sdkdir = @sdkdir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xglmoduledir = @xglmoduledir@ +xpconfigdir = @xpconfigdir@ +noinst_LTLIBRARIES = libxkb.la libxkbstubs.la +AM_CFLAGS = $(DIX_CFLAGS) \ + -DHAVE_XKB_CONFIG_H + +DDX_SRCS = \ + ddxBeep.c \ + ddxCtrls.c \ + ddxFakeBtn.c \ + ddxFakeMtn.c \ + ddxInit.c \ + ddxKeyClick.c \ + ddxLEDs.c \ + ddxLoad.c \ + ddxList.c \ + ddxDevBtn.c + +DIX_SRCS = \ + xkb.c \ + xkbUtils.c \ + xkbEvents.c \ + xkbAccessX.c \ + xkbSwap.c \ + xkbLEDs.c \ + xkbInit.c \ + xkbActions.c \ + xkbPrKeyEv.c + + +# this should be replaced by a common library or something, ideally -d +XKBFILE_SRCS = \ + maprules.c \ + xkmread.c \ + xkbtext.c \ + xkbfmisc.c \ + xkbout.c + +X11_SRCS = \ + XKBMisc.c \ + XKBAlloc.c \ + XKBGAlloc.c \ + XKBMAlloc.c + + +# ends up unused... +# XI_SRCS = xkbPrOtherEv.c +libxkb_la_SOURCES = $(DDX_SRCS) $(DIX_SRCS) $(XI_SRCS) $(XKBFILE_SRCS) \ + $(X11_SRCS) + +libxkbstubs_la_SOURCES = ddxVT.c ddxPrivate.c ddxKillSrv.c +EXTRA_DIST = xkbDflts.h xkbgeom.h xkb.h +xkbcompileddir = $(XKB_COMPILED_DIR) +dist_xkbcompiled_DATA = README.compiled +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign xkb/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign xkb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libxkb.la: $(libxkb_la_OBJECTS) $(libxkb_la_DEPENDENCIES) + $(LINK) $(libxkb_la_OBJECTS) $(libxkb_la_LIBADD) $(LIBS) +libxkbstubs.la: $(libxkbstubs_la_OBJECTS) $(libxkbstubs_la_DEPENDENCIES) + $(LINK) $(libxkbstubs_la_OBJECTS) $(libxkbstubs_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XKBAlloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XKBGAlloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XKBMAlloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XKBMisc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxBeep.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxCtrls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxDevBtn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxFakeBtn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxFakeMtn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxInit.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxKeyClick.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxKillSrv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxLEDs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxList.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxLoad.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxPrivate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddxVT.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maprules.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbAccessX.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbActions.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbEvents.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbInit.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbLEDs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbPrKeyEv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbSwap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbUtils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbfmisc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkbtext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkmread.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_xkbcompiledDATA: $(dist_xkbcompiled_DATA) + @$(NORMAL_INSTALL) + test -z "$(xkbcompileddir)" || $(MKDIR_P) "$(DESTDIR)$(xkbcompileddir)" + @list='$(dist_xkbcompiled_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(dist_xkbcompiledDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(xkbcompileddir)/$$f'"; \ + $(dist_xkbcompiledDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(xkbcompileddir)/$$f"; \ + done + +uninstall-dist_xkbcompiledDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_xkbcompiled_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(xkbcompileddir)/$$f'"; \ + rm -f "$(DESTDIR)$(xkbcompileddir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(xkbcompileddir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-dist_xkbcompiledDATA + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_xkbcompiledDATA + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_xkbcompiledDATA install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-dist_xkbcompiledDATA + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/xorg-server/xkb/README.compiled b/xorg-server/xkb/README.compiled new file mode 100644 index 000000000..71caa2f63 --- /dev/null +++ b/xorg-server/xkb/README.compiled @@ -0,0 +1,13 @@ + +The X server uses this directory to store the compiled version of the +current keymap and/or any scratch keymaps used by clients. The X server +or some other tool might destroy or replace the files in this directory, +so it is not a safe place to store compiled keymaps for long periods of +time. The default keymap for any server is usually stored in: + X<num>-default.xkm +where <num> is the display number of the server in question, which makes +it possible for several servers *on the same host* to share the same +directory. + +Unless the X server is modified, sharing this directory between servers on +different hosts could cause problems. diff --git a/xorg-server/xkb/XKBAlloc.c b/xorg-server/xkb/XKBAlloc.c new file mode 100644 index 000000000..790aede92 --- /dev/null +++ b/xorg-server/xkb/XKBAlloc.c @@ -0,0 +1,337 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include <xkbsrv.h> +#include "xkbgeom.h" + +/***===================================================================***/ + +/*ARGSUSED*/ +Status +XkbAllocCompatMap(XkbDescPtr xkb,unsigned which,unsigned nSI) +{ +XkbCompatMapPtr compat; +XkbSymInterpretRec *prev_interpret; + + if (!xkb) + return BadMatch; + if (xkb->compat) { + if (xkb->compat->size_si>=nSI) + return Success; + compat= xkb->compat; + compat->size_si= nSI; + if (compat->sym_interpret==NULL) + compat->num_si= 0; + prev_interpret = compat->sym_interpret; + compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret, + nSI,XkbSymInterpretRec); + if (compat->sym_interpret==NULL) { + _XkbFree(prev_interpret); + compat->size_si= compat->num_si= 0; + return BadAlloc; + } + if (compat->num_si!=0) { + _XkbClearElems(compat->sym_interpret,compat->num_si, + compat->size_si-1,XkbSymInterpretRec); + } + return Success; + } + compat= _XkbTypedCalloc(1,XkbCompatMapRec); + if (compat==NULL) + return BadAlloc; + if (nSI>0) { + compat->sym_interpret= _XkbTypedCalloc(nSI,XkbSymInterpretRec); + if (!compat->sym_interpret) { + _XkbFree(compat); + return BadAlloc; + } + } + compat->size_si= nSI; + compat->num_si= 0; + bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec)); + xkb->compat= compat; + return Success; +} + + +void +XkbFreeCompatMap(XkbDescPtr xkb,unsigned which,Bool freeMap) +{ +register XkbCompatMapPtr compat; + + if ((xkb==NULL)||(xkb->compat==NULL)) + return; + compat= xkb->compat; + if (freeMap) + which= XkbAllCompatMask; + if (which&XkbGroupCompatMask) + bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec)); + if (which&XkbSymInterpMask) { + if ((compat->sym_interpret)&&(compat->size_si>0)) + _XkbFree(compat->sym_interpret); + compat->size_si= compat->num_si= 0; + compat->sym_interpret= NULL; + } + if (freeMap) { + _XkbFree(compat); + xkb->compat= NULL; + } + return; +} + +/***===================================================================***/ + +Status +XkbAllocNames(XkbDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases) +{ +XkbNamesPtr names; + + if (xkb==NULL) + return BadMatch; + if (xkb->names==NULL) { + xkb->names = _XkbTypedCalloc(1,XkbNamesRec); + if (xkb->names==NULL) + return BadAlloc; + } + names= xkb->names; + if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){ + register int i; + XkbKeyTypePtr type; + + type= xkb->map->types; + for (i=0;i<xkb->map->num_types;i++,type++) { + if (type->level_names==NULL) { + type->level_names= _XkbTypedCalloc(type->num_levels,Atom); + if (type->level_names==NULL) + return BadAlloc; + } + } + } + if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadValue; + names->keys= _XkbTypedCalloc((xkb->max_key_code+1),XkbKeyNameRec); + if (names->keys==NULL) + return BadAlloc; + } + if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) { + if (names->key_aliases==NULL) { + names->key_aliases= _XkbTypedCalloc(nTotalAliases,XkbKeyAliasRec); + } + else if (nTotalAliases>names->num_key_aliases) { + XkbKeyAliasRec *prev_aliases = names->key_aliases; + + names->key_aliases= _XkbTypedRealloc(names->key_aliases, + nTotalAliases,XkbKeyAliasRec); + if (names->key_aliases!=NULL) { + _XkbClearElems(names->key_aliases,names->num_key_aliases, + nTotalAliases-1,XkbKeyAliasRec); + } else { + _XkbFree(prev_aliases); + } + } + if (names->key_aliases==NULL) { + names->num_key_aliases= 0; + return BadAlloc; + } + names->num_key_aliases= nTotalAliases; + } + if ((which&XkbRGNamesMask)&&(nTotalRG>0)) { + if (names->radio_groups==NULL) { + names->radio_groups= _XkbTypedCalloc(nTotalRG,Atom); + } + else if (nTotalRG>names->num_rg) { + Atom *prev_radio_groups = names->radio_groups; + + names->radio_groups= _XkbTypedRealloc(names->radio_groups,nTotalRG, + Atom); + if (names->radio_groups!=NULL) { + _XkbClearElems(names->radio_groups,names->num_rg,nTotalRG-1, + Atom); + } else { + _XkbFree(prev_radio_groups); + } + } + if (names->radio_groups==NULL) + return BadAlloc; + names->num_rg= nTotalRG; + } + return Success; +} + +void +XkbFreeNames(XkbDescPtr xkb,unsigned which,Bool freeMap) +{ +XkbNamesPtr names; + + if ((xkb==NULL)||(xkb->names==NULL)) + return; + names= xkb->names; + if (freeMap) + which= XkbAllNamesMask; + if (which&XkbKTLevelNamesMask) { + XkbClientMapPtr map= xkb->map; + if ((map!=NULL)&&(map->types!=NULL)) { + register int i; + register XkbKeyTypePtr type; + type= map->types; + for (i=0;i<map->num_types;i++,type++) { + if (type->level_names!=NULL) { + _XkbFree(type->level_names); + type->level_names= NULL; + } + } + } + } + if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) { + _XkbFree(names->keys); + names->keys= NULL; + names->num_keys= 0; + } + if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){ + _XkbFree(names->key_aliases); + names->key_aliases=NULL; + names->num_key_aliases=0; + } + if ((which&XkbRGNamesMask)&&(names->radio_groups)) { + _XkbFree(names->radio_groups); + names->radio_groups= NULL; + names->num_rg= 0; + } + if (freeMap) { + _XkbFree(names); + xkb->names= NULL; + } + return; +} + +/***===================================================================***/ + +/*ARGSUSED*/ +Status +XkbAllocControls(XkbDescPtr xkb,unsigned which) +{ + if (xkb==NULL) + return BadMatch; + + if (xkb->ctrls==NULL) { + xkb->ctrls= _XkbTypedCalloc(1,XkbControlsRec); + if (!xkb->ctrls) + return BadAlloc; + } + return Success; +} + +/*ARGSUSED*/ +static void +XkbFreeControls(XkbDescPtr xkb,unsigned which,Bool freeMap) +{ + if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) { + _XkbFree(xkb->ctrls); + xkb->ctrls= NULL; + } + return; +} + +/***===================================================================***/ + +Status +XkbAllocIndicatorMaps(XkbDescPtr xkb) +{ + if (xkb==NULL) + return BadMatch; + if (xkb->indicators==NULL) { + xkb->indicators= _XkbTypedCalloc(1,XkbIndicatorRec); + if (!xkb->indicators) + return BadAlloc; + } + return Success; +} + +static void +XkbFreeIndicatorMaps(XkbDescPtr xkb) +{ + if ((xkb!=NULL)&&(xkb->indicators!=NULL)) { + _XkbFree(xkb->indicators); + xkb->indicators= NULL; + } + return; +} + +/***====================================================================***/ + +XkbDescRec * +XkbAllocKeyboard(void) +{ +XkbDescRec *xkb; + + xkb = _XkbTypedCalloc(1,XkbDescRec); + if (xkb) + xkb->device_spec= XkbUseCoreKbd; + return xkb; +} + +void +XkbFreeKeyboard(XkbDescPtr xkb,unsigned which,Bool freeAll) +{ + if (xkb==NULL) + return; + if (freeAll) + which= XkbAllComponentsMask; + if (which&XkbClientMapMask) + XkbFreeClientMap(xkb,XkbAllClientInfoMask,True); + if (which&XkbServerMapMask) + XkbFreeServerMap(xkb,XkbAllServerInfoMask,True); + if (which&XkbCompatMapMask) + XkbFreeCompatMap(xkb,XkbAllCompatMask,True); + if (which&XkbIndicatorMapMask) + XkbFreeIndicatorMaps(xkb); + if (which&XkbNamesMask) + XkbFreeNames(xkb,XkbAllNamesMask,True); + if ((which&XkbGeometryMask) && (xkb->geom!=NULL)) { + XkbFreeGeometry(xkb->geom,XkbGeomAllMask,True); + /* PERHAPS BONGHITS etc */ + xkb->geom = NULL; + } + if (which&XkbControlsMask) + XkbFreeControls(xkb,XkbAllControlsMask,True); + if (freeAll) + _XkbFree(xkb); + return; +} diff --git a/xorg-server/xkb/XKBGAlloc.c b/xorg-server/xkb/XKBGAlloc.c new file mode 100644 index 000000000..c37f49a55 --- /dev/null +++ b/xorg-server/xkb/XKBGAlloc.c @@ -0,0 +1,999 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#define NEED_EVENTS +#define NEED_REPLIES + +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include <xkbsrv.h> +#include "xkbgeom.h" + +/***====================================================================***/ + +static void +_XkbFreeGeomLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz) +{ + if ((freeAll)||(*elems==NULL)) { + *num_inout= *sz_inout= 0; + if (*elems!=NULL) { + _XkbFree(*elems); + *elems= NULL; + } + return; + } + + if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + + if (first+count>=(*num_inout)) { + /* truncating the array is easy */ + (*num_inout)= first; + } + else { + char * ptr; + int extra; + ptr= *elems; + extra= ((*num_inout)-(first+count))*elem_sz; + if (extra>0) + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra); + (*num_inout)-= count; + } + return; +} + +typedef void (*ContentsClearFunc)( + char * /* priv */ +); + +static void +_XkbFreeGeomNonLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz, + ContentsClearFunc freeFunc) +{ +register int i; +register char *ptr; + + if (freeAll) { + first= 0; + count= (*num_inout); + } + else if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + else if (first+count>(*num_inout)) + count= (*num_inout)-first; + if (*elems==NULL) + return; + + if (freeFunc) { + ptr= *elems; + ptr+= first*elem_sz; + for (i=0;i<count;i++) { + (*freeFunc)(ptr); + ptr+= elem_sz; + } + } + if (freeAll) { + (*num_inout)= (*sz_inout)= 0; + if (*elems) { + _XkbFree(*elems); + *elems= NULL; + } + } + else if (first+count>=(*num_inout)) + *num_inout= first; + else { + i= ((*num_inout)-(first+count))*elem_sz; + ptr= *elems; + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i); + (*num_inout)-= count; + } + return; +} + +/***====================================================================***/ + +static void +_XkbClearProperty(char *prop_in) +{ +XkbPropertyPtr prop= (XkbPropertyPtr)prop_in; + + if (prop->name) { + _XkbFree(prop->name); + prop->name= NULL; + } + if (prop->value) { + _XkbFree(prop->value); + prop->value= NULL; + } + return; +} + +void +XkbFreeGeomProperties( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_properties,&geom->sz_properties, + (char **)&geom->properties, + sizeof(XkbPropertyRec),_XkbClearProperty); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomKeyAliases( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &geom->num_key_aliases,&geom->sz_key_aliases, + (char **)&geom->key_aliases, + sizeof(XkbKeyAliasRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearColor(char *color_in) +{ +XkbColorPtr color= (XkbColorPtr)color_in; + + if (color->spec) + _XkbFree(color->spec); + return; +} + +void +XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_colors,&geom->sz_colors, + (char **)&geom->colors, + sizeof(XkbColorRec),_XkbClearColor); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &outline->num_points,&outline->sz_points, + (char **)&outline->points, + sizeof(XkbPointRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOutline(char *outline_in) +{ +XkbOutlinePtr outline= (XkbOutlinePtr)outline_in; + + if (outline->points!=NULL) + XkbFreeGeomPoints(outline,0,outline->num_points,True); + return; +} + +void +XkbFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &shape->num_outlines,&shape->sz_outlines, + (char **)&shape->outlines, + sizeof(XkbOutlineRec),_XkbClearOutline); + + return; +} + +/***====================================================================***/ + +static void +_XkbClearShape(char *shape_in) +{ +XkbShapePtr shape= (XkbShapePtr)shape_in; + + if (shape->outlines) + XkbFreeGeomOutlines(shape,0,shape->num_outlines,True); + return; +} + +void +XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_shapes,&geom->sz_shapes, + (char **)&geom->shapes, + sizeof(XkbShapeRec),_XkbClearShape); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbOverlayKeyRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOverlayRow(char *row_in) +{ +XkbOverlayRowPtr row= (XkbOverlayRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomOverlayKeys(row,0,row->num_keys,True); + return; +} + +void +XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &overlay->num_rows,&overlay->sz_rows, + (char **)&overlay->rows, + sizeof(XkbOverlayRowRec),_XkbClearOverlayRow); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOverlay(char *overlay_in) +{ +XkbOverlayPtr overlay= (XkbOverlayPtr)overlay_in; + + if (overlay->rows!=NULL) + XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,True); + return; +} + +void +XkbFreeGeomOverlays(XkbSectionPtr section,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_overlays,§ion->sz_overlays, + (char **)§ion->overlays, + sizeof(XkbOverlayRec),_XkbClearOverlay); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbKeyRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearRow(char *row_in) +{ +XkbRowPtr row= (XkbRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomKeys(row,0,row->num_keys,True); + return; +} + +void +XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_rows,§ion->sz_rows, + (char **)§ion->rows, + sizeof(XkbRowRec),_XkbClearRow); +} + +/***====================================================================***/ + +static void +_XkbClearSection(char *section_in) +{ +XkbSectionPtr section= (XkbSectionPtr)section_in; + + if (section->rows!=NULL) + XkbFreeGeomRows(section,0,section->num_rows,True); + if (section->doodads!=NULL) { + XkbFreeGeomDoodads(section->doodads,section->num_doodads,True); + section->doodads= NULL; + } + return; +} + +void +XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_sections,&geom->sz_sections, + (char **)&geom->sections, + sizeof(XkbSectionRec),_XkbClearSection); + return; +} + +/***====================================================================***/ + +static void +_XkbClearDoodad(char *doodad_in) +{ +XkbDoodadPtr doodad= (XkbDoodadPtr)doodad_in; + + switch (doodad->any.type) { + case XkbTextDoodad: + { + if (doodad->text.text!=NULL) { + _XkbFree(doodad->text.text); + doodad->text.text= NULL; + } + if (doodad->text.font!=NULL) { + _XkbFree(doodad->text.font); + doodad->text.font= NULL; + } + } + break; + case XkbLogoDoodad: + { + if (doodad->logo.logo_name!=NULL) { + _XkbFree(doodad->logo.logo_name); + doodad->logo.logo_name= NULL; + } + } + break; + } + return; +} + +void +XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll) +{ +register int i; +register XkbDoodadPtr doodad; + + if (doodads) { + for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) { + _XkbClearDoodad((char *)doodad); + } + if (freeAll) + _XkbFree(doodads); + } + return; +} + +void +XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap) +{ + if (geom==NULL) + return; + if (freeMap) + which= XkbGeomAllMask; + if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL)) + XkbFreeGeomProperties(geom,0,geom->num_properties,True); + if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL)) + XkbFreeGeomColors(geom,0,geom->num_colors,True); + if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL)) + XkbFreeGeomShapes(geom,0,geom->num_shapes,True); + if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL)) + XkbFreeGeomSections(geom,0,geom->num_sections,True); + if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) { + XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,True); + geom->doodads= NULL; + geom->num_doodads= geom->sz_doodads= 0; + } + if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL)) + XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,True); + if (freeMap) { + if (geom->label_font!=NULL) { + _XkbFree(geom->label_font); + geom->label_font= NULL; + } + _XkbFree(geom); + } + return; +} + +/***====================================================================***/ + +static Status +_XkbGeomAlloc( void ** old, + unsigned short * num, + unsigned short * total, + int num_new, + size_t sz_elem) +{ + if (num_new<1) + return Success; + if ((*old)==NULL) + *num= *total= 0; + + if ((*num)+num_new<=(*total)) + return Success; + + *total= (*num)+num_new; + if ((*old)!=NULL) + (*old)= _XkbRealloc((*old),(*total)*sz_elem); + else (*old)= _XkbCalloc((*total),sz_elem); + if ((*old)==NULL) { + *total= *num= 0; + return BadAlloc; + } + + if (*num>0) { + char *tmp= (char *)(*old); + bzero(&tmp[sz_elem*(*num)],(num_new*sz_elem)); + } + return Success; +} + +#define _XkbAllocProps(g,n) _XkbGeomAlloc((void *)&(g)->properties,\ + &(g)->num_properties,&(g)->sz_properties,\ + (n),sizeof(XkbPropertyRec)) +#define _XkbAllocColors(g,n) _XkbGeomAlloc((void *)&(g)->colors,\ + &(g)->num_colors,&(g)->sz_colors,\ + (n),sizeof(XkbColorRec)) +#define _XkbAllocShapes(g,n) _XkbGeomAlloc((void *)&(g)->shapes,\ + &(g)->num_shapes,&(g)->sz_shapes,\ + (n),sizeof(XkbShapeRec)) +#define _XkbAllocSections(g,n) _XkbGeomAlloc((void *)&(g)->sections,\ + &(g)->num_sections,&(g)->sz_sections,\ + (n),sizeof(XkbSectionRec)) +#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((void *)&(g)->doodads,\ + &(g)->num_doodads,&(g)->sz_doodads,\ + (n),sizeof(XkbDoodadRec)) +#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((void *)&(g)->key_aliases,\ + &(g)->num_key_aliases,&(g)->sz_key_aliases,\ + (n),sizeof(XkbKeyAliasRec)) + +#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((void *)&(s)->outlines,\ + &(s)->num_outlines,&(s)->sz_outlines,\ + (n),sizeof(XkbOutlineRec)) +#define _XkbAllocRows(s,n) _XkbGeomAlloc((void *)&(s)->rows,\ + &(s)->num_rows,&(s)->sz_rows,\ + (n),sizeof(XkbRowRec)) +#define _XkbAllocPoints(o,n) _XkbGeomAlloc((void *)&(o)->points,\ + &(o)->num_points,&(o)->sz_points,\ + (n),sizeof(XkbPointRec)) +#define _XkbAllocKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbKeyRec)) +#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((void *)&(s)->overlays,\ + &(s)->num_overlays,&(s)->sz_overlays,\ + (n),sizeof(XkbOverlayRec)) +#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((void *)&(o)->rows,\ + &(o)->num_rows,&(o)->sz_rows,\ + (n),sizeof(XkbOverlayRowRec)) +#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbOverlayKeyRec)) + +Status +XkbAllocGeomProps(XkbGeometryPtr geom,int nProps) +{ + return _XkbAllocProps(geom,nProps); +} + +Status +XkbAllocGeomColors(XkbGeometryPtr geom,int nColors) +{ + return _XkbAllocColors(geom,nColors); +} + +Status +XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases) +{ + return _XkbAllocKeyAliases(geom,nKeyAliases); +} + +Status +XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes) +{ + return _XkbAllocShapes(geom,nShapes); +} + +Status +XkbAllocGeomSections(XkbGeometryPtr geom,int nSections) +{ + return _XkbAllocSections(geom,nSections); +} + +Status +XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays) +{ + return _XkbAllocOverlays(section,nOverlays); +} + +Status +XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows) +{ + return _XkbAllocOverlayRows(overlay,nRows); +} + +Status +XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys) +{ + return _XkbAllocOverlayKeys(row,nKeys); +} + +Status +XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads) +{ + return _XkbAllocDoodads(geom,nDoodads); +} + +Status +XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads) +{ + return _XkbAllocDoodads(section,nDoodads); +} + +Status +XkbAllocGeomOutlines(XkbShapePtr shape,int nOL) +{ + return _XkbAllocOutlines(shape,nOL); +} + +Status +XkbAllocGeomRows(XkbSectionPtr section,int nRows) +{ + return _XkbAllocRows(section,nRows); +} + +Status +XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts) +{ + return _XkbAllocPoints(ol,nPts); +} + +Status +XkbAllocGeomKeys(XkbRowPtr row,int nKeys) +{ + return _XkbAllocKeys(row,nKeys); +} + +Status +XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes) +{ +XkbGeometryPtr geom; +Status rtrn; + + if (xkb->geom==NULL) { + xkb->geom= _XkbTypedCalloc(1,XkbGeometryRec); + if (!xkb->geom) + return BadAlloc; + } + geom= xkb->geom; + if ((sizes->which&XkbGeomPropertiesMask)&& + ((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomColorsMask)&& + ((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomShapesMask)&& + ((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomSectionsMask)&& + ((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomDoodadsMask)&& + ((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomKeyAliasesMask)&& + ((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) { + goto BAIL; + } + return Success; +BAIL: + XkbFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= NULL; + return rtrn; +} + +/***====================================================================***/ + +XkbPropertyPtr +XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value) +{ +register int i; +register XkbPropertyPtr prop; + + if ((!geom)||(!name)||(!value)) + return NULL; + for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) { + if ((prop->name)&&(strcmp(name,prop->name)==0)) { + if (prop->value) + _XkbFree(prop->value); + prop->value= (char *)_XkbAlloc(strlen(value)+1); + if (prop->value) + strcpy(prop->value,value); + return prop; + } + } + if ((geom->num_properties>=geom->sz_properties)&& + (_XkbAllocProps(geom,1)!=Success)) { + return NULL; + } + prop= &geom->properties[geom->num_properties]; + prop->name= (char *)_XkbAlloc(strlen(name)+1); + if (!name) + return NULL; + strcpy(prop->name,name); + prop->value= (char *)_XkbAlloc(strlen(value)+1); + if (!value) { + _XkbFree(prop->name); + prop->name= NULL; + return NULL; + } + strcpy(prop->value,value); + geom->num_properties++; + return prop; +} + +XkbKeyAliasPtr +XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr) +{ +register int i; +register XkbKeyAliasPtr alias; + + if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0])) + return NULL; + for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) { + if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) { + bzero(alias->real,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + return alias; + } + } + if ((geom->num_key_aliases>=geom->sz_key_aliases)&& + (_XkbAllocKeyAliases(geom,1)!=Success)) { + return NULL; + } + alias= &geom->key_aliases[geom->num_key_aliases]; + bzero(alias,sizeof(XkbKeyAliasRec)); + strncpy(alias->alias,aliasStr,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + geom->num_key_aliases++; + return alias; +} + +XkbColorPtr +XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel) +{ +register int i; +register XkbColorPtr color; + + if ((!geom)||(!spec)) + return NULL; + for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) { + if ((color->spec)&&(strcmp(color->spec,spec)==0)) { + color->pixel= pixel; + return color; + } + } + if ((geom->num_colors>=geom->sz_colors)&& + (_XkbAllocColors(geom,1)!=Success)) { + return NULL; + } + color= &geom->colors[geom->num_colors]; + color->pixel= pixel; + color->spec= (char *)_XkbAlloc(strlen(spec)+1); + if (!color->spec) + return NULL; + strcpy(color->spec,spec); + geom->num_colors++; + return color; +} + +XkbOutlinePtr +XkbAddGeomOutline(XkbShapePtr shape,int sz_points) +{ +XkbOutlinePtr outline; + + if ((!shape)||(sz_points<0)) + return NULL; + if ((shape->num_outlines>=shape->sz_outlines)&& + (_XkbAllocOutlines(shape,1)!=Success)) { + return NULL; + } + outline= &shape->outlines[shape->num_outlines]; + bzero(outline,sizeof(XkbOutlineRec)); + if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success)) + return NULL; + shape->num_outlines++; + return outline; +} + +XkbShapePtr +XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines) +{ +XkbShapePtr shape; +register int i; + + if ((!geom)||(!name)||(sz_outlines<0)) + return NULL; + if (geom->num_shapes>0) { + for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) { + if (name==shape->name) + return shape; + } + } + if ((geom->num_shapes>=geom->sz_shapes)&& + (_XkbAllocShapes(geom,1)!=Success)) + return NULL; + shape= &geom->shapes[geom->num_shapes]; + bzero(shape,sizeof(XkbShapeRec)); + if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success)) + return NULL; + shape->name= name; + shape->primary= shape->approx= NULL; + geom->num_shapes++; + return shape; +} + +XkbKeyPtr +XkbAddGeomKey(XkbRowPtr row) +{ +XkbKeyPtr key; + if (!row) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys++]; + bzero(key,sizeof(XkbKeyRec)); + return key; +} + +XkbRowPtr +XkbAddGeomRow(XkbSectionPtr section,int sz_keys) +{ +XkbRowPtr row; + + if ((!section)||(sz_keys<0)) + return NULL; + if ((section->num_rows>=section->sz_rows)&& + (_XkbAllocRows(section,1)!=Success)) + return NULL; + row= §ion->rows[section->num_rows]; + bzero(row,sizeof(XkbRowRec)); + if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success)) + return NULL; + section->num_rows++; + return row; +} + +XkbSectionPtr +XkbAddGeomSection( XkbGeometryPtr geom, + Atom name, + int sz_rows, + int sz_doodads, + int sz_over) +{ +register int i; +XkbSectionPtr section; + + if ((!geom)||(name==None)||(sz_rows<0)) + return NULL; + for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) { + if (section->name!=name) + continue; + if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))|| + ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))|| + ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success))) + return NULL; + return section; + } + if ((geom->num_sections>=geom->sz_sections)&& + (_XkbAllocSections(geom,1)!=Success)) + return NULL; + section= &geom->sections[geom->num_sections]; + if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success)) + return NULL; + if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) { + if (section->rows) { + _XkbFree(section->rows); + section->rows= NULL; + section->sz_rows= section->num_rows= 0; + } + return NULL; + } + section->name= name; + geom->num_sections++; + return section; +} + +XkbDoodadPtr +XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name) +{ +XkbDoodadPtr old,doodad; +register int i,nDoodads; + + if ((!geom)||(name==None)) + return NULL; + if ((section!=NULL)&&(section->num_doodads>0)) { + old= section->doodads; + nDoodads= section->num_doodads; + } + else { + old= geom->doodads; + nDoodads= geom->num_doodads; + } + for (i=0,doodad=old;i<nDoodads;i++,doodad++) { + if (doodad->any.name==name) + return doodad; + } + if (section) { + if ((section->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(section,1)!=Success)) { + return NULL; + } + doodad= §ion->doodads[section->num_doodads++]; + } + else { + if ((geom->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(geom,1)!=Success)) + return NULL; + doodad= &geom->doodads[geom->num_doodads++]; + } + bzero(doodad,sizeof(XkbDoodadRec)); + doodad->any.name= name; + return doodad; +} + +XkbOverlayKeyPtr +XkbAddGeomOverlayKey( XkbOverlayPtr overlay, + XkbOverlayRowPtr row, + char * over, + char * under) +{ +register int i; +XkbOverlayKeyPtr key; +XkbSectionPtr section; +XkbRowPtr row_under; +Bool found; + + if ((!overlay)||(!row)||(!over)||(!under)) + return NULL; + section= overlay->section_under; + if (row->row_under>=section->num_rows) + return NULL; + row_under= §ion->rows[row->row_under]; + for (i=0,found=False;i<row_under->num_keys;i++) { + if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) { + found= True; + break; + } + } + if (!found) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys]; + strncpy(key->under.name,under,XkbKeyNameLength); + strncpy(key->over.name,over,XkbKeyNameLength); + row->num_keys++; + return key; +} + +XkbOverlayRowPtr +XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys) +{ +register int i; +XkbOverlayRowPtr row; + + if ((!overlay)||(sz_keys<0)) + return NULL; + if (row_under>=overlay->section_under->num_rows) + return NULL; + for (i=0;i<overlay->num_rows;i++) { + if (overlay->rows[i].row_under==row_under) { + row= &overlay->rows[i]; + if ((row->sz_keys<sz_keys)&& + (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) { + return NULL; + } + return &overlay->rows[i]; + } + } + if ((overlay->num_rows>=overlay->sz_rows)&& + (_XkbAllocOverlayRows(overlay,1)!=Success)) + return NULL; + row= &overlay->rows[overlay->num_rows]; + bzero(row,sizeof(XkbOverlayRowRec)); + if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) + return NULL; + row->row_under= row_under; + overlay->num_rows++; + return row; +} + +XkbOverlayPtr +XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows) +{ +register int i; +XkbOverlayPtr overlay; + + if ((!section)||(name==None)||(sz_rows==0)) + return NULL; + + for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) { + if (overlay->name==name) { + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + return overlay; + } + } + if ((section->num_overlays>=section->sz_overlays)&& + (_XkbAllocOverlays(section,1)!=Success)) + return NULL; + overlay= §ion->overlays[section->num_overlays]; + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + overlay->name= name; + overlay->section_under= section; + section->num_overlays++; + return overlay; +} diff --git a/xorg-server/xkb/XKBMAlloc.c b/xorg-server/xkb/XKBMAlloc.c new file mode 100644 index 000000000..178b5b89a --- /dev/null +++ b/xorg-server/xkb/XKBMAlloc.c @@ -0,0 +1,901 @@ +/************************************************************ +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 <dix-config.h> +#elif defined(HAVE_CONFIG_H) +#include <config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include <X11/keysym.h> +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> + +/***====================================================================***/ + +Status +XkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes) +{ +register int i; +XkbClientMapPtr map; + + if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes))) + return BadValue; + if ((which&XkbKeySymsMask)&& + ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code))) { + DebugF("bad keycode (%d,%d) in XkbAllocClientMap\n", + xkb->min_key_code,xkb->max_key_code); + return BadValue; + } + + if (xkb->map==NULL) { + map= _XkbTypedCalloc(1,XkbClientMapRec); + if (map==NULL) + return BadAlloc; + xkb->map= map; + } + else map= xkb->map; + + if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) { + if (map->types==NULL) { + map->types= _XkbTypedCalloc(nTotalTypes,XkbKeyTypeRec); + if (map->types==NULL) + return BadAlloc; + map->num_types= 0; + map->size_types= nTotalTypes; + } + else if (map->size_types<nTotalTypes) { + XkbKeyTypeRec *prev_types = map->types; + + map->types= _XkbTypedRealloc(map->types,nTotalTypes,XkbKeyTypeRec); + if (map->types==NULL) { + _XkbFree(prev_types); + map->num_types= map->size_types= 0; + return BadAlloc; + } + map->size_types= nTotalTypes; + bzero(&map->types[map->num_types], + ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec))); + } + } + if (which&XkbKeySymsMask) { + int nKeys= XkbNumKeys(xkb); + if (map->syms==NULL) { + map->size_syms= (nKeys*15)/10; + map->syms= _XkbTypedCalloc(map->size_syms,KeySym); + if (!map->syms) { + map->size_syms= 0; + return BadAlloc; + } + map->num_syms= 1; + map->syms[0]= NoSymbol; + } + if (map->key_sym_map==NULL) { + i= xkb->max_key_code+1; + map->key_sym_map= _XkbTypedCalloc(i,XkbSymMapRec); + if (map->key_sym_map==NULL) + return BadAlloc; + } + } + if (which&XkbModifierMapMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (map->modmap==NULL) { + i= xkb->max_key_code+1; + map->modmap= _XkbTypedCalloc(i,unsigned char); + if (map->modmap==NULL) + return BadAlloc; + } + } + return Success; +} + +Status +XkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions) +{ +register int i; +XkbServerMapPtr map; + + if (xkb==NULL) + return BadMatch; + if (xkb->server==NULL) { + map= _XkbTypedCalloc(1,XkbServerMapRec); + if (map==NULL) + return BadAlloc; + for (i=0;i<XkbNumVirtualMods;i++) { + map->vmods[i]= XkbNoModifierMask; + } + xkb->server= map; + } + else map= xkb->server; + if (which&XkbExplicitComponentsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (map->explicit==NULL) { + i= xkb->max_key_code+1; + map->explicit= _XkbTypedCalloc(i,unsigned char); + if (map->explicit==NULL) + return BadAlloc; + } + } + if (which&XkbKeyActionsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (nNewActions<1) + nNewActions= 1; + if (map->acts==NULL) { + map->acts= _XkbTypedCalloc((nNewActions+1),XkbAction); + if (map->acts==NULL) + return BadAlloc; + map->num_acts= 1; + map->size_acts= nNewActions+1; + } + else if ((map->size_acts-map->num_acts)<nNewActions) { + unsigned need; + XkbAction *prev_acts = map->acts; + need= map->num_acts+nNewActions; + map->acts= _XkbTypedRealloc(map->acts,need,XkbAction); + if (map->acts==NULL) { + _XkbFree(prev_acts); + map->num_acts= map->size_acts= 0; + return BadAlloc; + } + map->size_acts= need; + bzero(&map->acts[map->num_acts], + ((map->size_acts-map->num_acts)*sizeof(XkbAction))); + } + if (map->key_acts==NULL) { + i= xkb->max_key_code+1; + map->key_acts= _XkbTypedCalloc(i,unsigned short); + if (map->key_acts==NULL) + return BadAlloc; + } + } + if (which&XkbKeyBehaviorsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (map->behaviors==NULL) { + i= xkb->max_key_code+1; + map->behaviors= _XkbTypedCalloc(i,XkbBehavior); + if (map->behaviors==NULL) + return BadAlloc; + } + } + if (which&XkbVirtualModMapMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (map->vmodmap==NULL) { + i= xkb->max_key_code+1; + map->vmodmap= _XkbTypedCalloc(i,unsigned short); + if (map->vmodmap==NULL) + return BadAlloc; + } + } + return Success; +} + +/***====================================================================***/ + +static Status +XkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into) +{ + if ((!from)||(!into)) + return BadMatch; + if (into->map) { + _XkbFree(into->map); + into->map= NULL; + } + if (into->preserve) { + _XkbFree(into->preserve); + into->preserve= NULL; + } + if (into->level_names) { + _XkbFree(into->level_names); + into->level_names= NULL; + } + *into= *from; + if ((from->map)&&(into->map_count>0)) { + into->map= _XkbTypedCalloc(into->map_count,XkbKTMapEntryRec); + if (!into->map) + return BadAlloc; + memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec)); + } + if ((from->preserve)&&(into->map_count>0)) { + into->preserve= _XkbTypedCalloc(into->map_count,XkbModsRec); + if (!into->preserve) + return BadAlloc; + memcpy(into->preserve,from->preserve, + into->map_count*sizeof(XkbModsRec)); + } + if ((from->level_names)&&(into->num_levels>0)) { + into->level_names= _XkbTypedCalloc(into->num_levels,Atom); + if (!into->level_names) + return BadAlloc; + memcpy(into->level_names,from->level_names, + into->num_levels*sizeof(Atom)); + } + return Success; +} + +Status +XkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types) +{ +register int i,rtrn; + + if ((!from)||(!into)||(num_types<0)) + return BadMatch; + for (i=0;i<num_types;i++) { + if ((rtrn= XkbCopyKeyType(from++,into++))!=Success) + return rtrn; + } + return Success; +} + +Status +XkbResizeKeyType( XkbDescPtr xkb, + int type_ndx, + int map_count, + Bool want_preserve, + int new_num_lvls) +{ +XkbKeyTypePtr type; +KeyCode matchingKeys[XkbMaxKeyCount],nMatchingKeys; + + if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)|| + (new_num_lvls<1)) + return BadValue; + switch (type_ndx) { + case XkbOneLevelIndex: + if (new_num_lvls!=1) + return BadMatch; + break; + case XkbTwoLevelIndex: + case XkbAlphabeticIndex: + case XkbKeypadIndex: + if (new_num_lvls!=2) + return BadMatch; + break; + } + type= &xkb->map->types[type_ndx]; + if (map_count==0) { + if (type->map!=NULL) + _XkbFree(type->map); + type->map= NULL; + if (type->preserve!=NULL) + _XkbFree(type->preserve); + type->preserve= NULL; + type->map_count= 0; + } + else { + XkbKTMapEntryRec *prev_map = type->map; + + if ((map_count>type->map_count)||(type->map==NULL)) + type->map=_XkbTypedRealloc(type->map,map_count,XkbKTMapEntryRec); + if (!type->map) { + if (prev_map) + _XkbFree(prev_map); + return BadAlloc; + } + if (want_preserve) { + XkbModsRec *prev_preserve = type->preserve; + + if ((map_count>type->map_count)||(type->preserve==NULL)) { + type->preserve= _XkbTypedRealloc(type->preserve,map_count, + XkbModsRec); + } + if (!type->preserve) { + if (prev_preserve) + _XkbFree(prev_preserve); + return BadAlloc; + } + } + else if (type->preserve!=NULL) { + _XkbFree(type->preserve); + type->preserve= NULL; + } + type->map_count= map_count; + } + + if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) { + Atom * prev_level_names = type->level_names; + + type->level_names=_XkbTypedRealloc(type->level_names,new_num_lvls,Atom); + if (!type->level_names) { + if (prev_level_names) + _XkbFree(prev_level_names); + return BadAlloc; + } + } + /* + * Here's the theory: + * If the width of the type changed, we might have to resize the symbol + * maps for any keys that use the type for one or more groups. This is + * expensive, so we'll try to cull out any keys that are obviously okay: + * In any case: + * - keys that have a group width <= the old width are okay (because + * they could not possibly have been associated with the old type) + * If the key type increased in size: + * - keys that already have a group width >= to the new width are okay + * + keys that have a group width >= the old width but < the new width + * might have to be enlarged. + * If the key type decreased in size: + * - keys that have a group width > the old width don't have to be + * resized (because they must have some other wider type associated + * with some group). + * + keys that have a group width == the old width might have to be + * shrunk. + * The possibilities marked with '+' require us to examine the key types + * associated with each group for the key. + */ + bzero(matchingKeys,XkbMaxKeyCount*sizeof(KeyCode)); + nMatchingKeys= 0; + if (new_num_lvls>type->num_levels) { + int nTotal; + KeySym * newSyms; + int width,match,nResize; + register int i,g,nSyms; + + nResize= 0; + for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + width= XkbKeyGroupsWidth(xkb,i); + if (width<type->num_levels) + continue; + for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) { + if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) { + matchingKeys[nMatchingKeys++]= i; + match= 1; + } + } + if ((!match)||(width>=new_num_lvls)) + nTotal+= XkbKeyNumSyms(xkb,i); + else { + nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls; + nResize++; + } + } + if (nResize>0) { + int nextMatch; + xkb->map->size_syms= (nTotal*15)/10; + newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym); + if (newSyms==NULL) + return BadAlloc; + nextMatch= 0; + nSyms= 1; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (matchingKeys[nextMatch]==i) { + KeySym *pOld; + nextMatch++; + width= XkbKeyGroupsWidth(xkb,i); + pOld= XkbKeySymsPtr(xkb,i); + for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) { + memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g], + width*sizeof(KeySym)); + } + xkb->map->key_sym_map[i].offset= nSyms; + nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls; + } + else { + memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i), + XkbKeyNumSyms(xkb,i)*sizeof(KeySym)); + xkb->map->key_sym_map[i].offset= nSyms; + nSyms+= XkbKeyNumSyms(xkb,i); + } + } + type->num_levels= new_num_lvls; + _XkbFree(xkb->map->syms); + xkb->map->syms= newSyms; + xkb->map->num_syms= nSyms; + return Success; + } + } + else if (new_num_lvls<type->num_levels) { + int width,match; + register int g,i; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + width= XkbKeyGroupsWidth(xkb,i); + if (width<type->num_levels) + continue; + for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) { + if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) { + matchingKeys[nMatchingKeys++]= i; + match= 1; + } + } + } + } + if (nMatchingKeys>0) { + int key,firstClear; + register int i,g; + if (new_num_lvls>type->num_levels) + firstClear= type->num_levels; + else firstClear= new_num_lvls; + for (i=0;i<nMatchingKeys;i++) { + KeySym * pSyms; + int width,nClear; + + key= matchingKeys[i]; + width= XkbKeyGroupsWidth(xkb,key); + nClear= width-firstClear; + pSyms= XkbKeySymsPtr(xkb,key); + for (g=XkbKeyNumGroups(xkb,key)-1;g>=0;g--) { + if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) { + if (nClear>0) + bzero(&pSyms[g*width+firstClear],nClear*sizeof(KeySym)); + } + } + } + } + type->num_levels= new_num_lvls; + return Success; +} + +KeySym * +XkbResizeKeySyms(XkbDescPtr xkb,int key,int needed) +{ +register int i,nSyms,nKeySyms; +unsigned nOldSyms; +KeySym *newSyms; + + if (needed==0) { + xkb->map->key_sym_map[key].offset= 0; + return xkb->map->syms; + } + nOldSyms= XkbKeyNumSyms(xkb,key); + if (nOldSyms>=(unsigned)needed) { + return XkbKeySymsPtr(xkb,key); + } + if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) { + if (nOldSyms>0) { + memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key), + nOldSyms*sizeof(KeySym)); + } + if ((needed-nOldSyms)>0) { + bzero(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb,key)], + (needed-nOldSyms)*sizeof(KeySym)); + } + xkb->map->key_sym_map[key].offset = xkb->map->num_syms; + xkb->map->num_syms+= needed; + return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; + } + xkb->map->size_syms+= (needed>32?needed:32); + newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym); + if (newSyms==NULL) + return NULL; + newSyms[0]= NoSymbol; + nSyms = 1; + for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) { + int nCopy; + + nCopy= nKeySyms= XkbKeyNumSyms(xkb,i); + if ((nKeySyms==0)&&(i!=key)) + continue; + if (i==key) + nKeySyms= needed; + if (nCopy!=0) + memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym)); + if (nKeySyms>nCopy) + bzero(&newSyms[nSyms+nCopy],(nKeySyms-nCopy)*sizeof(KeySym)); + xkb->map->key_sym_map[i].offset = nSyms; + nSyms+= nKeySyms; + } + _XkbFree(xkb->map->syms); + xkb->map->syms = newSyms; + xkb->map->num_syms = nSyms; + return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; +} + +static unsigned +_ExtendRange( unsigned int old_flags, + unsigned int flag, + KeyCode newKC, + KeyCode * old_min, + unsigned char * old_num) +{ + if ((old_flags&flag)==0) { + old_flags|= flag; + *old_min= newKC; + *old_num= 1; + } + else { + int last= (*old_min)+(*old_num)-1; + if (newKC<*old_min) { + *old_min= newKC; + *old_num= (last-newKC)+1; + } + else if (newKC>last) { + *old_num= (newKC-(*old_min))+1; + } + } + return old_flags; +} + +Status +XkbChangeKeycodeRange( XkbDescPtr xkb, + int minKC, + int maxKC, + XkbChangesPtr changes) +{ +int tmp; + + if ((!xkb)||(minKC<XkbMinLegalKeyCode)||(maxKC>XkbMaxLegalKeyCode)) + return BadValue; + if (minKC>maxKC) + return BadMatch; + if (minKC<xkb->min_key_code) { + if (changes) + changes->map.min_key_code= minKC; + tmp= xkb->min_key_code-minKC; + if (xkb->map) { + if (xkb->map->key_sym_map) { + bzero((char *)&xkb->map->key_sym_map[minKC], + tmp*sizeof(XkbSymMapRec)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeySymsMask,minKC, + &changes->map.first_key_sym, + &changes->map.num_key_syms); + } + } + if (xkb->map->modmap) { + bzero((char *)&xkb->map->modmap[minKC],tmp); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbModifierMapMask,minKC, + &changes->map.first_modmap_key, + &changes->map.num_modmap_keys); + } + } + } + if (xkb->server) { + if (xkb->server->behaviors) { + bzero((char *)&xkb->server->behaviors[minKC], + tmp*sizeof(XkbBehavior)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyBehaviorsMask,minKC, + &changes->map.first_key_behavior, + &changes->map.num_key_behaviors); + } + } + if (xkb->server->key_acts) { + bzero((char *)&xkb->server->key_acts[minKC], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyActionsMask,minKC, + &changes->map.first_key_act, + &changes->map.num_key_acts); + } + } + if (xkb->server->vmodmap) { + bzero((char *)&xkb->server->vmodmap[minKC], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbVirtualModMapMask,minKC, + &changes->map.first_modmap_key, + &changes->map.num_vmodmap_keys); + } + } + } + if ((xkb->names)&&(xkb->names->keys)) { + bzero((char *)&xkb->names->keys[minKC],tmp*sizeof(XkbKeyNameRec)); + if (changes) { + changes->names.changed= _ExtendRange(changes->names.changed, + XkbKeyNamesMask,minKC, + &changes->names.first_key, + &changes->names.num_keys); + } + } + xkb->min_key_code= minKC; + } + if (maxKC>xkb->max_key_code) { + if (changes) + changes->map.max_key_code= maxKC; + tmp= maxKC-xkb->max_key_code; + if (xkb->map) { + if (xkb->map->key_sym_map) { + XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map; + + xkb->map->key_sym_map= _XkbTypedRealloc(xkb->map->key_sym_map, + (maxKC+1),XkbSymMapRec); + if (!xkb->map->key_sym_map) { + _XkbFree(prev_key_sym_map); + return BadAlloc; + } + bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code], + tmp*sizeof(XkbSymMapRec)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeySymsMask,maxKC, + &changes->map.first_key_sym, + &changes->map.num_key_syms); + } + } + if (xkb->map->modmap) { + unsigned char *prev_modmap = xkb->map->modmap; + + xkb->map->modmap= _XkbTypedRealloc(xkb->map->modmap, + (maxKC+1),unsigned char); + if (!xkb->map->modmap) { + _XkbFree(prev_modmap); + return BadAlloc; + } + bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbModifierMapMask,maxKC, + &changes->map.first_modmap_key, + &changes->map.num_modmap_keys); + } + } + } + if (xkb->server) { + if (xkb->server->behaviors) { + XkbBehavior *prev_behaviors = xkb->server->behaviors; + + xkb->server->behaviors=_XkbTypedRealloc(xkb->server->behaviors, + (maxKC+1),XkbBehavior); + if (!xkb->server->behaviors) { + _XkbFree(prev_behaviors); + return BadAlloc; + } + bzero((char *)&xkb->server->behaviors[xkb->max_key_code], + tmp*sizeof(XkbBehavior)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyBehaviorsMask,maxKC, + &changes->map.first_key_behavior, + &changes->map.num_key_behaviors); + } + } + if (xkb->server->key_acts) { + unsigned short *prev_key_acts = xkb->server->key_acts; + + xkb->server->key_acts= _XkbTypedRealloc(xkb->server->key_acts, + (maxKC+1),unsigned short); + if (!xkb->server->key_acts) { + _XkbFree(prev_key_acts); + return BadAlloc; + } + bzero((char *)&xkb->server->key_acts[xkb->max_key_code], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyActionsMask,maxKC, + &changes->map.first_key_act, + &changes->map.num_key_acts); + } + } + if (xkb->server->vmodmap) { + unsigned short *prev_vmodmap = xkb->server->vmodmap; + + xkb->server->vmodmap= _XkbTypedRealloc(xkb->server->vmodmap, + (maxKC+1),unsigned short); + if (!xkb->server->vmodmap) { + _XkbFree(prev_vmodmap); + return BadAlloc; + } + bzero((char *)&xkb->server->vmodmap[xkb->max_key_code], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbVirtualModMapMask,maxKC, + &changes->map.first_modmap_key, + &changes->map.num_vmodmap_keys); + } + } + } + if ((xkb->names)&&(xkb->names->keys)) { + XkbKeyNameRec *prev_keys = xkb->names->keys; + + xkb->names->keys= _XkbTypedRealloc(xkb->names->keys, + (maxKC+1),XkbKeyNameRec); + if (!xkb->names->keys) { + _XkbFree(prev_keys); + return BadAlloc; + } + bzero((char *)&xkb->names->keys[xkb->max_key_code], + tmp*sizeof(XkbKeyNameRec)); + if (changes) { + changes->names.changed= _ExtendRange(changes->names.changed, + XkbKeyNamesMask,maxKC, + &changes->names.first_key, + &changes->names.num_keys); + } + } + xkb->max_key_code= maxKC; + } + return Success; +} + +XkbAction * +XkbResizeKeyActions(XkbDescPtr xkb,int key,int needed) +{ +register int i,nActs; +XkbAction *newActs; + + if (needed==0) { + xkb->server->key_acts[key]= 0; + return NULL; + } + if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed)) + return XkbKeyActionsPtr(xkb,key); + if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) { + xkb->server->key_acts[key]= xkb->server->num_acts; + xkb->server->num_acts+= needed; + return &xkb->server->acts[xkb->server->key_acts[key]]; + } + xkb->server->size_acts= xkb->server->num_acts+needed+8; + newActs = _XkbTypedCalloc(xkb->server->size_acts,XkbAction); + if (newActs==NULL) + return NULL; + newActs[0].type = XkbSA_NoAction; + nActs = 1; + for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) { + int nKeyActs,nCopy; + + if ((xkb->server->key_acts[i]==0)&&(i!=key)) + continue; + + nCopy= nKeyActs= XkbKeyNumActions(xkb,i); + if (i==key) { + nKeyActs= needed; + if (needed<nCopy) + nCopy= needed; + } + + if (nCopy>0) + memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i), + nCopy*sizeof(XkbAction)); + if (nCopy<nKeyActs) + bzero(&newActs[nActs+nCopy],(nKeyActs-nCopy)*sizeof(XkbAction)); + xkb->server->key_acts[i]= nActs; + nActs+= nKeyActs; + } + _XkbFree(xkb->server->acts); + xkb->server->acts = newActs; + xkb->server->num_acts= nActs; + return &xkb->server->acts[xkb->server->key_acts[key]]; +} + +void +XkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap) +{ +XkbClientMapPtr map; + + if ((xkb==NULL)||(xkb->map==NULL)) + return; + if (freeMap) + what= XkbAllClientInfoMask; + map= xkb->map; + if (what&XkbKeyTypesMask) { + if (map->types!=NULL) { + if (map->num_types>0) { + register int i; + XkbKeyTypePtr type; + for (i=0,type=map->types;i<map->num_types;i++,type++) { + if (type->map!=NULL) { + _XkbFree(type->map); + type->map= NULL; + } + if (type->preserve!=NULL) { + _XkbFree(type->preserve); + type->preserve= NULL; + } + type->map_count= 0; + if (type->level_names!=NULL) { + _XkbFree(type->level_names); + type->level_names= NULL; + } + } + } + _XkbFree(map->types); + map->num_types= map->size_types= 0; + map->types= NULL; + } + } + if (what&XkbKeySymsMask) { + if (map->key_sym_map!=NULL) { + _XkbFree(map->key_sym_map); + map->key_sym_map= NULL; + } + if (map->syms!=NULL) { + _XkbFree(map->syms); + map->size_syms= map->num_syms= 0; + map->syms= NULL; + } + } + if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) { + _XkbFree(map->modmap); + map->modmap= NULL; + } + if (freeMap) { + _XkbFree(xkb->map); + xkb->map= NULL; + } + return; +} + +void +XkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap) +{ +XkbServerMapPtr map; + + if ((xkb==NULL)||(xkb->server==NULL)) + return; + if (freeMap) + what= XkbAllServerInfoMask; + map= xkb->server; + if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) { + _XkbFree(map->explicit); + map->explicit= NULL; + } + if (what&XkbKeyActionsMask) { + if (map->key_acts!=NULL) { + _XkbFree(map->key_acts); + map->key_acts= NULL; + } + if (map->acts!=NULL) { + _XkbFree(map->acts); + map->num_acts= map->size_acts= 0; + map->acts= NULL; + } + } + if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) { + _XkbFree(map->behaviors); + map->behaviors= NULL; + } + if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) { + _XkbFree(map->vmodmap); + map->vmodmap= NULL; + } + + if (freeMap) { + _XkbFree(xkb->server); + xkb->server= NULL; + } + return; +} diff --git a/xorg-server/xkb/XKBMisc.c b/xorg-server/xkb/XKBMisc.c new file mode 100644 index 000000000..ac81395d6 --- /dev/null +++ b/xorg-server/xkb/XKBMisc.c @@ -0,0 +1,795 @@ +/************************************************************ +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 <dix-config.h> +#elif defined(HAVE_CONFIG_H) +#include <config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include <X11/keysym.h> +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> + +/***====================================================================***/ + +#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) +#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) + +int +XkbKeyTypesForCoreSymbols( XkbDescPtr xkb, + int map_width, + KeySym * core_syms, + unsigned int protected, + int * types_inout, + KeySym * xkb_syms_rtrn) +{ +register int i; +unsigned int empty; +int nSyms[XkbNumKbdGroups]; +int nGroups,tmp,groupsWidth; + + /* Section 12.2 of the protocol describes this process in more detail */ + /* Step 1: find the # of symbols in the core mapping per group */ + groupsWidth= 2; + for (i=0;i<XkbNumKbdGroups;i++) { + if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) { + nSyms[i]= xkb->map->types[types_inout[i]].num_levels; + if (nSyms[i]>groupsWidth) + groupsWidth= nSyms[i]; + } + else { + types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */ + nSyms[i]= 2; + } + } + if (nSyms[XkbGroup1Index]<2) + nSyms[XkbGroup1Index]= 2; + if (nSyms[XkbGroup2Index]<2) + nSyms[XkbGroup2Index]= 2; + /* Step 2: Copy the symbols from the core ordering to XKB ordering */ + /* symbols in the core are in the order: */ + /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0); + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1); + for (i=2;i<nSyms[XkbGroup1Index];i++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i); + } + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2); + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3); + tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */ + for (i=2;i<nSyms[XkbGroup2Index];i++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i); + } + tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index]; + if ((tmp>=map_width)&& + ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) { + nSyms[XkbGroup3Index]= 0; + nSyms[XkbGroup4Index]= 0; + nGroups= 2; + } + else { + nGroups= 3; + for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp); + } + if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) { + nGroups= 4; + for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp); + } + } + else { + nSyms[XkbGroup4Index]= 0; + } + } + /* steps 3&4: alphanumeric expansion, assign canonical types */ + empty= 0; + for (i=0;i<nGroups;i++) { + KeySym *syms; + syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; + if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) { + KeySym upper,lower; + XConvertCase(syms[0],&lower,&upper); + if (upper!=lower) { + xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower; + xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper; + if ((protected&(1<<i))==0) + types_inout[i]= XkbAlphabeticIndex; + } + else if ((protected&(1<<i))==0) { + types_inout[i]= XkbOneLevelIndex; + /* nSyms[i]= 1;*/ + } + } + if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) { + if (IsKeypadKey(syms[0])||IsKeypadKey(syms[1])) + types_inout[i]= XkbKeypadIndex; + else { + KeySym upper,lower; + XConvertCase(syms[0],&lower,&upper); + if ((syms[0]==lower)&&(syms[1]==upper)) + types_inout[i]= XkbAlphabeticIndex; + } + } + if (syms[0]==NoSymbol) { + register int n; + Bool found; + for (n=1,found=False;(!found)&&(n<nSyms[i]);n++) { + found= (syms[n]!=NoSymbol); + } + if (!found) + empty|= (1<<i); + } + } + /* step 5: squoosh out empty groups */ + if (empty) { + for (i=nGroups-1;i>=0;i--) { + if (((empty&(1<<i))==0)||(protected&(1<<i))) + break; + nGroups--; + } + } + if (nGroups<1) + return 0; + + /* step 6: replicate group 1 into group two, if necessary */ + if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) { + if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) { + nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index]; + types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index]; + memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn, + 2*sizeof(KeySym)); + } + else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) { + memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]], + (char *)xkb_syms_rtrn, + nSyms[XkbGroup1Index]*sizeof(KeySym)); + } + } + + /* step 7: check for all groups identical or all width 1 + * + * Special feature: if group 1 has an explicit type and all other groups + * have canonical types with same symbols, we assume it's info lost from + * the core replication. + */ + if (nGroups>1) { + Bool sameType,allOneLevel, canonical = True; + allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1); + for (i=1,sameType=True;(allOneLevel||sameType)&&(i<nGroups);i++) { + sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index])); + if (allOneLevel) + allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1); + if (types_inout[i] > XkbLastRequiredType) + canonical = False; + } + if (((sameType) || canonical)&& + (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){ + register int s; + Bool identical; + for (i=1,identical=True;identical&&(i<nGroups);i++) { + KeySym *syms; + syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; + for (s=0;identical&&(s<nSyms[i]);s++) { + if (syms[s]!=xkb_syms_rtrn[s]) + identical= False; + } + } + if (identical) + nGroups= 1; + } + if (allOneLevel && (nGroups>1)) { + KeySym *syms; + syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; + nSyms[XkbGroup1Index]= 1; + for (i=1;i<nGroups;i++) { + xkb_syms_rtrn[i]= syms[0]; + syms+= nSyms[i]; + nSyms[i]= 1; + } + } + } + return nGroups; +} + +static XkbSymInterpretPtr +_XkbFindMatchingInterp( XkbDescPtr xkb, + KeySym sym, + unsigned int real_mods, + unsigned int level) +{ +register unsigned i; +XkbSymInterpretPtr interp,rtrn; +CARD8 mods; + + rtrn= NULL; + interp= xkb->compat->sym_interpret; + for (i=0;i<xkb->compat->num_si;i++,interp++) { + if ((interp->sym==NoSymbol)||(sym==interp->sym)) { + int match; + if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0)) + mods= real_mods; + else mods= 0; + switch (interp->match&XkbSI_OpMask) { + case XkbSI_NoneOf: + match= ((interp->mods&mods)==0); + break; + case XkbSI_AnyOfOrNone: + match= ((mods==0)||((interp->mods&mods)!=0)); + break; + case XkbSI_AnyOf: + match= ((interp->mods&mods)!=0); + break; + case XkbSI_AllOf: + match= ((interp->mods&mods)==interp->mods); + break; + case XkbSI_Exactly: + match= (interp->mods==mods); + break; + default: + match= 0; + break; + } + if (match) { + if (interp->sym!=NoSymbol) { + return interp; + } + else if (rtrn==NULL) { + rtrn= interp; + } + } + } + } + return rtrn; +} + +static void +_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey) +{ +KeyCode last; + + last= (*pFirst)+(*pNum); + if (newKey<*pFirst) { + *pFirst= newKey; + *pNum= (last-newKey)+1; + } + else if (newKey>last) { + *pNum= (last-*pFirst)+1; + } + return; +} + +static void +_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) +{ +unsigned tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (act->mods.flags&XkbSA_UseModMapMods) + act->mods.real_mods= act->mods.mask= mods; + if ((tmp= XkbModActionVMods(&act->mods))!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->mods.mask|= tmp; + } + break; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_UseModMapMods) + act->iso.real_mods= act->iso.mask= mods; + if ((tmp= XkbModActionVMods(&act->iso))!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->iso.mask|= tmp; + } + break; + } + return; +} + +#define IBUF_SIZE 8 + +Bool +XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes) +{ +KeySym * syms; +unsigned char explicit,mods; +XkbSymInterpretPtr *interps,ibuf[IBUF_SIZE]; +int n,nSyms,found; +unsigned changed,tmp; + + if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)|| + (!xkb->compat)||(!xkb->compat->sym_interpret)|| + (key<xkb->min_key_code)||(key>xkb->max_key_code)) { + return False; + } + if (((!xkb->server)||(!xkb->server->key_acts))&& + (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) { + return False; + } + changed= 0; /* keeps track of what has changed in _this_ call */ + explicit= xkb->server->explicit[key]; + if (explicit&XkbExplicitInterpretMask) /* nothing to do */ + return True; + mods= (xkb->map->modmap?xkb->map->modmap[key]:0); + nSyms= XkbKeyNumSyms(xkb,key); + syms= XkbKeySymsPtr(xkb,key); + if (nSyms>IBUF_SIZE) { + interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr); + if (interps==NULL) { + interps= ibuf; + nSyms= IBUF_SIZE; + } + } + else { + interps= ibuf; + } + found= 0; + for (n=0;n<nSyms;n++) { + unsigned level= (n%XkbKeyGroupsWidth(xkb,key)); + interps[n]= NULL; + if (syms[n]!=NoSymbol) { + interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level); + if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction) + found++; + else interps[n]= NULL; + } + } + /* 1/28/96 (ef) -- XXX! WORKING HERE */ + if (!found) { + if (xkb->server->key_acts[key]!=0) { + xkb->server->key_acts[key]= 0; + changed|= XkbKeyActionsMask; + } + } + else { + XkbAction *pActs; + unsigned int new_vmodmask; + changed|= XkbKeyActionsMask; + pActs= XkbResizeKeyActions(xkb,key,nSyms); + if (!pActs) { + if (nSyms > IBUF_SIZE) + xfree(interps); + return False; + } + new_vmodmask= 0; + for (n=0;n<nSyms;n++) { + if (interps[n]) { + unsigned effMods; + + pActs[n]= *((XkbAction *)&interps[n]->act); + if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) { + effMods= mods; + if (interps[n]->virtual_mod!=XkbNoModifier) + new_vmodmask|= (1<<interps[n]->virtual_mod); + } + else effMods= 0; + _XkbSetActionKeyMods(xkb,&pActs[n],effMods); + } + else pActs[n].type= XkbSA_NoAction; + } + if (((explicit&XkbExplicitVModMapMask)==0)&& + (xkb->server->vmodmap[key]!=new_vmodmask)) { + changed|= XkbVirtualModMapMask; + xkb->server->vmodmap[key]= new_vmodmask; + } + if (interps[0]) { + if ((interps[0]->flags&XkbSI_LockingKey)&& + ((explicit&XkbExplicitBehaviorMask)==0)) { + xkb->server->behaviors[key].type= XkbKB_Lock; + changed|= XkbKeyBehaviorsMask; + } + if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { + CARD8 old; + old= xkb->ctrls->per_key_repeat[key/8]; + if (interps[0]->flags&XkbSI_AutoRepeat) + xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); + else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8)); + if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; + } + } + } + if ((!found)||(interps[0]==NULL)) { + if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { + CARD8 old; + old= xkb->ctrls->per_key_repeat[key/8]; + xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); + if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; + } + if (((explicit&XkbExplicitBehaviorMask)==0)&& + (xkb->server->behaviors[key].type==XkbKB_Lock)) { + xkb->server->behaviors[key].type= XkbKB_Default; + changed|= XkbKeyBehaviorsMask; + } + } + if (changes) { + XkbMapChangesPtr mc; + mc= &changes->map; + tmp= (changed&mc->changed); + if (tmp&XkbKeyActionsMask) + _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key); + else if (changed&XkbKeyActionsMask) { + mc->changed|= XkbKeyActionsMask; + mc->first_key_act= key; + mc->num_key_acts= 1; + } + if (tmp&XkbKeyBehaviorsMask) { + _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors, + key); + } + else if (changed&XkbKeyBehaviorsMask) { + mc->changed|= XkbKeyBehaviorsMask; + mc->first_key_behavior= key; + mc->num_key_behaviors= 1; + } + if (tmp&XkbVirtualModMapMask) + _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key); + else if (changed&XkbVirtualModMapMask) { + mc->changed|= XkbVirtualModMapMask; + mc->first_vmodmap_key= key; + mc->num_vmodmap_keys= 1; + } + mc->changed|= changed; + } + if (interps!=ibuf) + _XkbFree(interps); + return True; +} + +Status +XkbChangeTypesOfKey( XkbDescPtr xkb, + int key, + int nGroups, + unsigned groups, + int * newTypesIn, + XkbMapChangesPtr changes) +{ +XkbKeyTypePtr pOldType,pNewType; +register int i; +int width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups]; + + if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) || + (!xkb->map->types)||(!newTypes)||((groups&XkbAllGroupsMask)==0)|| + (nGroups>XkbNumKbdGroups)) { + return BadMatch; + } + if (nGroups==0) { + for (i=0;i<XkbNumKbdGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex; + } + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,0); + xkb->map->key_sym_map[key].group_info= i; + XkbResizeKeySyms(xkb,key,0); + return Success; + } + + nOldGroups= XkbKeyNumGroups(xkb,key); + oldWidth= XkbKeyGroupsWidth(xkb,key); + for (width=i=0;i<nGroups;i++) { + if (groups&(1<<i)) + newTypes[i]= newTypesIn[i]; + else if (i<nOldGroups) + newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i); + else if (nOldGroups>0) + newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + else newTypes[i]= XkbTwoLevelIndex; + if (newTypes[i]>xkb->map->num_types) + return BadMatch; + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>width) + width= pNewType->num_levels; + } + if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups)) + xkb->ctrls->num_groups= nGroups; + if ((width!=oldWidth)||(nGroups!=nOldGroups)) { + KeySym oldSyms[XkbMaxSymsPerKey],*pSyms; + int nCopy; + + if (nOldGroups==0) { + pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); + if (pSyms!=NULL) { + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,nGroups); + xkb->map->key_sym_map[key].group_info= i; + xkb->map->key_sym_map[key].width= width; + for (i=0;i<nGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; + } + return Success; + } + return BadAlloc; + } + pSyms= XkbKeySymsPtr(xkb,key); + memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); + if (pSyms==NULL) + return BadAlloc; + bzero(pSyms,width*nGroups*sizeof(KeySym)); + for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { + pOldType= XkbKeyKeyType(xkb,key,i); + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>pOldType->num_levels) + nCopy= pOldType->num_levels; + else nCopy= pNewType->num_levels; + memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym)); + } + if (XkbKeyHasActions(xkb,key)) { + XkbAction oldActs[XkbMaxSymsPerKey],*pActs; + pActs= XkbKeyActionsPtr(xkb,key); + memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction)); + pActs= XkbResizeKeyActions(xkb,key,width*nGroups); + if (pActs==NULL) + return BadAlloc; + bzero(pActs,width*nGroups*sizeof(XkbAction)); + for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { + pOldType= XkbKeyKeyType(xkb,key,i); + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>pOldType->num_levels) + nCopy= pOldType->num_levels; + else nCopy= pNewType->num_levels; + memcpy(&pActs[i*width],&oldActs[i*oldWidth], + nCopy*sizeof(XkbAction)); + } + } + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,nGroups); + xkb->map->key_sym_map[key].group_info= i; + xkb->map->key_sym_map[key].width= width; + } + width= 0; + for (i=0;i<nGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; + if (xkb->map->types[newTypes[i]].num_levels>width) + width= xkb->map->types[newTypes[i]].num_levels; + } + xkb->map->key_sym_map[key].width= width; + if (changes!=NULL) { + if (changes->changed&XkbKeySymsMask) { + _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms, + key); + } + else { + changes->changed|= XkbKeySymsMask; + changes->first_key_sym= key; + changes->num_key_syms= 1; + } + } + return Success; +} + +/***====================================================================***/ + +Bool +XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn) +{ +register int i,bit; +register unsigned mask; + + if (xkb==NULL) + return False; + if (virtual_mask==0) { + *mask_rtrn= 0; + return True; + } + if (xkb->server==NULL) + return False; + for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (virtual_mask&bit) + mask|= xkb->server->vmods[i]; + } + *mask_rtrn= mask; + return True; +} + +/***====================================================================***/ + +static Bool +XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed) +{ +unsigned int tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->mods.mask= act->mods.real_mods; + act->mods.mask|= tmp; + return True; + } + break; + case XkbSA_ISOLock: + if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->iso.mask= act->iso.real_mods; + act->iso.mask|= tmp; + return True; + } + break; + } + return False; +} + +static void +XkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb, + XkbKeyTypePtr type, + unsigned int changed, + XkbChangesPtr changes) +{ +register unsigned int i; +unsigned int mask; + + XkbVirtualModsToReal(xkb,type->mods.vmods,&mask); + type->mods.mask= type->mods.real_mods|mask; + if ((type->map_count>0)&&(type->mods.vmods!=0)) { + XkbKTMapEntryPtr entry; + for (i=0,entry=type->map;i<type->map_count;i++,entry++) { + if (entry->mods.vmods!=0) { + XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask); + entry->mods.mask=entry->mods.real_mods|mask; + /* entry is active if vmods are bound*/ + entry->active= (mask!=0); + } + else entry->active= 1; + } + } + if (changes) { + int type_ndx; + type_ndx= type-xkb->map->types; + if ((type_ndx<0)||(type_ndx>xkb->map->num_types)) + return; + if (changes->map.changed&XkbKeyTypesMask) { + int last; + last= changes->map.first_type+changes->map.num_types-1; + if (type_ndx<changes->map.first_type) { + changes->map.first_type= type_ndx; + changes->map.num_types= (last-type_ndx)+1; + } + else if (type_ndx>last) { + changes->map.num_types= (type_ndx-changes->map.first_type)+1; + } + } + else { + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type= type_ndx; + changes->map.num_types= 1; + } + } + return; +} + +Bool +XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes) +{ +register int i; +unsigned int checkState = 0; + + if ((!xkb) || (!xkb->map) || (changed==0)) + return False; + for (i=0;i<xkb->map->num_types;i++) { + if (xkb->map->types[i].mods.vmods & changed) + XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes); + } + if (changed&xkb->ctrls->internal.vmods) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask); + newMask|= xkb->ctrls->internal.real_mods; + if (xkb->ctrls->internal.mask!=newMask) { + xkb->ctrls->internal.mask= newMask; + if (changes) { + changes->ctrls.changed_ctrls|= XkbInternalModsMask; + checkState= True; + } + } + } + if (changed&xkb->ctrls->ignore_lock.vmods) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask); + newMask|= xkb->ctrls->ignore_lock.real_mods; + if (xkb->ctrls->ignore_lock.mask!=newMask) { + xkb->ctrls->ignore_lock.mask= newMask; + if (changes) { + changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask; + checkState= True; + } + } + } + if (xkb->indicators!=NULL) { + XkbIndicatorMapPtr map; + map= &xkb->indicators->maps[0]; + for (i=0;i<XkbNumIndicators;i++,map++) { + if (map->mods.vmods&changed) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask); + newMask|= map->mods.real_mods; + if (newMask!=map->mods.mask) { + map->mods.mask= newMask; + if (changes) { + changes->indicators.map_changes|= (1<<i); + checkState= True; + } + } + } + } + } + if (xkb->compat!=NULL) { + XkbCompatMapPtr compat; + compat= xkb->compat; + for (i=0;i<XkbNumKbdGroups;i++) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask); + newMask|= compat->groups[i].real_mods; + if (compat->groups[i].mask!=newMask) { + compat->groups[i].mask= newMask; + if (changes) { + changes->compat.changed_groups|= (1<<i); + checkState= True; + } + } + } + } + if (xkb->map && xkb->server) { + int highChange = 0, lowChange = -1; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (XkbKeyHasActions(xkb,i)) { + register XkbAction *pAct; + register int n; + + pAct= XkbKeyActionsPtr(xkb,i); + for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) { + if ((pAct->type!=XkbSA_NoAction)&& + XkbUpdateActionVirtualMods(xkb,pAct,changed)) { + if (lowChange<0) + lowChange= i; + highChange= i; + } + } + } + } + if (changes && (lowChange>0)) { /* something changed */ + if (changes->map.changed&XkbKeyActionsMask) { + int last; + if (changes->map.first_key_act<lowChange) + lowChange= changes->map.first_key_act; + last= changes->map.first_key_act+changes->map.num_key_acts-1; + if (last>highChange) + highChange= last; + } + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act= lowChange; + changes->map.num_key_acts= (highChange-lowChange)+1; + } + } + return checkState; +} diff --git a/xorg-server/xkb/ddxBeep.c b/xorg-server/xkb/ddxBeep.c new file mode 100644 index 000000000..2faed5818 --- /dev/null +++ b/xorg-server/xkb/ddxBeep.c @@ -0,0 +1,332 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include <X11/extensions/XI.h> + +/*#define FALLING_TONE 1*/ +/*#define RISING_TONE 1*/ +#define FALLING_TONE 10 +#define RISING_TONE 10 +#define SHORT_TONE 50 +#define SHORT_DELAY 60 +#define LONG_TONE 75 +#define VERY_LONG_TONE 100 +#define LONG_DELAY 85 +#define CLICK_DURATION 1 + +#define DEEP_PITCH 250 +#define LOW_PITCH 500 +#define MID_PITCH 1000 +#define HIGH_PITCH 2000 +#define CLICK_PITCH 1500 + +static unsigned long atomGeneration= 0; +static Atom featureOn; +static Atom featureOff; +static Atom featureChange; +static Atom ledOn; +static Atom ledOff; +static Atom ledChange; +static Atom slowWarn; +static Atom slowPress; +static Atom slowReject; +static Atom slowAccept; +static Atom slowRelease; +static Atom stickyLatch; +static Atom stickyLock; +static Atom stickyUnlock; +static Atom bounceReject; +static char doesPitch = 1; + +#define FEATURE_ON "AX_FeatureOn" +#define FEATURE_OFF "AX_FeatureOff" +#define FEATURE_CHANGE "AX_FeatureChange" +#define LED_ON "AX_IndicatorOn" +#define LED_OFF "AX_IndicatorOff" +#define LED_CHANGE "AX_IndicatorChange" +#define SLOW_WARN "AX_SlowKeysWarning" +#define SLOW_PRESS "AX_SlowKeyPress" +#define SLOW_REJECT "AX_SlowKeyReject" +#define SLOW_ACCEPT "AX_SlowKeyAccept" +#define SLOW_RELEASE "AX_SlowKeyRelease" +#define STICKY_LATCH "AX_StickyLatch" +#define STICKY_LOCK "AX_StickyLock" +#define STICKY_UNLOCK "AX_StickyUnlock" +#define BOUNCE_REJECT "AX_BounceKeyReject" + +#define MAKE_ATOM(a) MakeAtom(a,sizeof(a)-1,True) + +static void +_XkbDDXBeepInitAtoms(void) +{ + featureOn= MAKE_ATOM(FEATURE_ON); + featureOff= MAKE_ATOM(FEATURE_OFF); + featureChange= MAKE_ATOM(FEATURE_CHANGE); + ledOn= MAKE_ATOM(LED_ON); + ledOff= MAKE_ATOM(LED_OFF); + ledChange= MAKE_ATOM(LED_CHANGE); + slowWarn= MAKE_ATOM(SLOW_WARN); + slowPress= MAKE_ATOM(SLOW_PRESS); + slowReject= MAKE_ATOM(SLOW_REJECT); + slowAccept= MAKE_ATOM(SLOW_ACCEPT); + slowRelease= MAKE_ATOM(SLOW_RELEASE); + stickyLatch= MAKE_ATOM(STICKY_LATCH); + stickyLock= MAKE_ATOM(STICKY_LOCK); + stickyUnlock= MAKE_ATOM(STICKY_UNLOCK); + bounceReject= MAKE_ATOM(BOUNCE_REJECT); + return; +} + +static CARD32 +_XkbDDXBeepExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +DeviceIntPtr dev= (DeviceIntPtr)arg; +KbdFeedbackPtr feed; +KeybdCtrl * ctrl; +XkbSrvInfoPtr xkbInfo; +CARD32 next; +int pitch,duration; +int oldPitch,oldDuration; +Atom name; + + if ((dev==NULL)||(dev->key==NULL)||(dev->key->xkbInfo==NULL)|| + (dev->kbdfeed==NULL)) + return 0; + if (atomGeneration!=serverGeneration) { + _XkbDDXBeepInitAtoms(); + atomGeneration= serverGeneration; + } + + feed= dev->kbdfeed; + ctrl= &feed->ctrl; + xkbInfo= dev->key->xkbInfo; + next= 0; + pitch= oldPitch= ctrl->bell_pitch; + duration= oldDuration= ctrl->bell_duration; + name= None; + switch (xkbInfo->beepType) { + default: + ErrorF("Unknown beep type %d\n",xkbInfo->beepType); + case _BEEP_NONE: + duration= 0; + break; + + /* When an LED is turned on, we want a high-pitched beep. + * When the LED it turned off, we want a low-pitched beep. + * If we cannot do pitch, we want a single beep for on and two + * beeps for off. + */ + case _BEEP_LED_ON: + if (name==None) name= ledOn; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + break; + case _BEEP_LED_OFF: + if (name==None) name= ledOff; + duration= SHORT_TONE; + pitch= LOW_PITCH; + if (!doesPitch && xkbInfo->beepCount<1) + next = SHORT_DELAY; + break; + + /* When a Feature is turned on, we want an up-siren. + * When a Feature is turned off, we want a down-siren. + * If we cannot do pitch, we want a single beep for on and two + * beeps for off. + */ + case _BEEP_FEATURE_ON: + if (name==None) name= featureOn; + if (xkbInfo->beepCount<1) { + pitch= LOW_PITCH; + duration= VERY_LONG_TONE; + if (doesPitch) + next= SHORT_DELAY; + } + else { + pitch= MID_PITCH; + duration= SHORT_TONE; + } + break; + + case _BEEP_FEATURE_OFF: + if (name==None) name= featureOff; + if (xkbInfo->beepCount<1) { + pitch= MID_PITCH; + if (doesPitch) + duration= VERY_LONG_TONE; + else duration= SHORT_TONE; + next= SHORT_DELAY; + } + else { + pitch= LOW_PITCH; + duration= SHORT_TONE; + } + break; + + /* Two high beeps indicate an LED or Feature changed + * state, but that another LED or Feature is also on. + * [[[WDW - This is not in AccessDOS ]]] + */ + case _BEEP_LED_CHANGE: + if (name==None) name= ledChange; + case _BEEP_FEATURE_CHANGE: + if (name==None) name= featureChange; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + if (xkbInfo->beepCount<1) { + next= SHORT_DELAY; + } + break; + + /* Three high-pitched beeps are the warning that SlowKeys + * is going to be turned on or off. + */ + case _BEEP_SLOW_WARN: + if (name==None) name= slowWarn; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + if (xkbInfo->beepCount<2) + next= SHORT_DELAY; + break; + + /* Click on SlowKeys press and accept. + * Deep pitch when a SlowKey or BounceKey is rejected. + * [[[WDW - Rejects are not in AccessDOS ]]] + * If we cannot do pitch, we want single beeps. + */ + case _BEEP_SLOW_PRESS: + if (name==None) name= slowPress; + case _BEEP_SLOW_ACCEPT: + if (name==None) name= slowAccept; + case _BEEP_SLOW_RELEASE: + if (name==None) name= slowRelease; + duration= CLICK_DURATION; + pitch= CLICK_PITCH; + break; + case _BEEP_BOUNCE_REJECT: + if (name==None) name= bounceReject; + case _BEEP_SLOW_REJECT: + if (name==None) name= slowReject; + duration= SHORT_TONE; + pitch= DEEP_PITCH; + break; + + /* Low followed by high pitch when a StickyKey is latched. + * High pitch when a StickyKey is locked. + * Low pitch when unlocked. + * If we cannot do pitch, two beeps for latch, nothing for + * lock, and two for unlock. + */ + case _BEEP_STICKY_LATCH: + if (name==None) name= stickyLatch; + duration= SHORT_TONE; + if (xkbInfo->beepCount<1) { + next= SHORT_DELAY; + pitch= LOW_PITCH; + } + else pitch= HIGH_PITCH; + break; + case _BEEP_STICKY_LOCK: + if (name==None) name= stickyLock; + if (doesPitch) { + duration= SHORT_TONE; + pitch= HIGH_PITCH; + } + break; + case _BEEP_STICKY_UNLOCK: + if (name==None) name= stickyUnlock; + duration= SHORT_TONE; + pitch= LOW_PITCH; + if (!doesPitch && xkbInfo->beepCount<1) + next = SHORT_DELAY; + break; + } + if (timer == NULL && duration>0) { + CARD32 starttime = GetTimeInMillis(); + CARD32 elapsedtime; + + ctrl->bell_duration= duration; + ctrl->bell_pitch= pitch; + if (xkbInfo->beepCount==0) { + XkbHandleBell(0,0,dev,ctrl->bell,(pointer)ctrl,KbdFeedbackClass,name,None, + NULL); + } + else if (xkbInfo->desc->ctrls->enabled_ctrls&XkbAudibleBellMask) { + (*dev->kbdfeed->BellProc)(ctrl->bell,dev,(pointer)ctrl,KbdFeedbackClass); + } + ctrl->bell_duration= oldDuration; + ctrl->bell_pitch= oldPitch; + xkbInfo->beepCount++; + + /* Some DDX schedule the beep and return immediately, others don't + return until the beep is completed. We measure the time and if + it's less than the beep duration, make sure not to schedule the + next beep until after the current one finishes. */ + + elapsedtime = GetTimeInMillis(); + if (elapsedtime > starttime) { /* watch out for millisecond counter + overflow! */ + elapsedtime -= starttime; + } else { + elapsedtime = 0; + } + if (elapsedtime < duration) { + next += duration - elapsedtime; + } + + } + return next; +} + +int +XkbDDXAccessXBeep(DeviceIntPtr dev,unsigned what,unsigned which) +{ +XkbSrvInfoRec *xkbInfo= dev->key->xkbInfo; +CARD32 next; + + xkbInfo->beepType= what; + xkbInfo->beepCount= 0; + next= _XkbDDXBeepExpire(NULL,0,(pointer)dev); + if (next>0) { + xkbInfo->beepTimer= TimerSet(xkbInfo->beepTimer, + 0, next, + _XkbDDXBeepExpire, (pointer)dev); + } + return 1; +} diff --git a/xorg-server/xkb/ddxCtrls.c b/xorg-server/xkb/ddxCtrls.c new file mode 100644 index 000000000..34ea0bd3f --- /dev/null +++ b/xorg-server/xkb/ddxCtrls.c @@ -0,0 +1,106 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include <X11/extensions/XI.h> + +void +XkbDDXKeybdCtrlProc(DeviceIntPtr dev,KeybdCtrl *ctrl) +{ +int realRepeat; + + realRepeat= ctrl->autoRepeat; + if ((dev->kbdfeed)&&(XkbDDXUsesSoftRepeat(dev))) + ctrl->autoRepeat= 0; + if (dev->key && dev->key->xkbInfo && dev->key->xkbInfo->kbdProc) + (*dev->key->xkbInfo->kbdProc)(dev,ctrl); + ctrl->autoRepeat= realRepeat; + return; +} + + +int +XkbDDXUsesSoftRepeat(DeviceIntPtr pXDev) +{ +#ifndef XKB_ALWAYS_USES_SOFT_REPEAT + if (pXDev && pXDev->kbdfeed ) { + if (pXDev->kbdfeed->ctrl.autoRepeat) { + if (pXDev->key && pXDev->key->xkbInfo) { + XkbDescPtr xkb; + xkb= pXDev->key->xkbInfo->desc; + if ((xkb->ctrls->repeat_delay == 660) && + (xkb->ctrls->repeat_interval == 40) && + ((xkb->ctrls->enabled_ctrls&(XkbSlowKeysMask| + XkbBounceKeysMask| + XkbMouseKeysMask))==0)) { + return 0; + } + return ((xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0); + } + } + } + return 0; +#else + return 1; +#endif +} + +void +XkbDDXChangeControls(DeviceIntPtr dev,XkbControlsPtr old,XkbControlsPtr new) +{ +unsigned changed, i; +unsigned char *rep_old, *rep_new, *rep_fb; + + changed= new->enabled_ctrls^old->enabled_ctrls; + for (rep_old = old->per_key_repeat, + rep_new = new->per_key_repeat, + rep_fb = dev->kbdfeed->ctrl.autoRepeats, + i = 0; i < XkbPerKeyBitArraySize; i++) { + if (rep_old[i] != rep_new[i]) { + rep_fb[i] = rep_new[i]; + changed &= XkbPerKeyRepeatMask; + } + } + + if (changed&XkbPerKeyRepeatMask) { + if (dev->kbdfeed->CtrlProc) + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + } + return; +} + diff --git a/xorg-server/xkb/ddxDevBtn.c b/xorg-server/xkb/ddxDevBtn.c new file mode 100644 index 000000000..5313a1ec5 --- /dev/null +++ b/xorg-server/xkb/ddxDevBtn.c @@ -0,0 +1,100 @@ +/************************************************************ +Copyright (c) 1995 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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> + +extern int DeviceValuator; + +void +XkbDDXFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) +{ +int * devVal; +INT32 * evVal; +xEvent events[2]; +deviceKeyButtonPointer *btn; +deviceValuator * val; +int x,y; +int nAxes, i, count; + + if (dev == inputInfo.pointer || !dev->public.on) + return; + + nAxes = (dev->valuator?dev->valuator->numAxes:0); + if (nAxes > 6) + nAxes = 6; + + GetSpritePosition(&x,&y); + btn= (deviceKeyButtonPointer *) &events[0]; + val= (deviceValuator *) &events[1]; + if (press) btn->type= DeviceButtonPress; + else btn->type= DeviceButtonRelease; + btn->detail= button; + btn->time= GetTimeInMillis(); + btn->root_x= x; + btn->root_y= y; + btn->deviceid= dev->id; + count= 1; + if (nAxes>0) { + btn->deviceid|= 0x80; + val->type = DeviceValuator; + val->deviceid = dev->id; + val->first_valuator = 0; + + evVal= &val->valuator0; + devVal= dev->valuator->axisVal; + for (i=nAxes;i>0;i--) { + *evVal++ = *devVal++; + if (evVal > &val->valuator5) { + int tmp = val->first_valuator+6; + val->num_valuators = 6; + val++; + evVal= &val->valuator0; + val->first_valuator= tmp; + } + } + if ((nAxes % 6) != 0) { + val->num_valuators = (nAxes % 6); + } + count= 1+((nAxes+5)/6); + } + + (*dev->public.processInputProc)((xEventPtr)btn, dev, count); + return; +} diff --git a/xorg-server/xkb/ddxFakeBtn.c b/xorg-server/xkb/ddxFakeBtn.c new file mode 100644 index 000000000..2dad54fea --- /dev/null +++ b/xorg-server/xkb/ddxFakeBtn.c @@ -0,0 +1,59 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include <X11/extensions/XI.h> + +void +XkbDDXFakePointerButton(int event,int button) +{ +xEvent ev; +int x,y; +DevicePtr ptr; + + if ((ptr = (DevicePtr)inputInfo.pointer)==NULL) + return; + GetSpritePosition(&x,&y); + ev.u.u.type = event; + ev.u.u.detail = button; + ev.u.keyButtonPointer.time = GetTimeInMillis(); + ev.u.keyButtonPointer.rootX = x; + ev.u.keyButtonPointer.rootY = y; + (*ptr->processInputProc)( &ev, (DeviceIntPtr)ptr, 1 ); + return; +} diff --git a/xorg-server/xkb/ddxFakeMtn.c b/xorg-server/xkb/ddxFakeMtn.c new file mode 100644 index 000000000..320e0ca33 --- /dev/null +++ b/xorg-server/xkb/ddxFakeMtn.c @@ -0,0 +1,119 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include <X11/extensions/XI.h> + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include "mipointer.h" +#include "mipointrst.h" + +void +XkbDDXFakePointerMotion(unsigned flags,int x,int y) +{ +int oldX,oldY; +ScreenPtr pScreen, oldScreen; + + GetSpritePosition(&oldX, &oldY); + pScreen = oldScreen = GetSpriteWindow()->drawable.pScreen; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + BoxRec box; + int i; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + oldX, oldY, &box)) { + FOR_NSCREENS(i) { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], + oldX, oldY, &box)) { + pScreen = screenInfo.screens[i]; + break; + } + } + } + oldScreen = pScreen; + + if (flags&XkbSA_MoveAbsoluteX) + oldX= x; + else oldX+= x; + if (flags&XkbSA_MoveAbsoluteY) + oldY= y; + else oldY+= y; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + oldX, oldY, &box)) { + FOR_NSCREENS(i) { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], + oldX, oldY, &box)) { + pScreen = screenInfo.screens[i]; + break; + } + } + } + oldX -= panoramiXdataPtr[pScreen->myNum].x; + oldY -= panoramiXdataPtr[pScreen->myNum].y; + } + else +#endif + { + if (flags&XkbSA_MoveAbsoluteX) + oldX= x; + else oldX+= x; + if (flags&XkbSA_MoveAbsoluteY) + oldY= y; + else oldY+= y; + +#define GetScreenPrivate(s) ((miPointerScreenPtr)dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) + (*(GetScreenPrivate(oldScreen))->screenFuncs->CursorOffScreen) + (&pScreen, &oldX, &oldY); + } + + if (pScreen != oldScreen) + NewCurrentScreen(pScreen, oldX, oldY); + if (pScreen->SetCursorPosition) + (*pScreen->SetCursorPosition)(pScreen, oldX, oldY, TRUE); +} diff --git a/xorg-server/xkb/ddxInit.c b/xorg-server/xkb/ddxInit.c new file mode 100644 index 000000000..4c78a621b --- /dev/null +++ b/xorg-server/xkb/ddxInit.c @@ -0,0 +1,46 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include <X11/extensions/XI.h> + +int +XkbDDXInitDevice(DeviceIntPtr dev) +{ + return 1; +} diff --git a/xorg-server/xkb/ddxKeyClick.c b/xorg-server/xkb/ddxKeyClick.c new file mode 100644 index 000000000..51d78f56d --- /dev/null +++ b/xorg-server/xkb/ddxKeyClick.c @@ -0,0 +1,46 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include <X11/extensions/XI.h> + +void +XkbDDXKeyClick(DeviceIntPtr pXDev,int keycode,int synthetic) +{ + return; +} diff --git a/xorg-server/xkb/ddxKillSrv.c b/xorg-server/xkb/ddxKillSrv.c new file mode 100644 index 000000000..3b5fd5353 --- /dev/null +++ b/xorg-server/xkb/ddxKillSrv.c @@ -0,0 +1,48 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> + +int +XkbDDXTerminateServer(DeviceIntPtr dev,KeyCode key,XkbAction *act) +{ + if (dev != inputInfo.keyboard) + GiveUp(1); + + return 0; +} diff --git a/xorg-server/xkb/ddxLEDs.c b/xorg-server/xkb/ddxLEDs.c new file mode 100644 index 000000000..b4c8086f5 --- /dev/null +++ b/xorg-server/xkb/ddxLEDs.c @@ -0,0 +1,72 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include <X11/extensions/XI.h> + +static void +XkbDDXUpdateIndicators(DeviceIntPtr dev,CARD32 new) +{ + dev->kbdfeed->ctrl.leds= new; + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + return; +} + +void +XkbDDXUpdateDeviceIndicators( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + CARD32 new) +{ + if (sli->fb.kf==dev->kbdfeed) + XkbDDXUpdateIndicators(dev,new); + else if (sli->class==KbdFeedbackClass) { + KbdFeedbackPtr kf; + kf= sli->fb.kf; + if (kf && kf->CtrlProc) { + (*kf->CtrlProc)(dev,&kf->ctrl); + } + } + else if (sli->class==LedFeedbackClass) { + LedFeedbackPtr lf; + lf= sli->fb.lf; + if (lf && lf->CtrlProc) { + (*lf->CtrlProc)(dev,&lf->ctrl); + } + } + return; +} diff --git a/xorg-server/xkb/ddxList.c b/xorg-server/xkb/ddxList.c new file mode 100644 index 000000000..80e050524 --- /dev/null +++ b/xorg-server/xkb/ddxList.c @@ -0,0 +1,296 @@ +/************************************************************ +Copyright (c) 1995 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 <dix-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/extensions/XKM.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> +#include <X11/extensions/XI.h> + +#ifdef WIN32 +/* from ddxLoad.c */ +extern const char* Win32TempDir(); +extern int Win32System(const char *cmdline); +#undef System +#define System Win32System + +#define W32_tmparg " '%s'" +#define W32_tmpfile ,tmpname +#define W32_tmplen strlen(tmpname)+3 +#else +#define W32_tmparg +#define W32_tmpfile +#define W32_tmplen 0 +#endif + +/***====================================================================***/ + +static char *componentDirs[_XkbListNumComponents] = { + "keymap", "keycodes", "types", "compat", "symbols", "geometry" +}; + +/***====================================================================***/ + +static Status +_AddListComponent( XkbSrvListInfoPtr list, + int what, + unsigned flags, + char * str, + ClientPtr client) +{ +int slen,wlen; +unsigned char * wire8; +unsigned short *wire16; +char * tmp; + + if (list->nTotal>=list->maxRtrn) { + list->nTotal++; + return Success; + } + tmp= strchr(str,')'); + if ((tmp==NULL)&&((tmp=strchr(str,'('))==NULL)) { + slen= strlen(str); + while ((slen>0) && isspace(str[slen-1])) { + slen--; + } + } + else { + slen= (tmp-str+1); + } + wlen= (((slen+1)/2)*2)+4; /* four bytes for flags and length, pad to */ + /* 2-byte boundary */ + if ((list->szPool-list->nPool)<wlen) { + if (wlen>1024) list->szPool+= XkbPaddedSize(wlen*2); + else list->szPool+= 1024; + list->pool= _XkbTypedRealloc(list->pool,list->szPool,char); + if (!list->pool) + return BadAlloc; + } + wire16= (unsigned short *)&list->pool[list->nPool]; + wire8= (unsigned char *)&wire16[2]; + wire16[0]= flags; + wire16[1]= slen; + memcpy(wire8,str,slen); + if (client->swapped) { + register int n; + swaps(&wire16[0],n); + swaps(&wire16[1],n); + } + list->nPool+= wlen; + list->nFound[what]++; + list->nTotal++; + return Success; +} + +/***====================================================================***/ +static Status +XkbDDXListComponent( DeviceIntPtr dev, + int what, + XkbSrvListInfoPtr list, + ClientPtr client) +{ +char *file,*map,*tmp,*buf=NULL; +FILE *in; +Status status; +int rval; +Bool haveDir; +#ifdef WIN32 +char tmpname[PATH_MAX]; +#endif + + if ((list->pattern[what]==NULL)||(list->pattern[what][0]=='\0')) + return Success; + file= list->pattern[what]; + map= strrchr(file,'('); + if (map!=NULL) { + char *tmp; + map++; + tmp= strrchr(map,')'); + if ((tmp==NULL)||(tmp[1]!='\0')) { + /* illegal pattern. No error, but no match */ + return Success; + } + } + + in= NULL; + haveDir= True; +#ifdef WIN32 + strcpy(tmpname, Win32TempDir()); + strcat(tmpname, "\\xkb_XXXXXX"); + (void) mktemp(tmpname); +#endif + if (XkbBaseDirectory!=NULL) { + if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) { + buf = Xprintf("%s/%s.dir",XkbBaseDirectory,componentDirs[what]); + in= fopen(buf,"r"); + } + if (!in) { + haveDir= False; + buf = Xprintf( + "'%s/xkbcomp' '-R%s/%s' -w %ld -l -vlfhpR '%s'" W32_tmparg, + XkbBinDirectory,XkbBaseDirectory,componentDirs[what],(long) + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file W32_tmpfile + ); + } + } + else { + if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) { + buf = Xprintf("%s.dir",componentDirs[what]); + in= fopen(buf,"r"); + } + if (!in) { + haveDir= False; + buf = Xprintf( + "xkbcomp -R%s -w %ld -l -vlfhpR '%s'" W32_tmparg, + componentDirs[what],(long) + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file W32_tmpfile + ); + } + } + status= Success; + if (!haveDir) + { +#ifndef WIN32 + in= Popen(buf,"r"); +#else + if (xkbDebugFlags) + DebugF("xkbList executes: %s\n",buf); + if (System(buf) < 0) + ErrorF("Could not invoke keymap compiler\n"); + else + in= fopen(tmpname, "r"); +#endif + } + if (!in) + { + if (buf != NULL) + xfree (buf); +#ifdef WIN32 + unlink(tmpname); +#endif + return BadImplementation; + } + list->nFound[what]= 0; + if (buf) { + xfree(buf); + buf = NULL; + } + buf = xalloc(PATH_MAX * sizeof(char)); + if (!buf) + return BadAlloc; + while ((status==Success)&&((tmp=fgets(buf,PATH_MAX,in))!=NULL)) { + unsigned flags; + register unsigned int i; + if (*tmp=='#') /* comment, skip it */ + continue; + if (!strncmp(tmp, "Warning:", 8) || !strncmp(tmp, " ", 8)) + /* skip warnings too */ + continue; + flags= 0; + /* each line in the listing is supposed to start with two */ + /* groups of eight characters, which specify the general */ + /* flags and the flags that are specific to the component */ + /* if they're missing, fail with BadImplementation */ + for (i=0;(i<8)&&(status==Success);i++) { /* read the general flags */ + if (isalpha(*tmp)) flags|= (1L<<i); + else if (*tmp!='-') status= BadImplementation; + tmp++; + } + if (status != Success) break; + if (!isspace(*tmp)) { + status= BadImplementation; + break; + } + else tmp++; + for (i=0;(i<8)&&(status==Success);i++) { /* read the component flags */ + if (isalpha(*tmp)) flags|= (1L<<(i+8)); + else if (*tmp!='-') status= BadImplementation; + tmp++; + } + if (status != Success) break; + if (isspace(*tmp)) { + while (isspace(*tmp)) { + tmp++; + } + } + else { + status= BadImplementation; + break; + } + status= _AddListComponent(list,what,flags,tmp,client); + } +#ifndef WIN32 + if (haveDir) + fclose(in); + else if ((rval=Pclose(in))!=0) { + if (xkbDebugFlags) + ErrorF("xkbcomp returned exit code %d\n",rval); + } +#else + fclose(in); + unlink(tmpname); +#endif + if (buf != NULL) + xfree (buf); + return status; +} + +/***====================================================================***/ + +/* ARGSUSED */ +Status +XkbDDXList(DeviceIntPtr dev,XkbSrvListInfoPtr list,ClientPtr client) +{ +Status status; + + status= XkbDDXListComponent(dev,_XkbListKeymaps,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListKeycodes,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListTypes,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListCompat,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListSymbols,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListGeometry,list,client); + return status; +} diff --git a/xorg-server/xkb/ddxLoad.c b/xorg-server/xkb/ddxLoad.c new file mode 100644 index 000000000..35c3a3d24 --- /dev/null +++ b/xorg-server/xkb/ddxLoad.c @@ -0,0 +1,431 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#ifdef HAVE_XKB_CONFIG_H +#include <xkb-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/extensions/XKM.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> +#include <X11/extensions/XI.h> +#include "xkb.h" + +#if defined(CSRG_BASED) || defined(linux) || defined(__sgi) || defined(AIXV3) || defined(__osf__) || defined(__GNU__) +#include <paths.h> +#endif + + /* + * 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 <X11/Xwindows.h> +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 = xstrdup(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("Starting '%s' failed!\n", cmdline); + } + else + { + ErrorF("Starting '%s' failed: %s", cmdline, (char *)buffer); + LocalFree(buffer); + } + + xfree(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 ); + xfree(cmd); + + return dwExitCode; +} +#undef System +#define System(x) Win32System(x) +#endif + +static void +OutputDirectory( + char* outdir, + size_t size) +{ +#ifndef WIN32 + if (getuid() == 0 && (strlen(XKM_OUTPUT_DIR) < size)) + { + /* if server running as root it *may* be able to write */ + /* FIXME: check whether directory is writable at all */ + (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]; + +#ifdef WIN32 +char tmpname[PATH_MAX]; +#endif + if ((names->keymap==NULL)||(names->keymap[0]=='\0')) { + sprintf(keymap,"server-%s",display); + } + else { + if (strlen(names->keymap) > PATH_MAX - 1) { + ErrorF("name of keymap (%s) exceeds max length\n", names->keymap); + return False; + } + strcpy(keymap,names->keymap); + } + + XkbEnsureSafeMapName(keymap); + OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); +#ifdef WIN32 + strcpy(tmpname, Win32TempDir()); + strcat(tmpname, "\\xkb_XXXXXX"); + (void) mktemp(tmpname); +#endif + if (XkbBaseDirectory!=NULL) { +#ifndef WIN32 + char *xkmfile = "-"; +#else + /* 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 *xkmfile = tmpname; +#endif + char *xkbbasedir = XkbBaseDirectory; + char *xkbbindir = XkbBinDirectory; + + buf = Xprintf( + "\"%s" PATHSEPARATOR "xkbcomp\" -w %d \"-R%s\" -xkm \"%s\" -em1 %s -emp %s -eml %s \"%s%s.xkm\"", + xkbbindir, + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:(int)xkbDebugFlags)), + xkbbasedir, xkmfile, + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap); + } + else { +#ifndef WIN32 + char *xkmfile = "-"; +#else + char *xkmfile = tmpname; +#endif + buf = Xprintf( + "xkbcomp -w %d -xkm \"%s\" -em1 %s -emp %s -eml %s \"%s%s.xkm\"", + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:(int)xkbDebugFlags)), + xkmfile, + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap); + } + +#ifndef WIN32 + out= Popen(buf,"w"); +#else + out= fopen(tmpname, "w"); +#endif + + if (out!=NULL) { +#ifdef DEBUG + if (xkbDebugFlags) { + ErrorF("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 executes: %s\n",buf); + if (nameRtrn) { + strncpy(nameRtrn,keymap,nameRtrnLen); + nameRtrn[nameRtrnLen-1]= '\0'; + } + if (buf != NULL) + xfree (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'; + if (buf != NULL) + xfree (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(0, 0); + 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; +} diff --git a/xorg-server/xkb/ddxPrivate.c b/xorg-server/xkb/ddxPrivate.c new file mode 100644 index 000000000..f67e20c27 --- /dev/null +++ b/xorg-server/xkb/ddxPrivate.c @@ -0,0 +1,15 @@ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#define NEED_EVENTS +#include <X11/X.h> +#include "windowstr.h" +#include <xkbsrv.h> + +int +XkbDDXPrivate(DeviceIntPtr dev,KeyCode key,XkbAction *act) +{ + return 0; +} diff --git a/xorg-server/xkb/ddxVT.c b/xorg-server/xkb/ddxVT.c new file mode 100644 index 000000000..55c82a865 --- /dev/null +++ b/xorg-server/xkb/ddxVT.c @@ -0,0 +1,45 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include <xkbsrv.h> + +int +XkbDDXSwitchScreen(DeviceIntPtr dev,KeyCode key,XkbAction *act) +{ + return 1; +} diff --git a/xorg-server/xkb/maprules.c b/xorg-server/xkb/maprules.c new file mode 100644 index 000000000..4c947f004 --- /dev/null +++ b/xorg-server/xkb/maprules.c @@ -0,0 +1,1300 @@ +/************************************************************ + Copyright (c) 1996 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 <dix-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#define X_INCLUDE_STRING_H +#define XOS_USE_NO_LOCKING +#include <X11/Xos_r.h> + +#define NEED_EVENTS +#include <X11/Xproto.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "xkbstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> + +/***====================================================================***/ + +#define DFLT_LINE_SIZE 128 + +typedef struct { + int line_num; + int sz_line; + int num_line; + char buf[DFLT_LINE_SIZE]; + char * line; +} InputLine; + +static void +InitInputLine(InputLine *line) +{ + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static void +FreeInputLine(InputLine *line) +{ + if (line->line!=line->buf) + _XkbFree(line->line); + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static int +InputLineAddChar(InputLine *line,int ch) +{ + if (line->num_line>=line->sz_line) { + if (line->line==line->buf) { + line->line= (char *)_XkbAlloc(line->sz_line*2); + memcpy(line->line,line->buf,line->sz_line); + } + else { + line->line=(char *)_XkbRealloc((char *)line->line,line->sz_line*2); + } + line->sz_line*= 2; + } + line->line[line->num_line++]= ch; + return ch; +} + +#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\ + (int)((l)->line[(l)->num_line++]= (c)):\ + InputLineAddChar(l,c)) + +static Bool +GetInputLine(FILE *file,InputLine *line,Bool checkbang) +{ +int ch; +Bool endOfFile,spacePending,slashPending,inComment; + + endOfFile= False; + while ((!endOfFile)&&(line->num_line==0)) { + spacePending= slashPending= inComment= False; + while (((ch=getc(file))!='\n')&&(ch!=EOF)) { + if (ch=='\\') { + if ((ch=getc(file))==EOF) + break; + if (ch=='\n') { + inComment= False; + ch= ' '; + line->line_num++; + } + } + if (inComment) + continue; + if (ch=='/') { + if (slashPending) { + inComment= True; + slashPending= False; + } + else { + slashPending= True; + } + continue; + } + else if (slashPending) { + if (spacePending) { + ADD_CHAR(line,' '); + spacePending= False; + } + ADD_CHAR(line,'/'); + slashPending= False; + } + if (isspace(ch)) { + while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) { + ch= getc(file); + } + if (ch==EOF) + break; + if ((ch!='\n')&&(line->num_line>0)) + spacePending= True; + ungetc(ch,file); + } + else { + if (spacePending) { + ADD_CHAR(line,' '); + spacePending= False; + } + if (checkbang && ch=='!') { + if (line->num_line!=0) { + DebugF("The '!' legal only at start of line\n"); + DebugF("Line containing '!' ignored\n"); + line->num_line= 0; + inComment= 0; + break; + } + + } + ADD_CHAR(line,ch); + } + } + if (ch==EOF) + endOfFile= True; +/* else line->num_line++;*/ + } + if ((line->num_line==0)&&(endOfFile)) + return False; + ADD_CHAR(line,'\0'); + return True; +} + +/***====================================================================***/ + +#define MODEL 0 +#define LAYOUT 1 +#define VARIANT 2 +#define OPTION 3 +#define KEYCODES 4 +#define SYMBOLS 5 +#define TYPES 6 +#define COMPAT 7 +#define GEOMETRY 8 +#define KEYMAP 9 +#define MAX_WORDS 10 + +#define PART_MASK 0x000F +#define COMPONENT_MASK 0x03F0 + +static char * cname[MAX_WORDS] = { + "model", "layout", "variant", "option", + "keycodes", "symbols", "types", "compat", "geometry", "keymap" +}; + +typedef struct _RemapSpec { + int number; + int num_remap; + struct { + int word; + int index; + } remap[MAX_WORDS]; +} RemapSpec; + +typedef struct _FileSpec { + char * name[MAX_WORDS]; + struct _FileSpec * pending; +} FileSpec; + +typedef struct { + char * model; + char * layout[XkbNumKbdGroups+1]; + char * variant[XkbNumKbdGroups+1]; + char * options; +} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; + +#define NDX_BUFF_SIZE 4 + +/***====================================================================***/ + +static char* +get_index(char *str, int *ndx) +{ + char ndx_buf[NDX_BUFF_SIZE]; + char *end; + + if (*str != '[') { + *ndx = 0; + return str; + } + str++; + end = strchr(str, ']'); + if (end == NULL) { + *ndx = -1; + return str - 1; + } + if ( (end - str) >= NDX_BUFF_SIZE) { + *ndx = -1; + return end + 1; + } + strncpy(ndx_buf, str, end - str); + ndx_buf[end - str] = '\0'; + *ndx = atoi(ndx_buf); + return end + 1; +} + +static void +SetUpRemap(InputLine *line,RemapSpec *remap) +{ +char * tok,*str; +unsigned present, l_ndx_present, v_ndx_present; +register int i; +int len, ndx; +_Xstrtokparams strtok_buf; +Bool found; + + + l_ndx_present = v_ndx_present = present= 0; + str= &line->line[1]; + len = remap->number; + bzero((char *)remap,sizeof(RemapSpec)); + remap->number = len; + while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { + found= False; + str= NULL; + if (strcmp(tok,"=")==0) + continue; + for (i=0;i<MAX_WORDS;i++) { + len = strlen(cname[i]); + if (strncmp(cname[i],tok,len)==0) { + if(strlen(tok) > len) { + char *end = get_index(tok+len, &ndx); + if ((i != LAYOUT && i != VARIANT) || + *end != '\0' || ndx == -1) + break; + if (ndx < 1 || ndx > XkbNumKbdGroups) { + DebugF("Illegal %s index: %d\n", cname[i], ndx); + DebugF("Index must be in range 1..%d\n", + XkbNumKbdGroups); + break; + } + } else { + ndx = 0; + } + found= True; + if (present&(1<<i)) { + if ((i == LAYOUT && l_ndx_present&(1<<ndx)) || + (i == VARIANT && v_ndx_present&(1<<ndx)) ) { + DebugF("Component \"%s\" listed twice\n",tok); + DebugF("Second definition ignored\n"); + break; + } + } + present |= (1<<i); + if (i == LAYOUT) + l_ndx_present |= 1 << ndx; + if (i == VARIANT) + v_ndx_present |= 1 << ndx; + remap->remap[remap->num_remap].word= i; + remap->remap[remap->num_remap++].index= ndx; + break; + } + } + if (!found) { + fprintf(stderr,"Unknown component \"%s\" ignored\n",tok); + } + } + if ((present&PART_MASK)==0) { + unsigned mask= PART_MASK; + ErrorF("Mapping needs at least one of "); + for (i=0; (i<MAX_WORDS); i++) { + if ((1L<<i)&mask) { + mask&= ~(1L<<i); + if (mask) DebugF("\"%s,\" ",cname[i]); + else DebugF("or \"%s\"\n",cname[i]); + } + } + DebugF("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + if ((present&COMPONENT_MASK)==0) { + DebugF("Mapping needs at least one component\n"); + DebugF("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + if (((present&COMPONENT_MASK)&(1<<KEYMAP))&& + ((present&COMPONENT_MASK)!=(1<<KEYMAP))) { + DebugF("Keymap cannot appear with other components\n"); + DebugF("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + remap->number++; + return; +} + +static Bool +MatchOneOf(char *wanted,char *vals_defined) +{ +char *str,*next; +int want_len= strlen(wanted); + + for (str=vals_defined,next=NULL;str!=NULL;str=next) { + int len; + next= strchr(str,','); + if (next) { + len= next-str; + next++; + } + else { + len= strlen(str); + } + if ((len==want_len)&&(strncmp(wanted,str,len)==0)) + return True; + } + return False; +} + +/***====================================================================***/ + +static Bool +CheckLine( InputLine * line, + RemapSpec * remap, + XkbRF_RulePtr rule, + XkbRF_GroupPtr group) +{ +char * str,*tok; +register int nread, i; +FileSpec tmp; +_Xstrtokparams strtok_buf; +Bool append = False; + + if (line->line[0]=='!') { + if (line->line[1] == '$' || + (line->line[1] == ' ' && line->line[2] == '$')) { + char *gname = strchr(line->line, '$'); + char *words = strchr(gname, ' '); + if(!words) + return False; + *words++ = '\0'; + for (; *words; words++) { + if (*words != '=' && *words != ' ') + break; + } + if (*words == '\0') + return False; + group->name = _XkbDupString(gname); + group->words = _XkbDupString(words); + for (i = 1, words = group->words; *words; words++) { + if ( *words == ' ') { + *words++ = '\0'; + i++; + } + } + group->number = i; + return True; + } else { + SetUpRemap(line,remap); + return False; + } + } + + if (remap->num_remap==0) { + DebugF("Must have a mapping before first line of data\n"); + DebugF("Illegal line of data ignored\n"); + return False; + } + bzero((char *)&tmp,sizeof(FileSpec)); + str= line->line; + for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) { + str= NULL; + if (strcmp(tok,"=")==0) { + nread--; + continue; + } + if (nread>remap->num_remap) { + DebugF("Too many words on a line\n"); + DebugF("Extra word \"%s\" ignored\n",tok); + continue; + } + tmp.name[remap->remap[nread].word]= tok; + if (*tok == '+' || *tok == '|') + append = True; + } + if (nread<remap->num_remap) { + DebugF("Too few words on a line: %s\n", line->line); + DebugF("line ignored\n"); + return False; + } + + rule->flags= 0; + rule->number = remap->number; + if (tmp.name[OPTION]) + rule->flags|= XkbRF_Option; + else if (append) + rule->flags|= XkbRF_Append; + else + rule->flags|= XkbRF_Normal; + rule->model= _XkbDupString(tmp.name[MODEL]); + rule->layout= _XkbDupString(tmp.name[LAYOUT]); + rule->variant= _XkbDupString(tmp.name[VARIANT]); + rule->option= _XkbDupString(tmp.name[OPTION]); + + rule->keycodes= _XkbDupString(tmp.name[KEYCODES]); + rule->symbols= _XkbDupString(tmp.name[SYMBOLS]); + rule->types= _XkbDupString(tmp.name[TYPES]); + rule->compat= _XkbDupString(tmp.name[COMPAT]); + rule->geometry= _XkbDupString(tmp.name[GEOMETRY]); + rule->keymap= NULL; + + rule->layout_num = rule->variant_num = 0; + for (i = 0; i < nread; i++) { + if (remap->remap[i].index) { + if (remap->remap[i].word == LAYOUT) + rule->layout_num = remap->remap[i].index; + if (remap->remap[i].word == VARIANT) + rule->variant_num = remap->remap[i].index; + } + } + return True; +} + +static char * +_Concat(char *str1,char *str2) +{ +int len; + + if ((!str1)||(!str2)) + return str1; + len= strlen(str1)+strlen(str2)+1; + str1= _XkbTypedRealloc(str1,len,char); + if (str1) + strcat(str1,str2); + return str1; +} + +static void +squeeze_spaces(char *p1) +{ + char *p2; + for (p2 = p1; *p2; p2++) { + *p1 = *p2; + if (*p1 != ' ') p1++; + } + *p1 = '\0'; +} + +static Bool +MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) +{ + + bzero((char *)mdefs,sizeof(XkbRF_MultiDefsRec)); + mdefs->model = defs->model; + mdefs->options = _XkbDupString(defs->options); + if (mdefs->options) squeeze_spaces(mdefs->options); + + if (defs->layout) { + if (!strchr(defs->layout, ',')) { + mdefs->layout[0] = defs->layout; + } else { + char *p; + int i; + mdefs->layout[1] = _XkbDupString(defs->layout); + if (mdefs->layout[1] == NULL) + return False; + squeeze_spaces(mdefs->layout[1]); + p = mdefs->layout[1]; + for (i = 2; i <= XkbNumKbdGroups; i++) { + if ((p = strchr(p, ','))) { + *p++ = '\0'; + mdefs->layout[i] = p; + } else { + break; + } + } + if (p && (p = strchr(p, ','))) + *p = '\0'; + } + } + + if (defs->variant) { + if (!strchr(defs->variant, ',')) { + mdefs->variant[0] = defs->variant; + } else { + char *p; + int i; + mdefs->variant[1] = _XkbDupString(defs->variant); + if (mdefs->variant[1] == NULL) + return False; + squeeze_spaces(mdefs->variant[1]); + p = mdefs->variant[1]; + for (i = 2; i <= XkbNumKbdGroups; i++) { + if ((p = strchr(p, ','))) { + *p++ = '\0'; + mdefs->variant[i] = p; + } else { + break; + } + } + if (p && (p = strchr(p, ','))) + *p = '\0'; + } + } + return True; +} + +static void +FreeMultiDefs(XkbRF_MultiDefsPtr defs) +{ + if (defs->options) _XkbFree(defs->options); + if (defs->layout[1]) _XkbFree(defs->layout[1]); + if (defs->variant[1]) _XkbFree(defs->variant[1]); +} + +static void +Apply(char *src, char **dst) +{ + if (src) { + if (*src == '+' || *src == '!') { + *dst= _Concat(*dst, src); + } else { + if (*dst == NULL) + *dst= _XkbDupString(src); + } + } +} + +static void +XkbRF_ApplyRule( XkbRF_RulePtr rule, + XkbComponentNamesPtr names) +{ + rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ + + Apply(rule->keycodes, &names->keycodes); + Apply(rule->symbols, &names->symbols); + Apply(rule->types, &names->types); + Apply(rule->compat, &names->compat); + Apply(rule->geometry, &names->geometry); +} + +static Bool +CheckGroup( XkbRF_RulesPtr rules, + char * group_name, + char * name) +{ + int i; + char *p; + XkbRF_GroupPtr group; + + for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { + if (! strcmp(group->name, group_name)) { + break; + } + } + if (i == rules->num_groups) + return False; + for (i = 0, p = group->words; i < group->number; i++, p += strlen(p)+1) { + if (! strcmp(p, name)) { + return True; + } + } + return False; +} + +static int +XkbRF_CheckApplyRule( XkbRF_RulePtr rule, + XkbRF_MultiDefsPtr mdefs, + XkbComponentNamesPtr names, + XkbRF_RulesPtr rules) +{ + Bool pending = False; + + if (rule->model != NULL) { + if(mdefs->model == NULL) + return 0; + if (strcmp(rule->model, "*") == 0) { + pending = True; + } else { + if (rule->model[0] == '$') { + if (!CheckGroup(rules, rule->model, mdefs->model)) + return 0; + } else { + if (strcmp(rule->model, mdefs->model) != 0) + return 0; + } + } + } + if (rule->option != NULL) { + if (mdefs->options == NULL) + return 0; + if ((!MatchOneOf(rule->option,mdefs->options))) + return 0; + } + + if (rule->layout != NULL) { + if(mdefs->layout[rule->layout_num] == NULL || + *mdefs->layout[rule->layout_num] == '\0') + return 0; + if (strcmp(rule->layout, "*") == 0) { + pending = True; + } else { + if (rule->layout[0] == '$') { + if (!CheckGroup(rules, rule->layout, + mdefs->layout[rule->layout_num])) + return 0; + } else { + if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0) + return 0; + } + } + } + if (rule->variant != NULL) { + if (mdefs->variant[rule->variant_num] == NULL || + *mdefs->variant[rule->variant_num] == '\0') + return 0; + if (strcmp(rule->variant, "*") == 0) { + pending = True; + } else { + if (rule->variant[0] == '$') { + if (!CheckGroup(rules, rule->variant, + mdefs->variant[rule->variant_num])) + return 0; + } else { + if (strcmp(rule->variant, + mdefs->variant[rule->variant_num]) != 0) + return 0; + } + } + } + if (pending) { + rule->flags|= XkbRF_PendingMatch; + return rule->number; + } + /* exact match, apply it now */ + XkbRF_ApplyRule(rule,names); + return rule->number; +} + +static void +XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) +{ +register int i; +XkbRF_RulePtr rule; + + for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { + rule->flags&= ~XkbRF_PendingMatch; + } +} + +static void +XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) +{ +int i; +XkbRF_RulePtr rule; + + for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { + if ((rule->flags&XkbRF_PendingMatch)==0) + continue; + XkbRF_ApplyRule(rule,names); + } +} + +static void +XkbRF_CheckApplyRules( XkbRF_RulesPtr rules, + XkbRF_MultiDefsPtr mdefs, + XkbComponentNamesPtr names, + int flags) +{ +int i; +XkbRF_RulePtr rule; +int skip; + + for (rule = rules->rules, i=0; i < rules->num_rules; rule++, i++) { + if ((rule->flags & flags) != flags) + continue; + skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules); + if (skip && !(flags & XkbRF_Option)) { + for ( ;(i < rules->num_rules) && (rule->number == skip); + rule++, i++); + rule--; i--; + } + } +} + +/***====================================================================***/ + +static char * +XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) +{ +char *str, *outstr, *orig, *var; +int len, ndx; + + orig= name; + str= index(name,'%'); + if (str==NULL) + return name; + len= strlen(name); + while (str!=NULL) { + char pfx= str[1]; + int extra_len= 0; + if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { + extra_len= 1; + str++; + } + else if (pfx=='(') { + extra_len= 2; + str++; + } + var = str + 1; + str = get_index(var + 1, &ndx); + if (ndx == -1) { + str = index(str,'%'); + continue; + } + if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) + len+= strlen(mdefs->layout[ndx])+extra_len; + else if ((*var=='m')&&mdefs->model) + len+= strlen(mdefs->model)+extra_len; + else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) + len+= strlen(mdefs->variant[ndx])+extra_len; + if ((pfx=='(')&&(*str==')')) { + str++; + } + str= index(&str[0],'%'); + } + name= (char *)_XkbAlloc(len+1); + str= orig; + outstr= name; + while (*str!='\0') { + if (str[0]=='%') { + char pfx,sfx; + str++; + pfx= str[0]; + sfx= '\0'; + if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { + str++; + } + else if (pfx=='(') { + sfx= ')'; + str++; + } + else pfx= '\0'; + + var = str; + str = get_index(var + 1, &ndx); + if (ndx == -1) { + continue; + } + if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) { + if (pfx) *outstr++= pfx; + strcpy(outstr,mdefs->layout[ndx]); + outstr+= strlen(mdefs->layout[ndx]); + if (sfx) *outstr++= sfx; + } + else if ((*var=='m')&&(mdefs->model)) { + if (pfx) *outstr++= pfx; + strcpy(outstr,mdefs->model); + outstr+= strlen(mdefs->model); + if (sfx) *outstr++= sfx; + } + else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) { + if (pfx) *outstr++= pfx; + strcpy(outstr,mdefs->variant[ndx]); + outstr+= strlen(mdefs->variant[ndx]); + if (sfx) *outstr++= sfx; + } + if ((pfx=='(')&&(*str==')')) + str++; + } + else { + *outstr++= *str++; + } + } + *outstr++= '\0'; + if (orig!=name) + _XkbFree(orig); + return name; +} + +/***====================================================================***/ + +Bool +XkbRF_GetComponents( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +{ + XkbRF_MultiDefsRec mdefs; + + MakeMultiDefs(&mdefs, defs); + + bzero((char *)names,sizeof(XkbComponentNamesRec)); + XkbRF_ClearPartialMatches(rules); + XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal); + XkbRF_ApplyPartialMatches(rules, names); + XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append); + XkbRF_ApplyPartialMatches(rules, names); + XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option); + + if (names->keycodes) + names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs); + if (names->symbols) + names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs); + if (names->types) + names->types= XkbRF_SubstituteVars(names->types, &mdefs); + if (names->compat) + names->compat= XkbRF_SubstituteVars(names->compat, &mdefs); + if (names->geometry) + names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs); + if (names->keymap) + names->keymap= XkbRF_SubstituteVars(names->keymap, &mdefs); + + FreeMultiDefs(&mdefs); + return (names->keycodes && names->symbols && names->types && + names->compat && names->geometry ) || names->keymap; +} + +XkbRF_RulePtr +XkbRF_AddRule(XkbRF_RulesPtr rules) +{ + if (rules->sz_rules<1) { + rules->sz_rules= 16; + rules->num_rules= 0; + rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); + } + else if (rules->num_rules>=rules->sz_rules) { + rules->sz_rules*= 2; + rules->rules= _XkbTypedRealloc(rules->rules,rules->sz_rules, + XkbRF_RuleRec); + } + if (!rules->rules) { + rules->sz_rules= rules->num_rules= 0; + DebugF("Allocation failure in XkbRF_AddRule\n"); + return NULL; + } + bzero((char *)&rules->rules[rules->num_rules],sizeof(XkbRF_RuleRec)); + return &rules->rules[rules->num_rules++]; +} + +XkbRF_GroupPtr +XkbRF_AddGroup(XkbRF_RulesPtr rules) +{ + if (rules->sz_groups<1) { + rules->sz_groups= 16; + rules->num_groups= 0; + rules->groups= _XkbTypedCalloc(rules->sz_groups,XkbRF_GroupRec); + } + else if (rules->num_groups >= rules->sz_groups) { + rules->sz_groups *= 2; + rules->groups= _XkbTypedRealloc(rules->groups,rules->sz_groups, + XkbRF_GroupRec); + } + if (!rules->groups) { + rules->sz_groups= rules->num_groups= 0; + return NULL; + } + + bzero((char *)&rules->groups[rules->num_groups],sizeof(XkbRF_GroupRec)); + return &rules->groups[rules->num_groups++]; +} + +Bool +XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) +{ +InputLine line; +RemapSpec remap; +XkbRF_RuleRec trule,*rule; +XkbRF_GroupRec tgroup,*group; + + if (!(rules && file)) + return False; + bzero((char *)&remap,sizeof(RemapSpec)); + bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); + InitInputLine(&line); + while (GetInputLine(file,&line,True)) { + if (CheckLine(&line,&remap,&trule,&tgroup)) { + if (tgroup.number) { + if ((group= XkbRF_AddGroup(rules))!=NULL) { + *group= tgroup; + bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); + } + } else { + if ((rule= XkbRF_AddRule(rules))!=NULL) { + *rule= trule; + bzero((char *)&trule,sizeof(XkbRF_RuleRec)); + } + } + } + line.num_line= 0; + } + FreeInputLine(&line); + return True; +} + +Bool +XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) +{ +FILE * file; +char buf[PATH_MAX]; +Bool ok; + + if ((!base)||(!rules)) + return False; + if (locale) { + if (strlen(base)+strlen(locale)+2 > PATH_MAX) + return False; + sprintf(buf,"%s-%s", base, locale); + } + else { + if (strlen(base)+1 > PATH_MAX) + return False; + strcpy(buf,base); + } + + file= fopen(buf, "r"); + if ((!file)&&(locale)) { /* fallback if locale was specified */ + strcpy(buf,base); + file= fopen(buf, "r"); + } + if (!file) + return False; + ok= XkbRF_LoadRules(file,rules); + fclose(file); + return ok; +} + +/***====================================================================***/ + +#define HEAD_NONE 0 +#define HEAD_MODEL 1 +#define HEAD_LAYOUT 2 +#define HEAD_VARIANT 3 +#define HEAD_OPTION 4 +#define HEAD_EXTRA 5 + +XkbRF_VarDescPtr +XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars) +{ + if (vars->sz_desc<1) { + vars->sz_desc= 16; + vars->num_desc= 0; + vars->desc= _XkbTypedCalloc(vars->sz_desc,XkbRF_VarDescRec); + } + else if (vars->num_desc>=vars->sz_desc) { + vars->sz_desc*= 2; + vars->desc= _XkbTypedRealloc(vars->desc,vars->sz_desc,XkbRF_VarDescRec); + } + if (!vars->desc) { + vars->sz_desc= vars->num_desc= 0; + DebugF("Allocation failure in XkbRF_AddVarDesc\n"); + return NULL; + } + vars->desc[vars->num_desc].name= NULL; + vars->desc[vars->num_desc].desc= NULL; + return &vars->desc[vars->num_desc++]; +} + +XkbRF_VarDescPtr +XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from) +{ +XkbRF_VarDescPtr nd; + + if ((nd=XkbRF_AddVarDesc(vars))!=NULL) { + nd->name= _XkbDupString(from->name); + nd->desc= _XkbDupString(from->desc); + } + return nd; +} + +XkbRF_DescribeVarsPtr +XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name) +{ + if (rules->sz_extra<1) { + rules->num_extra= 0; + rules->sz_extra= 1; + rules->extra_names= _XkbTypedCalloc(rules->sz_extra,char *); + rules->extra= _XkbTypedCalloc(rules->sz_extra, XkbRF_DescribeVarsRec); + } + else if (rules->num_extra>=rules->sz_extra) { + rules->sz_extra*= 2; + rules->extra_names= _XkbTypedRealloc(rules->extra_names,rules->sz_extra, + char *); + rules->extra=_XkbTypedRealloc(rules->extra, rules->sz_extra, + XkbRF_DescribeVarsRec); + } + if ((!rules->extra_names)||(!rules->extra)) { + DebugF("allocation error in extra parts\n"); + rules->sz_extra= rules->num_extra= 0; + rules->extra_names= NULL; + rules->extra= NULL; + return NULL; + } + rules->extra_names[rules->num_extra]= _XkbDupString(name); + bzero(&rules->extra[rules->num_extra],sizeof(XkbRF_DescribeVarsRec)); + return &rules->extra[rules->num_extra++]; +} + +Bool +XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules) +{ +InputLine line; +XkbRF_VarDescRec tmp; +char *tok; +int len,headingtype,extra_ndx = 0; + + bzero((char *)&tmp, sizeof(XkbRF_VarDescRec)); + headingtype = HEAD_NONE; + InitInputLine(&line); + for ( ; GetInputLine(file,&line,False); line.num_line= 0) { + if (line.line[0]=='!') { + tok = strtok(&(line.line[1]), " \t"); + if (strcasecmp(tok,"model") == 0) + headingtype = HEAD_MODEL; + else if (strcasecmp(tok,"layout") == 0) + headingtype = HEAD_LAYOUT; + else if (strcasecmp(tok,"variant") == 0) + headingtype = HEAD_VARIANT; + else if (strcasecmp(tok,"option") == 0) + headingtype = HEAD_OPTION; + else { + int i; + headingtype = HEAD_EXTRA; + extra_ndx= -1; + for (i=0;(i<rules->num_extra)&&(extra_ndx<0);i++) { + if (!strcasecmp(tok,rules->extra_names[i])) + extra_ndx= i; + } + if (extra_ndx<0) { + XkbRF_DescribeVarsPtr var; + DebugF("Extra heading \"%s\" encountered\n",tok); + var= XkbRF_AddVarToDescribe(rules,tok); + if (var) + extra_ndx= var-rules->extra; + else headingtype= HEAD_NONE; + } + } + continue; + } + + if (headingtype == HEAD_NONE) { + DebugF("Must have a heading before first line of data\n"); + DebugF("Illegal line of data ignored\n"); + continue; + } + + len = strlen(line.line); + if ((tmp.name= strtok(line.line, " \t")) == NULL) { + DebugF("Huh? No token on line\n"); + DebugF("Illegal line of data ignored\n"); + continue; + } + if (strlen(tmp.name) == len) { + DebugF("No description found\n"); + DebugF("Illegal line of data ignored\n"); + continue; + } + + tok = line.line + strlen(tmp.name) + 1; + while ((*tok!='\n')&&isspace(*tok)) + tok++; + if (*tok == '\0') { + DebugF("No description found\n"); + DebugF("Illegal line of data ignored\n"); + continue; + } + tmp.desc= tok; + switch (headingtype) { + case HEAD_MODEL: + XkbRF_AddVarDescCopy(&rules->models,&tmp); + break; + case HEAD_LAYOUT: + XkbRF_AddVarDescCopy(&rules->layouts,&tmp); + break; + case HEAD_VARIANT: + XkbRF_AddVarDescCopy(&rules->variants,&tmp); + break; + case HEAD_OPTION: + XkbRF_AddVarDescCopy(&rules->options,&tmp); + break; + case HEAD_EXTRA: + XkbRF_AddVarDescCopy(&rules->extra[extra_ndx],&tmp); + break; + } + } + FreeInputLine(&line); + if ((rules->models.num_desc==0) && (rules->layouts.num_desc==0) && + (rules->variants.num_desc==0) && (rules->options.num_desc==0) && + (rules->num_extra==0)) { + return False; + } + return True; +} + +Bool +XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules) +{ +FILE * file; +char buf[PATH_MAX]; +Bool ok; + + if ((!base)||(!rules)) + return False; + if (locale) { + if (strlen(base)+strlen(locale)+6 > PATH_MAX) + return False; + sprintf(buf,"%s-%s.lst", base, locale); + } + else { + if (strlen(base)+5 > PATH_MAX) + return False; + sprintf(buf,"%s.lst", base); + } + + file= fopen(buf, "r"); + if ((!file)&&(locale)) { /* fallback if locale was specified */ + sprintf(buf,"%s.lst", base); + + file= fopen(buf, "r"); + } + if (!file) + return False; + ok= XkbRF_LoadDescriptions(file,rules); + fclose(file); + return ok; +} + +/***====================================================================***/ + +XkbRF_RulesPtr +XkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules) +{ +XkbRF_RulesPtr rules; + + if ((!base)||((!wantDesc)&&(!wantRules))) + return NULL; + if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) + return NULL; + if (wantDesc&&(!XkbRF_LoadDescriptionsByName(base,locale,rules))) { + XkbRF_Free(rules,True); + return NULL; + } + if (wantRules&&(!XkbRF_LoadRulesByName(base,locale,rules))) { + XkbRF_Free(rules,True); + return NULL; + } + return rules; +} + +XkbRF_RulesPtr +XkbRF_Create(int szRules,int szExtra) +{ +XkbRF_RulesPtr rules; + + if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) + return NULL; + if (szRules>0) { + rules->sz_rules= szRules; + rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); + if (!rules->rules) { + _XkbFree(rules); + return NULL; + } + } + if (szExtra>0) { + rules->sz_extra= szExtra; + rules->extra= _XkbTypedCalloc(rules->sz_extra,XkbRF_DescribeVarsRec); + if (!rules->extra) { + if (rules->rules) + _XkbFree(rules->rules); + _XkbFree(rules); + return NULL; + } + } + return rules; +} + +/***====================================================================***/ + +static void +XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var) +{ +register int i; + + for (i=0;i<var->num_desc;i++) { + if (var->desc[i].name) + _XkbFree(var->desc[i].name); + if (var->desc[i].desc) + _XkbFree(var->desc[i].desc); + var->desc[i].name= var->desc[i].desc= NULL; + } + if (var->desc) + _XkbFree(var->desc); + var->desc= NULL; + return; +} + +void +XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) +{ +int i; +XkbRF_RulePtr rule; +XkbRF_GroupPtr group; + + if (!rules) + return; + XkbRF_ClearVarDescriptions(&rules->models); + XkbRF_ClearVarDescriptions(&rules->layouts); + XkbRF_ClearVarDescriptions(&rules->variants); + XkbRF_ClearVarDescriptions(&rules->options); + if (rules->extra) { + for (i = 0; i < rules->num_extra; i++) { + XkbRF_ClearVarDescriptions(&rules->extra[i]); + } + _XkbFree(rules->extra); + rules->num_extra= rules->sz_extra= 0; + rules->extra= NULL; + } + if (rules->rules) { + for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { + if (rule->model) _XkbFree(rule->model); + if (rule->layout) _XkbFree(rule->layout); + if (rule->variant) _XkbFree(rule->variant); + if (rule->option) _XkbFree(rule->option); + if (rule->keycodes) _XkbFree(rule->keycodes); + if (rule->symbols) _XkbFree(rule->symbols); + if (rule->types) _XkbFree(rule->types); + if (rule->compat) _XkbFree(rule->compat); + if (rule->geometry) _XkbFree(rule->geometry); + bzero((char *)rule,sizeof(XkbRF_RuleRec)); + } + _XkbFree(rules->rules); + rules->num_rules= rules->sz_rules= 0; + rules->rules= NULL; + } + + if (rules->groups) { + for (i=0, group=rules->groups;i<rules->num_groups;i++,group++) { + if (group->name) _XkbFree(group->name); + if (group->words) _XkbFree(group->words); + } + _XkbFree(rules->groups); + rules->num_groups= 0; + rules->groups= NULL; + } + if (freeRules) + _XkbFree(rules); + return; +} diff --git a/xorg-server/xkb/xkb.c b/xorg-server/xkb/xkb.c new file mode 100644 index 000000000..7c569d483 --- /dev/null +++ b/xorg-server/xkb/xkb.c @@ -0,0 +1,6736 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> +#include "extnsionst.h" +#include "xace.h" +#include "xkb.h" + +#include <X11/extensions/XI.h> + + 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 != XkbMajorVersion) { + /* pre-release version 0.65 is compatible with 1.00 */ + supported= ((XkbMajorVersion==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("Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n", + client->index, + (long)client->clientAsMask, + stuff->wantedMajor,stuff->wantedMinor, + XkbMajorVersion,XkbMinorVersion); + } + rep.type = X_Reply; + rep.supported = supported; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.serverMajor = XkbMajorVersion; + rep.serverMinor = XkbMinorVersion; + if ( client->swapped ) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.serverMajor, n); + swaps(&rep.serverMinor, n); + } + WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +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 client->noClientException; + + masks = XkbFindClientResource((DevicePtr)dev,client); + if (!masks){ + XID id = FakeClientID(client->index); + AddResource(id,RT_XKBCLIENT,dev); + 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("Extra data (%d bytes) after SelectEvents\n",dataLeft); + return BadLength; + } + return client->noClientException; + } + 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 && other->coreEvents) + { + 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, DixReadAccess); + + xkb= &dev->key->xkbInfo->state; + bzero(&rep,sizeof(xkbGetStateReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.mods = dev->key->state&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 client->noClientException; +} + +/***====================================================================***/ + +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 ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) || + tmpd == dev) { + if (!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); + tmpd->key->state = XkbStateFieldFromRec(newState); + + 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 client->noClientException; +} + +/***====================================================================***/ + +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 = (SIZEOF(xkbGetControlsReply)- + SIZEOF(xGenericReply)) >> 2; + 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(client->noClientException); +} + +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.keyboard; tmpd; tmpd = tmpd->next) { + if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) || + tmpd == 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); + + 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 client->noClientException; +} + +/***====================================================================***/ + +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;i<rep->nTypes;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;i<rep->nTypes;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;n<type->map_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;n<type->map_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;i<rep->nKeySyms;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;i<XkbNumVirtualMods;i++,bit<<=1) { + if (rep->virtualMods&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;i<rep->nKeySyms;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;i<rep->nKeyActs;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;i<rep->nKeyActs;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;i<rep->nKeyActs;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;i<rep->nKeyBehaviors;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;i<rep->nKeyBehaviors;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;i<rep->nKeyExplicit;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;i<rep->nKeyExplicit;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;i<rep->nModMapKeys;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;i<rep->nModMapKeys;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;i<rep->nVModMapKeys-1;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;i<rep->nVModMapKeys-1;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= (char *)xalloc(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;i<XkbNumVirtualMods;i++,bit<<=1) { + if (rep->virtualMods&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("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); + xfree((char *)start); + return client->noClientException; +} + +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; + bzero(&rep,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 (nMaps<XkbNumRequiredTypes) { /* canonical types must be there */ + *nMapsRtrn= _XkbErrCode4(0x02,req->firstType,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;i<xkb->map->num_types;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + return 1; + } + + for (i=0;i<req->firstType;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + for (i=0;i<req->nTypes;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;n<wire->nMapEntries;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;i<nMaps;i++) { + mapWidthRtrn[i] = xkb->map->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); + map = &xkb->map->key_sym_map[xkb->min_key_code]; + for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) { + register int g,ng,w; + ng= XkbNumGroups(map->group_info); + for (w=g=0;g<ng;g++) { + if (map->kt_index[g]>=(unsigned)nTypes) { + *errorRtrn = _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; + } + for (i=0;i<req->nKeySyms;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;g<nG;g++) { + if (wire->ktIndex[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;g<nG;g++) { + if (map->kt_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;i<req->nKeyActs;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 (first<req->minKeyCode) { + *errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode); + return 0; + } + + for (i=0;i<req->totalKeyBehaviors;i++,wire++) { + if ((wire->key<first)||(wire->key>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;i<XkbNumVirtualMods;i++,bit<<=1) { + if (req->virtualMods&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 (first<req->minKeyCode) { + *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;i<req->totalKeyExplicit;i++,wire+=2) { + if ((wire[0]<first)||(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 (first<req->minKeyCode) { + *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;i<req->totalModMapKeys;i++,wire+=2) { + if ((wire[0]<first)||(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 (first<req->minKeyCode) { + *errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode); + return 0; + } + for (i=0;i<req->totalVModMapKeys;i++,wire++) { + if ((wire->key<first)||(wire->key>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;i<req->nTypes;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;n<wire->nMapEntries;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_type<first) + first= changes->map.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;i<req->nKeySyms;i++,oldMap++) { + pSyms = (KeySym *)&wire[1]; + if (wire->nSyms>0) { + newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms); + for (s=0;s<wire->nSyms;s++) { + newSyms[s]= pSyms[s]; + } + if (client->swapped) { + int n; + for (s=0;s<wire->nSyms;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_sym<first) + first= changes->map.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;i<req->nKeyActs;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_act<first) + first= changes->map.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; + bzero(&server->behaviors[first],req->nKeyBehaviors*sizeof(XkbBehavior)); + for (i=0;i<req->totalKeyBehaviors;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=(XkbRadioGroupPtr)_XkbRealloc(xkbi->radioGroups,sz); + else xkbi->radioGroups= (XkbRadioGroupPtr)_XkbCalloc(1, sz); + if (xkbi->radioGroups) { + if (xkbi->nRadioGroups) + bzero(&xkbi->radioGroups[xkbi->nRadioGroups], + (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_behavior<req->firstKeyBehavior) + 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;i<XkbNumVirtualMods;i++,bit<<=1) { + if (req->virtualMods&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; + bzero(&xkb->explicit[first],req->nKeyExplicit); + for (i=0;i<req->totalKeyExplicit;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_explicit<first) + first= changes->map.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; + bzero(&xkb->modmap[first],req->nModMapKeys); + for (i=0;i<req->totalModMapKeys;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_key<first) + first= changes->map.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; + bzero(&srv->vmodmap[first],req->nVModMapKeys*sizeof(unsigned short)); + for (i=0;i<req->totalVModMapKeys;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_key<first) + first= changes->map.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]; + CARD16 symsPerKey[XkbMaxLegalKeyCode + 1]; + + 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; + } + 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); + bzero(&change, 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 (firstMM<first) + first= firstMM; + if (lastMM>last) + 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); + + XkbUpdateCoreDescription(dev,False); + 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 && other->coreEvents) + { + 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 && other->coreEvents) + { + 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 client->noClientException; +} + +/***====================================================================***/ + +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;i<XkbNumKbdGroups;i++,bit<<=1) { + if (rep->groups&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 = (char *)xalloc(size); + if (data) { + register unsigned i,bit; + xkbModsWireDesc * grp; + XkbSymInterpretPtr sym= &compat->sym_interpret[rep->firstSI]; + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + for (i=0;i<rep->nSI;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;i<XkbNumKbdGroups;i++,bit<<=1) { + if (rep->groups&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); + xfree((char *)data); + } + return client->noClientException; +} + +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;i<XkbNumKbdGroups;i++,bit<<=1) { + if ( req->groups&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= _XkbTypedRealloc(compat->sym_interpret, + compat->num_si, + 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;i<req->nSI;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); + bzero(&change,sizeof(XkbChangesRec)); + XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check, + &cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + XkbUpdateCoreDescription(dev,False); + 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 && other->coreEvents) + { + 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, 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 && other->coreEvents) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetCompatMap(client, other, stuff, data, TRUE); + if (rc != Success) + return rc; + } + } + } + } + + return client->noClientException; +} + +/***====================================================================***/ + +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 client->noClientException; +} + +/***====================================================================***/ + +static Status +XkbComputeGetIndicatorMapReplySize( + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply *rep) +{ +register int i,bit; +int nIndicators; + + rep->realIndicators = indicators->phys_indicators; + for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (rep->which&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= (CARD8 *)xalloc(length); + if (map) { + xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *)to; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (rep->which&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); + 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); + xfree((char *)map); + } + return client->noClientException; +} + +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 client->noClientException; + + for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (stuff->which&bit) + nIndicators++; + } + if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+ + (nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) { + return BadLength; + } + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (stuff->which&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 && other->coreEvents) + { + 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;i<XkbNumIndicators;i++) { + if (stuff->indicator==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<<i))!=0); + rep.realIndicator= ((sli->physIndicators&(1<<i))!=0); + rep.ndx= i; + rep.flags= map->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 client->noClientException; +} + + +/** + * 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; + int led; + + /* search for the right indicator */ + map = NULL; + if (sli->names && sli->maps) { + for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { + if (sli->names[led] == indicator) { + map= &sli->maps[led]; + break; + } + } + } + + *led_return = led; + 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<<led); + sli->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<<led); + } + + if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) + { + if (stuff->on) sli->explicitState |= (1<<led); + else sli->explicitState &= ~(1<<led); + statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led)); + } + + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + bzero((char *)&changes,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) && other->coreEvents && + (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) && other->coreEvents && + (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) + { + _XkbSetNamedIndicator(client, other, stuff); + } + } + } + + return client->noClientException; +} + +/***====================================================================***/ + +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;i<maxAtoms;i++,bit<<=1) { + if (atoms[i]!=None) { + atomsPresent|= bit; + nAtoms++; + } + } + if (count) + *count= nAtoms; + return atomsPresent; +} + +static char * +_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap) +{ +register unsigned int i; +Atom *atm; + + atm = (Atom *)wire; + for (i=0;i<maxAtoms;i++) { + if (atoms[i]!=None) { + *atm= atoms[i]; + if (swap) { + register int n; + swapl(atm,n); + } + atm++; + } + } + return (char *)atm; +} + +static Status +XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep) +{ +register unsigned which,length; +register int i; + + rep->minKeyCode= 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;i<xkb->map->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 = (char *)xalloc(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;i<xkb->map->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;i<rep->nTypes;i++,type++) { + *desc++ = type->num_levels; + } + desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes; + + atm= (CARD32 *)desc; + type = xkb->map->types; + for (i=0;i<xkb->map->num_types;i++,type++) { + register unsigned l; + if (type->level_names) { + for (l=0;l<type->num_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;i<rep->nKeys;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;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) { + *((XkbKeyAliasPtr)desc)= *pAl; + } + } + if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) { + register CARD32 *atm= (CARD32 *)desc; + for (i=0;i<rep->nRadioGroups;i++,atm++) { + *atm= (CARD32)xkb->names->radio_groups[i]; + if (client->swapped) { + swapl(atm,n); + } + } + desc+= rep->nRadioGroups*4; + } + } + + if ((desc-start)!=(length)) { + ErrorF("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); + xfree((char *)start); + return client->noClientException; +} + +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; + 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;i<nAtoms;i++,wire++) { + if (swapped) { + register int n; + swapl(wire,n); + } + if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) { + *pError= ((Atom)*wire); + return NULL; + } + } + return wire; +} + +static CARD32 * +_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped, + Atom *pError) +{ +register unsigned i,bit; + + for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) { + if ((present&bit)==0) + continue; + if (swapped) { + register int n; + swapl(wire,n); + } + if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) { + *pError= (Atom)*wire; + return NULL; + } + wire++; + } + return wire; +} + +static Atom * +_XkbCopyMaskedAtoms( Atom *wire, + Atom *dest, + int nAtoms, + CARD32 present) +{ +register int i,bit; + + for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) { + if ((present&bit)==0) + continue; + dest[i]= *wire++; + } + return wire; +} + +static Bool +_XkbCheckTypeName(Atom name,int typeNdx) +{ +char * str; + + str= NameForAtom(name); + if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)|| + (strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0)) + return False; + return True; +} + +/** + * Check the device-dependent data in the request against the device. Returns + * Success, or the appropriate error code. + */ +static int +_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, + xkbSetNamesReq *stuff, CARD32 *data) +{ + XkbDescRec *xkb; + XkbNamesRec *names; + CARD32 *tmp; + Atom bad; + + tmp = data; + xkb = dev->key->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;i<stuff->nTypes;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;i<stuff->nKTLevels;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; + } + + bzero(&nn,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;i<stuff->nTypes;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;i<stuff->nKTLevels;i++,type++) { + if (width[i]>0) { + if (type->level_names) { + register unsigned n; + for (n=0;n<width[i];n++) { + type->level_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) { + _XkbFree(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;i<stuff->nRadioGroups;i++) { + names->radio_groups[i]= tmp[i]; + } + tmp+= stuff->nRadioGroups; + } + else if (names->radio_groups) { + _XkbFree(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;i<XkbNumIndicators;i++,bit<<=1) { + if (names->indicators[i]!=None) + sli->namesPresent|= bit; + } + bzero(&edev,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 && other->coreEvents) + { + + 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 && other->coreEvents) + { + + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + _XkbSetNames(client, other, stuff); + } + } + } + + /* everything is okay -- update names */ + + return client->noClientException; +} + +/***====================================================================***/ + +#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; + + len= (str?strlen(str):0); + 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;i<geom->num_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;i<geom->num_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;i<geom->num_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;i<geom->num_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;i<geom->num_shapes;i++,shape++) { + register int n; + register XkbOutlinePtr ol; + size+= SIZEOF(xkbShapeWireDesc); + for (n=0,ol=shape->outlines;n<shape->num_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;i<geom->num_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;o<shape->num_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;p<ol->num_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;i<num_doodads;i++,doodad++) { + size+= SIZEOF(xkbAnyDoodadWireDesc); + if (doodad->any.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;i<num_doodads;i++,doodad++) { + doodadWire= (xkbDoodadWireDesc *)wire; + wire= (char *)&doodadWire[1]; + bzero(doodadWire,SIZEOF(xkbDoodadWireDesc)); + doodadWire->any.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("Unknown doodad type %d in XkbWriteGeomDoodads\n", + doodad->any.type); + ErrorF("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;r<ol->num_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;k<row->num_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;i<geom->num_sections;i++,section++) { + size+= SIZEOF(xkbSectionWireDesc); + if (section->rows) { + int r; + XkbRowPtr row; + for (r=0,row=section->rows;r<section->num_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;o<section->num_overlays;o++,ol++) { + int r; + XkbOverlayRowPtr row; + size+= SIZEOF(xkbOverlayWireDesc); + for (r=0,row=ol->rows;r<ol->num_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;i<geom->num_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;r<section->num_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;k<row->num_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;o<section->num_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= (char *)xalloc(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("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) + xfree((char *)start); + if (freeGeom) + XkbFreeGeometry(geom,XkbGeomAllMask,True); + return client->noClientException; +} + +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= (char *)_XkbAlloc(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;r<olWire->nRows;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;k<rWire->nKeys;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;s<req->nSections;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;r<sWire->nRows;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;k<rWire->nKeys;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;d<sWire->nDoodads;d++) { + status=_CheckSetDoodad(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + if (sWire->nOverlays>0) { + register int o; + for (o=0;o<sWire->nOverlays;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;i<req->nShapes;i++) { + xkbOutlineWireDesc * olWire; + XkbOutlinePtr ol; + shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines); + if (!shape) + return BadAlloc; + olWire= (xkbOutlineWireDesc *)(&shapeWire[1]); + for (o=0;o<shapeWire->nOutlines;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;p<olWire->nPoints;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;i<req->nProperties;i++) { + char *name,*val; + name= _GetCountedString(&wire,client->swapped); + if (!name) + return BadAlloc; + val= _GetCountedString(&wire,client->swapped); + if (!val) { + xfree(name); + return BadAlloc; + } + if (XkbAddGeomProperty(geom,name,val)==NULL) { + xfree(name); + xfree(val); + return BadAlloc; + } + xfree(name); + xfree(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;i<req->nColors;i++) { + char *name; + name= _GetCountedString(&wire,client->swapped); + if (!name) + return BadAlloc; + if (!XkbAddGeomColor(geom,name,geom->num_colors)) { + xfree(name); + return BadAlloc; + } + xfree(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;i<req->nDoodads;i++) { + status=_CheckSetDoodad(&wire,geom,NULL,client); + if (status!=Success) + return status; + } + + for (i=0;i<req->nKeyAliases;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; + bzero(&nn,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 && other->coreEvents) + { + 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); + 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); + AddResource(id,RT_XKBCLIENT,dev); + 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 client->noClientException; +} + +/***====================================================================***/ + +/* 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= (unsigned char *)_XkbCalloc(1, len+1); + if (str) { + tmp= str; + for (i=0;i<len;i++) { + if (legal[(*wire)/8]&(1<<((*wire)%8))) + *tmp++= *wire++; + else wire++; + } + if (tmp!=str) + *tmp++= '\0'; + else { + _XkbFree(str); + str= NULL; + } + } + else { + *errRtrn= BadAlloc; + } + } + else { + str= NULL; + } + *pWire= wire; + return (char *)str; +} + +/***====================================================================***/ + +int +ProcXkbListComponents(ClientPtr client) +{ + DeviceIntPtr dev; + xkbListComponentsReply rep; + unsigned len; + int status; + unsigned char * str; + XkbSrvListInfoRec list; + + REQUEST(xkbListComponentsReq); + REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + status= Success; + str= (unsigned char *)&stuff[1]; + bzero(&list,sizeof(XkbSrvListInfoRec)); + list.maxRtrn= stuff->maxNames; + list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status); + 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) { + if (list.pool) { + _XkbFree(list.pool); + list.pool= NULL; + } + return status; + } + bzero(&rep,sizeof(xkbListComponentsReply)); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = XkbPaddedSize(list.nPool)/4; + rep.nKeymaps = list.nFound[_XkbListKeymaps]; + 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); + _XkbFree(list.pool); + list.pool= NULL; + } + return client->noClientException; +} + +/***====================================================================***/ + +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]; + names.keymap= GetComponentSpec(&str,True,&status); + 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; + } + + bzero(mapFile,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; + bzero(&changes,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= 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); + } + 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 || + (dev->id == inputInfo.keyboard->id && tmpd->key && + tmpd->coreEvents)) { + + memcpy(tmpd->key->modifierMap, xkb->map->modmap, + xkb->max_key_code + 1); + if (tmpd != dev) + XkbCopyKeymap(dev->key->xkbInfo->desc, + tmpd->key->xkbInfo->desc, True); + XkbUpdateCoreDescription(tmpd, True); + + 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); + } + } + } + + /* this should be either a MN or an NKN, depending on whether or not + * the keycode range changed? */ + 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 ((new!=NULL)&&(new!=xkb)) { + XkbFreeKeyboard(new,XkbAllComponentsMask,True); + new= NULL; + } + if (names.keymap) { _XkbFree(names.keymap); names.keymap= NULL; } + if (names.keycodes) { _XkbFree(names.keycodes); names.keycodes= NULL; } + if (names.types) { _XkbFree(names.types); names.types= NULL; } + if (names.compat) { _XkbFree(names.compat); names.compat= NULL; } + if (names.symbols) { _XkbFree(names.symbols); names.symbols= NULL; } + if (names.geometry) { _XkbFree(names.geometry); names.geometry= NULL; } + return client->noClientException; +} + +/***====================================================================***/ + +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;n<XkbNumIndicators;n++,bit<<=1) { + if (sli->names && 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) { + if (rep->supported&XkbXI_IndicatorsMask) { + 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;i<XkbNumIndicators;i++,bit<<=1) { + if (sli->namesPresent&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;i<XkbNumIndicators;i++,bit<<=1) { + xkbIndicatorMapWireDesc iwire; + if (sli->mapsPresent&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,supported; +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); + bzero((char *)&rep,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->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;i<rep.nBtnsRtrn;i++,act++) { + if (act->type!=XkbSA_NoAction) + break; + } + rep.firstBtnRtrn+= i; + rep.nBtnsRtrn-= i; + act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1]; + for (i=0;i<rep.nBtnsRtrn;i++,act--) { + if (act->type!=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; + supported= rep.supported; + 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= (char*) xalloc(nameLen); + if (!str) + return BadAlloc; + XkbWriteCountedString(str,dev->name,client->swapped); + WriteToClient(client,nameLen,str); + xfree(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("Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); + ErrorF(" Wrote %d fewer bytes than expected\n",length); + return BadLength; + } + if (stuff->wanted&(~supported)) { + xkbExtensionDeviceNotify ed; + bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify)); + ed.ledClass= ledClass; + ed.ledID= ledID; + ed.ledsDefined= 0; + ed.ledState= 0; + ed.firstBtn= ed.nBtns= 0; + ed.reason= XkbXI_UnsupportedFeatureMask; + ed.supported= supported; + ed.unsupported= stuff->wanted&(~supported); + XkbSendExtensionDeviceNotify(dev,client,&ed); + } + return client->noClientException; +} + +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;i<num;i++) { + if (client->swapped) { + 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;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->namesPresent&bit) + nNames++; + if (ledWire->mapsPresent&bit) + nMaps++; + } + atomWire= (CARD32 *)&ledWire[1]; + if (nNames>0) { + for (n=0;n<nNames;n++) { + if (client->swapped) { + 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;n<nMaps;n++) { + if (client->swapped) { + 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; + + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + bzero((char *)&changes,sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client); + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;i<num;i++) { + register int n; + register unsigned bit; + CARD32 * atomWire; + xkbIndicatorMapWireDesc * mapWire; + XkbSrvLedInfoPtr sli; + + namec= mapc= statec= 0; + sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,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; + bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom)); + } + if (ledWire->namesPresent) { + sli->namesPresent= ledWire->namesPresent; + bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom)); + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->namesPresent&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; + bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec)); + } + if (ledWire->mapsPresent) { + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->mapsPresent&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; + + bzero((char *)&ed,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= _XkbTypedCalloc(nBtns,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;i<stuff->nBtns;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) && other->coreEvents) && + ((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) && other->coreEvents) && + ((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 client->noClientException; +} + +/***====================================================================***/ + +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("XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags); + if (newCtrls!=xkbDebugCtrls) + ErrorF("XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls); + } + extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq; + if (stuff->msgLength>0) { + char *msg; + if (extraLength<XkbPaddedSize(stuff->msgLength)) { + ErrorF("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("XkbDebug: message not null-terminated\n"); + return BadValue; + } + ErrorF("XkbDebug: %s\n",msg); + } + xkbDebugFlags = newFlags; + xkbDebugCtrls = newCtrls; + + XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks); + + 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 client->noClientException; +} + +/***====================================================================***/ + +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("Internal Error! bad RemoveResourceClient in XkbClientGone\n"); + } + return 1; +} + +/*ARGSUSED*/ +static void +XkbResetProc(ExtensionEntry *extEntry) +{ +} + +void +XkbExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, + ProcXkbDispatch, SProcXkbDispatch, + XkbResetProc, StandardMinorOpcode))) { + XkbReqCode = (unsigned char)extEntry->base; + XkbEventBase = (unsigned char)extEntry->eventBase; + XkbErrorBase = (unsigned char)extEntry->errorBase; + XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard; + RT_XKBCLIENT = CreateNewResourceType(XkbClientGone); + } + return; +} + + diff --git a/xorg-server/xkb/xkb.h b/xorg-server/xkb/xkb.h new file mode 100644 index 000000000..bc6c6c954 --- /dev/null +++ b/xorg-server/xkb/xkb.h @@ -0,0 +1,40 @@ +#ifndef _XKB_H +#define _XKB_H + +extern int ProcXkbUseExtension(ClientPtr client); +extern int ProcXkbSelectEvents(ClientPtr client); +extern int ProcXkbBell(ClientPtr client); +extern int ProcXkbGetState(ClientPtr client); +extern int ProcXkbLatchLockState(ClientPtr client); +extern int ProcXkbGetControls(ClientPtr client); +extern int ProcXkbSetControls(ClientPtr client); +extern int ProcXkbGetMap(ClientPtr client); +extern int ProcXkbSetMap(ClientPtr client); +extern int ProcXkbGetCompatMap(ClientPtr client); +extern int ProcXkbSetCompatMap(ClientPtr client); +extern int ProcXkbGetIndicatorState(ClientPtr client); +extern int ProcXkbGetIndicatorMap(ClientPtr client); +extern int ProcXkbSetIndicatorMap(ClientPtr client); +extern int ProcXkbGetNamedIndicator(ClientPtr client); +extern int ProcXkbSetNamedIndicator(ClientPtr client); +extern int ProcXkbGetNames(ClientPtr client); +extern int ProcXkbSetNames(ClientPtr client); +extern int ProcXkbGetGeometry(ClientPtr client); +extern int ProcXkbSetGeometry(ClientPtr client); +extern int ProcXkbPerClientFlags(ClientPtr client); +extern int ProcXkbListComponents(ClientPtr client); +extern int ProcXkbGetKbdByName(ClientPtr client); +extern int ProcXkbGetDeviceInfo(ClientPtr client); +extern int ProcXkbSetDeviceInfo(ClientPtr client); +extern int ProcXkbSetDebuggingFlags(ClientPtr client); + +extern void XkbExtensionInit(void); + +extern Bool XkbFilterEvents(ClientPtr pClient, int nEvents, xEvent *xE); + +extern Bool XkbCopyKeymap( + XkbDescPtr src, + XkbDescPtr dst, + Bool sendNotifies); + +#endif diff --git a/xorg-server/xkb/xkbAccessX.c b/xorg-server/xkb/xkbAccessX.c new file mode 100644 index 000000000..89be839d0 --- /dev/null +++ b/xorg-server/xkb/xkbAccessX.c @@ -0,0 +1,770 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#include <math.h> +#ifdef __QNX__ +#include <limits.h> +#endif +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include <xkbsrv.h> +#if !defined(WIN32) && !defined(Lynx) +#include <sys/time.h> +#endif + +_X_EXPORT int XkbDfltRepeatDelay= 660; +_X_EXPORT int XkbDfltRepeatInterval= 40; +pointer XkbLastRepeatEvent= NULL; + +#define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask) +#define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask) + +unsigned short XkbDfltAccessXTimeout= 120; +unsigned int XkbDfltAccessXTimeoutMask= DFLT_TIMEOUT_CTRLS; +static unsigned int XkbDfltAccessXTimeoutValues= 0; +static unsigned int XkbDfltAccessXTimeoutOptionsMask= DFLT_TIMEOUT_OPTS; +static unsigned int XkbDfltAccessXTimeoutOptionsValues= 0; +unsigned int XkbDfltAccessXFeedback= XkbAccessXFeedbackMask; +unsigned short XkbDfltAccessXOptions= XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask|XkbAX_SKReleaseFBMask|XkbAX_SKRejectFBMask); + +void +AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls) +{ + xkbi->mouseKeysCurve= 1.0+(((double)ctrls->mk_curve)*0.001); + xkbi->mouseKeysCurveFactor= ( ((double)ctrls->mk_max_speed)/ + pow((double)ctrls->mk_time_to_max,xkbi->mouseKeysCurve)); + return; +} + +void +AccessXInit(DeviceIntPtr keybd) +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; + + xkbi->shiftKeyCount= 0; + xkbi->mouseKeysCounter= 0; + xkbi->inactiveKey= 0; + xkbi->slowKey= 0; + xkbi->repeatKey= 0; + xkbi->krgTimerActive= _OFF_TIMER; + xkbi->beepType= _BEEP_NONE; + xkbi->beepCount= 0; + xkbi->mouseKeyTimer= NULL; + xkbi->slowKeysTimer= NULL; + xkbi->bounceKeysTimer= NULL; + xkbi->repeatKeyTimer= NULL; + xkbi->krgTimer= NULL; + xkbi->beepTimer= NULL; + ctrls->repeat_delay = XkbDfltRepeatDelay; + ctrls->repeat_interval = XkbDfltRepeatInterval; + ctrls->debounce_delay = 300; + ctrls->slow_keys_delay = 300; + ctrls->mk_delay = 160; + ctrls->mk_interval = 40; + ctrls->mk_time_to_max = 30; + ctrls->mk_max_speed = 30; + ctrls->mk_curve = 500; + ctrls->mk_dflt_btn = 1; + ctrls->ax_timeout = XkbDfltAccessXTimeout; + ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask; + ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues; + ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask; + ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues; + if (XkbDfltAccessXTimeout) + ctrls->enabled_ctrls |= XkbAccessXTimeoutMask; + else + ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask; + ctrls->enabled_ctrls |= XkbDfltAccessXFeedback; + ctrls->ax_options = XkbDfltAccessXOptions; + AccessXComputeCurveFactor(xkbi,ctrls); + return; +} + +/************************************************************************/ +/* */ +/* AccessXKeyboardEvent */ +/* */ +/* Generate a synthetic keyboard event. */ +/* */ +/************************************************************************/ +static void +AccessXKeyboardEvent(DeviceIntPtr keybd, + BYTE type, + BYTE keyCode, + Bool isRepeat) +{ +xEvent xE; + + xE.u.u.type = type; + xE.u.u.detail = keyCode; + xE.u.keyButtonPointer.time = GetTimeInMillis(); + if (xkbDebugFlags&0x8) { + DebugF("AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up")); + } + + if (_XkbIsPressEvent(type)) + XkbDDXKeyClick(keybd,keyCode,TRUE); + else if (isRepeat) + XkbLastRepeatEvent= (pointer)&xE; + XkbProcessKeyboardEvent(&xE,keybd,1L); + XkbLastRepeatEvent= NULL; + return; + +} /* AccessXKeyboardEvent */ + +/************************************************************************/ +/* */ +/* AccessXKRGTurnOn */ +/* */ +/* Turn the keyboard response group on. */ +/* */ +/************************************************************************/ +static void +AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old= *ctrls; + ctrls->enabled_ctrls |= (KRGControl&XkbAX_KRGMask); + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,KRGControl); + return; + +} /* AccessXKRGTurnOn */ + +/************************************************************************/ +/* */ +/* AccessXKRGTurnOff */ +/* */ +/* Turn the keyboard response group off. */ +/* */ +/************************************************************************/ +static void +AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls &= ~XkbAX_KRGMask; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + unsigned changes= old.enabled_ctrls^ctrls->enabled_ctrls; + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,changes); + } + return; + +} /* AccessXKRGTurnOff */ + +/************************************************************************/ +/* */ +/* AccessXStickyKeysTurnOn */ +/* */ +/* Turn StickyKeys on. */ +/* */ +/************************************************************************/ +static void +AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls |= XkbStickyKeysMask; + xkbi->shiftKeyCount = 0; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,XkbStickyKeysMask); + } + return; + +} /* AccessXStickyKeysTurnOn */ + +/************************************************************************/ +/* */ +/* AccessXStickyKeysTurnOff */ +/* */ +/* Turn StickyKeys off. */ +/* */ +/************************************************************************/ +static void +AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls &= ~XkbStickyKeysMask; + xkbi->shiftKeyCount = 0; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,XkbStickyKeysMask); + } +#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF + XkbClearAllLatchesAndLocks(dev,xkbi,False,&cause); +#endif + return; +} /* AccessXStickyKeysTurnOff */ + +static CARD32 +AccessXKRGExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; +xkbControlsNotify cn; + + if (xkbi->krgTimerActive==_KRG_WARN_TIMER) { + XkbDDXAccessXBeep((DeviceIntPtr)arg,_BEEP_SLOW_WARN,XkbStickyKeysMask); + xkbi->krgTimerActive= _KRG_TIMER; + return 4000; + } + xkbi->krgTimerActive= _OFF_TIMER; + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = 0; + cn.requestMinor = 0; + if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask) + AccessXKRGTurnOff((DeviceIntPtr)arg,&cn); + else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn); + return 0; +} + +static CARD32 +AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +DeviceIntPtr dev = (DeviceIntPtr) arg; +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +KeyCode key; +BOOL is_core; + + if (xkbi->repeatKey == 0) + return 0; + + is_core = (dev == inputInfo.keyboard); + key = xkbi->repeatKey; + AccessXKeyboardEvent(dev, is_core ? KeyRelease : DeviceKeyRelease, key, + True); + AccessXKeyboardEvent(dev, is_core ? KeyPress : DeviceKeyPress, key, True); + return xkbi->desc->ctrls->repeat_interval; +} + +void +AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key) +{ + if (xkbi->repeatKey==key) + xkbi->repeatKey= 0; + return; +} + +static CARD32 +AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +DeviceIntPtr keybd; +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +XkbControlsPtr ctrls; + + keybd= (DeviceIntPtr)arg; + xkbi= keybd->key->xkbInfo; + xkb= xkbi->desc; + ctrls= xkb->ctrls; + if (xkbi->slowKey!=0) { + xkbAccessXNotify ev; + KeySym *sym= XkbKeySymsPtr(xkb,xkbi->slowKey); + ev.detail= XkbAXN_SKAccept; + ev.keycode= xkbi->slowKey; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKAcceptFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_SLOW_ACCEPT,XkbSlowKeysMask); + AccessXKeyboardEvent(keybd, + (keybd == inputInfo.keyboard) ? KeyPress : DeviceKeyPress, + xkbi->slowKey,False); + /* check for magic sequences */ + if ((ctrls->enabled_ctrls&XkbAccessXKeysMask) && + ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L))) + xkbi->shiftKeyCount++; + + /* Start repeating if necessary. Stop autorepeating if the user + * presses a non-modifier key that doesn't autorepeat. + */ + if (keybd->kbdfeed->ctrl.autoRepeat && + ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) && + (ctrls->enabled_ctrls&XkbRepeatKeysMask)) { + if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,xkbi->slowKey)) { + xkbi->repeatKey = xkbi->slowKey; + xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, + 0, ctrls->repeat_delay, + AccessXRepeatKeyExpire, (pointer)keybd); + } + } + } + return 0; +} + +static CARD32 +AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; + + xkbi->inactiveKey= 0; + return 0; +} + +static CARD32 +AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +DeviceIntPtr dev = (DeviceIntPtr)arg; +XkbSrvInfoPtr xkbi= dev->key->xkbInfo; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +XkbControlsRec old; +xkbControlsNotify cn; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + if (xkbi->lastPtrEventTime) { + unsigned timeToWait = (ctrls->ax_timeout*1000); + unsigned timeElapsed = (now-xkbi->lastPtrEventTime); + + if (timeToWait > timeElapsed) + return (timeToWait - timeElapsed); + } + old= *ctrls; + xkbi->shiftKeyCount= 0; + ctrls->enabled_ctrls&= ~ctrls->axt_ctrls_mask; + ctrls->enabled_ctrls|= + (ctrls->axt_ctrls_values&ctrls->axt_ctrls_mask); + if (ctrls->axt_opts_mask) { + ctrls->ax_options&= ~ctrls->axt_opts_mask; + ctrls->ax_options|= (ctrls->axt_opts_values&ctrls->axt_opts_mask); + } + if (XkbComputeControlsNotify(dev,&old,ctrls,&cn,False)) { + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(dev,&cn); + } + XkbSetCauseUnknown(&cause); + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (ctrls->ax_options!=old.ax_options) { + unsigned set,cleared,bell; + set= ctrls->ax_options&(~old.ax_options); + cleared= (~ctrls->ax_options)&old.ax_options; + if (set && cleared) bell= _BEEP_FEATURE_CHANGE; + else if (set) bell= _BEEP_FEATURE_ON; + else bell= _BEEP_FEATURE_OFF; + XkbDDXAccessXBeep(dev,bell,XkbAccessXTimeoutMask); + } + xkbi->krgTimerActive= _OFF_TIMER; + return 0; +} + + +/************************************************************************/ +/* */ +/* AccessXFilterPressEvent */ +/* */ +/* Filter events before they get any further if SlowKeys is turned on. */ +/* In addition, this routine handles the ever so popular magic key */ +/* acts for turning various accessibility features on/off. */ +/* */ +/* Returns TRUE if this routine has discarded the event. */ +/* Returns FALSE if the event needs further processing. */ +/* */ +/************************************************************************/ +Bool +AccessXFilterPressEvent( register xEvent * xE, + register DeviceIntPtr keybd, + int count) +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +Bool ignoreKeyEvent = FALSE; +KeyCode key = xE->u.u.detail; +KeySym * sym = XkbKeySymsPtr(xkbi->desc,key); + + if (ctrls->enabled_ctrls&XkbAccessXKeysMask) { + /* check for magic sequences */ + if ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)) { + if (XkbAX_NeedFeedback(ctrls,XkbAX_SlowWarnFBMask)) { + xkbi->krgTimerActive = _KRG_WARN_TIMER; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 4000, + AccessXKRGExpire, (pointer)keybd); + } + else { + xkbi->krgTimerActive = _KRG_TIMER; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 8000, + AccessXKRGExpire, (pointer)keybd); + } + if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) { + CARD32 now= GetTimeInMillis(); + if ((now-xkbi->lastShiftEventTime)>15000) + xkbi->shiftKeyCount= 1; + else xkbi->shiftKeyCount++; + xkbi->lastShiftEventTime= now; + } + } + else { + if (xkbi->krgTimerActive) { + xkbi->krgTimer= TimerSet(xkbi->krgTimer,0, 0, NULL, NULL); + xkbi->krgTimerActive= _OFF_TIMER; + } + } + } + + /* Don't transmit the KeyPress if SlowKeys is turned on; + * The wakeup handler will synthesize one for us if the user + * has held the key long enough. + */ + if (ctrls->enabled_ctrls & XkbSlowKeysMask) { + xkbAccessXNotify ev; + /* If key was already pressed, ignore subsequent press events + * from the server's autorepeat + */ + if(xkbi->slowKey == key) + return TRUE; + ev.detail= XkbAXN_SKPress; + ev.keycode= key; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKPressFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_SLOW_PRESS,XkbSlowKeysMask); + xkbi->slowKey= key; + xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer, + 0, ctrls->slow_keys_delay, + AccessXSlowKeyExpire, (pointer)keybd); + ignoreKeyEvent = TRUE; + } + + /* Don't transmit the KeyPress if BounceKeys is turned on + * and the user pressed the same key within a given time period + * from the last release. + */ + else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) && + (key == xkbi->inactiveKey)) { + if (XkbAX_NeedFeedback(ctrls,XkbAX_BKRejectFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_BOUNCE_REJECT,XkbBounceKeysMask); + ignoreKeyEvent = TRUE; + } + + /* Start repeating if necessary. Stop autorepeating if the user + * presses a non-modifier key that doesn't autorepeat. + */ + if (XkbDDXUsesSoftRepeat(keybd)) { + if ((keybd->kbdfeed->ctrl.autoRepeat) && + ((ctrls->enabled_ctrls&(XkbSlowKeysMask|XkbRepeatKeysMask))== + XkbRepeatKeysMask)) { + if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) { + if (xkbDebugFlags&0x10) + DebugF("Starting software autorepeat...\n"); + xkbi->repeatKey = key; + xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, + 0, ctrls->repeat_delay, + AccessXRepeatKeyExpire, (pointer)keybd); + } + } + } + + /* Check for two keys being pressed at the same time. This section + * essentially says the following: + * + * If StickyKeys is on, and a modifier is currently being held down, + * and one of the following is true: the current key is not a modifier + * or the currentKey is a modifier, but not the only modifier being + * held down, turn StickyKeys off if the TwoKeys off ctrl is set. + */ + if ((ctrls->enabled_ctrls & XkbStickyKeysMask) && + (xkbi->state.base_mods!=0) && + (XkbAX_NeedOption(ctrls,XkbAX_TwoKeysMask))) { + xkbControlsNotify cn; + cn.keycode = key; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + AccessXStickyKeysTurnOff(keybd,&cn); + } + + if (!ignoreKeyEvent) + XkbProcessKeyboardEvent(xE,keybd,count); + return ignoreKeyEvent; +} /* AccessXFilterPressEvent */ + +/************************************************************************/ +/* */ +/* AccessXFilterReleaseEvent */ +/* */ +/* Filter events before they get any further if SlowKeys is turned on. */ +/* In addition, this routine handles the ever so popular magic key */ +/* acts for turning various accessibility features on/off. */ +/* */ +/* Returns TRUE if this routine has discarded the event. */ +/* Returns FALSE if the event needs further processing. */ +/* */ +/************************************************************************/ +Bool +AccessXFilterReleaseEvent( register xEvent * xE, + register DeviceIntPtr keybd, + int count) +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +KeyCode key = xE->u.u.detail; +Bool ignoreKeyEvent = FALSE; + + /* Don't transmit the KeyRelease if BounceKeys is on and + * this is the release of a key that was ignored due to + * BounceKeys. + */ + if (ctrls->enabled_ctrls & XkbBounceKeysMask) { + if ((key!=xkbi->mouseKey)&&(!BitIsOn(keybd->key->down,key))) + ignoreKeyEvent = TRUE; + xkbi->inactiveKey= key; + xkbi->bounceKeysTimer= TimerSet(xkbi->bounceKeysTimer, 0, + ctrls->debounce_delay, + AccessXBounceKeyExpire, (pointer)keybd); + } + + /* Don't transmit the KeyRelease if SlowKeys is turned on and + * the user didn't hold the key long enough. We know we passed + * the key if the down bit was set by CoreProcessKeyboadEvent. + */ + if (ctrls->enabled_ctrls & XkbSlowKeysMask) { + xkbAccessXNotify ev; + unsigned beep_type; + ev.keycode= key; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + if (BitIsOn(keybd->key->down,key) | (xkbi->mouseKey == key)) { + ev.detail= XkbAXN_SKRelease; + beep_type= _BEEP_SLOW_RELEASE; + } + else { + ev.detail= XkbAXN_SKReject; + beep_type= _BEEP_SLOW_REJECT; + ignoreKeyEvent = TRUE; + } + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKRejectFBMask)) { + XkbDDXAccessXBeep(keybd,beep_type,XkbSlowKeysMask); + } + if (xkbi->slowKey==key) + xkbi->slowKey= 0; + } + + /* Stop Repeating if the user releases the key that is currently + * repeating. + */ + if (xkbi->repeatKey==key) { + xkbi->repeatKey= 0; + } + + if ((ctrls->enabled_ctrls&XkbAccessXTimeoutMask)&&(ctrls->ax_timeout>0)) { + xkbi->lastPtrEventTime= 0; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, + ctrls->ax_timeout*1000, + AccessXTimeoutExpire, (pointer)keybd); + xkbi->krgTimerActive= _ALL_TIMEOUT_TIMER; + } + else if (xkbi->krgTimerActive!=_OFF_TIMER) { + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL); + xkbi->krgTimerActive= _OFF_TIMER; + } + + /* Keep track of how many times the Shift key has been pressed. + * If it has been pressed and released 5 times in a row, toggle + * the state of StickyKeys. + */ + if ((!ignoreKeyEvent)&&(xkbi->shiftKeyCount)) { + KeySym *pSym= XkbKeySymsPtr(xkbi->desc,key); + if ((pSym[0]!=XK_Shift_L)&&(pSym[0]!=XK_Shift_R)) { + xkbi->shiftKeyCount= 0; + } + else if (xkbi->shiftKeyCount>=5) { + xkbControlsNotify cn; + cn.keycode = key; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + if (ctrls->enabled_ctrls & XkbStickyKeysMask) + AccessXStickyKeysTurnOff(keybd,&cn); + else + AccessXStickyKeysTurnOn(keybd,&cn); + xkbi->shiftKeyCount= 0; + } + } + + if (!ignoreKeyEvent) + XkbProcessKeyboardEvent(xE,keybd,count); + return ignoreKeyEvent; + +} /* AccessXFilterReleaseEvent */ + +/************************************************************************/ +/* */ +/* ProcessPointerEvent */ +/* */ +/* This routine merely sets the shiftKeyCount and clears the keyboard */ +/* response group timer (if necessary) on a mouse event. This is so */ +/* multiple shifts with just the mouse and shift-drags with the mouse */ +/* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/ +/* */ +/************************************************************************/ +void +ProcessPointerEvent( register xEvent * xE, + register DeviceIntPtr mouse, + int count) +{ +DeviceIntPtr dev = inputInfo.keyboard; +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +unsigned changed = 0; +ProcessInputProc backupproc; +xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse); + + xkbi->shiftKeyCount = 0; + xkbi->lastPtrEventTime= xE->u.keyButtonPointer.time; + + if (xE->u.u.type==ButtonPress) { + changed |= XkbPointerButtonMask; + } + else if (xE->u.u.type==ButtonRelease) { + xkbi->lockedPtrButtons&= ~(1<<(xE->u.u.detail&0x7)); + changed |= XkbPointerButtonMask; + } + + /* Guesswork. mostly. + * xkb actuall goes through some effort to transparently wrap the + * processInputProcs (see XkbSetExtension). But we all love fun, so the + * previous XKB implementation just hardcoded the CPPE call here instead + * of unwrapping like anybody with any sense of decency would do. + * I got no clue what the correct thing to do is, but my guess is that + * it's not hardcoding. I may be wrong. whatever it is, don't come whining + * to me. I just work here. + * + * Anyway. here's the old call, if you don't like the wrapping, revert it. + * + * CoreProcessPointerEvent(xE,mouse,count); + * + * see. it's still steaming. told you. (whot) + */ + UNWRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc); + mouse->public.processInputProc(xE, mouse, count); + COND_WRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, + backupproc, xkbUnwrapProc); + + xkbi->state.ptr_buttons = mouse->button->state; + + /* clear any latched modifiers */ + if ( xkbi->state.latched_mods && (xE->u.u.type==ButtonRelease) ) { + unsigned changed_leds; + XkbStateRec oldState; + XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + oldState= xkbi->state; + XkbLatchModifiers(dev,0xFF,0x00); + + XkbComputeDerivedState(xkbi); + changed |= XkbStateChangedFlags(&oldState,&xkbi->state); + if (changed&sli->usedComponents) { + changed_leds= XkbIndicatorsToUpdate(dev,changed,False); + if (changed_leds) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause,(xE->u.u.detail&0x7),xE->u.u.type); + XkbUpdateIndicators(dev,changed_leds,True,NULL,&cause); + } + } + dev->key->state= XkbStateFieldFromRec(&xkbi->state); + } + + if (((xkbi->flags&_XkbStateNotifyInProgress)==0)&&(changed!=0)) { + xkbStateNotify sn; + sn.keycode= xE->u.u.detail; + sn.eventType= xE->u.u.type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + +} /* ProcessPointerEvent */ + + + + diff --git a/xorg-server/xkb/xkbActions.c b/xorg-server/xkb/xkbActions.c new file mode 100644 index 000000000..8c72874df --- /dev/null +++ b/xorg-server/xkb/xkbActions.c @@ -0,0 +1,1418 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "exevents.h" +#include <xkbsrv.h> +#include "xkb.h" +#include <ctype.h> +#define EXTENSION_EVENT_BASE 64 + +DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKey; + +void +xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, + pointer data) +{ + xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device); + ProcessInputProc backupproc; + if(xkbPrivPtr->unwrapProc) + xkbPrivPtr->unwrapProc = NULL; + + UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc); + proc(device,data); + COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, + backupproc,xkbUnwrapProc); +} + + +void +XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc) +{ + xkbDeviceInfoPtr xkbPrivPtr; + + xkbPrivPtr = (xkbDeviceInfoPtr) xcalloc(1, sizeof(xkbDeviceInfoRec)); + if (!xkbPrivPtr) + return; + xkbPrivPtr->unwrapProc = NULL; + + dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr); + WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc); +} + +extern void ProcessOtherEvent( + xEvent * /* xE */, + DeviceIntPtr /* dev */, + int /* count */ +); + +/***====================================================================***/ + +static XkbAction +_FixUpAction(XkbDescPtr xkb,XkbAction *act) +{ +static XkbAction fake; + + if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) { + fake.type = XkbSA_NoAction; + return fake; + } + if (XkbDisableLockActions) { + switch (act->type) { + case XkbSA_LockMods: + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->mods.mask; + return fake; + case XkbSA_LatchMods: + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->mods.mask; + return fake; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_ISODfltIsGroup) { + fake.group.type = XkbSA_SetGroup; + fake.group.flags = act->iso.flags&XkbSA_GroupAbsolute; + XkbSASetGroup(&fake.group,XkbSAGroup(&act->iso)); + } + else { + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->iso.mask; + } + return fake; + case XkbSA_LockGroup: + case XkbSA_LatchGroup: + /* We want everything from the latch/lock action except the + * type should be changed to set. + */ + fake = *act; + fake.group.type = XkbSA_SetGroup; + return fake; + } + } + else + if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) { + if (act->any.type==XkbSA_SetMods) { + fake.mods.type = XkbSA_LatchMods; + fake.mods.mask = act->mods.mask; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.mods.flags= XkbSA_ClearLocks; + return fake; + } + if (act->any.type==XkbSA_SetGroup) { + fake.group.type = XkbSA_LatchGroup; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.group.flags= XkbSA_ClearLocks; + XkbSASetGroup(&fake.group,XkbSAGroup(&act->group)); + return fake; + } + } + return *act; +} + +static XkbAction +XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key) +{ +int effectiveGroup; +int col; +XkbDescPtr xkb; +XkbKeyTypePtr type; +XkbAction * pActs; +static XkbAction fake; + + xkb= xkbi->desc; + if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) { + fake.type = XkbSA_NoAction; + return fake; + } + pActs= XkbKeyActionsPtr(xkb,key); + col= 0; + effectiveGroup= xkbState->group; + if (effectiveGroup!=XkbGroup1Index) { + if (XkbKeyNumGroups(xkb,key)>(unsigned)1) { + if (effectiveGroup>=XkbKeyNumGroups(xkb,key)) { + unsigned gi= XkbKeyGroupInfo(xkb,key); + switch (XkbOutOfRangeGroupAction(gi)) { + default: + case XkbWrapIntoRange: + effectiveGroup %= XkbKeyNumGroups(xkb,key); + break; + case XkbClampIntoRange: + effectiveGroup = XkbKeyNumGroups(xkb,key)-1; + break; + case XkbRedirectIntoRange: + effectiveGroup= XkbOutOfRangeGroupInfo(gi); + if (effectiveGroup>=XkbKeyNumGroups(xkb,key)) + effectiveGroup= 0; + break; + } + } + } + else effectiveGroup= XkbGroup1Index; + col+= (effectiveGroup*XkbKeyGroupsWidth(xkb,key)); + } + type= XkbKeyKeyType(xkb,key,effectiveGroup); + if (type->map!=NULL) { + register unsigned i,mods; + register XkbKTMapEntryPtr entry; + mods= xkbState->mods&type->mods.mask; + for (entry= type->map,i=0;i<type->map_count;i++,entry++) { + if ((entry->active)&&(entry->mods.mask==mods)) { + col+= entry->level; + break; + } + } + } + if (pActs[col].any.type==XkbSA_NoAction) + return pActs[col]; + fake= _FixUpAction(xkb,&pActs[col]); + return fake; +} + +static XkbAction +XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button) +{ +XkbAction fake; + if ((dev->button)&&(dev->button->xkb_acts)) { + if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) { + fake= _FixUpAction(kbd->key->xkbInfo->desc, + &dev->button->xkb_acts[button-1]); + return fake; + } + } + fake.any.type= XkbSA_NoAction; + return fake; +} + +/***====================================================================***/ + +#define SYNTHETIC_KEYCODE 1 +#define BTN_ACT_FLAG 0x100 + +static int +_XkbFilterSetState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction *pAction) +{ + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0); + filter->priv = 0; + filter->filter = _XkbFilterSetState; + if (pAction->type==XkbSA_SetMods) { + filter->upAction = *pAction; + xkbi->setMods= pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if (filter->keycode==keycode) { + if (filter->upAction.type==XkbSA_SetMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if (filter->upAction.mods.flags&XkbSA_ClearLocks) { + xkbi->state.locked_mods&= ~filter->upAction.mods.mask; + } + } + else { + if (filter->upAction.group.flags&XkbSA_ClearLocks) { + xkbi->state.locked_group = 0; + } + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + } + filter->active = 0; + } + else { + filter->upAction.mods.flags&= ~XkbSA_ClearLocks; + filter->filterOthers = 0; + } + return 1; +} + +#define LATCH_KEY_DOWN 1 +#define LATCH_PENDING 2 +#define NO_LATCH 3 + +static int +_XkbFilterLatchState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = LATCH_KEY_DOWN; + filter->filter = _XkbFilterLatchState; + if (pAction->type==XkbSA_LatchMods) { + filter->upAction = *pAction; + xkbi->setMods = pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if ( pAction && (filter->priv==LATCH_PENDING) ) { + if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) { + filter->active = 0; + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + } + else if ((pAction->type==filter->upAction.type)&& + (pAction->mods.flags==filter->upAction.mods.flags)&& + (pAction->mods.mask==filter->upAction.mods.mask)) { + if (filter->upAction.mods.flags&XkbSA_LatchToLock) { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_LockMods; + else pAction->group.type= XkbSA_LockGroup; + if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&& + (ctrls->enabled_ctrls&XkbStickyKeysMask)) { + XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK, + XkbStickyKeysMask); + } + } + else { + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_SetMods; + else pAction->group.type= XkbSA_SetGroup; + } + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + filter->active = 0; + } + } + else if (filter->keycode==keycode) { /* release */ + XkbControlsPtr ctrls= xkbi->desc->ctrls; + int needBeep; + int beepType= _BEEP_NONE; + + needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&& + XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)); + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&& + (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) { + xkbi->state.locked_mods&= ~xkbi->clearMods; + filter->priv= NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + else { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + if ((filter->upAction.group.flags&XkbSA_ClearLocks)&& + (xkbi->state.locked_group)) { + xkbi->state.locked_group = 0; + filter->priv = NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + if (filter->priv==NO_LATCH) { + filter->active= 0; + } + else { + filter->priv= LATCH_PENDING; + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->state.latched_mods |= filter->upAction.mods.mask; + needBeep = xkbi->state.latched_mods ? needBeep : 0; + xkbi->state.latched_mods |= filter->upAction.mods.mask; + } + else { + xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group); + } + if (needBeep && (beepType==_BEEP_NONE)) + beepType= _BEEP_STICKY_LATCH; + } + if (needBeep && (beepType!=_BEEP_NONE)) + XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask); + } + else if (filter->priv==LATCH_KEY_DOWN) { + filter->priv= NO_LATCH; + filter->filterOthers = 0; + } + return 1; +} + +static int +_XkbFilterLockState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + if (pAction&&(pAction->type==XkbSA_LockGroup)) { + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->state.locked_group= XkbSAGroup(&pAction->group); + else xkbi->state.locked_group+= XkbSAGroup(&pAction->group); + return 1; + } + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterLockState; + filter->upAction = *pAction; + xkbi->state.locked_mods^= pAction->mods.mask; + xkbi->setMods = pAction->mods.mask; + } + else if (filter->keycode==keycode) { + filter->active = 0; + xkbi->clearMods = filter->upAction.mods.mask; + } + return 1; +} + +#define ISO_KEY_DOWN 0 +#define NO_ISO_LOCK 1 + +static int +_XkbFilterISOLock( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + + if (filter->keycode==0) { /* initial press */ + CARD8 flags= pAction->iso.flags; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = ISO_KEY_DOWN; + filter->upAction = *pAction; + filter->filter = _XkbFilterISOLock; + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = XkbSAGroup(&pAction->iso); + xkbi->setMods = 0; + } + else { + xkbi->setMods = pAction->iso.mask; + xkbi->groupChange = 0; + } + if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) { + filter->priv= NO_ISO_LOCK; + xkbi->state.locked_mods^= xkbi->state.base_mods; + } + if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) { +/* 6/22/93 (ef) -- lock groups if group key is down first */ + } + if (!(flags&XkbSA_ISONoAffectPtr)) { +/* 6/22/93 (ef) -- lock mouse buttons if they're down */ + } + } + else if (filter->keycode==keycode) { + CARD8 flags= filter->upAction.iso.flags; + + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso); + xkbi->clearMods = 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso); + } + else { + xkbi->clearMods= filter->upAction.iso.mask; + xkbi->groupChange= 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_mods^= filter->upAction.iso.mask; + } + filter->active = 0; + } + else if (pAction) { + CARD8 flags= filter->upAction.iso.flags; + + switch (pAction->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: + if (!(flags&XkbSA_ISONoAffectMods)) { + pAction->type= XkbSA_LockMods; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetGroup: case XkbSA_LatchGroup: + if (!(flags&XkbSA_ISONoAffectGroup)) { + pAction->type= XkbSA_LockGroup; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_PtrBtn: + if (!(flags&XkbSA_ISONoAffectPtr)) { + pAction->type= XkbSA_LockPtrBtn; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetControls: + if (!(flags&XkbSA_ISONoAffectCtrls)) { + pAction->type= XkbSA_LockControls; + filter->priv= NO_ISO_LOCK; + } + break; + } + } + return 1; +} + + +static CARD32 +_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +int dx,dy; + + if (xkbi->mouseKey==0) + return 0; + + if (xkbi->mouseKeysAccel) { + if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) { + double step; + xkbi->mouseKeysCounter++; + step= xkbi->mouseKeysCurveFactor* + pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve); + if (xkbi->mouseKeysDX<0) + dx= floor( ((double)xkbi->mouseKeysDX)*step ); + else dx= ceil( ((double)xkbi->mouseKeysDX)*step ); + if (xkbi->mouseKeysDY<0) + dy= floor( ((double)xkbi->mouseKeysDY)*step ); + else dy= ceil( ((double)xkbi->mouseKeysDY)*step ); + } + else { + dx= xkbi->mouseKeysDX*ctrls->mk_max_speed; + dy= xkbi->mouseKeysDY*ctrls->mk_max_speed; + } + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX) + dx= xkbi->mouseKeysDX; + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY) + dy= xkbi->mouseKeysDY; + } + else { + dx= xkbi->mouseKeysDX; + dy= xkbi->mouseKeysDY; + } + XkbDDXFakePointerMotion(xkbi->mouseKeysFlags,dx,dy); + return xkbi->desc->ctrls->mk_interval; +} + +static int +_XkbFilterPointerMove( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +int x,y; +Bool accel; + + if (xkbi->device == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerMove; + filter->upAction= *pAction; + xkbi->mouseKeysCounter= 0; + xkbi->mouseKey= keycode; + accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0); + x= XkbPtrActionX(&pAction->ptr); + y= XkbPtrActionY(&pAction->ptr); + XkbDDXFakePointerMotion(pAction->ptr.flags,x,y); + AccessXCancelRepeatKey(xkbi,keycode); + xkbi->mouseKeysAccel= accel&& + (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask); + xkbi->mouseKeysFlags= pAction->ptr.flags; + xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr); + xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr); + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, + xkbi->desc->ctrls->mk_delay, + _XkbPtrAccelExpire,(pointer)xkbi); + } + else if (filter->keycode==keycode) { + filter->active = 0; + if (xkbi->mouseKey==keycode) { + xkbi->mouseKey= 0; + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0, + NULL, NULL); + } + } + return 0; +} + +static int +_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + if (xkbi->device == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + int button= pAction->btn.button; + + if (button==XkbSA_UseDfltButton) + button = xkbi->desc->ctrls->mk_dflt_btn; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerBtn; + filter->upAction= *pAction; + filter->upAction.btn.button= button; + switch (pAction->type) { + case XkbSA_LockPtrBtn: + if (((xkbi->lockedPtrButtons&(1<<button))==0)&& + ((pAction->btn.flags&XkbSA_LockNoLock)==0)) { + xkbi->lockedPtrButtons|= (1<<button); + AccessXCancelRepeatKey(xkbi,keycode); + XkbDDXFakePointerButton(ButtonPress,button); + filter->upAction.type= XkbSA_NoAction; + } + break; + case XkbSA_PtrBtn: + { + register int i,nClicks; + AccessXCancelRepeatKey(xkbi,keycode); + if (pAction->btn.count>0) { + nClicks= pAction->btn.count; + for (i=0;i<nClicks;i++) { + XkbDDXFakePointerButton(ButtonPress,button); + XkbDDXFakePointerButton(ButtonRelease,button); + } + filter->upAction.type= XkbSA_NoAction; + } + else XkbDDXFakePointerButton(ButtonPress,button); + } + break; + case XkbSA_SetPtrDflt: + { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + XkbControlsRec old; + xkbControlsNotify cn; + + old= *ctrls; + AccessXCancelRepeatKey(xkbi,keycode); + switch (pAction->dflt.affect) { + case XkbSA_AffectDfltBtn: + if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute) + ctrls->mk_dflt_btn= + XkbSAPtrDfltValue(&pAction->dflt); + else { + ctrls->mk_dflt_btn+= + XkbSAPtrDfltValue(&pAction->dflt); + if (ctrls->mk_dflt_btn>5) + ctrls->mk_dflt_btn= 5; + else if (ctrls->mk_dflt_btn<1) + ctrls->mk_dflt_btn= 1; + } + break; + default: + ErrorF( + "Attempt to change unknown pointer default (%d) ignored\n", + pAction->dflt.affect); + break; + } + if (XkbComputeControlsNotify(xkbi->device, + &old,xkbi->desc->ctrls, + &cn,False)) { + cn.keycode = keycode; + /* XXX: what about DeviceKeyPress? */ + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(xkbi->device,&cn); + } + } + break; + } + } + else if (filter->keycode==keycode) { + int button= filter->upAction.btn.button; + + switch (filter->upAction.type) { + case XkbSA_LockPtrBtn: + if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)|| + ((xkbi->lockedPtrButtons&(1<<button))==0)) { + break; + } + xkbi->lockedPtrButtons&= ~(1<<button); + case XkbSA_PtrBtn: + XkbDDXFakePointerButton(ButtonRelease,button); + break; + } + filter->active = 0; + } + return 0; +} + +static int +_XkbFilterControls( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +XkbControlsRec old; +XkbControlsPtr ctrls; +DeviceIntPtr kbd; +unsigned int change; +XkbEventCauseRec cause; + + kbd= xkbi->device; + ctrls= xkbi->desc->ctrls; + old= *ctrls; + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + change= XkbActionCtrls(&pAction->ctrls); + filter->priv = change; + filter->filter = _XkbFilterControls; + filter->upAction = *pAction; + + if (pAction->type==XkbSA_LockControls) { + filter->priv= (ctrls->enabled_ctrls&change); + change&= ~ctrls->enabled_ctrls; + } + + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls|= change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) { + cn.keycode = keycode; + /* XXX: what about DeviceKeyPress? */ + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyPress); + + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change); + } + } + else if (filter->keycode==keycode) { + change= filter->priv; + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls&= ~change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) { + cn.keycode = keycode; + cn.eventType = KeyRelease; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyRelease); + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change); + } + filter->keycode= 0; + filter->active= 0; + } + return 1; +} + +static int +_XkbFilterActionMessage(XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +XkbMessageAction * pMsg; +DeviceIntPtr kbd; + + kbd= xkbi->device; + if (filter->keycode==0) { /* initial press */ + pMsg= &pAction->msg; + if ((pMsg->flags&XkbSA_MessageOnRelease)|| + ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) { + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterActionMessage; + filter->upAction = *pAction; + } + if (pMsg->flags&XkbSA_MessageOnPress) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 1; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message, + (char *)pMsg->message,XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0); + } + else if (filter->keycode==keycode) { + pMsg= &filter->upAction.msg; + if (pMsg->flags&XkbSA_MessageOnRelease) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 0; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message,(char *)pMsg->message, + XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + filter->keycode= 0; + filter->active= 0; + return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + } + return 0; +} + +static int +_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +unsigned realMods = 0; +xEvent ev; +int x,y; +XkbStateRec old; +unsigned mods,mask,oldCoreState = 0,oldCorePrevState = 0; +xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device); +ProcessInputProc backupproc; + + /* never actually used uninitialised, but gcc isn't smart enough + * to work that out. */ + memset(&old, 0, sizeof(old)); + + if ((filter->keycode!=0)&&(filter->keycode!=keycode)) + return 1; + + GetSpritePosition(&x,&y); + ev.u.keyButtonPointer.time = GetTimeInMillis(); + ev.u.keyButtonPointer.rootX = x; + ev.u.keyButtonPointer.rootY = y; + + if (filter->keycode==0) { /* initial press */ + if ((pAction->redirect.new_key<xkbi->desc->min_key_code)|| + (pAction->redirect.new_key>xkbi->desc->max_key_code)) { + return 1; + } + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterRedirectKey; + filter->upAction = *pAction; + + /* XXX: what about DeviceKeyPress */ + ev.u.u.type = KeyPress; + ev.u.u.detail = pAction->redirect.new_key; + + mask= XkbSARedirectVModsMask(&pAction->redirect); + mods= XkbSARedirectVMods(&pAction->redirect); + if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); + if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); + mask|= pAction->redirect.mods_mask; + mods|= pAction->redirect.mods; + + if ( mask || mods ) { + old= xkbi->state; + oldCoreState= xkbi->device->key->state; + oldCorePrevState= xkbi->device->key->prev_state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + xkbi->device->key->state= xkbi->device->key->prev_state= + xkbi->state.mods; + } + + realMods = xkbi->device->key->modifierMap[ev.u.u.detail]; + xkbi->device->key->modifierMap[ev.u.u.detail] = 0; + /* XXX: Bad! Since the switch to XI devices xkbi->device will be the + * XI device. Sending a core event through ProcessOtherEvent will + * cause trouble. Somebody should fix this. + */ + UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); + xkbi->device->public.processInputProc(&ev,xkbi->device,1); + COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, + backupproc,xkbUnwrapProc); + xkbi->device->key->modifierMap[ev.u.u.detail] = realMods; + + if ( mask || mods ) { + xkbi->device->key->state= oldCoreState; + xkbi->device->key->prev_state= oldCorePrevState; + xkbi->state= old; + } + } + else if (filter->keycode==keycode) { + + /* XXX: what about DeviceKeyRelease */ + ev.u.u.type = KeyRelease; + ev.u.u.detail = filter->upAction.redirect.new_key; + + mask= XkbSARedirectVModsMask(&filter->upAction.redirect); + mods= XkbSARedirectVMods(&filter->upAction.redirect); + if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); + if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); + mask|= filter->upAction.redirect.mods_mask; + mods|= filter->upAction.redirect.mods; + + if ( mask || mods ) { + old= xkbi->state; + oldCoreState= xkbi->device->key->state; + oldCorePrevState= xkbi->device->key->prev_state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + xkbi->device->key->state= xkbi->device->key->prev_state= + xkbi->state.mods; + } + + realMods = xkbi->device->key->modifierMap[ev.u.u.detail]; + xkbi->device->key->modifierMap[ev.u.u.detail] = 0; + /* XXX: Bad! Since the switch to XI devices xkbi->device will be the + * XI device. Sending a core event through ProcessOtherEvent will + * cause trouble. Somebody should fix this. + */ + UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); + xkbi->device->public.processInputProc(&ev,xkbi->device,1); + COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, + backupproc,xkbUnwrapProc); + xkbi->device->key->modifierMap[ev.u.u.detail] = realMods; + + if ( mask || mods ) { + xkbi->device->key->state= oldCoreState; + xkbi->device->key->prev_state= oldCorePrevState; + xkbi->state= old; + } + + filter->keycode= 0; + filter->active= 0; + } + return 0; +} + +static int +_XkbFilterSwitchScreen( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + DeviceIntPtr dev = xkbi->device; + if (dev == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->filter = _XkbFilterSwitchScreen; + AccessXCancelRepeatKey(xkbi, keycode); + XkbDDXSwitchScreen(dev,keycode,pAction); + return 0; + } + else if (filter->keycode==keycode) { + filter->active= 0; + return 0; + } + return 1; +} + +static int +_XkbFilterXF86Private( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + DeviceIntPtr dev = xkbi->device; + if (dev == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->filter = _XkbFilterXF86Private; + XkbDDXPrivate(dev,keycode,pAction); + return 0; + } + else if (filter->keycode==keycode) { + filter->active= 0; + return 0; + } + return 1; +} + + +static int +_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +DeviceIntPtr dev; +int button; + + if (dev == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient, + DixUnknownAccess, &button); + if (!dev || !dev->public.on || dev == inputInfo.pointer) + return 1; + + button= pAction->devbtn.button; + if ((button<1)||(button>dev->button->numButtons)) + return 1; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterDeviceBtn; + filter->upAction= *pAction; + switch (pAction->type) { + case XkbSA_LockDeviceBtn: + if ((pAction->devbtn.flags&XkbSA_LockNoLock)|| + (dev->button->down[button/8]&(1L<<(button%8)))) + return 0; + XkbDDXFakeDeviceButton(dev,True,button); + filter->upAction.type= XkbSA_NoAction; + break; + case XkbSA_DeviceBtn: + if (pAction->devbtn.count>0) { + int nClicks,i; + nClicks= pAction->btn.count; + for (i=0;i<nClicks;i++) { + XkbDDXFakeDeviceButton(dev,True,button); + XkbDDXFakeDeviceButton(dev,False,button); + } + filter->upAction.type= XkbSA_NoAction; + } + else XkbDDXFakeDeviceButton(dev,True,button); + break; + } + } + else if (filter->keycode==keycode) { + int button; + + filter->active= 0; + _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device, + serverClient, DixUnknownAccess, &button); + if (!dev || !dev->public.on || dev == inputInfo.pointer) + return 1; + + button= filter->upAction.btn.button; + switch (filter->upAction.type) { + case XkbSA_LockDeviceBtn: + if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)|| + ((dev->button->down[button/8]&(1L<<(button%8)))==0)) + return 0; + XkbDDXFakeDeviceButton(dev,False,button); + break; + case XkbSA_DeviceBtn: + XkbDDXFakeDeviceButton(dev,False,button); + break; + } + filter->active = 0; + } + return 0; +} + +static XkbFilterPtr +_XkbNextFreeFilter( + XkbSrvInfoPtr xkbi +) +{ +register int i; + + if (xkbi->szFilters==0) { + xkbi->szFilters = 4; + xkbi->filters = _XkbTypedCalloc(xkbi->szFilters,XkbFilterRec); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + } + for (i=0;i<xkbi->szFilters;i++) { + if (!xkbi->filters[i].active) { + xkbi->filters[i].keycode = 0; + return &xkbi->filters[i]; + } + } + xkbi->szFilters*=2; + xkbi->filters= _XkbTypedRealloc(xkbi->filters, + xkbi->szFilters, + XkbFilterRec); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + bzero(&xkbi->filters[xkbi->szFilters/2], + (xkbi->szFilters/2)*sizeof(XkbFilterRec)); + return &xkbi->filters[xkbi->szFilters/2]; +} + +static int +_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction) +{ +register int i,send; + + send= 1; + for (i=0;i<xkbi->szFilters;i++) { + if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter)) + send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction) + && send); + } + return send; +} + +void +XkbHandleActions(DeviceIntPtr dev,DeviceIntPtr kbd,xEvent *xE,int count) +{ +int key,bit,i; +CARD8 realMods = 0; +XkbSrvInfoPtr xkbi; +KeyClassPtr keyc; +int changed,sendEvent; +Bool genStateNotify; +XkbStateRec oldState; +XkbAction act; +XkbFilterPtr filter; +Bool keyEvent; +Bool pressEvent; +ProcessInputProc backupproc; + +xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev); + + keyc= kbd->key; + xkbi= keyc->xkbInfo; + key= xE->u.u.detail; + /* The state may change, so if we're not in the middle of sending a state + * notify, prepare for it */ + if ((xkbi->flags&_XkbStateNotifyInProgress)==0) { + oldState= xkbi->state; + xkbi->flags|= _XkbStateNotifyInProgress; + genStateNotify= True; + } + else genStateNotify= False; + + xkbi->clearMods = xkbi->setMods = 0; + xkbi->groupChange = 0; + + sendEvent = 1; + keyEvent= ((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)|| + (xE->u.u.type==KeyRelease)||(xE->u.u.type==DeviceKeyRelease)); + pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)|| + (xE->u.u.type==ButtonPress)||(xE->u.u.type==DeviceButtonPress); + + if (pressEvent) { + if (keyEvent) + act = XkbGetKeyAction(xkbi,&xkbi->state,key); + else { + act = XkbGetButtonAction(kbd,dev,key); + key|= BTN_ACT_FLAG; + } + sendEvent = _XkbApplyFilters(xkbi,key,&act); + if (sendEvent) { + switch (act.type) { + case XkbSA_SetMods: + case XkbSA_SetGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent = _XkbFilterSetState(xkbi,filter,key,&act); + break; + case XkbSA_LatchMods: + case XkbSA_LatchGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act); + break; + case XkbSA_LockMods: + case XkbSA_LockGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterLockState(xkbi,filter,key,&act); + break; + case XkbSA_ISOLock: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act); + break; + case XkbSA_MovePtr: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act); + break; + case XkbSA_PtrBtn: + case XkbSA_LockPtrBtn: + case XkbSA_SetPtrDflt: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act); + break; + case XkbSA_Terminate: + sendEvent= XkbDDXTerminateServer(dev,key,&act); + break; + case XkbSA_SwitchScreen: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act); + break; + case XkbSA_SetControls: + case XkbSA_LockControls: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterControls(xkbi,filter,key,&act); + break; + case XkbSA_ActionMessage: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act); + break; + case XkbSA_RedirectKey: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act); + break; + case XkbSA_DeviceBtn: + case XkbSA_LockDeviceBtn: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act); + break; + case XkbSA_XFree86Private: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act); + break; + } + } + } + else { + if (!keyEvent) + key|= BTN_ACT_FLAG; + sendEvent = _XkbApplyFilters(xkbi,key,NULL); + } + + if (xkbi->groupChange!=0) + xkbi->state.base_group+= xkbi->groupChange; + if (xkbi->setMods) { + for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) { + if (xkbi->setMods&bit) { + keyc->modifierKeyCount[i]++; + xkbi->state.base_mods|= bit; + xkbi->setMods&= ~bit; + } + } + } + if (xkbi->clearMods) { + for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) { + if (xkbi->clearMods&bit) { + keyc->modifierKeyCount[i]--; + if (keyc->modifierKeyCount[i]<=0) { + xkbi->state.base_mods&= ~bit; + keyc->modifierKeyCount[i] = 0; + } + xkbi->clearMods&= ~bit; + } + } + } + + if (sendEvent) { + if (keyEvent) { + realMods = keyc->modifierMap[key]; + keyc->modifierMap[key] = 0; + } + + UNWRAP_PROCESS_INPUT_PROC(dev,xkbPrivPtr, backupproc); + dev->public.processInputProc(xE,dev,count); + COND_WRAP_PROCESS_INPUT_PROC(dev, xkbPrivPtr, + backupproc,xkbUnwrapProc); + if (keyEvent) + keyc->modifierMap[key] = realMods; + } + else if (keyEvent) { + FixKeyState(xE,dev); + } + + xkbi->prev_state= oldState; + XkbComputeDerivedState(xkbi); + keyc->prev_state= keyc->state; + keyc->state= XkbStateFieldFromRec(&xkbi->state); + changed = XkbStateChangedFlags(&oldState,&xkbi->state); + if (genStateNotify) { + if (changed) { + xkbStateNotify sn; + sn.keycode= key; + sn.eventType= xE->u.u.type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + xkbi->flags&= ~_XkbStateNotifyInProgress; + } + changed= XkbIndicatorsToUpdate(dev,changed,False); + if (changed) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause,key,xE->u.u.type); + XkbUpdateIndicators(dev,changed,False,NULL,&cause); + } + return; +} + +int +XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches) +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; +unsigned clear; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + clear= (mask&(~latches)); + xkbi->state.latched_mods&= ~clear; + /* Clear any pending latch to locks. + */ + act.type = XkbSA_NoAction; + _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act); + act.type = XkbSA_LatchMods; + act.mods.flags = 0; + act.mods.mask = mask&latches; + filter = _XkbNextFreeFilter(xkbi); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +int +XkbLatchGroup(DeviceIntPtr pXDev,int group) +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + act.type = XkbSA_LatchGroup; + act.group.flags = 0; + XkbSASetGroup(&act.group,group); + filter = _XkbNextFreeFilter(xkbi); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +/***====================================================================***/ + +void +XkbClearAllLatchesAndLocks( DeviceIntPtr dev, + XkbSrvInfoPtr xkbi, + Bool genEv, + XkbEventCausePtr cause) +{ +XkbStateRec os; +xkbStateNotify sn; + + sn.changed= 0; + os= xkbi->state; + if (os.latched_mods) { /* clear all latches */ + XkbLatchModifiers(dev,~0,0); + sn.changed|= XkbModifierLatchMask; + } + if (os.latched_group) { + XkbLatchGroup(dev,0); + sn.changed|= XkbGroupLatchMask; + } + if (os.locked_mods) { + xkbi->state.locked_mods= 0; + sn.changed|= XkbModifierLockMask; + } + if (os.locked_group) { + xkbi->state.locked_group= 0; + sn.changed|= XkbGroupLockMask; + } + if ( genEv && sn.changed) { + CARD32 changed; + + XkbComputeDerivedState(xkbi); + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + sn.changed= XkbStateChangedFlags(&os,&xkbi->state); + XkbSendStateNotify(dev,&sn); + changed= XkbIndicatorsToUpdate(dev,sn.changed,False); + if (changed) { + XkbUpdateIndicators(dev,changed,True,NULL,cause); + } + } + return; +} + diff --git a/xorg-server/xkb/xkbDflts.h b/xorg-server/xkb/xkbDflts.h new file mode 100644 index 000000000..5d8690650 --- /dev/null +++ b/xorg-server/xkb/xkbDflts.h @@ -0,0 +1,469 @@ +/* This file generated automatically by xkbcomp */ +/* DO NOT EDIT */ +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef DEFAULT_H +#define DEFAULT_H 1 + +#define GET_ATOM(d,s) MakeAtom(s,strlen(s),1) +#define DPYTYPE char * +#define NUM_KEYS 1 + +#define vmod_NumLock 0 +#define vmod_Alt 1 +#define vmod_LevelThree 2 +#define vmod_AltGr 3 +#define vmod_ScrollLock 4 + +#define vmod_NumLockMask (1<<0) +#define vmod_AltMask (1<<1) +#define vmod_LevelThreeMask (1<<2) +#define vmod_AltGrMask (1<<3) +#define vmod_ScrollLockMask (1<<4) + +/* types name is "default" */ +static Atom lnames_ONE_LEVEL[1]; + +static XkbKTMapEntryRec map_TWO_LEVEL[1]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } } +}; +static Atom lnames_TWO_LEVEL[2]; + +static XkbKTMapEntryRec map_ALPHABETIC[2]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 1, 0, { LockMask, LockMask, 0 } } +}; +static XkbModsRec preserve_ALPHABETIC[2]= { + { 0, 0, 0 }, + { LockMask, LockMask, 0 } +}; +static Atom lnames_ALPHABETIC[2]; + +static XkbKTMapEntryRec map_KEYPAD[2]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 0, 1, { 0, 0, vmod_NumLockMask } } +}; +static Atom lnames_KEYPAD[2]; + +static XkbKTMapEntryRec map_PC_BREAK[1]= { + { 1, 1, { ControlMask, ControlMask, 0 } } +}; +static Atom lnames_PC_BREAK[2]; + +static XkbKTMapEntryRec map_PC_SYSRQ[1]= { + { 0, 1, { 0, 0, vmod_AltMask } } +}; +static Atom lnames_PC_SYSRQ[2]; + +static XkbKTMapEntryRec map_CTRL_ALT[1]= { + { 0, 1, { ControlMask, ControlMask, vmod_AltMask } } +}; +static Atom lnames_CTRL_ALT[2]; + +static XkbKTMapEntryRec map_THREE_LEVEL[3]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 0, 2, { 0, 0, vmod_LevelThreeMask } }, + { 0, 2, { ShiftMask, ShiftMask, vmod_LevelThreeMask } } +}; +static Atom lnames_THREE_LEVEL[3]; + +static XkbKTMapEntryRec map_SHIFT_ALT[1]= { + { 0, 1, { ShiftMask, ShiftMask, vmod_AltMask } } +}; +static Atom lnames_SHIFT_ALT[2]; + +static XkbKeyTypeRec dflt_types[]= { + { + { 0, 0, 0 }, + 1, + 0, NULL, NULL, + None, lnames_ONE_LEVEL + }, + { + { ShiftMask, ShiftMask, 0 }, + 2, + 1, map_TWO_LEVEL, NULL, + None, lnames_TWO_LEVEL + }, + { + { ShiftMask|LockMask, ShiftMask|LockMask, 0 }, + 2, + 2, map_ALPHABETIC, preserve_ALPHABETIC, + None, lnames_ALPHABETIC + }, + { + { ShiftMask, ShiftMask, vmod_NumLockMask }, + 2, + 2, map_KEYPAD, NULL, + None, lnames_KEYPAD + }, + { + { ControlMask, ControlMask, 0 }, + 2, + 1, map_PC_BREAK, NULL, + None, lnames_PC_BREAK + }, + { + { 0, 0, vmod_AltMask }, + 2, + 1, map_PC_SYSRQ, NULL, + None, lnames_PC_SYSRQ + }, + { + { ControlMask, ControlMask, vmod_AltMask }, + 2, + 1, map_CTRL_ALT, NULL, + None, lnames_CTRL_ALT + }, + { + { ShiftMask, ShiftMask, vmod_LevelThreeMask }, + 3, + 3, map_THREE_LEVEL, NULL, + None, lnames_THREE_LEVEL + }, + { + { ShiftMask, ShiftMask, vmod_AltMask }, + 2, + 1, map_SHIFT_ALT, NULL, + None, lnames_SHIFT_ALT + } +}; +#define num_dflt_types (sizeof(dflt_types)/sizeof(XkbKeyTypeRec)) + + +static void +initTypeNames(DPYTYPE dpy) +{ + dflt_types[0].name= GET_ATOM(dpy,"ONE_LEVEL"); + lnames_ONE_LEVEL[0]= GET_ATOM(dpy,"Any"); + dflt_types[1].name= GET_ATOM(dpy,"TWO_LEVEL"); + lnames_TWO_LEVEL[0]= GET_ATOM(dpy,"Base"); + lnames_TWO_LEVEL[1]= GET_ATOM(dpy,"Shift"); + dflt_types[2].name= GET_ATOM(dpy,"ALPHABETIC"); + lnames_ALPHABETIC[0]= GET_ATOM(dpy,"Base"); + lnames_ALPHABETIC[1]= GET_ATOM(dpy,"Caps"); + dflt_types[3].name= GET_ATOM(dpy,"KEYPAD"); + lnames_KEYPAD[0]= GET_ATOM(dpy,"Base"); + lnames_KEYPAD[1]= GET_ATOM(dpy,"Number"); + dflt_types[4].name= GET_ATOM(dpy,"PC_BREAK"); + lnames_PC_BREAK[0]= GET_ATOM(dpy,"Base"); + lnames_PC_BREAK[1]= GET_ATOM(dpy,"Control"); + dflt_types[5].name= GET_ATOM(dpy,"PC_SYSRQ"); + lnames_PC_SYSRQ[0]= GET_ATOM(dpy,"Base"); + lnames_PC_SYSRQ[1]= GET_ATOM(dpy,"Alt"); + dflt_types[6].name= GET_ATOM(dpy,"CTRL+ALT"); + lnames_CTRL_ALT[0]= GET_ATOM(dpy,"Base"); + lnames_CTRL_ALT[1]= GET_ATOM(dpy,"Ctrl+Alt"); + dflt_types[7].name= GET_ATOM(dpy,"THREE_LEVEL"); + lnames_THREE_LEVEL[0]= GET_ATOM(dpy,"Base"); + lnames_THREE_LEVEL[1]= GET_ATOM(dpy,"Shift"); + lnames_THREE_LEVEL[2]= GET_ATOM(dpy,"Level3"); + dflt_types[8].name= GET_ATOM(dpy,"SHIFT+ALT"); + lnames_SHIFT_ALT[0]= GET_ATOM(dpy,"Base"); + lnames_SHIFT_ALT[1]= GET_ATOM(dpy,"Shift+Alt"); +} +/* compat name is "default" */ +static XkbSymInterpretRec dfltSI[69]= { + { XK_ISO_Level2_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_Exactly, ShiftMask, + 255, + { XkbSA_LatchMods, { 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Eisu_Shift, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Eisu_toggle, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Kana_Shift, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Kana_Lock, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Shift_Lock, 0x0000, + XkbSI_AnyOf, ShiftMask|LockMask, + 255, + { XkbSA_LockMods, { 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Num_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 0, + { XkbSA_LockMods, { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } } }, + { XK_Alt_L, 0x0000, + XkbSI_AnyOf, 0xff, + 1, + { XkbSA_SetMods, { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Alt_R, 0x0000, + XkbSI_AnyOf, 0xff, + 1, + { XkbSA_SetMods, { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Scroll_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 4, + { XkbSA_LockMods, { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_ISO_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 255, + { XkbSA_ISOLock, { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_ISO_Level3_Shift, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOf, 0xff, + 2, + { XkbSA_SetMods, { 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 } } }, + { XK_ISO_Level3_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOf, 0xff, + 2, + { XkbSA_LatchMods, { 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 } } }, + { XK_Mode_switch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_SetGroup, { 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_1, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00 } } }, + { XK_KP_End, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00 } } }, + { XK_KP_2, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } } }, + { XK_KP_Down, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } } }, + { XK_KP_3, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00 } } }, + { XK_KP_Next, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00 } } }, + { XK_KP_4, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Left, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_6, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Right, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_7, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } } }, + { XK_KP_Home, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } } }, + { XK_KP_8, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } } }, + { XK_KP_Up, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } } }, + { XK_KP_9, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } } }, + { XK_KP_Prior, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, { 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00 } } }, + { XK_KP_5, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Begin, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_F1, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, { 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Divide, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, { 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_F2, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, { 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Multiply, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, { 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_F3, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, { 0x04, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Subtract, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, { 0x04, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Separator, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Add, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_0, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Insert, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Decimal, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_KP_Delete, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_Button_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_Button1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_Button2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_Button3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_DblClick_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_DblClick1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_DblClick2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_DblClick3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, { 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_Drag_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_Drag1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_Drag2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, { 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_Drag3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, { 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_EnableKeys, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00 } } }, + { XK_Pointer_Accelerate, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 } } }, + { XK_Pointer_DfltBtnNext, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, { 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_Pointer_DfltBtnPrev, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, { 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_AccessX_Enable, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, { 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00 } } }, + { XK_Terminate_Server, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_Terminate, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_ISO_Group_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LatchGroup, { 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_ISO_Next_Group, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LockGroup, { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_ISO_Prev_Group, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LockGroup, { 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_ISO_First_Group, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockGroup, { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { XK_ISO_Last_Group, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockGroup, { 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, + { NoSymbol, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_LockMods, { 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00 } } }, + { NoSymbol, 0x0000, + XkbSI_AnyOf, 0xff, + 255, + { XkbSA_SetMods, { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } } +}; +#define num_dfltSI (sizeof(dfltSI)/sizeof(XkbSymInterpretRec)) + +static XkbCompatMapRec compatMap= { + dfltSI, + { /* group compatibility */ + { 0, 0, 0 }, + { 0, 0, vmod_AltGrMask }, + { 0, 0, vmod_AltGrMask }, + { 0, 0, vmod_AltGrMask } + }, + num_dfltSI, num_dfltSI +}; + +static void +initIndicatorNames(DPYTYPE dpy,XkbDescPtr xkb) +{ + xkb->names->indicators[ 0]= GET_ATOM(dpy,"Caps Lock"); + xkb->names->indicators[ 1]= GET_ATOM(dpy,"Num Lock"); + xkb->names->indicators[ 2]= GET_ATOM(dpy,"Shift Lock"); + xkb->names->indicators[ 3]= GET_ATOM(dpy,"Mouse Keys"); + xkb->names->indicators[ 4]= GET_ATOM(dpy,"Scroll Lock"); + xkb->names->indicators[ 5]= GET_ATOM(dpy,"Group 2"); +} +#endif /* DEFAULT_H */ diff --git a/xorg-server/xkb/xkbEvents.c b/xorg-server/xkb/xkbEvents.c new file mode 100644 index 000000000..49725d065 --- /dev/null +++ b/xorg-server/xkb/xkbEvents.c @@ -0,0 +1,1031 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "inputstr.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include "xkb.h" + +/***====================================================================***/ + +void +XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN) +{ +register int i; +Time time; +CARD16 changed; + + pNKN->type = XkbEventCode + XkbEventBase; + pNKN->xkbType = XkbNewKeyboardNotify; + pNKN->time = time = GetTimeInMillis(); + changed = pNKN->changed; + + for (i=1; i<currentMaxClients; i++) { + if ((!clients[i]) || clients[i]->clientGone || + (clients[i]->requestVector==InitialVector)) { + continue; + } + + if (clients[i]->xkbClientFlags&_XkbClientInitialized) { + if (clients[i]->newKeyboardNotifyMask&changed) { + pNKN->sequenceNumber = clients[i]->sequence; + pNKN->time = time; + pNKN->changed = changed; + if ( clients[i]->swapped ) { + register int n; + swaps(&pNKN->sequenceNumber,n); + swapl(&pNKN->time,n); + swaps(&pNKN->changed,n); + } + WriteToClient(clients[i],sizeof(xEvent),(char *)pNKN); + if (changed&XkbNKN_KeycodesMask) { + clients[i]->minKC= pNKN->minKeyCode; + clients[i]->maxKC= pNKN->maxKeyCode; + } + } + } + else if (changed&XkbNKN_KeycodesMask) { + xEvent event; + event.u.u.type= MappingNotify; + event.u.mappingNotify.request= MappingKeyboard; + event.u.mappingNotify.firstKeyCode= clients[i]->minKC; + event.u.mappingNotify.count= clients[i]->maxKC-clients[i]->minKC+1; + event.u.u.sequenceNumber= clients[i]->sequence; + if (clients[i]->swapped) { + int n; + swaps(&event.u.u.sequenceNumber,n); + } + WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event); + event.u.mappingNotify.request= MappingModifier; + WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event); + } + } + return; +} + +/***====================================================================***/ + +void +XkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN) +{ +XkbSrvInfoPtr xkbi; +XkbStatePtr state; +XkbInterestPtr interest; +Time time; +register CARD16 changed,bState; + + interest = kbd->xkb_interest; + if (!interest) + return; + xkbi = kbd->key->xkbInfo; + state= &xkbi->state; + + pSN->type = XkbEventCode + XkbEventBase; + pSN->xkbType = XkbStateNotify; + pSN->deviceID = kbd->id; + pSN->time = time = GetTimeInMillis(); + pSN->mods = state->mods; + pSN->baseMods = state->base_mods; + pSN->latchedMods = state->latched_mods; + pSN->lockedMods = state->locked_mods; + pSN->group = state->group; + pSN->baseGroup = state->base_group; + pSN->latchedGroup = state->latched_group; + pSN->lockedGroup = state->locked_group; + pSN->compatState = state->compat_state; + pSN->grabMods = state->grab_mods; + pSN->compatGrabMods = state->compat_grab_mods; + pSN->lookupMods = state->lookup_mods; + pSN->compatLookupMods = state->compat_lookup_mods; + pSN->ptrBtnState = state->ptr_buttons; + changed = pSN->changed; + bState= pSN->ptrBtnState; + + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->stateNotifyMask&changed)) { + pSN->sequenceNumber = interest->client->sequence; + pSN->time = time; + pSN->changed = changed; + pSN->ptrBtnState = bState; + if ( interest->client->swapped ) { + register int n; + swaps(&pSN->sequenceNumber,n); + swapl(&pSN->time,n); + swaps(&pSN->changed,n); + swaps(&pSN->ptrBtnState,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pSN); + } + interest= interest->next; + } + return; +} + +/***====================================================================***/ + +void +XkbSendMapNotify(DeviceIntPtr kbd,xkbMapNotify *pMN) +{ +int i; +XkbSrvInfoPtr xkbi; +unsigned time = 0,initialized; +CARD16 changed; + + xkbi = kbd->key->xkbInfo; + initialized= 0; + + changed = pMN->changed; + pMN->minKeyCode= xkbi->desc->min_key_code; + pMN->maxKeyCode= xkbi->desc->max_key_code; + for (i=1; i<currentMaxClients; i++) { + if (clients[i] && ! clients[i]->clientGone && + (clients[i]->requestVector != InitialVector) && + (clients[i]->xkbClientFlags&_XkbClientInitialized) && + (clients[i]->mapNotifyMask&changed)) + { + if (!initialized) { + pMN->type = XkbEventCode + XkbEventBase; + pMN->xkbType = XkbMapNotify; + pMN->deviceID = kbd->id; + time = GetTimeInMillis(); + initialized= 1; + } + pMN->time= time; + pMN->sequenceNumber = clients[i]->sequence; + pMN->changed = changed; + if ( clients[i]->swapped ) { + register int n; + swaps(&pMN->sequenceNumber,n); + swapl(&pMN->time,n); + swaps(&pMN->changed,n); + } + WriteToClient(clients[i],sizeof(xEvent),(char *)pMN); + } + } + return; +} + +int +XkbComputeControlsNotify( DeviceIntPtr kbd, + XkbControlsPtr old, + XkbControlsPtr new, + xkbControlsNotify * pCN, + Bool forceCtrlProc) +{ +int i; +CARD32 changedControls; + + changedControls= 0; + + if (!kbd || !kbd->kbdfeed) + return 0; + + if (old->enabled_ctrls!=new->enabled_ctrls) + changedControls|= XkbControlsEnabledMask; + if ((old->repeat_delay!=new->repeat_delay)|| + (old->repeat_interval!=new->repeat_interval)) + changedControls|= XkbRepeatKeysMask; + for (i = 0; i < XkbPerKeyBitArraySize; i++) + if (old->per_key_repeat[i] != new->per_key_repeat[i]) + changedControls|= XkbPerKeyRepeatMask; + if (old->slow_keys_delay!=new->slow_keys_delay) + changedControls|= XkbSlowKeysMask; + if (old->debounce_delay!=new->debounce_delay) + changedControls|= XkbBounceKeysMask; + if ((old->mk_delay!=new->mk_delay)|| + (old->mk_interval!=new->mk_interval)|| + (old->mk_dflt_btn!=new->mk_dflt_btn)) + changedControls|= XkbMouseKeysMask; + if ((old->mk_time_to_max!=new->mk_time_to_max)|| + (old->mk_curve!=new->mk_curve)|| + (old->mk_max_speed!=new->mk_max_speed)) + changedControls|= XkbMouseKeysAccelMask; + if (old->ax_options!=new->ax_options) + changedControls|= XkbAccessXKeysMask; + if ((old->ax_options^new->ax_options) & XkbAX_SKOptionsMask) + changedControls|= XkbStickyKeysMask; + if ((old->ax_options^new->ax_options) & XkbAX_FBOptionsMask) + changedControls|= XkbAccessXFeedbackMask; + if ((old->ax_timeout!=new->ax_timeout)|| + (old->axt_ctrls_mask!=new->axt_ctrls_mask)|| + (old->axt_ctrls_values!=new->axt_ctrls_values)|| + (old->axt_opts_mask!=new->axt_opts_mask)|| + (old->axt_opts_values!= new->axt_opts_values)) { + changedControls|= XkbAccessXTimeoutMask; + } + if ((old->internal.mask!=new->internal.mask)|| + (old->internal.real_mods!=new->internal.real_mods)|| + (old->internal.vmods!=new->internal.vmods)) + changedControls|= XkbInternalModsMask; + if ((old->ignore_lock.mask!=new->ignore_lock.mask)|| + (old->ignore_lock.real_mods!=new->ignore_lock.real_mods)|| + (old->ignore_lock.vmods!=new->ignore_lock.vmods)) + changedControls|= XkbIgnoreLockModsMask; + + if (new->enabled_ctrls&XkbRepeatKeysMask) + kbd->kbdfeed->ctrl.autoRepeat=TRUE; + else kbd->kbdfeed->ctrl.autoRepeat=FALSE; + + if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc && + (changedControls || forceCtrlProc)) + (*kbd->kbdfeed->CtrlProc)(kbd, &kbd->kbdfeed->ctrl); + + if ((!changedControls)&&(old->num_groups==new->num_groups)) + return 0; + + if (!kbd->xkb_interest) + return 0; + + pCN->changedControls = changedControls; + pCN->enabledControls = new->enabled_ctrls; + pCN->enabledControlChanges = (new->enabled_ctrls^old->enabled_ctrls); + pCN->numGroups = new->num_groups; + + return 1; +} + +void +XkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify *pCN) +{ +int initialized; +CARD32 changedControls, enabledControls, enabledChanges = 0; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +Time time = 0; + + interest = kbd->xkb_interest; + if (!interest) + return; + xkbi = kbd->key->xkbInfo; + + initialized = 0; + enabledControls = xkbi->desc->ctrls->enabled_ctrls; + changedControls = pCN->changedControls; + pCN->numGroups= xkbi->desc->ctrls->num_groups; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->ctrlsNotifyMask&changedControls)) { + if (!initialized) { + pCN->type = XkbEventCode + XkbEventBase; + pCN->xkbType = XkbControlsNotify; + pCN->deviceID = kbd->id; + pCN->time = time = GetTimeInMillis(); + enabledChanges = pCN->enabledControlChanges; + initialized= 1; + } + pCN->changedControls = changedControls; + pCN->enabledControls = enabledControls; + pCN->enabledControlChanges = enabledChanges; + pCN->sequenceNumber = interest->client->sequence; + pCN->time = time; + if ( interest->client->swapped ) { + register int n; + swaps(&pCN->sequenceNumber,n); + swapl(&pCN->changedControls,n); + swapl(&pCN->enabledControls,n); + swapl(&pCN->enabledControlChanges,n); + swapl(&pCN->time,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pCN); + } + interest= interest->next; + } + return; +} + +static void +XkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD32 state,changed; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + state = pEv->state; + changed = pEv->changed; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (((xkbType==XkbIndicatorStateNotify)&& + (interest->iStateNotifyMask&changed))|| + ((xkbType==XkbIndicatorMapNotify)&& + (interest->iMapNotifyMask&changed)))) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = xkbType; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->changed = changed; + pEv->state = state; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swapl(&pEv->changed,n); + swapl(&pEv->state,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + + +void +XkbHandleBell( BOOL force, + BOOL eventOnly, + DeviceIntPtr kbd, + CARD8 percent, + pointer pCtrl, + CARD8 class, + Atom name, + WindowPtr pWin, + ClientPtr pClient) +{ +xkbBellNotify bn; +int initialized; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +CARD8 id; +CARD16 pitch,duration; +Time time = 0; +XID winID = 0; + + xkbi = kbd->key->xkbInfo; + + if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&& + (!eventOnly)) { + if (kbd->kbdfeed->BellProc) + (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class); + } + interest = kbd->xkb_interest; + if ((!interest)||(force)) + return; + + if ((class==0)||(class==KbdFeedbackClass)) { + KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl; + id= pKeyCtrl->id; + pitch= pKeyCtrl->bell_pitch; + duration= pKeyCtrl->bell_duration; + } + else if (class==BellFeedbackClass) { + BellCtrl *pBellCtrl= (BellCtrl *)pCtrl; + id= pBellCtrl->id; + pitch= pBellCtrl->pitch; + duration= pBellCtrl->duration; + } + else return; + + initialized = 0; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->bellNotifyMask)) { + if (!initialized) { + time = GetTimeInMillis(); + bn.type = XkbEventCode + XkbEventBase; + bn.xkbType = XkbBellNotify; + bn.deviceID = kbd->id; + bn.bellClass = class; + bn.bellID = id; + bn.percent= percent; + bn.eventOnly = (eventOnly!=0); + winID= (pWin?pWin->drawable.id:None); + initialized= 1; + } + bn.sequenceNumber = interest->client->sequence; + bn.time = time; + bn.pitch = pitch; + bn.duration = duration; + bn.name = name; + bn.window= winID; + if ( interest->client->swapped ) { + register int n; + swaps(&bn.sequenceNumber,n); + swapl(&bn.time,n); + swaps(&bn.pitch,n); + swaps(&bn.duration,n); + swapl(&bn.name,n); + swapl(&bn.window,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)&bn); + } + interest= interest->next; + } + return; +} + +void +XkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD16 sk_delay,db_delay; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + sk_delay= pEv->slowKeysDelay; + db_delay= pEv->debounceDelay; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->accessXNotifyMask&(1<<pEv->detail))) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbAccessXNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->slowKeysDelay = sk_delay; + pEv->debounceDelay = db_delay; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->slowKeysDelay,n); + swaps(&pEv->debounceDelay,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD16 changed,changedVirtualMods; +CARD32 changedIndicators; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + changed= pEv->changed; + changedIndicators= pEv->changedIndicators; + changedVirtualMods= pEv->changedVirtualMods; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->namesNotifyMask&pEv->changed)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbNamesNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->changed = changed; + pEv->changedIndicators = changedIndicators; + pEv->changedVirtualMods= changedVirtualMods; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->changed,n); + swapl(&pEv->changedIndicators,n); + swaps(&pEv->changedVirtualMods,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD16 firstSI = 0, nSI = 0, nTotalSI = 0; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->compatNotifyMask)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbCompatMapNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + firstSI= pEv->firstSI; + nSI= pEv->nSI; + nTotalSI= pEv->nTotalSI; + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->firstSI = firstSI; + pEv->nSI = nSI; + pEv->nTotalSI = nTotalSI; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->firstSI,n); + swaps(&pEv->nSI,n); + swaps(&pEv->nTotalSI,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv) +{ +int initialized; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +Time time = 0; + + xkbi = kbd->key->xkbInfo; + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + pEv->mods= xkbi->state.mods; + pEv->group= xkbi->state.group; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->actionMessageMask)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbActionMessage; + pEv->deviceID = kbd->id; + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendExtensionDeviceNotify( DeviceIntPtr dev, + ClientPtr client, + xkbExtensionDeviceNotify * pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD32 defined, state; +CARD16 reason, supported = 0; + + interest = dev->xkb_interest; + if (!interest) + return; + + initialized = 0; + reason= pEv->reason; + defined= pEv->ledsDefined; + state= pEv->ledState; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->extDevNotifyMask&reason)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbExtensionDeviceNotify; + pEv->deviceID = dev->id; + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time = GetTimeInMillis(); + supported= pEv->supported; + initialized= 1; + } + else { + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->ledsDefined= defined; + pEv->ledState= state; + pEv->reason= reason; + pEv->supported= supported; + } + if (client!=interest->client) { + /* only report UnsupportedFeature to the client that */ + /* issued the failing request */ + pEv->reason&= ~XkbXI_UnsupportedFeatureMask; + if ((interest->extDevNotifyMask&reason)==0) + continue; + } + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swapl(&pEv->ledsDefined,n); + swapl(&pEv->ledState,n); + swaps(&pEv->reason,n); + swaps(&pEv->supported,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendNotification( DeviceIntPtr kbd, + XkbChangesPtr pChanges, + XkbEventCausePtr cause) +{ +XkbSrvLedInfoPtr sli; + + sli= NULL; + if (pChanges->state_changes) { + xkbStateNotify sn; + sn.changed= pChanges->state_changes; + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + XkbSendStateNotify(kbd,&sn); + } + if (pChanges->map.changed) { + xkbMapNotify mn; + mn.changed= pChanges->map.changed; + mn.firstType= pChanges->map.first_type; + mn.nTypes= pChanges->map.num_types; + mn.firstKeySym= pChanges->map.first_key_sym; + mn.nKeySyms= pChanges->map.num_key_syms; + mn.firstKeyAct= pChanges->map.first_key_act; + mn.nKeyActs= pChanges->map.num_key_acts; + mn.firstKeyBehavior= pChanges->map.first_key_behavior; + mn.nKeyBehaviors= pChanges->map.num_key_behaviors; + mn.virtualMods= pChanges->map.vmods; + mn.firstKeyExplicit= pChanges->map.first_key_explicit; + mn.nKeyExplicit= pChanges->map.num_key_explicit; + mn.firstModMapKey= pChanges->map.first_modmap_key; + mn.nModMapKeys= pChanges->map.num_modmap_keys; + mn.firstVModMapKey= pChanges->map.first_vmodmap_key; + mn.nVModMapKeys= pChanges->map.num_vmodmap_keys; + XkbSendMapNotify(kbd,&mn); + } + if ((pChanges->ctrls.changed_ctrls)|| + (pChanges->ctrls.enabled_ctrls_changes)) { + xkbControlsNotify cn; + cn.changedControls= pChanges->ctrls.changed_ctrls; + cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes; + cn.keycode= cause->kc; + cn.eventType= cause->event; + cn.requestMajor= cause->mjr; + cn.requestMinor= cause->mnr; + XkbSendControlsNotify(kbd,&cn); + } + if (pChanges->indicators.map_changes) { + xkbIndicatorNotify in; + if (sli==NULL) + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + in.state= sli->effectiveState; + in.changed= pChanges->indicators.map_changes; + XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in); + } + if (pChanges->indicators.state_changes) { + xkbIndicatorNotify in; + if (sli==NULL) + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + in.state= sli->effectiveState; + in.changed= pChanges->indicators.state_changes; + XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in); + } + if (pChanges->names.changed) { + xkbNamesNotify nn; + nn.changed= pChanges->names.changed; + nn.firstType= pChanges->names.first_type; + nn.nTypes= pChanges->names.num_types; + nn.firstLevelName= pChanges->names.first_lvl; + nn.nLevelNames= pChanges->names.num_lvls; + nn.nRadioGroups= pChanges->names.num_rg; + nn.changedVirtualMods= pChanges->names.changed_vmods; + nn.changedIndicators= pChanges->names.changed_indicators; + XkbSendNamesNotify(kbd,&nn); + } + if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) { + xkbCompatMapNotify cmn; + cmn.changedGroups= pChanges->compat.changed_groups; + cmn.firstSI= pChanges->compat.first_si; + cmn.nSI= pChanges->compat.num_si; + cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si; + XkbSendCompatMapNotify(kbd,&cmn); + } + return; +} + +/***====================================================================***/ + +Bool +XkbFilterEvents(ClientPtr pClient,int nEvents,xEvent *xE) +{ +int i, button_mask; +DeviceIntPtr pXDev = inputInfo.keyboard; +XkbSrvInfoPtr xkbi; + + xkbi= pXDev->key->xkbInfo; + if ( pClient->xkbClientFlags & _XkbClientInitialized ) { + if ((xkbDebugFlags&0x10)&& + ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)|| + (xE[0].u.u.type==DeviceKeyPress)|| + (xE[0].u.u.type == DeviceKeyRelease))) { + DebugF("XKbFilterWriteEvents:\n"); + DebugF(" Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state); + DebugF(" XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n", + XkbLastRepeatEvent,xE, + ((XkbLastRepeatEvent!=(pointer)xE)?"True":"False")); + DebugF(" (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n", + pClient->xkbClientFlags, + (_XkbWantsDetectableAutoRepeat(pClient)?"True":"False")); + DebugF(" !IsRelease(%d) %s\n",xE[0].u.u.type, + (!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False"); + } + if ( (XkbLastRepeatEvent==(pointer)xE) && + (_XkbWantsDetectableAutoRepeat(pClient)) && + (_XkbIsReleaseEvent(xE[0].u.u.type)) ) { + return False; + } + if ((pXDev->grab != NullGrab) && pXDev->fromPassiveGrab && + ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)|| + (xE[0].u.u.type==DeviceKeyPress)|| + (xE[0].u.u.type == DeviceKeyRelease))) { + register unsigned state,flags; + + flags= pClient->xkbClientFlags; + state= xkbi->state.compat_grab_mods; + if (flags & XkbPCF_GrabsUseXKBStateMask) { + int group; + if (flags&XkbPCF_LookupStateWhenGrabbed) { + group= xkbi->state.group; + state= xkbi->state.lookup_mods; + } + else { + state= xkbi->state.grab_mods; + group= xkbi->state.base_group+xkbi->state.latched_group; + if ((group<0)||(group>=xkbi->desc->ctrls->num_groups)) { + group= XkbAdjustGroup(group,xkbi->desc->ctrls); + } + } + state = XkbBuildCoreState(state, group); + } + else if (flags&XkbPCF_LookupStateWhenGrabbed) + state= xkbi->state.compat_lookup_mods; + xE[0].u.keyButtonPointer.state= state; + } + button_mask = 1 << xE[0].u.u.detail; + if (xE[0].u.u.type == ButtonPress && + ((xE[0].u.keyButtonPointer.state >> 7) & button_mask) == button_mask && + (xkbi->lockedPtrButtons & button_mask) == button_mask) { + /* If the MouseKeys is pressed, and the "real" mouse is also pressed + * when the mouse is released, the server does not behave properly. + * Faking a release of the button here solves the problem. + */ + DebugF("Faking release of button %d\n", xE[0].u.u.detail); + XkbDDXFakePointerButton(ButtonRelease, xE[0].u.u.detail); + } + } + else { + register CARD8 type; + + for (i=0;i<nEvents;i++) { + type= xE[i].u.u.type; + if ((xkbDebugFlags&0x4)&& + ((xE[i].u.u.type==KeyPress)||(xE[i].u.u.type==KeyRelease)|| + (xE[i].u.u.type==DeviceKeyPress)|| + (xE[i].u.u.type == DeviceKeyRelease))) { + XkbStatePtr s= &xkbi->state; + DebugF("XKbFilterWriteEvents (non-XKB):\n"); + DebugF("event= 0x%04x\n",xE[i].u.keyButtonPointer.state); + DebugF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods, + s->grab_mods); + DebugF("compat lookup= 0x%02x, grab= 0x%02x\n", + s->compat_lookup_mods, + s->compat_grab_mods); + } + if ( (type>=KeyPress)&&(type<=MotionNotify) ) { + CARD16 old,new; + + old= xE[i].u.keyButtonPointer.state&(~0x1f00); + new= xE[i].u.keyButtonPointer.state&0x1F00; + + if (old==XkbStateFieldFromRec(&xkbi->state)) + new|= xkbi->state.compat_lookup_mods; + else new|= xkbi->state.compat_grab_mods; + xE[i].u.keyButtonPointer.state= new; + } + else if ((type==EnterNotify)||(type==LeaveNotify)) { + xE[i].u.enterLeave.state&= 0x1F00; + xE[i].u.enterLeave.state|= xkbi->state.compat_grab_mods; + } else if ((type>=DeviceKeyPress)&&(type<=DeviceMotionNotify)) { + CARD16 old, new; + deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*)&xE[i]; + old= kbp->state&(~0x1F00); + new= kbp->state&0x1F00; + if (old==XkbStateFieldFromRec(&xkbi->state)) + new|= xkbi->state.compat_lookup_mods; + else new|= xkbi->state.compat_grab_mods; + kbp->state= new; + } + button_mask = 1 << xE[i].u.u.detail; + if (type == ButtonPress && + ((xE[i].u.keyButtonPointer.state >> 7) & button_mask) == button_mask && + (xkbi->lockedPtrButtons & button_mask) == button_mask) { + DebugF("Faking release of button %d\n", xE[i].u.u.detail); + XkbDDXFakePointerButton(ButtonRelease, xE[i].u.u.detail); + } else if (type == DeviceButtonPress && + ((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask && + (xkbi->lockedPtrButtons & button_mask) == button_mask) { + DebugF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state); + XkbDDXFakePointerButton(DeviceButtonRelease, ((deviceKeyButtonPointer*)&xE[i])->state); + } + } + } + return True; +} + +/***====================================================================***/ + +XkbInterestPtr +XkbFindClientResource(DevicePtr inDev,ClientPtr client) +{ +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; + + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + while (interest){ + if (interest->client==client) { + return interest; + } + interest = interest->next; + } + } + return NULL; +} + +XkbInterestPtr +XkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id) +{ +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; + + interest = dev->xkb_interest; + while (interest) { + if (interest->client==client) + return ((interest->resource==id)?interest:NULL); + interest = interest->next; + } + interest = _XkbTypedAlloc(XkbInterestRec); + bzero(interest,sizeof(XkbInterestRec)); + if (interest) { + interest->dev = dev; + interest->client = client; + interest->resource = id; + interest->stateNotifyMask= 0; + interest->ctrlsNotifyMask= 0; + interest->namesNotifyMask= 0; + interest->compatNotifyMask= 0; + interest->bellNotifyMask= FALSE; + interest->accessXNotifyMask= 0; + interest->iStateNotifyMask= 0; + interest->iMapNotifyMask= 0; + interest->altSymsNotifyMask= 0; + interest->next = dev->xkb_interest; + dev->xkb_interest= interest; + return interest; + } + return NULL; +} + +int +XkbRemoveResourceClient(DevicePtr inDev,XID id) +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; +Bool found; +unsigned long autoCtrls,autoValues; +ClientPtr client = NULL; + + found= False; + autoCtrls= autoValues= 0; + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + if (interest && (interest->resource==id)){ + dev->xkb_interest = interest->next; + autoCtrls= interest->autoCtrls; + autoValues= interest->autoCtrlValues; + client= interest->client; + _XkbFree(interest); + found= True; + } + while ((!found)&&(interest->next)) { + if (interest->next->resource==id) { + XkbInterestPtr victim = interest->next; + interest->next = victim->next; + autoCtrls= victim->autoCtrls; + autoValues= victim->autoCtrlValues; + client= victim->client; + _XkbFree(victim); + found= True; + } + interest = interest->next; + } + } + if (found && autoCtrls && dev->key && dev->key->xkbInfo ) { + XkbEventCauseRec cause; + + xkbi= dev->key->xkbInfo; + XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client); + XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause); + } + return found; +} diff --git a/xorg-server/xkb/xkbInit.c b/xorg-server/xkb/xkbInit.c new file mode 100644 index 000000000..3b47396e5 --- /dev/null +++ b/xorg-server/xkb/xkbInit.c @@ -0,0 +1,902 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#ifdef HAVE_XKB_CONFIG_H +#include <xkb-config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <unistd.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include "misc.h" +#include "inputstr.h" +#include "opaque.h" +#include "property.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> +#include "xkbgeom.h" +#include <X11/extensions/XKMformat.h> +#include "xkbfile.h" +#include "xkb.h" + +#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1) + +#ifdef sgi +#define LED_CAPS 5 +#define LED_NUM 6 +#define LED_SCROLL 7 +#define PHYS_LEDS 0x7f +#define LED_COMPOSE 8 +#else +#if defined(ultrix) || defined(__osf__) || defined(__alpha) || defined(__alpha__) +#define LED_COMPOSE 2 +#define LED_CAPS 3 +#define LED_SCROLL 4 +#define LED_NUM 5 +#define PHYS_LEDS 0x1f +#else +#ifdef sun +#define LED_NUM 1 +#define LED_SCROLL 2 +#define LED_COMPOSE 3 +#define LED_CAPS 4 +#define PHYS_LEDS 0x0f +#else +#define LED_CAPS 1 +#define LED_NUM 2 +#define LED_SCROLL 3 +#define PHYS_LEDS 0x07 +#endif +#endif +#endif + +#define MAX_TOC 16 +typedef struct _SrvXkmInfo { + DeviceIntPtr dev; + FILE * file; + XkbDescPtr xkb; +} SrvXkmInfo; + + +/***====================================================================***/ + +#ifndef XKB_BASE_DIRECTORY +#define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb" +#endif +#ifndef XKB_BIN_DIRECTORY +#define XKB_BIN_DIRECTORY XKB_BASE_DIRECTORY +#endif +#ifndef XKB_DFLT_RULES_FILE +#define XKB_DFLT_RULES_FILE "rules" +#endif +#ifndef XKB_DFLT_KB_LAYOUT +#define XKB_DFLT_KB_LAYOUT "us" +#endif +#ifndef XKB_DFLT_KB_MODEL +#define XKB_DFLT_KB_MODEL "dflt" +#endif +#ifndef XKB_DFLT_KB_VARIANT +#define XKB_DFLT_KB_VARIANT NULL +#endif +#ifndef XKB_DFLT_KB_OPTIONS +#define XKB_DFLT_KB_OPTIONS NULL +#endif +#ifndef XKB_DFLT_DISABLED +#define XKB_DFLT_DISABLED True +#endif +#ifndef XKB_DFLT_RULES_PROP +#define XKB_DFLT_RULES_PROP True +#endif + +char * XkbBaseDirectory= XKB_BASE_DIRECTORY; +char * XkbBinDirectory= XKB_BIN_DIRECTORY; +static int XkbWantAccessX= 0; + +static Bool rulesDefined= False; +static char * XkbRulesFile= NULL; +static char * XkbModelDflt= NULL; +static char * XkbLayoutDflt= NULL; +static char * XkbVariantDflt= NULL; +static char * XkbOptionsDflt= NULL; + +static char * XkbModelUsed= NULL; +static char * XkbLayoutUsed= NULL; +static char * XkbVariantUsed= NULL; +static char * XkbOptionsUsed= NULL; + +static XkbDescPtr xkb_cached_map = NULL; + +_X_EXPORT Bool noXkbExtension= XKB_DFLT_DISABLED; +static Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP; + +/***====================================================================***/ + +static char * +XkbGetRulesDflts(XkbRF_VarDefsPtr defs) +{ + if (XkbModelDflt) defs->model= XkbModelDflt; + else defs->model= XKB_DFLT_KB_MODEL; + if (XkbLayoutDflt) defs->layout= XkbLayoutDflt; + else defs->layout= XKB_DFLT_KB_LAYOUT; + if (XkbVariantDflt) defs->variant= XkbVariantDflt; + else defs->variant= XKB_DFLT_KB_VARIANT; + if (XkbOptionsDflt) defs->options= XkbOptionsDflt; + else defs->options= XKB_DFLT_KB_OPTIONS; + return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE); +} + +static Bool +XkbWriteRulesProp(ClientPtr client, pointer closure) +{ +int len,out; +Atom name; +char * pval; + + if (rulesDefined && (!XkbRulesFile)) + return False; + len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE)); + len+= (XkbModelUsed?strlen(XkbModelUsed):0); + len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0); + len+= (XkbVariantUsed?strlen(XkbVariantUsed):0); + len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0); + if (len<1) + return True; + + len+= 5; /* trailing NULs */ + + name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1); + if (name==None) { + ErrorF("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM); + return True; + } + pval= (char*) xalloc(len); + if (!pval) { + ErrorF("Allocation error: %s proprerty not created\n", + _XKB_RF_NAMES_PROP_ATOM); + return True; + } + out= 0; + if (XkbRulesFile) { + strcpy(&pval[out],XkbRulesFile); + out+= strlen(XkbRulesFile); + } else { + strcpy(&pval[out],XKB_DFLT_RULES_FILE); + out+= strlen(XKB_DFLT_RULES_FILE); + } + pval[out++]= '\0'; + if (XkbModelUsed) { + strcpy(&pval[out],XkbModelUsed); + out+= strlen(XkbModelUsed); + } + pval[out++]= '\0'; + if (XkbLayoutUsed) { + strcpy(&pval[out],XkbLayoutUsed); + out+= strlen(XkbLayoutUsed); + } + pval[out++]= '\0'; + if (XkbVariantUsed) { + strcpy(&pval[out],XkbVariantUsed); + out+= strlen(XkbVariantUsed); + } + pval[out++]= '\0'; + if (XkbOptionsUsed) { + strcpy(&pval[out],XkbOptionsUsed); + out+= strlen(XkbOptionsUsed); + } + pval[out++]= '\0'; + if (out!=len) { + ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n", + out,len); + } + dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8, + PropModeReplace, len, pval, True); + xfree(pval); + return True; +} + +static void +XkbSetRulesUsed(XkbRF_VarDefsPtr defs) +{ + if (XkbModelUsed) + _XkbFree(XkbModelUsed); + XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL); + if (XkbLayoutUsed) + _XkbFree(XkbLayoutUsed); + XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL); + if (XkbVariantUsed) + _XkbFree(XkbVariantUsed); + XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL); + if (XkbOptionsUsed) + _XkbFree(XkbOptionsUsed); + XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL); + if (XkbWantRulesProp) + QueueWorkProc(XkbWriteRulesProp,NULL,NULL); + return; +} + +_X_EXPORT void +XkbSetRulesDflts(char *rulesFile,char *model,char *layout, + char *variant,char *options) +{ + if (XkbRulesFile) + _XkbFree(XkbRulesFile); + XkbRulesFile= _XkbDupString(rulesFile); + rulesDefined= True; + if (model) { + if (XkbModelDflt) + _XkbFree(XkbModelDflt); + XkbModelDflt= _XkbDupString(model); + } + if (layout) { + if (XkbLayoutDflt) + _XkbFree(XkbLayoutDflt); + XkbLayoutDflt= _XkbDupString(layout); + } + if (variant) { + if (XkbVariantDflt) + _XkbFree(XkbVariantDflt); + XkbVariantDflt= _XkbDupString(variant); + } + if (options) { + if (XkbOptionsDflt) + _XkbFree(XkbOptionsDflt); + XkbOptionsDflt= _XkbDupString(options); + } + return; +} + +/***====================================================================***/ + +#include "xkbDflts.h" + +static Bool +XkbInitKeyTypes(XkbDescPtr xkb) +{ + if (xkb->defined & XkmTypesMask) + return True; + + initTypeNames(NULL); + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success) + return False; + if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!= + Success) { + return False; + } + xkb->map->size_types= xkb->map->num_types= num_dflt_types; + return True; +} + +static void +XkbInitRadioGroups(XkbSrvInfoPtr xkbi) +{ + xkbi->nRadioGroups = 0; + xkbi->radioGroups = NULL; + return; +} + + +static Status +XkbInitCompatStructs(XkbDescPtr xkb) +{ +register int i; +XkbCompatMapPtr compat; + + if (xkb->defined & XkmCompatMapMask) + return True; + + if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success) + return BadAlloc; + compat = xkb->compat; + if (compat->sym_interpret) { + compat->num_si = num_dfltSI; + memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI)); + } + for (i=0;i<XkbNumKbdGroups;i++) { + compat->groups[i]= compatMap.groups[i]; + if (compat->groups[i].vmods!=0) { + unsigned mask; + mask= XkbMaskForVMask(xkb,compat->groups[i].vmods); + compat->groups[i].mask= compat->groups[i].real_mods|mask; + } + else compat->groups[i].mask= compat->groups[i].real_mods; + } + return Success; +} + +static void +XkbInitSemantics(XkbDescPtr xkb) +{ + XkbInitKeyTypes(xkb); + XkbInitCompatStructs(xkb); + return; +} + +/***====================================================================***/ + +static Status +XkbInitNames(XkbSrvInfoPtr xkbi) +{ +XkbDescPtr xkb; +XkbNamesPtr names; +Status rtrn; +Atom unknown; + + xkb= xkbi->desc; + if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success) + return rtrn; + unknown= CREATE_ATOM("unknown"); + names = xkb->names; + if (names->keycodes==None) names->keycodes= unknown; + if (names->geometry==None) names->geometry= unknown; + if (names->phys_symbols==None) names->phys_symbols= unknown; + if (names->symbols==None) names->symbols= unknown; + if (names->types==None) names->types= unknown; + if (names->compat==None) names->compat= unknown; + if (!(xkb->defined & XkmVirtualModsMask)) { + if (names->vmods[vmod_NumLock]==None) + names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock"); + if (names->vmods[vmod_Alt]==None) + names->vmods[vmod_Alt]= CREATE_ATOM("Alt"); + if (names->vmods[vmod_AltGr]==None) + names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch"); + } + + if (!(xkb->defined & XkmIndicatorsMask) || + !(xkb->defined & XkmGeometryMask)) { + initIndicatorNames(NULL,xkb); + if (names->indicators[LED_CAPS-1]==None) + names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock"); + if (names->indicators[LED_NUM-1]==None) + names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock"); + if (names->indicators[LED_SCROLL-1]==None) + names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock"); +#ifdef LED_COMPOSE + if (names->indicators[LED_COMPOSE-1]==None) + names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose"); +#endif + } + + if (xkb->geom!=NULL) + names->geometry= xkb->geom->name; + else names->geometry= unknown; + + return Success; +} + +static Status +XkbInitIndicatorMap(XkbSrvInfoPtr xkbi) +{ +XkbDescPtr xkb; +XkbIndicatorPtr map; +XkbSrvLedInfoPtr sli; + + xkb= xkbi->desc; + if (XkbAllocIndicatorMaps(xkb)!=Success) + return BadAlloc; + + if (!(xkb->defined & XkmIndicatorsMask)) { + map= xkb->indicators; + map->phys_indicators = PHYS_LEDS; + map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit; + map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked; + map->maps[LED_CAPS-1].mods.mask= LockMask; + map->maps[LED_CAPS-1].mods.real_mods= LockMask; + + map->maps[LED_NUM-1].flags= XkbIM_NoExplicit; + map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked; + map->maps[LED_NUM-1].mods.mask= 0; + map->maps[LED_NUM-1].mods.real_mods= 0; + map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask; + + map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit; + map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked; + map->maps[LED_SCROLL-1].mods.mask= Mod3Mask; + map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask; + } + + sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); + if (sli) + XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); + + return Success; +} + +static Status +XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi) +{ +XkbDescPtr xkb; +XkbControlsPtr ctrls; + + xkb= xkbi->desc; + /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */ + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) + FatalError("Couldn't allocate keyboard controls\n"); + ctrls= xkb->ctrls; + if (!(xkb->defined & XkmSymbolsMask)) + ctrls->num_groups = 1; + ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0); + ctrls->internal.mask = 0; + ctrls->internal.real_mods = 0; + ctrls->internal.vmods = 0; + ctrls->ignore_lock.mask = 0; + ctrls->ignore_lock.real_mods = 0; + ctrls->ignore_lock.vmods = 0; + ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask| + XkbMouseKeysAccelMask|XkbAudibleBellMask| + XkbIgnoreGroupLockMask; + if (XkbWantAccessX) + ctrls->enabled_ctrls|= XkbAccessXKeysMask; + AccessXInit(pXDev); + return Success; +} + +void +XkbInitDevice(DeviceIntPtr pXDev) +{ +int i; +XkbSrvInfoPtr xkbi; +XkbChangesRec changes; +unsigned check; +XkbEventCauseRec cause; + + bzero(&changes,sizeof(XkbChangesRec)); + pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec); + if ( xkbi ) { + XkbDescPtr xkb; + + if (xkb_cached_map) { + xkbi->desc = xkb_cached_map; + xkb_cached_map = NULL; + } + else { + xkbi->desc= XkbAllocKeyboard(); + if (!xkbi->desc) + FatalError("Couldn't allocate keyboard description\n"); + xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode; + xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode; + } + xkb= xkbi->desc; + if (xkb->min_key_code == 0) + xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode; + if (xkb->max_key_code == 0) + xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode; + if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)|| + (pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) { + /* 12/9/95 (ef) -- XXX! Maybe we should try to fix up one or */ + /* the other here, but for now just complain */ + /* can't just update the core range without */ + /* reallocating the KeySymsRec (pain) */ + ErrorF("Internal Error!! XKB and core keymap have different range\n"); + } + if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) + FatalError("Couldn't allocate client map in XkbInitDevice\n"); + i= XkbNumKeys(xkb)/3+1; + if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success) + FatalError("Couldn't allocate server map in XkbInitDevice\n"); + + xkbi->dfltPtrDelta=1; + xkbi->device = pXDev; + + XkbInitSemantics(xkb); + XkbInitNames(xkbi); + XkbInitRadioGroups(xkbi); + + /* 12/31/94 (ef) -- XXX! Should check if state loaded from file */ + bzero(&xkbi->state,sizeof(XkbStateRec)); + + XkbInitControls(pXDev,xkbi); + + if (xkb->defined & XkmSymbolsMask) + memcpy(pXDev->key->modifierMap, xkb->map->modmap, + xkb->max_key_code + 1); + else + memcpy(xkb->map->modmap, pXDev->key->modifierMap, + xkb->max_key_code + 1); + + XkbInitIndicatorMap(xkbi); + + XkbDDXInitDevice(pXDev); + + if (xkb->defined & XkmSymbolsMask) + XkbUpdateCoreDescription(pXDev, True); + else + XkbUpdateKeyTypesFromCore(pXDev, xkb->min_key_code, + XkbNumKeys(xkb), &changes); + + XkbSetCauseUnknown(&cause); + XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes, + &check,&cause); + /* For sanity. The first time the connection + * is opened, the client side min and max are set + * using QueryMinMaxKeyCodes() which grabs them + * from pXDev. + */ + pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code; + pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code; + } + return; +} + +#if MAP_LENGTH > XkbMaxKeyCount +#undef XkbMaxKeyCount +#define XkbMaxKeyCount MAP_LENGTH +#endif + +_X_EXPORT Bool +XkbInitKeyboardDeviceStruct( + DeviceIntPtr dev, + XkbComponentNamesPtr names, + KeySymsPtr pSymsIn, + CARD8 pModsIn[], + void (*bellProc)( + int /*percent*/, + DeviceIntPtr /*device*/, + pointer /*ctrl*/, + int), + void (*ctrlProc)( + DeviceIntPtr /*device*/, + KeybdCtrl * /*ctrl*/)) +{ +KeySymsRec tmpSyms,*pSyms; +CARD8 tmpMods[XkbMaxLegalKeyCode+1],*pMods; +char name[PATH_MAX],*rules; +Bool ok=False; +XkbRF_VarDefsRec defs; +XkbDescPtr xkb; + + if ((dev->key!=NULL)||(dev->kbdfeed!=NULL)) + return False; + pSyms= pSymsIn; + pMods= pModsIn; + bzero(&defs,sizeof(XkbRF_VarDefsRec)); + rules= XkbGetRulesDflts(&defs); + + /* + * The strings are duplicated because it is not guaranteed that + * they are allocated, or that they are allocated for every server + * generation. Eventually they will be freed at the end of this + * function. + */ + names->keymap = NULL; + if (names->keycodes) names->keycodes = _XkbDupString(names->keycodes); + if (names->types) names->types = _XkbDupString(names->types); + if (names->compat) names->compat = _XkbDupString(names->compat); + if (names->geometry) names->geometry = _XkbDupString(names->geometry); + if (names->symbols) names->symbols = _XkbDupString(names->symbols); + + if (defs.model && defs.layout && rules) { + XkbComponentNamesRec rNames; + bzero(&rNames,sizeof(XkbComponentNamesRec)); + if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) { + if (rNames.keycodes) { + if (!names->keycodes) + names->keycodes = rNames.keycodes; + else + _XkbFree(rNames.keycodes); + } + if (rNames.types) { + if (!names->types) + names->types = rNames.types; + else _XkbFree(rNames.types); + } + if (rNames.compat) { + if (!names->compat) + names->compat = rNames.compat; + else _XkbFree(rNames.compat); + } + if (rNames.symbols) { + if (!names->symbols) + names->symbols = rNames.symbols; + else _XkbFree(rNames.symbols); + } + if (rNames.geometry) { + if (!names->geometry) + names->geometry = rNames.geometry; + else _XkbFree(rNames.geometry); + } + XkbSetRulesUsed(&defs); + } + } + + ok = (Bool) XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0, + &xkb,name,PATH_MAX); + + if (ok && (xkb!=NULL)) { + KeyCode minKC,maxKC; + + minKC= xkb->min_key_code; + maxKC= xkb->max_key_code; + if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&& + ((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) { + if (xkb->map!=NULL) { + KeySym *inSym,*outSym; + int width= pSymsIn->mapWidth; + + tmpSyms.minKeyCode= minKC; + tmpSyms.maxKeyCode= maxKC; + + if (minKC<pSymsIn->minKeyCode) + minKC= pSymsIn->minKeyCode; + if (maxKC>pSymsIn->maxKeyCode) + maxKC= pSymsIn->maxKeyCode; + + tmpSyms.mapWidth= width; + tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym); + inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width]; + outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width]; + memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym)); + pSyms= &tmpSyms; + } + if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) { + bzero(tmpMods,XkbMaxKeyCount); + memcpy(tmpMods,xkb->map->modmap,maxKC+1); + pMods= tmpMods; + } + } + /* Store the map here so we can pick it back up in XkbInitDevice. + * Sigh. */ + xkb_cached_map = xkb; + } + else { + LogMessage(X_WARNING, "Couldn't load XKB keymap, falling back to pre-XKB keymap\n"); + } + ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc); + xkb_cached_map = NULL; + if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) { + _XkbFree(pSyms->map); + pSyms->map= NULL; + } + + if (names->keycodes) _XkbFree(names->keycodes); + names->keycodes = NULL; + if (names->types) _XkbFree(names->types); + names->types = NULL; + if (names->compat) _XkbFree(names->compat); + names->compat = NULL; + if (names->geometry) _XkbFree(names->geometry); + names->geometry = NULL; + if (names->symbols) _XkbFree(names->symbols); + names->symbols = NULL; + + return ok; +} + +/***====================================================================***/ + + /* + * InitKeyClassDeviceStruct initializes the key class before it + * initializes the keyboard feedback class for a device. + * UpdateActions can't set up the correct autorepeat for keyboard + * initialization because the keyboard feedback isn't created yet. + * Instead, UpdateActions notes the "correct" autorepeat in the + * SrvInfo structure and InitKbdFeedbackClass calls UpdateAutoRepeat + * to apply the computed autorepeat once the feedback class exists. + * + * DIX will apply the changed autorepeat, so there's no need to + * do so here. This function returns True if both RepeatKeys and + * the core protocol autorepeat ctrls are set (i.e. should use + * software autorepeat), false otherwise. + * + * This function also computes the autorepeat accelerators for the + * default indicator feedback. + */ +int +XkbFinishDeviceInit(DeviceIntPtr pXDev) +{ +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +int softRepeat; +XkbSrvLedInfoPtr sli; + + xkbi = NULL; + if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) { + xkbi= pXDev->key->xkbInfo; + xkb= xkbi->desc; + if (pXDev->kbdfeed) { + xkbi->kbdProc= pXDev->kbdfeed->CtrlProc; + pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc; + } + if (pXDev->kbdfeed->ctrl.autoRepeat) + xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask; + softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0; + if (pXDev->kbdfeed) { + memcpy(pXDev->kbdfeed->ctrl.autoRepeats, + xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize); + softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat; + } + } + else softRepeat= 0; + sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0); + if (sli && xkbi) + XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); + else DebugF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n"); + return softRepeat; +} + + /* + * Be very careful about what does and doesn't get freed by this + * function. To reduce fragmentation, XkbInitDevice allocates a + * single huge block per device and divides it up into most of the + * fixed-size structures for the device. Don't free anything that + * is part of this larger block. + */ +void +XkbFreeInfo(XkbSrvInfoPtr xkbi) +{ + if (xkbi->radioGroups) { + _XkbFree(xkbi->radioGroups); + xkbi->radioGroups= NULL; + } + if (xkbi->mouseKeyTimer) { + TimerFree(xkbi->mouseKeyTimer); + xkbi->mouseKeyTimer= NULL; + } + if (xkbi->slowKeysTimer) { + TimerFree(xkbi->slowKeysTimer); + xkbi->slowKeysTimer= NULL; + } + if (xkbi->bounceKeysTimer) { + TimerFree(xkbi->bounceKeysTimer); + xkbi->bounceKeysTimer= NULL; + } + if (xkbi->repeatKeyTimer) { + TimerFree(xkbi->repeatKeyTimer); + xkbi->repeatKeyTimer= NULL; + } + if (xkbi->krgTimer) { + TimerFree(xkbi->krgTimer); + xkbi->krgTimer= NULL; + } + xkbi->beepType= _BEEP_NONE; + if (xkbi->beepTimer) { + TimerFree(xkbi->beepTimer); + xkbi->beepTimer= NULL; + } + if (xkbi->desc) { + XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True); + xkbi->desc= NULL; + } + _XkbFree(xkbi); + return; +} + +/***====================================================================***/ + +extern int XkbDfltRepeatDelay; +extern int XkbDfltRepeatInterval; + +extern unsigned short XkbDfltAccessXTimeout; +extern unsigned int XkbDfltAccessXTimeoutMask; +extern unsigned int XkbDfltAccessXFeedback; +extern unsigned char XkbDfltAccessXOptions; + +int +XkbProcessArguments(int argc,char *argv[],int i) +{ + if (strcmp(argv[i],"-kb")==0) { + noXkbExtension= True; + return 1; + } + else if (strcmp(argv[i],"+kb")==0) { + noXkbExtension= False; + return 1; + } + else if (strncmp(argv[i], "-xkbdir", 7) == 0) { + if(++i < argc) { +#if !defined(WIN32) && !defined(__CYGWIN__) + if (getuid() != geteuid()) { + LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n"); + return -1; + } else +#endif + { + if (strlen(argv[i]) < PATH_MAX) { + XkbBaseDirectory= argv[i]; + return 2; + } else { + LogMessage(X_ERROR, "-xkbdir pathname too long\n"); + return -1; + } + } + } + else { + return -1; + } + } + else if ((strncmp(argv[i],"-accessx",8)==0)|| + (strncmp(argv[i],"+accessx",8)==0)) { + int j=1; + if (argv[i][0]=='-') + XkbWantAccessX= 0; + else { + XkbWantAccessX= 1; + + if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { + XkbDfltAccessXTimeout = atoi(argv[++i]); + j++; + + if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { + /* + * presumption that the reasonably useful range of + * values fits in 0..MAXINT since SunOS 4 doesn't + * have strtoul. + */ + XkbDfltAccessXTimeoutMask=(unsigned int) + strtol(argv[++i],NULL,16); + j++; + } + if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { + if (argv[++i][0] == '1' ) + XkbDfltAccessXFeedback=XkbAccessXFeedbackMask; + else + XkbDfltAccessXFeedback=0; + j++; + } + if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { + XkbDfltAccessXOptions=(unsigned char) + strtol(argv[++i],NULL,16); + j++; + } + } + } + return j; + } + if ((strcmp(argv[i], "-ardelay") == 0) || + (strcmp (argv[i], "-ar1") == 0)) { /* -ardelay int */ + if (++i >= argc) UseMsg (); + XkbDfltRepeatDelay = (long)atoi(argv[i]); + return 2; + } + if ((strcmp(argv[i], "-arinterval") == 0) || + (strcmp (argv[i], "-ar2") == 0)) { /* -arinterval int */ + if (++i >= argc) UseMsg (); + XkbDfltRepeatInterval = (long)atoi(argv[i]); + return 2; + } + return 0; +} + +void +XkbUseMsg(void) +{ + ErrorF("-kb disable the X Keyboard Extension\n"); + ErrorF("+kb enable the X Keyboard Extension\n"); + ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n"); + ErrorF(" enable/disable accessx key sequences\n"); + ErrorF("-ardelay set XKB autorepeat delay\n"); + ErrorF("-arinterval set XKB autorepeat interval\n"); +} diff --git a/xorg-server/xkb/xkbLEDs.c b/xorg-server/xkb/xkbLEDs.c new file mode 100644 index 000000000..55ce12aad --- /dev/null +++ b/xorg-server/xkb/xkbLEDs.c @@ -0,0 +1,937 @@ +/************************************************************ +Copyright (c) 1995 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 <dix-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" + +#include <X11/extensions/XI.h> +#include <xkbsrv.h> +#include "xkb.h" + +/***====================================================================***/ + + /* + * unsigned + * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn) + * + * Given a keyboard and a set of state components that have changed, + * this function returns the indicators on the default keyboard + * feedback that might be affected. It also reports whether or not + * any extension devices might be affected in check_devs_rtrn. + */ + +unsigned +XkbIndicatorsToUpdate( DeviceIntPtr dev, + unsigned long state_changes, + Bool enable_changes) +{ +register unsigned update= 0; +XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + + if (!sli) + return update; + + if (state_changes&(XkbModifierStateMask|XkbGroupStateMask)) + update|= sli->usesEffective; + if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask)) + update|= sli->usesBase; + if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask)) + update|= sli->usesLatched; + if (state_changes&(XkbModifierLockMask|XkbGroupLockMask)) + update|= sli->usesLocked; + if (state_changes&XkbCompatStateMask) + update|= sli->usesCompat; + if (enable_changes) + update|= sli->usesControls; + return update; +} + +/***====================================================================***/ + + /* + * Bool + *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change) + * + * Some indicators "drive" the keyboard when their state is explicitly + * changed, as described in section 9.2.1 of the XKB protocol spec. + * This function updates the state and controls for the keyboard + * specified by 'xkbi' to reflect any changes that are required + * when the indicator described by 'map' is turned on or off. The + * extent of the changes is reported in change, which must be defined. + */ +static Bool +XkbApplyLEDChangeToKeyboard( XkbSrvInfoPtr xkbi, + XkbIndicatorMapPtr map, + Bool on, + XkbChangesPtr change) +{ +Bool ctrlChange,stateChange; +XkbStatePtr state; + + if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0)) + return False; + ctrlChange= stateChange= False; + if (map->ctrls) { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + unsigned old; + + old= ctrls->enabled_ctrls; + if (on) ctrls->enabled_ctrls|= map->ctrls; + else ctrls->enabled_ctrls&= ~map->ctrls; + if (old!=ctrls->enabled_ctrls) { + change->ctrls.changed_ctrls= XkbControlsEnabledMask; + change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls; + ctrlChange= True; + } + } + state= &xkbi->state; + if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) { + register int i; + register unsigned bit,match; + + if (on) match= (map->groups)&XkbAllGroupsMask; + else match= (~map->groups)&XkbAllGroupsMask; + if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) { + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (bit&match) + break; + } + if (map->which_groups&XkbIM_UseLatched) + XkbLatchGroup(xkbi->device,0); /* unlatch group */ + state->locked_group= i; + stateChange= True; + } + else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) { + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (bit&match) + break; + } + state->locked_group= 0; + XkbLatchGroup(xkbi->device,i); + stateChange= True; + } + } + if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) { + if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) { + register unsigned long old; + old= state->locked_mods; + if (on) state->locked_mods|= map->mods.mask; + else state->locked_mods&= ~map->mods.mask; + if (state->locked_mods!=old) + stateChange= True; + } + if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) { + register unsigned long newmods; + newmods= state->latched_mods; + if (on) newmods|= map->mods.mask; + else newmods&= ~map->mods.mask; + if (newmods!=state->locked_mods) { + newmods&= map->mods.mask; + XkbLatchModifiers(xkbi->device,map->mods.mask,newmods); + stateChange= True; + } + } + } + return (stateChange || ctrlChange); +} + + /* + * Bool + * ComputeAutoState(map,state,ctrls) + * + * This function reports the effect of applying the specified + * indicator map given the specified state and controls, as + * described in section 9.2 of the XKB protocol specification. + */ + +static Bool +ComputeAutoState( XkbIndicatorMapPtr map, + XkbStatePtr state, + XkbControlsPtr ctrls) +{ +Bool on; +CARD8 mods,group; + + on= False; + mods= group= 0; + if (map->which_mods&XkbIM_UseAnyMods) { + if (map->which_mods&XkbIM_UseBase) + mods|= state->base_mods; + if (map->which_mods&XkbIM_UseLatched) + mods|= state->latched_mods; + if (map->which_mods&XkbIM_UseLocked) + mods|= state->locked_mods; + if (map->which_mods&XkbIM_UseEffective) + mods|= state->mods; + if (map->which_mods&XkbIM_UseCompat) + mods|= state->compat_state; + on = ((map->mods.mask&mods)!=0); + on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0)); + } + if (map->which_groups&XkbIM_UseAnyGroup) { + if (map->which_groups&XkbIM_UseBase) + group|= (1L << state->base_group); + if (map->which_groups&XkbIM_UseLatched) + group|= (1L << state->latched_group); + if (map->which_groups&XkbIM_UseLocked) + group|= (1L << state->locked_group); + if (map->which_groups&XkbIM_UseEffective) + group|= (1L << state->group); + on = on||(((map->groups&group)!=0)||(map->groups==0)); + } + if (map->ctrls) + on = on||(ctrls->enabled_ctrls&map->ctrls); + return on; +} + + +static void +XkbUpdateLedAutoState( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned maps_to_check, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +{ +DeviceIntPtr kbd; +XkbStatePtr state; +XkbControlsPtr ctrls; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; +register unsigned i,bit,affected; +register XkbIndicatorMapPtr map; +unsigned oldState; + + if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0)) + return; + + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= inputInfo.keyboard; + + state= &kbd->key->xkbInfo->state; + ctrls= kbd->key->xkbInfo->desc->ctrls; + affected= maps_to_check; + oldState= sli->effectiveState; + sli->autoState&= ~affected; + for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) { + if ((affected&bit)==0) + continue; + affected&= ~bit; + map= &sli->maps[i]; + if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls)) + sli->autoState|= bit; + } + sli->effectiveState= (sli->autoState|sli->explicitState); + affected= sli->effectiveState^oldState; + if (affected==0) + return; + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->indicators.state_changes|= affected; + } + + ed->reason|= XkbXI_IndicatorStateMask; + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXI_IndicatorStateMask; + ed->supported= XkbXI_AllFeaturesMask; + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} + +static void +XkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause) +{ +DeviceIntPtr edev; +XkbSrvLedInfoPtr sli; + + for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) { + if (edev->kbdfeed) { + KbdFeedbackPtr kf; + for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) { + if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL)) + continue; + sli= kf->xkb_sli; + XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, + changes,cause); + + } + } + if (edev->leds) { + LedFeedbackPtr lf; + for (lf=edev->leds;lf!=NULL;lf=lf->next) { + if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL)) + continue; + sli= lf->xkb_sli; + XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, + changes,cause); + + } + } + } + return; +} + + +/***====================================================================***/ + + /* + * void + * XkbSetIndicators(dev,affect,values,cause) + * + * Attempts to change the indicators specified in 'affect' to the + * states specified in 'values' for the default keyboard feedback + * on the keyboard specified by 'dev.' Attempts to change indicator + * state might be ignored or have no affect, depending on the XKB + * indicator map for any affected indicators, as described in section + * 9.2 of the XKB protocol specification. + * + * If 'changes' is non-NULL, this function notes any changes to the + * keyboard state, controls, or indicator state that result from this + * attempted change. If 'changes' is NULL, this function generates + * XKB events to report any such changes to interested clients. + * + * If 'cause' is non-NULL, it specifies the reason for the change, + * as reported in some XKB events. If it is NULL, this function + * assumes that the change is the result of a core protocol + * ChangeKeyboardMapping request. + */ + +void +XkbSetIndicators( DeviceIntPtr dev, + CARD32 affect, + CARD32 values, + XkbEventCausePtr cause) +{ +XkbSrvLedInfoPtr sli; +XkbChangesRec changes; +xkbExtensionDeviceNotify ed; +unsigned side_affected; + + bzero((char *)&changes,sizeof(XkbChangesRec)); + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + sli->explicitState&= ~affect; + sli->explicitState|= (affect&values); + XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause); + + side_affected= 0; + if (changes.state_changes!=0) + side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,False); + if (changes.ctrls.enabled_ctrls_changes) + side_affected|= sli->usesControls; + + if (side_affected) { + XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause); + affect|= side_affected; + } + if (changes.state_changes || changes.ctrls.enabled_ctrls_changes) + XkbUpdateAllDeviceIndicators(NULL,cause); + + XkbFlushLedEvents(dev,dev,sli,&ed,&changes,cause); + return; +} + +/***====================================================================***/ + +/***====================================================================***/ + + /* + * void + * XkbUpdateIndicators(dev,update,check_edevs,changes,cause) + * + * Applies the indicator maps for any indicators specified in + * 'update' from the default keyboard feedback on the device + * specified by 'dev.' + * + * If 'changes' is NULL, this function generates and XKB events + * required to report the necessary changes, otherwise it simply + * notes the indicators with changed state. + * + * If 'check_edevs' is True, this function also checks the indicator + * maps for any open extension devices that have them, and updates + * the state of any extension device indicators as necessary. + */ + +void +XkbUpdateIndicators( DeviceIntPtr dev, + register CARD32 update, + Bool check_edevs, + XkbChangesPtr changes, + XkbEventCausePtr cause) +{ +XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause); + if (check_edevs) + XkbUpdateAllDeviceIndicators(changes,cause); + return; +} + +/***====================================================================***/ + +/***====================================================================***/ + + /* + * void + * XkbCheckIndicatorMaps(dev,sli,which) + * + * Updates the 'indicator accelerators' for the indicators specified + * by 'which' in the feedback specified by 'sli.' The indicator + * accelerators are internal to the server and are used to simplify + * and speed up the process of figuring out which indicators might + * be affected by a particular change in keyboard state or controls. + */ + +void +XkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which) +{ +register unsigned i,bit; +XkbIndicatorMapPtr map; +XkbDescPtr xkb; + + if ((sli->flags&XkbSLI_HasOwnState)==0) + dev= inputInfo.keyboard; + + sli->usesBase&= ~which; + sli->usesLatched&= ~which; + sli->usesLocked&= ~which; + sli->usesEffective&= ~which; + sli->usesCompat&= ~which; + sli->usesControls&= ~which; + sli->mapsPresent&= ~which; + + xkb= dev->key->xkbInfo->desc; + for (i=0,bit=1,map=sli->maps;i<XkbNumIndicators;i++,bit<<=1,map++) { + if (which&bit) { + CARD8 what; + + if (!XkbIM_InUse(map)) + continue; + sli->mapsPresent|= bit; + + what= (map->which_mods|map->which_groups); + if (what&XkbIM_UseBase) + sli->usesBase|= bit; + if (what&XkbIM_UseLatched) + sli->usesLatched|= bit; + if (what&XkbIM_UseLocked) + sli->usesLocked|= bit; + if (what&XkbIM_UseEffective) + sli->usesEffective|= bit; + if (what&XkbIM_UseCompat) + sli->usesCompat|= bit; + if (map->ctrls) + sli->usesControls|= bit; + + map->mods.mask= map->mods.real_mods; + if (map->mods.vmods!=0) { + map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods); + } + } + } + sli->usedComponents= 0; + if (sli->usesBase) + sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask; + if (sli->usesLatched) + sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask; + if (sli->usesLocked) + sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask; + if (sli->usesEffective) + sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask; + if (sli->usesCompat) + sli->usedComponents|= XkbCompatStateMask; + return; +} + +/***====================================================================***/ + + /* + * XkbSrvLedInfoPtr + * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts) + * + * Allocates an XkbSrvLedInfoPtr for the feedback specified by either + * 'kf' or 'lf' on the keyboard specified by 'dev.' + * + * If 'needed_parts' is non-zero, this function makes sure that any + * of the parts speicified therein are allocated. + */ +XkbSrvLedInfoPtr +XkbAllocSrvLedInfo( DeviceIntPtr dev, + KbdFeedbackPtr kf, + LedFeedbackPtr lf, + unsigned needed_parts) +{ +XkbSrvLedInfoPtr sli; +Bool checkAccel; +Bool checkNames; + + sli= NULL; + checkAccel= checkNames= False; + if ((kf!=NULL)&&(kf->xkb_sli==NULL)) { + kf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec); + if (sli==NULL) + return NULL; /* ALLOCATION ERROR */ + if (dev->key && dev->key->xkbInfo) + sli->flags= XkbSLI_HasOwnState; + else sli->flags= 0; + sli->class= KbdFeedbackClass; + sli->id= kf->ctrl.id; + sli->fb.kf= kf; + + sli->autoState= 0; + sli->explicitState= kf->ctrl.leds; + sli->effectiveState= kf->ctrl.leds; + + if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) { + XkbDescPtr xkb; + xkb= dev->key->xkbInfo->desc; + sli->flags|= XkbSLI_IsDefault; + sli->physIndicators= xkb->indicators->phys_indicators; + sli->names= xkb->names->indicators; + sli->maps= xkb->indicators->maps; + checkNames= checkAccel= True; + } + else { + sli->physIndicators= XkbAllIndicatorsMask; + sli->names= NULL; + sli->maps= NULL; + } + } + else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) { + XkbDescPtr xkb; + xkb= dev->key->xkbInfo->desc; + sli->physIndicators= xkb->indicators->phys_indicators; + if (xkb->names->indicators!=sli->names) { + checkNames= True; + sli->names= xkb->names->indicators; + } + if (xkb->indicators->maps!=sli->maps) { + checkAccel= True; + sli->maps= xkb->indicators->maps; + } + } + else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) { + lf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec); + if (sli==NULL) + return NULL; /* ALLOCATION ERROR */ + if (dev->key && dev->key->xkbInfo) + sli->flags= XkbSLI_HasOwnState; + else sli->flags= 0; + sli->class= LedFeedbackClass; + sli->id= lf->ctrl.id; + sli->fb.lf= lf; + + sli->physIndicators= lf->ctrl.led_mask; + sli->autoState= 0; + sli->explicitState= lf->ctrl.led_values; + sli->effectiveState= lf->ctrl.led_values; + sli->maps= NULL; + sli->names= NULL; + } + if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) + sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom); + if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) + sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); + if (checkNames) { + register unsigned i,bit; + sli->namesPresent= 0; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (sli->names[i]!=None) + sli->namesPresent|= bit; + } + } + if (checkAccel) + XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask); + return sli; +} + +void +XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli) +{ + if ((sli->flags&XkbSLI_IsDefault)==0) { + if (sli->maps) _XkbFree(sli->maps); + if (sli->names) _XkbFree(sli->names); + } + sli->maps= NULL; + sli->names= NULL; + _XkbFree(sli); + return; +} + + +/***====================================================================***/ + + /* + * XkbSrvLedInfoPtr + * XkbFindSrvLedInfo(dev,class,id,needed_parts) + * + * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id' + * on the device specified by 'dev.' If the class and id specify + * a valid device feedback, this function returns the existing + * feedback or allocates a new one. + * + */ + +XkbSrvLedInfoPtr +XkbFindSrvLedInfo( DeviceIntPtr dev, + unsigned class, + unsigned id, + unsigned needed_parts) +{ +XkbSrvLedInfoPtr sli; + + /* optimization to check for most common case */ + if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) { + XkbSrvLedInfoPtr sli; + sli= dev->kbdfeed->xkb_sli; + if (dev->kbdfeed->xkb_sli==NULL) { + sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts); + dev->kbdfeed->xkb_sli= sli; + } + return dev->kbdfeed->xkb_sli; + } + + sli= NULL; + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + else return NULL; + } + if (class==KbdFeedbackClass) { + KbdFeedbackPtr kf; + for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) { + if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) { + if (kf->xkb_sli==NULL) + kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts); + sli= kf->xkb_sli; + break; + } + } + } + else if (class==LedFeedbackClass) { + LedFeedbackPtr lf; + for (lf=dev->leds;lf!=NULL;lf=lf->next) { + if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) { + if (lf->xkb_sli==NULL) + lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts); + sli= lf->xkb_sli; + break; + } + } + } + if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) + sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom); + if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) + sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); + return sli; +} + +/***====================================================================***/ + +void +XkbFlushLedEvents( DeviceIntPtr dev, + DeviceIntPtr kbd, + XkbSrvLedInfoPtr sli, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +{ + if (changes) { + if (changes->indicators.state_changes) + XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); + XkbSendNotification(kbd,changes,cause); + bzero((char *)changes,sizeof(XkbChangesRec)); + + if (XkbAX_NeedFeedback(kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) { + if (sli->effectiveState) + /* it appears that the which parameter is not used */ + XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask); + else + XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask); + } + } + if (ed && (ed->reason)) { + if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask)) + XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); + XkbSendExtensionDeviceNotify(dev,cause->client,ed); + } + bzero((char *)ed,sizeof(XkbExtensionDeviceNotify)); + return; +} + +/***====================================================================***/ + +void +XkbApplyLedNameChanges( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_names, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +{ +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; + + if (changed_names==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= inputInfo.keyboard; + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->names.changed|= XkbIndicatorNamesMask; + changes->names.changed_indicators|= changed_names; + } + + ed->reason|= XkbXI_IndicatorNamesMask; + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported= 0; + ed->supported= XkbXI_AllFeaturesMask; + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} +/***====================================================================***/ + + /* + * void + * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause) + * + * Handles all of the secondary effects of the changes to the + * feedback specified by 'sli' on the device specified by 'dev.' + * + * If 'changed_maps' specifies any indicators, this function generates + * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify + * events to report the changes, and recalculates the effective + * state of each indicator with a changed map. If any indicators + * change state, the server generates XkbExtensionDeviceNotify and + * XkbIndicatorStateNotify events as appropriate. + * + * If 'changes' is non-NULL, this function updates it to reflect + * any changes to the keyboard state or controls or to the 'core' + * indicator names, maps, or state. If 'changes' is NULL, this + * function generates XKB events as needed to report the changes. + * If 'dev' is not a keyboard device, any changes are reported + * for the core keyboard. + * + * The 'cause' specifies the reason for the event (key event or + * request) for the change, as reported in some XKB events. + */ + +void +XkbApplyLedMapChanges( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_maps, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +{ +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; + + if (changed_maps==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= inputInfo.keyboard; + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->indicators.map_changes|= changed_maps; + } + + XkbCheckIndicatorMaps(dev,sli,changed_maps); + + ed->reason|= XkbXI_IndicatorMapsMask; + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXI_IndicatorMapsMask; + ed->supported= XkbXI_AllFeaturesMask; + + XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause); + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} + +/***====================================================================***/ + +void +XkbApplyLedStateChanges(DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_leds, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; +register unsigned i,bit,affected; +XkbIndicatorMapPtr map; +unsigned oldState; +Bool kb_changed; + + if (changed_leds==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= inputInfo.keyboard; + xkbi= kbd->key->xkbInfo; + + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + + kb_changed= False; + affected= changed_leds; + oldState= sli->effectiveState; + for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) { + if ((affected&bit)==0) + continue; + affected&= ~bit; + map= &sli->maps[i]; + if (map->flags&XkbIM_NoExplicit) { + sli->explicitState&= ~bit; + continue; + } + if (map->flags&XkbIM_LEDDrivesKB) { + Bool on= ((sli->explicitState&bit)!=0); + if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes)) + kb_changed= True; + } + } + sli->effectiveState= (sli->autoState|sli->explicitState); + affected= sli->effectiveState^oldState; + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) + changes->indicators.state_changes|= affected; + if (affected) { + ed->reason|= XkbXI_IndicatorStateMask; + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXI_IndicatorStateMask; + ed->supported= XkbXI_AllFeaturesMask; + } + + if (kb_changed) { + XkbComputeDerivedState(kbd->key->xkbInfo); + XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause); + } + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + if (kb_changed) + XkbUpdateAllDeviceIndicators(NULL,cause); + return; +} diff --git a/xorg-server/xkb/xkbPrKeyEv.c b/xorg-server/xkb/xkbPrKeyEv.c new file mode 100644 index 000000000..69c218c8c --- /dev/null +++ b/xorg-server/xkb/xkbPrKeyEv.c @@ -0,0 +1,232 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include <stdio.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "exevents.h" +#include <xkbsrv.h> +#include <ctype.h> +#define EXTENSION_EVENT_BASE 64 + +/***====================================================================***/ + +void +XkbProcessKeyboardEvent(xEvent *xE,DeviceIntPtr keybd,int count) +{ +KeyClassPtr keyc = keybd->key; +XkbSrvInfoPtr xkbi; +int key; +XkbBehavior behavior; +unsigned ndx; +int xiEvent; + + xkbi= keyc->xkbInfo; + key= xE->u.u.detail; + xiEvent= (xE->u.u.type & EXTENSION_EVENT_BASE); + if (xkbDebugFlags&0x8) { + DebugF("XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up")); + } + + if ( (xkbi->repeatKey==key) && (xE->u.u.type==KeyRelease) && + ((xkbi->desc->ctrls->enabled_ctrls&XkbRepeatKeysMask)==0) ) { + AccessXCancelRepeatKey(xkbi,key); + } + + behavior= xkbi->desc->server->behaviors[key]; + /* The "permanent" flag indicates a hard-wired behavior that occurs */ + /* below XKB, such as a key that physically locks. XKB does not */ + /* do anything to implement the behavior, but it *does* report that */ + /* key is hardwired */ + + if ((behavior.type&XkbKB_Permanent)==0) { + switch (behavior.type) { + case XkbKB_Default: + if (( xE->u.u.type == KeyPress || + xE->u.u.type == DeviceKeyPress) && + (keyc->down[key>>3] & (1<<(key&7)))) { + XkbLastRepeatEvent= (pointer)xE; + + if (xiEvent) + xE->u.u.type = DeviceKeyRelease; + else + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + + if (xiEvent) + xE->u.u.type = DeviceKeyPress; + else + xE->u.u.type = KeyPress; + XkbHandleActions(keybd,keybd,xE,count); + XkbLastRepeatEvent= NULL; + return; + } + else if ((xE->u.u.type==KeyRelease || + xE->u.u.type == DeviceKeyRelease) && + (!(keyc->down[key>>3]&(1<<(key&7))))) { + XkbLastRepeatEvent= (pointer)&xE; + if (xiEvent) + xE->u.u.type = DeviceKeyPress; + else + xE->u.u.type = KeyPress; + XkbHandleActions(keybd,keybd,xE,count); + if (xiEvent) + xE->u.u.type = DeviceKeyRelease; + else + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + XkbLastRepeatEvent= NULL; + return; + } + break; + case XkbKB_Lock: + if ( xE->u.u.type == KeyRelease || + xE->u.u.type == DeviceKeyRelease) { + return; + } + else { + int bit= 1<<(key&7); + if ( keyc->down[key>>3]&bit ) { + if (xiEvent) + xE->u.u.type = DeviceKeyRelease; + else + xE->u.u.type= KeyRelease; + } + } + break; + case XkbKB_RadioGroup: + ndx= (behavior.data&(~XkbKB_RGAllowNone)); + if ( ndx<xkbi->nRadioGroups ) { + XkbRadioGroupPtr rg; + + if ( xE->u.u.type == KeyRelease || + xE->u.u.type == DeviceKeyRelease) + return; + + rg = &xkbi->radioGroups[ndx]; + if ( rg->currentDown == xE->u.u.detail ) { + if (behavior.data&XkbKB_RGAllowNone) { + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + rg->currentDown= 0; + } + return; + } + if ( rg->currentDown!=0 ) { + int key = xE->u.u.detail; + if (xiEvent) + xE->u.u.type = DeviceKeyRelease; + else + xE->u.u.type= KeyRelease; + xE->u.u.detail= rg->currentDown; + XkbHandleActions(keybd,keybd,xE,count); + if (xiEvent) + xE->u.u.type = DeviceKeyPress; + else + xE->u.u.type= KeyPress; + xE->u.u.detail= key; + } + rg->currentDown= key; + } + else ErrorF("InternalError! Illegal radio group %d\n",ndx); + break; + case XkbKB_Overlay1: case XkbKB_Overlay2: + { + unsigned which; + if (behavior.type==XkbKB_Overlay1) which= XkbOverlay1Mask; + else which= XkbOverlay2Mask; + if ( (xkbi->desc->ctrls->enabled_ctrls&which)==0 ) + break; + if ((behavior.data>=xkbi->desc->min_key_code)&& + (behavior.data<=xkbi->desc->max_key_code)) { + xE->u.u.detail= behavior.data; + /* 9/11/94 (ef) -- XXX! need to match release with */ + /* press even if the state of the */ + /* corresponding overlay control */ + /* changes while the key is down */ + } + } + break; + default: + ErrorF("unknown key behavior 0x%04x\n",behavior.type); + break; + } + } + XkbHandleActions(keybd,keybd,xE,count); + return; +} + +void +ProcessKeyboardEvent(xEvent *xE,DeviceIntPtr keybd,int count) +{ + + KeyClassPtr keyc = keybd->key; + XkbSrvInfoPtr xkbi = NULL; + ProcessInputProc backup_proc; + xkbDeviceInfoPtr xkb_priv = XKBDEVICEINFO(keybd); + int is_press = (xE->u.u.type == KeyPress || xE->u.u.type == DeviceKeyPress); + int is_release = (xE->u.u.type == KeyRelease || + xE->u.u.type == DeviceKeyRelease); + + if (keyc) + xkbi = keyc->xkbInfo; + + /* We're only interested in key events. */ + if (!is_press && !is_release) { + UNWRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc); + keybd->public.processInputProc(xE, keybd, count); + COND_WRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc, + xkbUnwrapProc); + return; + } + + /* If AccessX filters are active, then pass it through to + * AccessXFilter{Press,Release}Event; else, punt to + * XkbProcessKeyboardEvent. + * + * If AXF[PK]E don't intercept anything (which they probably won't), + * they'll punt through XPKE anyway. */ + if ((xkbi->desc->ctrls->enabled_ctrls & XkbAllFilteredEventsMask)) { + if (is_press) + AccessXFilterPressEvent(xE, keybd, count); + else if (is_release) + AccessXFilterReleaseEvent(xE, keybd, count); + } + else { + XkbProcessKeyboardEvent(xE, keybd, count); + } + + return; +} diff --git a/xorg-server/xkb/xkbSwap.c b/xorg-server/xkb/xkbSwap.c new file mode 100644 index 000000000..50b08f46c --- /dev/null +++ b/xorg-server/xkb/xkbSwap.c @@ -0,0 +1,595 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include "stdio.h" +#include <X11/X.h> +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include <xkbsrv.h> +#include "xkbstr.h" +#include "extnsionst.h" +#include "xkb.h" + + /* + * REQUEST SWAPPING + */ +static int +SProcXkbUseExtension(ClientPtr client) +{ +register int n; + + REQUEST(xkbUseExtensionReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbUseExtensionReq); + swaps(&stuff->wantedMajor,n); + swaps(&stuff->wantedMinor,n); + return ProcXkbUseExtension(client); +} + +static int +SProcXkbSelectEvents(ClientPtr client) +{ +register int n; + + REQUEST(xkbSelectEventsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->affectWhich,n); + swaps(&stuff->clear,n); + swaps(&stuff->selectAll,n); + swaps(&stuff->affectMap,n); + swaps(&stuff->map,n); + if ((stuff->affectWhich&(~XkbMapNotifyMask))!=0) { + union { + BOOL *b; + CARD8 *c8; + CARD16 *c16; + CARD32 *c32; + } from; + 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)||(ndx==XkbMapNotify)) + continue; + maskLeft&= ~bit; + if ((stuff->selectAll&bit)||(stuff->clear&bit)) + continue; + switch (ndx) { + case XkbNewKeyboardNotify: + case XkbStateNotify: + case XkbNamesNotify: + case XkbAccessXNotify: + case XkbExtensionDeviceNotify: + size= 2; + break; + case XkbControlsNotify: + case XkbIndicatorStateNotify: + case XkbIndicatorMapNotify: + size= 4; + break; + case XkbBellNotify: + case XkbActionMessage: + case XkbCompatMapNotify: + size= 1; + break; + default: + client->errorValue = _XkbErrCode2(0x1,bit); + return BadValue; + } + if (dataLeft<(size*2)) + return BadLength; + if (size==2) { + swaps(&from.c16[0],n); + swaps(&from.c16[1],n); + } + else if (size==4) { + swapl(&from.c32[0],n); + swapl(&from.c32[1],n); + } + else { + size= 2; + } + from.c8+= (size*2); + dataLeft-= (size*2); + } + if (dataLeft>2) { + ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft); + return BadLength; + } + } + return ProcXkbSelectEvents(client); +} + +static int +SProcXkbBell(ClientPtr client) +{ +register int n; + + REQUEST(xkbBellReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbBellReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->bellClass,n); + swaps(&stuff->bellID,n); + swapl(&stuff->name,n); + swapl(&stuff->window,n); + swaps(&stuff->pitch,n); + swaps(&stuff->duration,n); + return ProcXkbBell(client); +} + +static int +SProcXkbGetState(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetStateReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetState(client); +} + +static int +SProcXkbLatchLockState(ClientPtr client) +{ +register int n; + + REQUEST(xkbLatchLockStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbLatchLockStateReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->groupLatch,n); + return ProcXkbLatchLockState(client); +} + +static int +SProcXkbGetControls(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetControlsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetControlsReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetControls(client); +} + +static int +SProcXkbSetControls(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetControlsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbSetControlsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->affectInternalVMods,n); + swaps(&stuff->internalVMods,n); + swaps(&stuff->affectIgnoreLockVMods,n); + swaps(&stuff->ignoreLockVMods,n); + swaps(&stuff->axOptions,n); + swapl(&stuff->affectEnabledCtrls,n); + swapl(&stuff->enabledCtrls,n); + swapl(&stuff->changeCtrls,n); + swaps(&stuff->repeatDelay,n); + swaps(&stuff->repeatInterval,n); + swaps(&stuff->slowKeysDelay,n); + swaps(&stuff->debounceDelay,n); + swaps(&stuff->mkDelay,n); + swaps(&stuff->mkInterval,n); + swaps(&stuff->mkTimeToMax,n); + swaps(&stuff->mkMaxSpeed,n); + swaps(&stuff->mkCurve,n); + swaps(&stuff->axTimeout,n); + swapl(&stuff->axtCtrlsMask,n); + swapl(&stuff->axtCtrlsValues,n); + swaps(&stuff->axtOptsMask,n); + swaps(&stuff->axtOptsValues,n); + return ProcXkbSetControls(client); +} + +static int +SProcXkbGetMap(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->full,n); + swaps(&stuff->partial,n); + swaps(&stuff->virtualMods,n); + return ProcXkbGetMap(client); +} + +static int +SProcXkbSetMap(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->present,n); + swaps(&stuff->flags,n); + swaps(&stuff->totalSyms,n); + swaps(&stuff->totalActs,n); + swaps(&stuff->virtualMods,n); + return ProcXkbSetMap(client); +} + + +static int +SProcXkbGetCompatMap(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetCompatMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetCompatMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->firstSI,n); + swaps(&stuff->nSI,n); + return ProcXkbGetCompatMap(client); +} + +static int +SProcXkbSetCompatMap(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetCompatMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->firstSI,n); + swaps(&stuff->nSI,n); + return ProcXkbSetCompatMap(client); +} + +static int +SProcXkbGetIndicatorState(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetIndicatorStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetIndicatorState(client); +} + +static int +SProcXkbGetIndicatorMap(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetIndicatorMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbGetIndicatorMap(client); +} + +static int +SProcXkbSetIndicatorMap(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetIndicatorMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbSetIndicatorMap(client); +} + +static int +SProcXkbGetNamedIndicator(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetNamedIndicatorReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + swapl(&stuff->indicator,n); + return ProcXkbGetNamedIndicator(client); +} + +static int +SProcXkbSetNamedIndicator(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetNamedIndicatorReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + swapl(&stuff->indicator,n); + swaps(&stuff->virtualMods,n); + swapl(&stuff->ctrls,n); + return ProcXkbSetNamedIndicator(client); +} + + +static int +SProcXkbGetNames(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetNamesReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetNamesReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbGetNames(client); +} + +static int +SProcXkbSetNames(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetNamesReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->virtualMods,n); + swapl(&stuff->which,n); + swapl(&stuff->indicators,n); + swaps(&stuff->totalKTLevelNames,n); + return ProcXkbSetNames(client); +} + +static int +SProcXkbGetGeometry(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetGeometryReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetGeometryReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->name,n); + return ProcXkbGetGeometry(client); +} + +static int +SProcXkbSetGeometry(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetGeometryReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->name,n); + swaps(&stuff->widthMM,n); + swaps(&stuff->heightMM,n); + swaps(&stuff->nProperties,n); + swaps(&stuff->nColors,n); + swaps(&stuff->nDoodads,n); + swaps(&stuff->nKeyAliases,n); + return ProcXkbSetGeometry(client); +} + +static int +SProcXkbPerClientFlags(ClientPtr client) +{ +register int n; + + REQUEST(xkbPerClientFlagsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->change,n); + swapl(&stuff->value,n); + swapl(&stuff->ctrlsToChange,n); + swapl(&stuff->autoCtrls,n); + swapl(&stuff->autoCtrlValues,n); + return ProcXkbPerClientFlags(client); +} + +static int +SProcXkbListComponents(ClientPtr client) +{ +register int n; + + REQUEST(xkbListComponentsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->maxNames,n); + return ProcXkbListComponents(client); +} + +static int +SProcXkbGetKbdByName(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetKbdByNameReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->want,n); + swaps(&stuff->need,n); + return ProcXkbGetKbdByName(client); +} + +static int +SProcXkbGetDeviceInfo(ClientPtr client) +{ +register int n; + + REQUEST(xkbGetDeviceInfoReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->wanted,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + return ProcXkbGetDeviceInfo(client); +} + +static int +SProcXkbSetDeviceInfo(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetDeviceInfoReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->change,n); + swaps(&stuff->nDeviceLedFBs,n); + return ProcXkbSetDeviceInfo(client); +} + +static int +SProcXkbSetDebuggingFlags(ClientPtr client) +{ +register int n; + + REQUEST(xkbSetDebuggingFlagsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); + swapl(&stuff->affectFlags,n); + swapl(&stuff->flags,n); + swapl(&stuff->affectCtrls,n); + swapl(&stuff->ctrls,n); + swaps(&stuff->msgLength,n); + return ProcXkbSetDebuggingFlags(client); +} + +int +SProcXkbDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_kbUseExtension: + return SProcXkbUseExtension(client); + case X_kbSelectEvents: + return SProcXkbSelectEvents(client); + case X_kbBell: + return SProcXkbBell(client); + case X_kbGetState: + return SProcXkbGetState(client); + case X_kbLatchLockState: + return SProcXkbLatchLockState(client); + case X_kbGetControls: + return SProcXkbGetControls(client); + case X_kbSetControls: + return SProcXkbSetControls(client); + case X_kbGetMap: + return SProcXkbGetMap(client); + case X_kbSetMap: + return SProcXkbSetMap(client); + case X_kbGetCompatMap: + return SProcXkbGetCompatMap(client); + case X_kbSetCompatMap: + return SProcXkbSetCompatMap(client); + case X_kbGetIndicatorState: + return SProcXkbGetIndicatorState(client); + case X_kbGetIndicatorMap: + return SProcXkbGetIndicatorMap(client); + case X_kbSetIndicatorMap: + return SProcXkbSetIndicatorMap(client); + case X_kbGetNamedIndicator: + return SProcXkbGetNamedIndicator(client); + case X_kbSetNamedIndicator: + return SProcXkbSetNamedIndicator(client); + case X_kbGetNames: + return SProcXkbGetNames(client); + case X_kbSetNames: + return SProcXkbSetNames(client); + case X_kbGetGeometry: + return SProcXkbGetGeometry(client); + case X_kbSetGeometry: + return SProcXkbSetGeometry(client); + case X_kbPerClientFlags: + return SProcXkbPerClientFlags(client); + case X_kbListComponents: + return SProcXkbListComponents(client); + case X_kbGetKbdByName: + return SProcXkbGetKbdByName(client); + case X_kbGetDeviceInfo: + return SProcXkbGetDeviceInfo(client); + case X_kbSetDeviceInfo: + return SProcXkbSetDeviceInfo(client); + case X_kbSetDebuggingFlags: + return SProcXkbSetDebuggingFlags(client); + default: + return BadRequest; + } +} diff --git a/xorg-server/xkb/xkbUtils.c b/xorg-server/xkb/xkbUtils.c new file mode 100644 index 000000000..b5c0ac271 --- /dev/null +++ b/xorg-server/xkb/xkbUtils.c @@ -0,0 +1,2122 @@ +/************************************************************ +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 <dix-config.h> +#endif + +#include "os.h" +#include <stdio.h> +#include <ctype.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#define XK_CYRILLIC +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" + +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> +#include "xkbgeom.h" +#include "xkb.h" + +int XkbDisableLockActions = 0; + +/***====================================================================***/ + +int +_XkbLookupAnyDevice(DeviceIntPtr *pDev, int id, ClientPtr client, + Mask access_mode, int *xkb_err) +{ + int rc = XkbKeyboardErrorCode; + + if (id == XkbUseCoreKbd) { + if (inputInfo.keyboard) + id = inputInfo.keyboard->id; + else + goto out; + } + if (id == XkbUseCorePtr) { + if (inputInfo.pointer) + id = inputInfo.pointer->id; + else + goto out; + } + rc = dixLookupDevice(pDev, id, client, access_mode); +out: + if (rc != Success) + *xkb_err = XkbErr_BadDevice; + return rc; +} + +int +_XkbLookupKeyboard(DeviceIntPtr *pDev, int id, ClientPtr client, + Mask access_mode, int *xkb_err) +{ + DeviceIntPtr dev; + int rc; + + if (id == XkbDfltXIId) + id = XkbUseCoreKbd; + + rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); + if (rc != Success) + return rc; + + dev = *pDev; + if (!dev->key || !dev->key->xkbInfo) { + *pDev = NULL; + *xkb_err= XkbErr_BadClass; + return XkbKeyboardErrorCode; + } + return Success; +} + +int +_XkbLookupBellDevice(DeviceIntPtr *pDev, int id, ClientPtr client, + Mask access_mode, int *xkb_err) +{ + DeviceIntPtr dev; + int rc; + + rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); + if (rc != Success) + return rc; + + dev = *pDev; + if (!dev->kbdfeed && !dev->bell) { + *pDev = NULL; + *xkb_err= XkbErr_BadClass; + return XkbKeyboardErrorCode; + } + return Success; +} + +int +_XkbLookupLedDevice(DeviceIntPtr *pDev, int id, ClientPtr client, + Mask access_mode, int *xkb_err) +{ + DeviceIntPtr dev; + int rc; + + if (id == XkbDfltXIId) + id = XkbUseCorePtr; + + rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); + if (rc != Success) + return rc; + + dev = *pDev; + if (!dev->kbdfeed && !dev->leds) { + *pDev = NULL; + *xkb_err= XkbErr_BadClass; + return XkbKeyboardErrorCode; + } + return Success; +} + +int +_XkbLookupButtonDevice(DeviceIntPtr *pDev, int id, ClientPtr client, + Mask access_mode, int *xkb_err) +{ + DeviceIntPtr dev; + int rc; + + rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); + if (rc != Success) + return rc; + + dev = *pDev; + if (!dev->button) { + *pDev = NULL; + *xkb_err= XkbErr_BadClass; + return XkbKeyboardErrorCode; + } + return Success; +} + +void +XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) +{ +register unsigned tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (act->mods.flags&XkbSA_UseModMapMods) + act->mods.real_mods= act->mods.mask= mods; + if ((tmp= XkbModActionVMods(&act->mods))!=0) + act->mods.mask|= XkbMaskForVMask(xkb,tmp); + break; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_UseModMapMods) + act->iso.real_mods= act->iso.mask= mods; + if ((tmp= XkbModActionVMods(&act->iso))!=0) + act->iso.mask|= XkbMaskForVMask(xkb,tmp); + break; + } + return; +} + +unsigned +XkbMaskForVMask(XkbDescPtr xkb,unsigned vmask) +{ +register int i,bit; +register unsigned mask; + + for (mask=i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (vmask&bit) + mask|= xkb->server->vmods[i]; + } + return mask; +} + +/***====================================================================***/ + +void +XkbUpdateKeyTypesFromCore( DeviceIntPtr pXDev, + KeyCode first, + CARD8 num, + XkbChangesPtr changes) +{ +XkbDescPtr xkb; +unsigned key,nG,explicit; +KeySymsPtr pCore; +int types[XkbNumKbdGroups]; +KeySym tsyms[XkbMaxSymsPerKey],*syms; +XkbMapChangesPtr mc; + + xkb= pXDev->key->xkbInfo->desc; + if (first+num-1>xkb->max_key_code) { + /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */ + num= xkb->max_key_code-first+1; + } + + mc= (changes?(&changes->map):NULL); + + pCore= &pXDev->key->curKeySyms; + syms= &pCore->map[(first-xkb->min_key_code)*pCore->mapWidth]; + for (key=first; key<(first+num); key++,syms+= pCore->mapWidth) { + explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask; + types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index); + types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index); + types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index); + nG= XkbKeyTypesForCoreSymbols(xkb,pCore->mapWidth,syms,explicit,types, + tsyms); + XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc); + memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms, + XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + } + if (changes->map.changed&XkbKeySymsMask) { + CARD8 oldLast,newLast; + oldLast = changes->map.first_key_sym+changes->map.num_key_syms-1; + newLast = first+num-1; + + if (first<changes->map.first_key_sym) + changes->map.first_key_sym = first; + if (oldLast>newLast) + newLast= oldLast; + changes->map.num_key_syms = newLast-changes->map.first_key_sym+1; + } + else { + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym = first; + changes->map.num_key_syms = num; + } + return; +} + +void +XkbUpdateDescActions( XkbDescPtr xkb, + KeyCode first, + CARD8 num, + XkbChangesPtr changes) +{ +register unsigned key; + + for (key=first;key<(first+num);key++) { + XkbApplyCompatMapToKey(xkb,key,changes); + } + + if (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask)) { + unsigned char newVMods[XkbNumVirtualMods]; + register unsigned bit,i; + unsigned present; + + bzero(newVMods,XkbNumVirtualMods); + present= 0; + for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { + if (xkb->server->vmodmap[key]==0) + continue; + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (bit&xkb->server->vmodmap[key]) { + present|= bit; + newVMods[i]|= xkb->map->modmap[key]; + } + } + } + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + xkb->server->vmods[i]= newVMods[i]; + } + } + } + if (changes->map.changed&XkbVirtualModsMask) + XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes); + + if (changes->map.changed&XkbKeyActionsMask) { + CARD8 oldLast,newLast; + oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; + newLast = first+num-1; + + if (first<changes->map.first_key_act) + changes->map.first_key_act = first; + if (newLast>oldLast) + newLast= oldLast; + changes->map.num_key_acts= newLast-changes->map.first_key_act+1; + } + else { + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act = first; + changes->map.num_key_acts = num; + } + return; +} + +void +XkbUpdateActions( DeviceIntPtr pXDev, + KeyCode first, + CARD8 num, + XkbChangesPtr changes, + unsigned * needChecksRtrn, + XkbEventCausePtr cause) +{ +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +CARD8 * repeat; + + if (needChecksRtrn) + *needChecksRtrn= 0; + xkbi= pXDev->key->xkbInfo; + xkb= xkbi->desc; + repeat= xkb->ctrls->per_key_repeat; + + if (pXDev->kbdfeed) + memcpy(repeat,pXDev->kbdfeed->ctrl.autoRepeats,32); + + XkbUpdateDescActions(xkb,first,num,changes); + + if ((pXDev->kbdfeed)&& + (changes->ctrls.enabled_ctrls_changes&XkbPerKeyRepeatMask)) { + memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, 32); + (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl); + } + return; +} + +void +XkbUpdateCoreDescription(DeviceIntPtr keybd,Bool resize) +{ +register int key,tmp; +int maxSymsPerKey,maxKeysPerMod; +int first,last,firstCommon,lastCommon; +XkbDescPtr xkb; +KeyClassPtr keyc; +CARD8 keysPerMod[XkbNumModifiers]; + + if (!keybd || !keybd->key || !keybd->key->xkbInfo) + return; + xkb= keybd->key->xkbInfo->desc; + keyc= keybd->key; + maxSymsPerKey= maxKeysPerMod= 0; + bzero(keysPerMod,sizeof(keysPerMod)); + memcpy(keyc->modifierMap,xkb->map->modmap,xkb->max_key_code+1); + if ((xkb->min_key_code==keyc->curKeySyms.minKeyCode)&& + (xkb->max_key_code==keyc->curKeySyms.maxKeyCode)) { + first= firstCommon= xkb->min_key_code; + last= lastCommon= xkb->max_key_code; + } + else if (resize) { + keyc->curKeySyms.minKeyCode= xkb->min_key_code; + keyc->curKeySyms.maxKeyCode= xkb->max_key_code; + tmp= keyc->curKeySyms.mapWidth*_XkbCoreNumKeys(keyc); + keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym); + if (!keyc->curKeySyms.map) + FatalError("Couldn't allocate keysyms\n"); + first= firstCommon= xkb->min_key_code; + last= lastCommon= xkb->max_key_code; + } + else { + if (xkb->min_key_code<keyc->curKeySyms.minKeyCode) { + first= xkb->min_key_code; + firstCommon= keyc->curKeySyms.minKeyCode; + } + else { + firstCommon= xkb->min_key_code; + first= keyc->curKeySyms.minKeyCode; + } + if (xkb->max_key_code>keyc->curKeySyms.maxKeyCode) { + lastCommon= keyc->curKeySyms.maxKeyCode; + last= xkb->max_key_code; + } + else { + lastCommon= xkb->max_key_code; + last= keyc->curKeySyms.maxKeyCode; + } + } + + /* determine sizes */ + for (key=first;key<=last;key++) { + if (XkbKeycodeInRange(xkb,key)) { + int nGroups; + int w; + nGroups= XkbKeyNumGroups(xkb,key); + tmp= 0; + if (nGroups>0) { + if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup1Index))<=2) + tmp+= 2; + else tmp+= w + 2; + } + if (nGroups>1) { + if (tmp <= 2) { + if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))<2) + tmp+= 2; + else tmp+= w; + } else { + if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))>2) + tmp+= w - 2; + } + } + if (nGroups>2) + tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup3Index); + if (nGroups>3) + tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup4Index); + if (tmp>maxSymsPerKey) + maxSymsPerKey= tmp; + } + if (_XkbCoreKeycodeInRange(keyc,key)) { + if (keyc->modifierMap[key]!=0) { + register unsigned bit,i,mask; + mask= keyc->modifierMap[key]; + for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { + if (mask&bit) { + keysPerMod[i]++; + if (keysPerMod[i]>maxKeysPerMod) + maxKeysPerMod= keysPerMod[i]; + } + } + } + } + } + + if (maxKeysPerMod>0) { + tmp= maxKeysPerMod*XkbNumModifiers; + if (keyc->modifierKeyMap==NULL) + keyc->modifierKeyMap= (KeyCode *)_XkbCalloc(1, tmp); + else if (keyc->maxKeysPerModifier<maxKeysPerMod) + keyc->modifierKeyMap= (KeyCode *)_XkbRealloc(keyc->modifierKeyMap,tmp); + if (keyc->modifierKeyMap==NULL) + FatalError("Couldn't allocate modifierKeyMap in UpdateCore\n"); + bzero(keyc->modifierKeyMap,tmp); + } + else if ((keyc->maxKeysPerModifier>0)&&(keyc->modifierKeyMap!=NULL)) { + _XkbFree(keyc->modifierKeyMap); + keyc->modifierKeyMap= NULL; + } + keyc->maxKeysPerModifier= maxKeysPerMod; + + if (maxSymsPerKey>0) { + tmp= maxSymsPerKey*_XkbCoreNumKeys(keyc); + keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym); + if (keyc->curKeySyms.map==NULL) + FatalError("Couldn't allocate symbols map in UpdateCore\n"); + } + else if ((keyc->curKeySyms.mapWidth>0)&&(keyc->curKeySyms.map!=NULL)) { + _XkbFree(keyc->curKeySyms.map); + keyc->curKeySyms.map= NULL; + } + keyc->curKeySyms.mapWidth= maxSymsPerKey; + + bzero(keysPerMod,sizeof(keysPerMod)); + for (key=firstCommon;key<=lastCommon;key++) { + if (keyc->curKeySyms.map!=NULL) { + KeySym *pCore,*pXKB; + unsigned nGroups,groupWidth,n,nOut; + + nGroups= XkbKeyNumGroups(xkb,key); + n= (key-keyc->curKeySyms.minKeyCode)*maxSymsPerKey; + pCore= &keyc->curKeySyms.map[n]; + bzero(pCore,maxSymsPerKey*sizeof(KeySym)); + pXKB= XkbKeySymsPtr(xkb,key); + nOut= 2; + if (nGroups>0) { + groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup1Index); + if (groupWidth>0) pCore[0]= pXKB[0]; + if (groupWidth>1) pCore[1]= pXKB[1]; + for (n=2;n<groupWidth;n++) { + pCore[2+n]= pXKB[n]; + } + if (groupWidth>2) + nOut= groupWidth; + } + + /* See XKB Protocol Sec, Section 12.4. + A 1-group key with ABCDE on a 2 group keyboard must be + duplicated across all groups as ABABCDECDE. + */ + if (nGroups == 1) + { + int idx; + + groupWidth = XkbKeyGroupWidth(xkb, key, XkbGroup1Index); + + /* AB..CDE... -> ABABCDE... */ + if (groupWidth > 0 && maxSymsPerKey >= 3) + pCore[2] = pCore[0]; + if (groupWidth > 1 && maxSymsPerKey >= 4) + pCore[3] = pCore[1]; + + /* ABABCDE... -> ABABCDECDE */ + idx = 2 + groupWidth; + while (groupWidth > 2 && + idx < maxSymsPerKey && + idx < groupWidth * 2) + { + pCore[idx] = pCore[idx - groupWidth + 2]; + idx++; + } + idx = 2 * groupWidth; + if (idx < 4) + idx = 4; + /* 3 or more groups: ABABCDECDEABCDEABCDE */ + for (n = 0; n < groupWidth && idx < maxSymsPerKey; n++) + pCore[idx++] = pXKB[n]; + } + + pXKB+= XkbKeyGroupsWidth(xkb,key); + nOut+= 2; + if (nGroups>1) { + groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup2Index); + if (groupWidth>0) pCore[2]= pXKB[0]; + if (groupWidth>1) pCore[3]= pXKB[1]; + for (n=2;n<groupWidth;n++) { + pCore[nOut+(n-2)]= pXKB[n]; + } + if (groupWidth>2) + nOut+= (groupWidth-2); + } + pXKB+= XkbKeyGroupsWidth(xkb,key); + for (n=XkbGroup3Index;n<nGroups;n++) { + register int s; + groupWidth= XkbKeyGroupWidth(xkb,key,n); + for (s=0;s<groupWidth;s++) { + pCore[nOut++]= pXKB[s]; + } + pXKB+= XkbKeyGroupsWidth(xkb,key); + } + } + if (keyc->modifierMap[key]!=0) { + register unsigned bit,i,mask; + mask= keyc->modifierMap[key]; + for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { + if (mask&bit) { + tmp= i*maxKeysPerMod+keysPerMod[i]; + keyc->modifierKeyMap[tmp]= key; + keysPerMod[i]++; + } + } + } + } + return; +} + +void +XkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff) +{ + if (pXDev && pXDev->key && pXDev->key->xkbInfo) { + xkbControlsNotify cn; + XkbControlsPtr ctrls = pXDev->key->xkbInfo->desc->ctrls; + XkbControlsRec old; + old = *ctrls; + + if (key== -1) { /* global autorepeat setting changed */ + if (onoff) ctrls->enabled_ctrls |= XkbRepeatKeysMask; + else ctrls->enabled_ctrls &= ~XkbRepeatKeysMask; + } + else if (pXDev->kbdfeed) { + ctrls->per_key_repeat[key/8] = + pXDev->kbdfeed->ctrl.autoRepeats[key/8]; + } + + if (XkbComputeControlsNotify(pXDev,&old,ctrls,&cn,True)) + XkbSendControlsNotify(pXDev,&cn); + } + return; +} + +void +XkbApplyMappingChange( DeviceIntPtr kbd, + CARD8 request, + KeyCode firstKey, + CARD8 num, + ClientPtr client) +{ +XkbEventCauseRec cause; +XkbChangesRec changes; +unsigned check; + + if (kbd->key->xkbInfo==NULL) + XkbInitDevice(kbd); + bzero(&changes,sizeof(XkbChangesRec)); + check= 0; + if (request==MappingKeyboard) { + XkbSetCauseCoreReq(&cause,X_ChangeKeyboardMapping,client); + XkbUpdateKeyTypesFromCore(kbd,firstKey,num,&changes); + XkbUpdateActions(kbd,firstKey,num,&changes,&check,&cause); + if (check) + XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); + } + else if (request==MappingModifier) { + XkbDescPtr xkb= kbd->key->xkbInfo->desc; + + XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client); + + num = xkb->max_key_code-xkb->min_key_code+1; + memcpy(xkb->map->modmap,kbd->key->modifierMap,xkb->max_key_code+1); + + changes.map.changed|= XkbModifierMapMask; + changes.map.first_modmap_key= xkb->min_key_code; + changes.map.num_modmap_keys= num; + XkbUpdateActions(kbd,xkb->min_key_code,num,&changes,&check,&cause); + if (check) + XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); + } + /* 3/26/94 (ef) -- XXX! Doesn't deal with input extension requests */ + XkbSendNotification(kbd,&changes,&cause); + return; +} + +void +XkbDisableComputedAutoRepeats(DeviceIntPtr dev,unsigned key) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +xkbMapNotify mn; + + xkbi->desc->server->explicit[key]|= XkbExplicitAutoRepeatMask; + bzero(&mn,sizeof(mn)); + mn.changed= XkbExplicitComponentsMask; + mn.firstKeyExplicit= key; + mn.nKeyExplicit= 1; + XkbSendMapNotify(dev,&mn); + return; +} + +unsigned +XkbStateChangedFlags(XkbStatePtr old,XkbStatePtr new) +{ +int changed; + + changed=(old->group!=new->group?XkbGroupStateMask:0); + changed|=(old->base_group!=new->base_group?XkbGroupBaseMask:0); + changed|=(old->latched_group!=new->latched_group?XkbGroupLatchMask:0); + changed|=(old->locked_group!=new->locked_group?XkbGroupLockMask:0); + changed|=(old->mods!=new->mods?XkbModifierStateMask:0); + changed|=(old->base_mods!=new->base_mods?XkbModifierBaseMask:0); + changed|=(old->latched_mods!=new->latched_mods?XkbModifierLatchMask:0); + changed|=(old->locked_mods!=new->locked_mods?XkbModifierLockMask:0); + changed|=(old->compat_state!=new->compat_state?XkbCompatStateMask:0); + changed|=(old->grab_mods!=new->grab_mods?XkbGrabModsMask:0); + if (old->compat_grab_mods!=new->compat_grab_mods) + changed|= XkbCompatGrabModsMask; + changed|=(old->lookup_mods!=new->lookup_mods?XkbLookupModsMask:0); + if (old->compat_lookup_mods!=new->compat_lookup_mods) + changed|= XkbCompatLookupModsMask; + changed|=(old->ptr_buttons!=new->ptr_buttons?XkbPointerButtonMask:0); + return changed; +} + +static void +XkbComputeCompatState(XkbSrvInfoPtr xkbi) +{ +CARD16 grp_mask; +XkbStatePtr state= &xkbi->state; +XkbCompatMapPtr map; + + if (!state || !xkbi->desc || !xkbi->desc->ctrls || !xkbi->desc->compat) + return; + + map= xkbi->desc->compat; + grp_mask= map->groups[state->group].mask; + state->compat_state = state->mods|grp_mask; + state->compat_lookup_mods= state->lookup_mods|grp_mask; + + if (xkbi->desc->ctrls->enabled_ctrls&XkbIgnoreGroupLockMask) + grp_mask= map->groups[state->base_group].mask; + state->compat_grab_mods= state->grab_mods|grp_mask; + return; +} + +unsigned +XkbAdjustGroup(int group,XkbControlsPtr ctrls) +{ +unsigned act; + + act= XkbOutOfRangeGroupAction(ctrls->groups_wrap); + if (group<0) { + while ( group < 0 ) { + if (act==XkbClampIntoRange) { + group= XkbGroup1Index; + } + else if (act==XkbRedirectIntoRange) { + int newGroup; + newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); + if (newGroup>=ctrls->num_groups) + group= XkbGroup1Index; + else group= newGroup; + } + else { + group+= ctrls->num_groups; + } + } + } + else if (group>=ctrls->num_groups) { + if (act==XkbClampIntoRange) { + group= ctrls->num_groups-1; + } + else if (act==XkbRedirectIntoRange) { + int newGroup; + newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); + if (newGroup>=ctrls->num_groups) + group= XkbGroup1Index; + else group= newGroup; + } + else { + group%= ctrls->num_groups; + } + } + return group; +} + +void +XkbComputeDerivedState(XkbSrvInfoPtr xkbi) +{ +XkbStatePtr state= &xkbi->state; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +unsigned char grp; + + if (!state || !ctrls) + return; + + state->mods= (state->base_mods|state->latched_mods); + state->mods|= state->locked_mods; + state->lookup_mods= state->mods&(~ctrls->internal.mask); + state->grab_mods= state->lookup_mods&(~ctrls->ignore_lock.mask); + state->grab_mods|= + ((state->base_mods|state->latched_mods)&ctrls->ignore_lock.mask); + + + grp= state->locked_group; + if (grp>=ctrls->num_groups) + state->locked_group= XkbAdjustGroup(XkbCharToInt(grp),ctrls); + + grp= state->locked_group+state->base_group+state->latched_group; + if (grp>=ctrls->num_groups) + state->group= XkbAdjustGroup(XkbCharToInt(grp),ctrls); + else state->group= grp; + XkbComputeCompatState(xkbi); + return; +} + +/***====================================================================***/ + +void +XkbCheckSecondaryEffects( XkbSrvInfoPtr xkbi, + unsigned which, + XkbChangesPtr changes, + XkbEventCausePtr cause) +{ + if (which&XkbStateNotifyMask) { + XkbStateRec old; + old= xkbi->state; + changes->state_changes|= XkbStateChangedFlags(&old,&xkbi->state); + XkbComputeDerivedState(xkbi); + } + if (which&XkbIndicatorStateNotifyMask) + XkbUpdateIndicators(xkbi->device,XkbAllIndicatorsMask,True,changes, + cause); + return; +} + +/***====================================================================***/ + +Bool +XkbEnableDisableControls( XkbSrvInfoPtr xkbi, + unsigned long change, + unsigned long newValues, + XkbChangesPtr changes, + XkbEventCausePtr cause) +{ +XkbControlsPtr ctrls; +unsigned old; +XkbSrvLedInfoPtr sli; + + ctrls= xkbi->desc->ctrls; + old= ctrls->enabled_ctrls; + ctrls->enabled_ctrls&= ~change; + ctrls->enabled_ctrls|= (change&newValues); + if (old==ctrls->enabled_ctrls) + return False; + if (cause!=NULL) { + xkbControlsNotify cn; + cn.numGroups= ctrls->num_groups; + cn.changedControls|= XkbControlsEnabledMask; + cn.enabledControls= ctrls->enabled_ctrls; + cn.enabledControlChanges= (ctrls->enabled_ctrls^old); + cn.keycode= cause->kc; + cn.eventType= cause->event; + cn.requestMajor= cause->mjr; + cn.requestMinor= cause->mnr; + XkbSendControlsNotify(xkbi->device,&cn); + } + else { + /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes*/ + /* is non-zero, the controls in question changed already in "this" */ + /* request and this change merely undoes the previous one. By the */ + /* same token, we have to figure out whether or not ControlsEnabled */ + /* should be set or not in the changes structure */ + changes->ctrls.enabled_ctrls_changes^= (ctrls->enabled_ctrls^old); + if (changes->ctrls.enabled_ctrls_changes) + changes->ctrls.changed_ctrls|= XkbControlsEnabledMask; + else changes->ctrls.changed_ctrls&= ~XkbControlsEnabledMask; + } + sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(xkbi->device,sli->usesControls,True,changes,cause); + return True; +} + +/***====================================================================***/ + +#define MAX_TOC 16 + +XkbGeometryPtr +XkbLookupNamedGeometry(DeviceIntPtr dev,Atom name,Bool *shouldFree) +{ +XkbSrvInfoPtr xkbi= dev->key->xkbInfo; +XkbDescPtr xkb= xkbi->desc; + + *shouldFree= 0; + if (name==None) { + if (xkb->geom!=NULL) + return xkb->geom; + name= xkb->names->geometry; + } + if ((xkb->geom!=NULL)&&(xkb->geom->name==name)) + return xkb->geom; + *shouldFree= 1; + return NULL; +} + +void +XkbConvertCase(register KeySym sym, KeySym *lower, KeySym *upper) +{ + *lower = sym; + *upper = sym; + switch(sym >> 8) { + case 0: /* Latin 1 */ + if ((sym >= XK_A) && (sym <= XK_Z)) + *lower += (XK_a - XK_A); + else if ((sym >= XK_a) && (sym <= XK_z)) + *upper -= (XK_a - XK_A); + else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) + *lower += (XK_agrave - XK_Agrave); + else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) + *upper -= (XK_agrave - XK_Agrave); + else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) + *lower += (XK_oslash - XK_Ooblique); + else if ((sym >= XK_oslash) && (sym <= XK_thorn)) + *upper -= (XK_oslash - XK_Ooblique); + break; + case 1: /* Latin 2 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym == XK_Aogonek) + *lower = XK_aogonek; + else if (sym >= XK_Lstroke && sym <= XK_Sacute) + *lower += (XK_lstroke - XK_Lstroke); + else if (sym >= XK_Scaron && sym <= XK_Zacute) + *lower += (XK_scaron - XK_Scaron); + else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) + *lower += (XK_zcaron - XK_Zcaron); + else if (sym == XK_aogonek) + *upper = XK_Aogonek; + else if (sym >= XK_lstroke && sym <= XK_sacute) + *upper -= (XK_lstroke - XK_Lstroke); + else if (sym >= XK_scaron && sym <= XK_zacute) + *upper -= (XK_scaron - XK_Scaron); + else if (sym >= XK_zcaron && sym <= XK_zabovedot) + *upper -= (XK_zcaron - XK_Zcaron); + else if (sym >= XK_Racute && sym <= XK_Tcedilla) + *lower += (XK_racute - XK_Racute); + else if (sym >= XK_racute && sym <= XK_tcedilla) + *upper -= (XK_racute - XK_Racute); + break; + case 2: /* Latin 3 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) + *lower += (XK_hstroke - XK_Hstroke); + else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) + *lower += (XK_gbreve - XK_Gbreve); + else if (sym >= XK_hstroke && sym <= XK_hcircumflex) + *upper -= (XK_hstroke - XK_Hstroke); + else if (sym >= XK_gbreve && sym <= XK_jcircumflex) + *upper -= (XK_gbreve - XK_Gbreve); + else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) + *lower += (XK_cabovedot - XK_Cabovedot); + else if (sym >= XK_cabovedot && sym <= XK_scircumflex) + *upper -= (XK_cabovedot - XK_Cabovedot); + break; + case 3: /* Latin 4 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Rcedilla && sym <= XK_Tslash) + *lower += (XK_rcedilla - XK_Rcedilla); + else if (sym >= XK_rcedilla && sym <= XK_tslash) + *upper -= (XK_rcedilla - XK_Rcedilla); + else if (sym == XK_ENG) + *lower = XK_eng; + else if (sym == XK_eng) + *upper = XK_ENG; + else if (sym >= XK_Amacron && sym <= XK_Umacron) + *lower += (XK_amacron - XK_Amacron); + else if (sym >= XK_amacron && sym <= XK_umacron) + *upper -= (XK_amacron - XK_Amacron); + break; + case 6: /* Cyrillic */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) + *lower -= (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) + *upper += (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) + *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); + else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) + *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); + break; + case 7: /* Greek */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) + *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && + sym != XK_Greek_iotaaccentdieresis && + sym != XK_Greek_upsilonaccentdieresis) + *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) + *lower += (XK_Greek_alpha - XK_Greek_ALPHA); + else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && + sym != XK_Greek_finalsmallsigma) + *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); + break; + } +} + + +/** + * Copy an XKB map from src to dst, reallocating when necessary: if some + * map components are present in one, but not in the other, the destination + * components will be allocated or freed as necessary. + * + * Basic map consistency is assumed on both sides, so maps with random + * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19) + * _will_ cause failures. You've been warned. + * + * Returns TRUE on success, or FALSE on failure. If this function fails, + * dst may be in an inconsistent state: all its pointers are guaranteed + * to remain valid, but part of the map may be from src and part from dst. + * + * FIXME: This function wants to be broken up into multiple functions. + */ +Bool +XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies) +{ + int i = 0, j = 0, k = 0; + void *tmp = NULL; + XkbColorPtr scolor = NULL, dcolor = NULL; + XkbDoodadPtr sdoodad = NULL, ddoodad = NULL; + XkbKeyTypePtr stype = NULL, dtype = NULL; + XkbOutlinePtr soutline = NULL, doutline = NULL; + XkbPropertyPtr sprop = NULL, dprop = NULL; + XkbRowPtr srow = NULL, drow = NULL; + XkbSectionPtr ssection = NULL, dsection = NULL; + XkbShapePtr sshape = NULL, dshape = NULL; + DeviceIntPtr pDev = NULL, tmpDev = NULL; + xkbMapNotify mn; + xkbNewKeyboardNotify nkn; + + if (!src || !dst || src == dst) + return FALSE; + + /* client map */ + if (src->map) { + if (!dst->map) { + tmp = xcalloc(1, sizeof(XkbClientMapRec)); + if (!tmp) + return FALSE; + dst->map = tmp; + } + + if (src->map->syms) { + if (src->map->size_syms != dst->map->size_syms) { + if (dst->map->syms) + tmp = xrealloc(dst->map->syms, + src->map->size_syms * sizeof(KeySym)); + else + tmp = xalloc(src->map->size_syms * sizeof(KeySym)); + if (!tmp) + return FALSE; + dst->map->syms = tmp; + + } + memcpy(dst->map->syms, src->map->syms, + src->map->size_syms * sizeof(KeySym)); + } + else { + if (dst->map->syms) { + xfree(dst->map->syms); + dst->map->syms = NULL; + } + } + dst->map->num_syms = src->map->num_syms; + dst->map->size_syms = src->map->size_syms; + + if (src->map->key_sym_map) { + if (src->max_key_code != dst->max_key_code) { + if (dst->map->key_sym_map) + tmp = xrealloc(dst->map->key_sym_map, + (src->max_key_code + 1) * + sizeof(XkbSymMapRec)); + else + tmp = xalloc((src->max_key_code + 1) * + sizeof(XkbSymMapRec)); + if (!tmp) + return FALSE; + dst->map->key_sym_map = tmp; + } + memcpy(dst->map->key_sym_map, src->map->key_sym_map, + (src->max_key_code + 1) * sizeof(XkbSymMapRec)); + } + else { + if (dst->map->key_sym_map) { + xfree(dst->map->key_sym_map); + dst->map->key_sym_map = NULL; + } + } + + if (src->map->types && src->map->num_types) { + if (src->map->num_types > dst->map->size_types || + !dst->map->types || !dst->map->size_types) { + if (dst->map->types && dst->map->size_types) { + tmp = xrealloc(dst->map->types, + src->map->num_types * sizeof(XkbKeyTypeRec)); + if (!tmp) + return FALSE; + dst->map->types = tmp; + bzero(dst->map->types + dst->map->num_types, + (src->map->num_types - dst->map->num_types) * + sizeof(XkbKeyTypeRec)); + } + else { + tmp = xcalloc(src->map->num_types, sizeof(XkbKeyTypeRec)); + if (!tmp) + return FALSE; + dst->map->types = tmp; + } + } + else if (src->map->num_types < dst->map->num_types && + dst->map->types) { + for (i = src->map->num_types, dtype = (dst->map->types + i); + i < dst->map->num_types; i++, dtype++) { + if (dtype->level_names) + xfree(dtype->level_names); + dtype->level_names = NULL; + dtype->num_levels = 0; + if (dtype->map_count) { + if (dtype->map) + xfree(dtype->map); + if (dtype->preserve) + xfree(dtype->preserve); + } + } + } + + stype = src->map->types; + dtype = dst->map->types; + for (i = 0; i < src->map->num_types; i++, dtype++, stype++) { + if (stype->num_levels && stype->level_names) { + if (stype->num_levels != dtype->num_levels && + dtype->num_levels && dtype->level_names && + i < dst->map->num_types) { + tmp = xrealloc(dtype->level_names, + stype->num_levels * sizeof(Atom)); + if (!tmp) + continue; + dtype->level_names = tmp; + } + else if (!dtype->num_levels || !dtype->level_names || + i >= dst->map->num_types) { + tmp = xalloc(stype->num_levels * sizeof(Atom)); + if (!tmp) + continue; + dtype->level_names = tmp; + } + dtype->num_levels = stype->num_levels; + memcpy(dtype->level_names, stype->level_names, + stype->num_levels * sizeof(Atom)); + } + else { + if (dtype->num_levels && dtype->level_names && + i < dst->map->num_types) + xfree(dtype->level_names); + dtype->num_levels = 0; + dtype->level_names = NULL; + } + + dtype->name = stype->name; + memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec)); + + if (stype->map_count) { + if (stype->map) { + if (stype->map_count != dtype->map_count && + dtype->map_count && dtype->map && + i < dst->map->num_types) { + tmp = xrealloc(dtype->map, + stype->map_count * + sizeof(XkbKTMapEntryRec)); + if (!tmp) + return FALSE; + dtype->map = tmp; + } + else if (!dtype->map_count || !dtype->map || + i >= dst->map->num_types) { + tmp = xalloc(stype->map_count * + sizeof(XkbKTMapEntryRec)); + if (!tmp) + return FALSE; + dtype->map = tmp; + } + + memcpy(dtype->map, stype->map, + stype->map_count * sizeof(XkbKTMapEntryRec)); + } + else { + if (dtype->map && i < dst->map->num_types) + xfree(dtype->map); + dtype->map = NULL; + } + + if (stype->preserve) { + if (stype->map_count != dtype->map_count && + dtype->map_count && dtype->preserve && + i < dst->map->num_types) { + tmp = xrealloc(dtype->preserve, + stype->map_count * + sizeof(XkbModsRec)); + if (!tmp) + return FALSE; + dtype->preserve = tmp; + } + else if (!dtype->preserve || !dtype->map_count || + i >= dst->map->num_types) { + tmp = xalloc(stype->map_count * + sizeof(XkbModsRec)); + if (!tmp) + return FALSE; + dtype->preserve = tmp; + } + + memcpy(dtype->preserve, stype->preserve, + stype->map_count * sizeof(XkbModsRec)); + } + else { + if (dtype->preserve && i < dst->map->num_types) + xfree(dtype->preserve); + dtype->preserve = NULL; + } + + dtype->map_count = stype->map_count; + } + else { + if (dtype->map_count && i < dst->map->num_types) { + if (dtype->map) + xfree(dtype->map); + if (dtype->preserve) + xfree(dtype->preserve); + } + dtype->map_count = 0; + dtype->map = NULL; + dtype->preserve = NULL; + } + } + + dst->map->size_types = src->map->num_types; + dst->map->num_types = src->map->num_types; + } + else { + if (dst->map->types) { + for (i = 0, dtype = dst->map->types; i < dst->map->num_types; + i++, dtype++) { + if (dtype->level_names) + xfree(dtype->level_names); + if (dtype->map && dtype->map_count) + xfree(dtype->map); + if (dtype->preserve && dtype->map_count) + xfree(dtype->preserve); + } + xfree(dst->map->types); + dst->map->types = NULL; + } + dst->map->num_types = 0; + dst->map->size_types = 0; + } + + if (src->map->modmap) { + if (src->max_key_code != dst->max_key_code) { + if (dst->map->modmap) + tmp = xrealloc(dst->map->modmap, src->max_key_code + 1); + else + tmp = xalloc(src->max_key_code + 1); + if (!tmp) + return FALSE; + dst->map->modmap = tmp; + } + memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1); + } + else { + if (dst->map->modmap) { + xfree(dst->map->modmap); + dst->map->modmap = NULL; + } + } + } + else { + if (dst->map) + XkbFreeClientMap(dst, XkbAllClientInfoMask, True); + } + + /* server map */ + if (src->server) { + if (!dst->server) { + tmp = xcalloc(1, sizeof(XkbServerMapRec)); + if (!tmp) + return FALSE; + dst->server = tmp; + } + + if (src->server->explicit) { + if (src->max_key_code != dst->max_key_code) { + if (dst->server->explicit) + tmp = xrealloc(dst->server->explicit, src->max_key_code + 1); + else + tmp = xalloc(src->max_key_code + 1); + if (!tmp) + return FALSE; + dst->server->explicit = tmp; + } + memcpy(dst->server->explicit, src->server->explicit, + src->max_key_code + 1); + } + else { + if (dst->server->explicit) { + xfree(dst->server->explicit); + dst->server->explicit = NULL; + } + } + + if (src->server->acts) { + if (src->server->size_acts != dst->server->size_acts) { + if (dst->server->acts) + tmp = xrealloc(dst->server->acts, + src->server->size_acts * sizeof(XkbAction)); + else + tmp = xalloc(src->server->size_acts * sizeof(XkbAction)); + if (!tmp) + return FALSE; + dst->server->acts = tmp; + } + memcpy(dst->server->acts, src->server->acts, + src->server->size_acts * sizeof(XkbAction)); + } + else { + if (dst->server->acts) { + xfree(dst->server->acts); + dst->server->acts = NULL; + } + } + dst->server->size_acts = src->server->size_acts; + dst->server->num_acts = src->server->num_acts; + + if (src->server->key_acts) { + if (src->max_key_code != dst->max_key_code) { + if (dst->server->key_acts) + tmp = xrealloc(dst->server->key_acts, + (src->max_key_code + 1) * + sizeof(unsigned short)); + else + tmp = xalloc((src->max_key_code + 1) * + sizeof(unsigned short)); + if (!tmp) + return FALSE; + dst->server->key_acts = tmp; + } + memcpy(dst->server->key_acts, src->server->key_acts, + (src->max_key_code + 1) * sizeof(unsigned short)); + } + else { + if (dst->server->key_acts) { + xfree(dst->server->key_acts); + dst->server->key_acts = NULL; + } + } + + if (src->server->behaviors) { + if (src->max_key_code != dst->max_key_code) { + if (dst->server->behaviors) + tmp = xrealloc(dst->server->behaviors, + (src->max_key_code + 1) * + sizeof(XkbBehavior)); + else + tmp = xalloc((src->max_key_code + 1) * + sizeof(XkbBehavior)); + if (!tmp) + return FALSE; + dst->server->behaviors = tmp; + } + memcpy(dst->server->behaviors, src->server->behaviors, + (src->max_key_code + 1) * sizeof(XkbBehavior)); + } + else { + if (dst->server->behaviors) { + xfree(dst->server->behaviors); + dst->server->behaviors = NULL; + } + } + + memcpy(dst->server->vmods, src->server->vmods, XkbNumVirtualMods); + + if (src->server->vmodmap) { + if (src->max_key_code != dst->max_key_code) { + if (dst->server->vmodmap) + tmp = xrealloc(dst->server->vmodmap, + (src->max_key_code + 1) * + sizeof(unsigned short)); + else + tmp = xalloc((src->max_key_code + 1) * + sizeof(unsigned short)); + if (!tmp) + return FALSE; + dst->server->vmodmap = tmp; + } + memcpy(dst->server->vmodmap, src->server->vmodmap, + (src->max_key_code + 1) * sizeof(unsigned short)); + } + else { + if (dst->server->vmodmap) { + xfree(dst->server->vmodmap); + dst->server->vmodmap = NULL; + } + } + } + else { + if (dst->server) + XkbFreeServerMap(dst, XkbAllServerInfoMask, True); + } + + /* indicators */ + if (src->indicators) { + if (!dst->indicators) { + dst->indicators = xalloc(sizeof(XkbIndicatorRec)); + if (!dst->indicators) + return FALSE; + } + memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec)); + } + else { + if (dst->indicators) { + xfree(dst->indicators); + dst->indicators = NULL; + } + } + + /* controls */ + if (src->ctrls) { + if (!dst->ctrls) { + dst->ctrls = xalloc(sizeof(XkbControlsRec)); + if (!dst->ctrls) + return FALSE; + } + memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec)); + } + else { + if (dst->ctrls) { + xfree(dst->ctrls); + dst->ctrls = NULL; + } + } + + /* names */ + if (src->names) { + if (!dst->names) { + dst->names = xcalloc(1, sizeof(XkbNamesRec)); + if (!dst->names) + return FALSE; + } + + if (src->names->keys) { + if (src->max_key_code != dst->max_key_code) { + if (dst->names->keys) + tmp = xrealloc(dst->names->keys, (src->max_key_code + 1) * + sizeof(XkbKeyNameRec)); + else + tmp = xalloc((src->max_key_code + 1) * + sizeof(XkbKeyNameRec)); + if (!tmp) + return FALSE; + dst->names->keys = tmp; + } + memcpy(dst->names->keys, src->names->keys, + (src->max_key_code + 1) * sizeof(XkbKeyNameRec)); + } + else { + if (dst->names->keys) { + xfree(dst->names->keys); + dst->names->keys = NULL; + } + } + + if (src->names->num_key_aliases) { + if (src->names->num_key_aliases != dst->names->num_key_aliases) { + if (dst->names->key_aliases) + tmp = xrealloc(dst->names->key_aliases, + src->names->num_key_aliases * + sizeof(XkbKeyAliasRec)); + else + tmp = xalloc(src->names->num_key_aliases * + sizeof(XkbKeyAliasRec)); + if (!tmp) + return FALSE; + dst->names->key_aliases = tmp; + } + memcpy(dst->names->key_aliases, src->names->key_aliases, + src->names->num_key_aliases * sizeof(XkbKeyAliasRec)); + } + else { + if (dst->names->key_aliases) { + xfree(dst->names->key_aliases); + dst->names->key_aliases = NULL; + } + } + dst->names->num_key_aliases = src->names->num_key_aliases; + + if (src->names->num_rg) { + if (src->names->num_rg != dst->names->num_rg) { + if (dst->names->radio_groups) + tmp = xrealloc(dst->names->radio_groups, + src->names->num_rg * sizeof(Atom)); + else + tmp = xalloc(src->names->num_rg * sizeof(Atom)); + if (!tmp) + return FALSE; + dst->names->radio_groups = tmp; + } + memcpy(dst->names->radio_groups, src->names->radio_groups, + src->names->num_rg * sizeof(Atom)); + } + else { + if (dst->names->radio_groups) + xfree(dst->names->radio_groups); + } + dst->names->num_rg = src->names->num_rg; + + dst->names->keycodes = src->names->keycodes; + dst->names->geometry = src->names->geometry; + dst->names->symbols = src->names->symbols; + dst->names->types = src->names->types; + dst->names->compat = src->names->compat; + dst->names->phys_symbols = src->names->phys_symbols; + + memcpy(dst->names->vmods, src->names->vmods, + XkbNumVirtualMods * sizeof(Atom)); + memcpy(dst->names->indicators, src->names->indicators, + XkbNumIndicators * sizeof(Atom)); + memcpy(dst->names->groups, src->names->groups, + XkbNumKbdGroups * sizeof(Atom)); + } + else { + if (dst->names) + XkbFreeNames(dst, XkbAllNamesMask, True); + } + + /* compat */ + if (src->compat) { + if (!dst->compat) { + dst->compat = xcalloc(1, sizeof(XkbCompatMapRec)); + if (!dst->compat) + return FALSE; + } + + if (src->compat->sym_interpret && src->compat->num_si) { + if (src->compat->num_si != dst->compat->size_si) { + if (dst->compat->sym_interpret) + tmp = xrealloc(dst->compat->sym_interpret, + src->compat->num_si * + sizeof(XkbSymInterpretRec)); + else + tmp = xalloc(src->compat->num_si * + sizeof(XkbSymInterpretRec)); + if (!tmp) + return FALSE; + dst->compat->sym_interpret = tmp; + } + memcpy(dst->compat->sym_interpret, src->compat->sym_interpret, + src->compat->num_si * sizeof(XkbSymInterpretRec)); + + dst->compat->num_si = src->compat->num_si; + dst->compat->size_si = src->compat->num_si; + } + else { + if (dst->compat->sym_interpret && dst->compat->size_si) + xfree(dst->compat->sym_interpret); + + dst->compat->sym_interpret = NULL; + dst->compat->num_si = 0; + dst->compat->size_si = 0; + } + + memcpy(dst->compat->groups, src->compat->groups, + XkbNumKbdGroups * sizeof(XkbModsRec)); + } + else { + if (dst->compat) + XkbFreeCompatMap(dst, XkbAllCompatMask, True); + } + + /* geometry */ + if (src->geom) { + if (!dst->geom) { + dst->geom = xcalloc(sizeof(XkbGeometryRec), 1); + if (!dst->geom) + return FALSE; + } + + /* properties */ + if (src->geom->num_properties) { + if (src->geom->num_properties != dst->geom->sz_properties) { + /* If we've got more properties in the destination than + * the source, run through and free all the excess ones + * first. */ + if (src->geom->num_properties < dst->geom->sz_properties) { + for (i = src->geom->num_properties, + dprop = dst->geom->properties + i; + i < dst->geom->num_properties; + i++, dprop++) { + xfree(dprop->name); + xfree(dprop->value); + } + } + + if (dst->geom->sz_properties) + tmp = xrealloc(dst->geom->properties, + src->geom->num_properties * + sizeof(XkbPropertyRec)); + else + tmp = xalloc(src->geom->num_properties * + sizeof(XkbPropertyRec)); + if (!tmp) + return FALSE; + dst->geom->properties = tmp; + } + + /* We don't set num_properties as we need it to try and avoid + * too much reallocing. */ + dst->geom->sz_properties = src->geom->num_properties; + + if (dst->geom->sz_properties > dst->geom->num_properties) { + bzero(dst->geom->properties + dst->geom->num_properties, + (dst->geom->sz_properties - dst->geom->num_properties) * + sizeof(XkbPropertyRec)); + } + + for (i = 0, + sprop = src->geom->properties, + dprop = dst->geom->properties; + i < src->geom->num_properties; + i++, sprop++, dprop++) { + if (i < dst->geom->num_properties) { + if (strlen(sprop->name) != strlen(dprop->name)) { + tmp = xrealloc(dprop->name, strlen(sprop->name) + 1); + if (!tmp) + return FALSE; + dprop->name = tmp; + } + if (strlen(sprop->value) != strlen(dprop->value)) { + tmp = xrealloc(dprop->value, strlen(sprop->value) + 1); + if (!tmp) + return FALSE; + dprop->value = tmp; + } + strcpy(dprop->name, sprop->name); + strcpy(dprop->value, sprop->value); + } + else { + dprop->name = xstrdup(sprop->name); + dprop->value = xstrdup(sprop->value); + } + } + + /* ... which is already src->geom->num_properties. */ + dst->geom->num_properties = dst->geom->sz_properties; + } + else { + if (dst->geom->sz_properties) { + for (i = 0, dprop = dst->geom->properties; + i < dst->geom->num_properties; + i++, dprop++) { + xfree(dprop->name); + xfree(dprop->value); + } + xfree(dst->geom->properties); + dst->geom->properties = NULL; + } + + dst->geom->num_properties = 0; + dst->geom->sz_properties = 0; + } + + /* colors */ + if (src->geom->num_colors) { + if (src->geom->num_colors != dst->geom->sz_colors) { + if (src->geom->num_colors < dst->geom->sz_colors) { + for (i = src->geom->num_colors, + dcolor = dst->geom->colors + i; + i < dst->geom->num_colors; + i++, dcolor++) { + xfree(dcolor->spec); + } + } + + if (dst->geom->sz_colors) + tmp = xrealloc(dst->geom->colors, + src->geom->num_colors * + sizeof(XkbColorRec)); + else + tmp = xalloc(src->geom->num_colors * + sizeof(XkbColorRec)); + if (!tmp) + return FALSE; + dst->geom->colors = tmp; + } + + dst->geom->sz_colors = src->geom->num_colors; + + if (dst->geom->sz_colors > dst->geom->num_colors) { + bzero(dst->geom->colors + dst->geom->num_colors, + (dst->geom->sz_colors - dst->geom->num_colors) * + sizeof(XkbColorRec)); + } + + for (i = 0, + scolor = src->geom->colors, + dcolor = dst->geom->colors; + i < src->geom->num_colors; + i++, scolor++, dcolor++) { + if (i < dst->geom->num_colors) { + if (strlen(scolor->spec) != strlen(dcolor->spec)) { + tmp = xrealloc(dcolor->spec, strlen(scolor->spec) + 1); + if (!tmp) + return FALSE; + dcolor->spec = tmp; + } + strcpy(dcolor->spec, scolor->spec); + } + else { + dcolor->spec = xstrdup(scolor->spec); + } + } + + dst->geom->num_colors = dst->geom->sz_colors; + } + else { + if (dst->geom->sz_colors) { + for (i = 0, dcolor = dst->geom->colors; + i < dst->geom->num_colors; + i++, dcolor++) { + xfree(dcolor->spec); + } + xfree(dst->geom->colors); + dst->geom->colors = NULL; + } + + dst->geom->num_colors = 0; + dst->geom->sz_colors = 0; + } + + /* shapes */ + /* shapes break down into outlines, which break down into points. */ + if (dst->geom->num_shapes) { + for (i = 0, dshape = dst->geom->shapes; + i < dst->geom->num_shapes; + i++, dshape++) { + for (j = 0, doutline = dshape->outlines; + j < dshape->num_outlines; + j++, doutline++) { + if (doutline->sz_points) + xfree(doutline->points); + } + + if (dshape->sz_outlines) { + xfree(dshape->outlines); + dshape->outlines = NULL; + } + + dshape->num_outlines = 0; + dshape->sz_outlines = 0; + } + } + + if (src->geom->num_shapes) { + tmp = xcalloc(src->geom->num_shapes, sizeof(XkbShapeRec)); + if (!tmp) + return FALSE; + dst->geom->shapes = tmp; + + for (i = 0, sshape = src->geom->shapes, dshape = dst->geom->shapes; + i < src->geom->num_shapes; + i++, sshape++, dshape++) { + if (sshape->num_outlines) { + tmp = xcalloc(sshape->num_outlines, sizeof(XkbOutlineRec)); + if (!tmp) + return FALSE; + dshape->outlines = tmp; + + for (j = 0, + soutline = sshape->outlines, + doutline = dshape->outlines; + j < sshape->num_outlines; + j++, soutline++, doutline++) { + if (soutline->num_points) { + tmp = xalloc(soutline->num_points * + sizeof(XkbPointRec)); + if (!tmp) + return FALSE; + doutline->points = tmp; + + memcpy(doutline->points, soutline->points, + soutline->num_points * sizeof(XkbPointRec)); + } + + doutline->num_points = soutline->num_points; + doutline->sz_points = soutline->num_points; + } + } + + dshape->num_outlines = sshape->num_outlines; + dshape->sz_outlines = sshape->num_outlines; + } + + dst->geom->num_shapes = src->geom->num_shapes; + dst->geom->sz_shapes = src->geom->num_shapes; + } + else { + if (dst->geom->sz_shapes) { + xfree(dst->geom->shapes); + } + dst->geom->shapes = NULL; + dst->geom->num_shapes = 0; + dst->geom->sz_shapes = 0; + } + + /* sections */ + /* sections break down into doodads, and also into rows, which break + * down into keys. */ + if (dst->geom->num_sections) { + for (i = 0, dsection = dst->geom->sections; + i < dst->geom->num_sections; + i++, dsection++) { + for (j = 0, drow = dsection->rows; + j < dsection->num_rows; + j++, drow++) { + if (drow->num_keys) + xfree(drow->keys); + } + + if (dsection->num_rows) + xfree(dsection->rows); + + /* cut and waste from geom/doodad below. */ + for (j = 0, ddoodad = dsection->doodads; + j < dsection->num_doodads; + j++, ddoodad++) { + if (ddoodad->any.type == XkbTextDoodad) { + if (ddoodad->text.text) { + xfree(ddoodad->text.text); + ddoodad->text.text = NULL; + } + if (ddoodad->text.font) { + xfree(ddoodad->text.font); + ddoodad->text.font = NULL; + } + } + else if (ddoodad->any.type == XkbLogoDoodad) { + if (ddoodad->logo.logo_name) { + xfree(ddoodad->logo.logo_name); + ddoodad->logo.logo_name = NULL; + } + } + } + + if (dsection->num_doodads) + xfree(dsection->doodads); + } + + dst->geom->num_sections = 0; + dst->geom->sections = NULL; + } + + if (src->geom->num_sections) { + if (dst->geom->sz_sections) + tmp = xrealloc(dst->geom->sections, + src->geom->num_sections * + sizeof(XkbSectionRec)); + else + tmp = xalloc(src->geom->num_sections * sizeof(XkbSectionRec)); + if (!tmp) + return FALSE; + memset(tmp, 0, src->geom->num_sections * sizeof(XkbSectionRec)); + dst->geom->sections = tmp; + dst->geom->num_sections = src->geom->num_sections; + dst->geom->sz_sections = src->geom->num_sections; + + for (i = 0, + ssection = src->geom->sections, + dsection = dst->geom->sections; + i < src->geom->num_sections; + i++, ssection++, dsection++) { + *dsection = *ssection; + if (ssection->num_rows) { + tmp = xcalloc(ssection->num_rows, sizeof(XkbRowRec)); + if (!tmp) + return FALSE; + dsection->rows = tmp; + } + dsection->num_rows = ssection->num_rows; + dsection->sz_rows = ssection->num_rows; + + for (j = 0, srow = ssection->rows, drow = dsection->rows; + j < ssection->num_rows; + j++, srow++, drow++) { + if (srow->num_keys) { + tmp = xalloc(srow->num_keys * sizeof(XkbKeyRec)); + if (!tmp) + return FALSE; + drow->keys = tmp; + memcpy(drow->keys, srow->keys, + srow->num_keys * sizeof(XkbKeyRec)); + } + drow->num_keys = srow->num_keys; + drow->sz_keys = srow->num_keys; + } + + if (ssection->num_doodads) { + tmp = xcalloc(ssection->num_doodads, sizeof(XkbDoodadRec)); + if (!tmp) + return FALSE; + dsection->doodads = tmp; + } + else { + dsection->doodads = NULL; + } + + dsection->sz_doodads = ssection->num_doodads; + for (k = 0, + sdoodad = ssection->doodads, + ddoodad = dsection->doodads; + k < ssection->num_doodads; + k++, sdoodad++, ddoodad++) { + if (sdoodad->any.type == XkbTextDoodad) { + if (sdoodad->text.text) + ddoodad->text.text = + xstrdup(sdoodad->text.text); + if (sdoodad->text.font) + ddoodad->text.font = + xstrdup(sdoodad->text.font); + } + else if (sdoodad->any.type == XkbLogoDoodad) { + if (sdoodad->logo.logo_name) + ddoodad->logo.logo_name = + xstrdup(sdoodad->logo.logo_name); + } + ddoodad->any.type = sdoodad->any.type; + } + dsection->overlays = NULL; + dsection->sz_overlays = 0; + dsection->num_overlays = 0; + } + } + else { + if (dst->geom->sz_sections) { + xfree(dst->geom->sections); + } + + dst->geom->sections = NULL; + dst->geom->num_sections = 0; + dst->geom->sz_sections = 0; + } + + /* doodads */ + if (dst->geom->num_doodads) { + for (i = src->geom->num_doodads, + ddoodad = dst->geom->doodads + + src->geom->num_doodads; + i < dst->geom->num_doodads; + i++, ddoodad++) { + if (ddoodad->any.type == XkbTextDoodad) { + if (ddoodad->text.text) { + xfree(ddoodad->text.text); + ddoodad->text.text = NULL; + } + if (ddoodad->text.font) { + xfree(ddoodad->text.font); + ddoodad->text.font = NULL; + } + } + else if (ddoodad->any.type == XkbLogoDoodad) { + if (ddoodad->logo.logo_name) { + xfree(ddoodad->logo.logo_name); + ddoodad->logo.logo_name = NULL; + } + } + } + dst->geom->num_doodads = 0; + dst->geom->doodads = NULL; + } + + if (src->geom->num_doodads) { + if (dst->geom->sz_doodads) + tmp = xrealloc(dst->geom->doodads, + src->geom->num_doodads * + sizeof(XkbDoodadRec)); + else + tmp = xalloc(src->geom->num_doodads * + sizeof(XkbDoodadRec)); + if (!tmp) + return FALSE; + memset(tmp, 0, src->geom->num_doodads * sizeof(XkbDoodadRec)); + dst->geom->doodads = tmp; + + dst->geom->sz_doodads = src->geom->num_doodads; + + for (i = 0, + sdoodad = src->geom->doodads, + ddoodad = dst->geom->doodads; + i < src->geom->num_doodads; + i++, sdoodad++, ddoodad++) { + ddoodad->any.type = sdoodad->any.type; + if (sdoodad->any.type == XkbTextDoodad) { + if (sdoodad->text.text) + ddoodad->text.text = xstrdup(sdoodad->text.text); + if (sdoodad->text.font) + ddoodad->text.font = xstrdup(sdoodad->text.font); + } + else if (sdoodad->any.type == XkbLogoDoodad) { + if (sdoodad->logo.logo_name) + ddoodad->logo.logo_name = + xstrdup(sdoodad->logo.logo_name); + } + } + + dst->geom->num_doodads = dst->geom->sz_doodads; + } + else { + if (dst->geom->sz_doodads) { + xfree(dst->geom->doodads); + } + + dst->geom->doodads = NULL; + dst->geom->num_doodads = 0; + dst->geom->sz_doodads = 0; + } + + /* key aliases */ + if (src->geom->num_key_aliases) { + if (src->geom->num_key_aliases != dst->geom->sz_key_aliases) { + if (dst->geom->sz_key_aliases) + tmp = xrealloc(dst->geom->key_aliases, + src->geom->num_key_aliases * + 2 * XkbKeyNameLength); + else + tmp = xalloc(src->geom->num_key_aliases * + 2 * XkbKeyNameLength); + if (!tmp) + return FALSE; + dst->geom->key_aliases = tmp; + + dst->geom->sz_key_aliases = src->geom->num_key_aliases; + } + + memcpy(dst->geom->key_aliases, src->geom->key_aliases, + src->geom->num_key_aliases * 2 * XkbKeyNameLength); + + dst->geom->num_key_aliases = dst->geom->sz_key_aliases; + } + else { + if (dst->geom->key_aliases) { + xfree(dst->geom->key_aliases); + } + dst->geom->key_aliases = NULL; + dst->geom->num_key_aliases = 0; + dst->geom->sz_key_aliases = 0; + } + + /* font */ + if (src->geom->label_font) { + if (!dst->geom->label_font) { + tmp = xalloc(strlen(src->geom->label_font)); + if (!tmp) + return FALSE; + dst->geom->label_font = tmp; + } + else if (strlen(src->geom->label_font) != + strlen(dst->geom->label_font)) { + tmp = xrealloc(dst->geom->label_font, + strlen(src->geom->label_font)); + if (!tmp) + return FALSE; + dst->geom->label_font = tmp; + } + + strcpy(dst->geom->label_font, src->geom->label_font); + i = XkbGeomColorIndex(src->geom, src->geom->label_color); + dst->geom->label_color = &(src->geom->colors[i]); + i = XkbGeomColorIndex(src->geom, src->geom->base_color); + dst->geom->base_color = &(src->geom->colors[i]); + } + else { + if (dst->geom->label_font) { + xfree(dst->geom->label_font); + } + dst->geom->label_font = NULL; + dst->geom->label_color = NULL; + dst->geom->base_color = NULL; + } + + dst->geom->name = src->geom->name; + dst->geom->width_mm = src->geom->width_mm; + dst->geom->height_mm = src->geom->height_mm; + } + else + { + if (dst->geom) { + /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */ + XkbFreeGeometry(dst->geom, XkbGeomAllMask, True); + dst->geom = NULL; + } + } + + if (inputInfo.keyboard->key->xkbInfo && + inputInfo.keyboard->key->xkbInfo->desc == dst) { + pDev = inputInfo.keyboard; + } + else { + for (tmpDev = inputInfo.devices; tmpDev && !pDev; + tmpDev = tmpDev->next) { + if (tmpDev->key && tmpDev->key->xkbInfo && + tmpDev->key->xkbInfo->desc == dst) { + pDev = tmpDev; + break; + } + } + for (tmpDev = inputInfo.off_devices; tmpDev && !pDev; + tmpDev = tmpDev->next) { + if (tmpDev->key && tmpDev->key->xkbInfo && + tmpDev->key->xkbInfo->desc == dst) { + pDev = tmpDev; + break; + } + } + } + + if (sendNotifies) { + if (!pDev) { + ErrorF("XkbCopyKeymap: asked for notifies, but can't find device!\n"); + } + else { + /* send NewKeyboardNotify if the keycode range changed, else + * just MapNotify. we also need to send NKN if the geometry + * changed (obviously ...). */ + if ((src->min_key_code != dst->min_key_code || + src->max_key_code != dst->max_key_code) && sendNotifies) { + nkn.oldMinKeyCode = dst->min_key_code; + nkn.oldMaxKeyCode = dst->max_key_code; + nkn.deviceID = nkn.oldDeviceID = pDev->id; + nkn.minKeyCode = src->min_key_code; + nkn.maxKeyCode = src->max_key_code; + nkn.requestMajor = XkbReqCode; + nkn.requestMinor = X_kbSetMap; /* XXX bare-faced lie */ + nkn.changed = XkbAllNewKeyboardEventsMask; + XkbSendNewKeyboardNotify(pDev, &nkn); + } + else if (sendNotifies) { + mn.deviceID = pDev->id; + mn.minKeyCode = src->min_key_code; + mn.maxKeyCode = src->max_key_code; + mn.firstType = 0; + mn.nTypes = src->map->num_types; + mn.firstKeySym = src->min_key_code; + mn.nKeySyms = XkbNumKeys(src); + mn.firstKeyAct = src->min_key_code; + mn.nKeyActs = XkbNumKeys(src); + /* Cargo-culted from ProcXkbGetMap. */ + mn.firstKeyBehavior = src->min_key_code; + mn.nKeyBehaviors = XkbNumKeys(src); + mn.firstKeyExplicit = src->min_key_code; + mn.nKeyExplicit = XkbNumKeys(src); + mn.firstModMapKey = src->min_key_code; + mn.nModMapKeys = XkbNumKeys(src); + mn.firstVModMapKey = src->min_key_code; + mn.nVModMapKeys = XkbNumKeys(src); + mn.virtualMods = ~0; /* ??? */ + mn.changed = XkbAllMapComponentsMask; + XkbSendMapNotify(pDev, &mn); + } + } + } + + dst->min_key_code = src->min_key_code; + dst->max_key_code = src->max_key_code; + + return TRUE; +} diff --git a/xorg-server/xkb/xkbfmisc.c b/xorg-server/xkb/xkbfmisc.c new file mode 100644 index 000000000..ae752e945 --- /dev/null +++ b/xorg-server/xkb/xkbfmisc.c @@ -0,0 +1,470 @@ +/************************************************************ + Copyright (c) 1995 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 <dix-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#include <X11/Xos.h> +#include <X11/Xfuncs.h> + +#include <X11/X.h> +#define NEED_EVENTS +#include <X11/keysym.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "xkbstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include <xkbsrv.h> +#include "xkbgeom.h" +#include "xkb.h" + +unsigned +_XkbKSCheckCase(KeySym ks) +{ +unsigned set,rtrn; + + set= (ks & (~0xff)) >> 8; + rtrn= 0; + switch (set) { + case 0: /* latin 1 */ + if (((ks>=XK_A)&&(ks<=XK_Z))|| + ((ks>=XK_Agrave)&&(ks<=XK_THORN)&&(ks!=XK_multiply))) { + rtrn|= _XkbKSUpper; + } + if (((ks>=XK_a)&&(ks<=XK_z))|| + ((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) { + rtrn|= _XkbKSLower; + } + break; + case 1: /* latin 2 */ + if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))|| + ((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) { + rtrn|= _XkbKSUpper; + } + if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))|| + ((ks>=XK_racute)&&(ks<=XK_tcedilla))) { + rtrn|= _XkbKSLower; + } + break; + case 2: /* latin 3 */ + if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))|| + ((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) { + rtrn|= _XkbKSUpper; + } + if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))|| + ((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) { + rtrn|= _XkbKSLower; + } + break; + case 3: /* latin 4 */ + if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))|| + (ks==XK_ENG)|| + ((ks>=XK_Amacron)&&(ks<=XK_Umacron))) { + rtrn|= _XkbKSUpper; + } + if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))|| + (ks==XK_eng)|| + ((ks>=XK_amacron)&&(ks<=XK_umacron))) { + rtrn|= _XkbKSLower; + } + break; + case 18: /* latin 8 */ + if ((ks==XK_Babovedot)|| + ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))|| + ((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))|| + (ks==XK_Mabovedot)|| + (ks==XK_Pabovedot)|| + (ks==XK_Sabovedot)|| + (ks==XK_Wdiaeresis)|| + ((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) { + rtrn|= _XkbKSUpper; + } + if ((ks==XK_babovedot)|| + (ks==XK_dabovedot)|| + (ks==XK_fabovedot)|| + (ks==XK_mabovedot)|| + ((ks>=XK_wgrave)&&(ks<=XK_wacute))|| + (ks==XK_ygrave)|| + ((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) { + rtrn|= _XkbKSLower; + } + break; + case 19: /* latin 9 */ + if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) { + rtrn|= _XkbKSUpper; + } + if (ks==XK_oe) { + rtrn|= _XkbKSLower; + } + break; + } + return rtrn; +} + +/***===================================================================***/ + +static Bool +XkbWriteSectionFromName(FILE *file,char *sectionName,char *name) +{ + fprintf(file," xkb_%-20s { include \"%s\" };\n",sectionName,name); + return True; +} + +#define NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%'))) +#define COMPLETE(n) ((n)&&(!NEED_DESC(n))) + +/* ARGSUSED */ +static void +_AddIncl( FILE * file, + XkbDescPtr xkb, + Bool topLevel, + Bool showImplicit, + int index, + void * priv) +{ + if ((priv)&&(strcmp((char *)priv,"%")!=0)) + fprintf(file," include \"%s\"\n",(char *)priv); + return; +} + +Bool +XkbWriteXKBKeymapForNames( FILE * file, + XkbComponentNamesPtr names, + XkbDescPtr xkb, + unsigned want, + unsigned need) +{ +char * name,*tmp; +unsigned complete; +XkbNamesPtr old_names; +int multi_section; +unsigned wantNames,wantConfig,wantDflts; + + complete= 0; + if ((name=names->keymap)==NULL) name= "default"; + if (COMPLETE(names->keycodes)) complete|= XkmKeyNamesMask; + if (COMPLETE(names->types)) complete|= XkmTypesMask; + if (COMPLETE(names->compat)) complete|= XkmCompatMapMask; + if (COMPLETE(names->symbols)) complete|= XkmSymbolsMask; + if (COMPLETE(names->geometry)) complete|= XkmGeometryMask; + want|= (complete|need); + if (want&XkmSymbolsMask) + want|= XkmKeyNamesMask|XkmTypesMask; + + if (want==0) + return False; + + if (xkb) { + old_names = xkb->names; + + xkb->defined = 0; + /* Wow would it ever be neat if we didn't need this noise. */ + if (xkb->names && xkb->names->keys) + xkb->defined |= XkmKeyNamesMask; + if (xkb->map && xkb->map->types) + xkb->defined |= XkmTypesMask; + if (xkb->compat) + xkb->defined |= XkmCompatMapMask; + if (xkb->map && xkb->map->num_syms) + xkb->defined |= XkmSymbolsMask; + if (xkb->indicators) + xkb->defined |= XkmIndicatorsMask; + if (xkb->geom) + xkb->defined |= XkmGeometryMask; + } + else { + old_names= NULL; + } + + wantConfig= want&(~complete); + if (xkb!=NULL) { + if (wantConfig&XkmTypesMask) { + if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes)) + wantConfig&= ~XkmTypesMask; + } + if (wantConfig&XkmCompatMapMask) { + if ((!xkb->compat) || (xkb->compat->num_si<1)) + wantConfig&= ~XkmCompatMapMask; + } + if (wantConfig&XkmSymbolsMask) { + if ((!xkb->map) || (!xkb->map->key_sym_map)) + wantConfig&= ~XkmSymbolsMask; + } + if (wantConfig&XkmIndicatorsMask) { + if (!xkb->indicators) + wantConfig&= ~XkmIndicatorsMask; + } + if (wantConfig&XkmKeyNamesMask) { + if ((!xkb->names)||(!xkb->names->keys)) + wantConfig&= ~XkmKeyNamesMask; + } + if ((wantConfig&XkmGeometryMask)&&(!xkb->geom)) + wantConfig&= ~XkmGeometryMask; + } + else { + wantConfig= 0; + } + complete|= wantConfig; + + wantDflts= 0; + wantNames= want&(~complete); + if ((xkb!=NULL) && (old_names!=NULL)) { + if (wantNames&XkmTypesMask) { + if (old_names->types!=None) { + tmp= XkbAtomGetString(old_names->types); + names->types= _XkbDupString(tmp); + } + else { + wantDflts|= XkmTypesMask; + } + complete|= XkmTypesMask; + } + if (wantNames&XkmCompatMapMask) { + if (old_names->compat!=None) { + tmp= XkbAtomGetString(old_names->compat); + names->compat= _XkbDupString(tmp); + } + else wantDflts|= XkmCompatMapMask; + complete|= XkmCompatMapMask; + } + if (wantNames&XkmSymbolsMask) { + if (old_names->symbols==None) + return False; + tmp= XkbAtomGetString(old_names->symbols); + names->symbols= _XkbDupString(tmp); + complete|= XkmSymbolsMask; + } + if (wantNames&XkmKeyNamesMask) { + if (old_names->keycodes!=None) { + tmp= XkbAtomGetString(old_names->keycodes); + names->keycodes= _XkbDupString(tmp); + } + else wantDflts|= XkmKeyNamesMask; + complete|= XkmKeyNamesMask; + } + if (wantNames&XkmGeometryMask) { + if (old_names->geometry==None) + return False; + tmp= XkbAtomGetString(old_names->geometry); + names->geometry= _XkbDupString(tmp); + complete|= XkmGeometryMask; + wantNames&= ~XkmGeometryMask; + } + } + if (complete&XkmCompatMapMask) + complete|= XkmIndicatorsMask|XkmVirtualModsMask; + else if (complete&(XkmSymbolsMask|XkmTypesMask)) + complete|= XkmVirtualModsMask; + if (need & (~complete)) + return False; + if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete))) + return False; + + multi_section= 1; + if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&& + ((complete&(~XkmKeymapLegal))==0)) { + fprintf(file,"xkb_keymap \"%s\" {\n",name); + } + else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&& + ((complete&(~XkmSemanticsLegal))==0)) { + fprintf(file,"xkb_semantics \"%s\" {\n",name); + } + else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&& + ((complete&(~XkmLayoutLegal))==0)) { + fprintf(file,"xkb_layout \"%s\" {\n",name); + } + else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) { + multi_section= 0; + } + else { + return False; + } + + wantNames= complete&(~(wantConfig|wantDflts)); + name= names->keycodes; + if (wantConfig&XkmKeyNamesMask) + XkbWriteXKBKeycodes(file,xkb,False,False,_AddIncl,name); + else if (wantDflts&XkmKeyNamesMask) + fprintf(stderr,"Default symbols not implemented yet!\n"); + else if (wantNames&XkmKeyNamesMask) + XkbWriteSectionFromName(file,"keycodes",name); + + name= names->types; + if (wantConfig&XkmTypesMask) + XkbWriteXKBKeyTypes(file,xkb,False,False,_AddIncl,name); + else if (wantDflts&XkmTypesMask) + fprintf(stderr,"Default types not implemented yet!\n"); + else if (wantNames&XkmTypesMask) + XkbWriteSectionFromName(file,"types",name); + + name= names->compat; + if (wantConfig&XkmCompatMapMask) + XkbWriteXKBCompatMap(file,xkb,False,False,_AddIncl,name); + else if (wantDflts&XkmCompatMapMask) + fprintf(stderr,"Default interps not implemented yet!\n"); + else if (wantNames&XkmCompatMapMask) + XkbWriteSectionFromName(file,"compatibility",name); + + name= names->symbols; + if (wantConfig&XkmSymbolsMask) + XkbWriteXKBSymbols(file,xkb,False,False,_AddIncl,name); + else if (wantNames&XkmSymbolsMask) + XkbWriteSectionFromName(file,"symbols",name); + + name= names->geometry; + if (wantConfig&XkmGeometryMask) + XkbWriteXKBGeometry(file,xkb,False,False,_AddIncl,name); + else if (wantNames&XkmGeometryMask) + XkbWriteSectionFromName(file,"geometry",name); + + if (multi_section) + fprintf(file,"};\n"); + return True; +} + +/***====================================================================***/ + +int +XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases) +{ +register int i; + + if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) + return 0; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0) + return i; + } + if (!use_aliases) + return 0; + if (xkb->geom && xkb->geom->key_aliases) { + XkbKeyAliasPtr a; + a= xkb->geom->key_aliases; + for (i=0;i<xkb->geom->num_key_aliases;i++,a++) { + if (strncmp(name,a->alias,XkbKeyNameLength)==0) + return XkbFindKeycodeByName(xkb,a->real,False); + } + } + if (xkb->names && xkb->names->key_aliases) { + XkbKeyAliasPtr a; + a= xkb->names->key_aliases; + for (i=0;i<xkb->names->num_key_aliases;i++,a++) { + if (strncmp(name,a->alias,XkbKeyNameLength)==0) + return XkbFindKeycodeByName(xkb,a->real,False); + } + } + return 0; +} + + +unsigned +XkbConvertGetByNameComponents(Bool toXkm,unsigned orig) +{ +unsigned rtrn; + + rtrn= 0; + if (toXkm) { + if (orig&XkbGBN_TypesMask) rtrn|= XkmTypesMask; + if (orig&XkbGBN_CompatMapMask) rtrn|= XkmCompatMapMask; + if (orig&XkbGBN_SymbolsMask) rtrn|= XkmSymbolsMask; + if (orig&XkbGBN_IndicatorMapMask) rtrn|= XkmIndicatorsMask; + if (orig&XkbGBN_KeyNamesMask) rtrn|= XkmKeyNamesMask; + if (orig&XkbGBN_GeometryMask) rtrn|= XkmGeometryMask; + } + else { + if (orig&XkmTypesMask) rtrn|= XkbGBN_TypesMask; + if (orig&XkmCompatMapMask) rtrn|= XkbGBN_CompatMapMask; + if (orig&XkmSymbolsMask) rtrn|= XkbGBN_SymbolsMask; + if (orig&XkmIndicatorsMask) rtrn|= XkbGBN_IndicatorMapMask; + if (orig&XkmKeyNamesMask) rtrn|= XkbGBN_KeyNamesMask; + if (orig&XkmGeometryMask) rtrn|= XkbGBN_GeometryMask; + if (orig!=0) rtrn|= XkbGBN_OtherNamesMask; + } + return rtrn; +} + +/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */ +/* wildcards */ + +static unsigned char componentSpecLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +void +XkbEnsureSafeMapName(char *name) +{ + if (name==NULL) + return; + while (*name!='\0') { + if ((componentSpecLegal[(*name)/8]&(1<<((*name)%8)))==0) + *name= '_'; + name++; + } + return; +} + +/***====================================================================***/ + +#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/')) + +Bool +XkbNameMatchesPattern(char *name,char *ptrn) +{ + while (ptrn[0]!='\0') { + if (name[0]=='\0') { + if (ptrn[0]=='*') { + ptrn++; + continue; + } + return False; + } + if (ptrn[0]=='?') { + if (UNMATCHABLE(name[0])) + return False; + } + else if (ptrn[0]=='*') { + if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn)) + return True; + return XkbNameMatchesPattern(name,ptrn+1); + } + else if (ptrn[0]!=name[0]) + return False; + name++; + ptrn++; + } + /* if we get here, the pattern is exhausted (-:just like me:-) */ + return (name[0]=='\0'); +} diff --git a/xorg-server/xkb/xkbgeom.h b/xorg-server/xkb/xkbgeom.h new file mode 100644 index 000000000..173affee9 --- /dev/null +++ b/xorg-server/xkb/xkbgeom.h @@ -0,0 +1,635 @@ +/************************************************************ +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. + +********************************************************/ + +#ifndef _XKBGEOM_H_ +#define _XKBGEOM_H_ + +#include "xkbstr.h" + +#define XkbAddGeomKeyAlias SrvXkbAddGeomKeyAlias +#define XkbAddGeomColor SrvXkbAddGeomColor +#define XkbAddGeomDoodad SrvXkbAddGeomDoodad +#define XkbAddGeomKey SrvXkbAddGeomKey +#define XkbAddGeomOutline SrvXkbAddGeomOutline +#define XkbAddGeomOverlay SrvXkbAddGeomOverlay +#define XkbAddGeomOverlayRow SrvXkbAddGeomOverlayRow +#define XkbAddGeomOverlayKey SrvXkbAddGeomOverlayKey +#define XkbAddGeomProperty SrvXkbAddGeomProperty +#define XkbAddGeomRow SrvXkbAddGeomRow +#define XkbAddGeomSection SrvXkbAddGeomSection +#define XkbAddGeomShape SrvXkbAddGeomShape +#define XkbAllocGeomKeyAliases SrvXkbAllocGeomKeyAliases +#define XkbAllocGeomColors SrvXkbAllocGeomColors +#define XkbAllocGeomDoodads SrvXkbAllocGeomDoodads +#define XkbAllocGeomKeys SrvXkbAllocGeomKeys +#define XkbAllocGeomOutlines SrvXkbAllocGeomOutlines +#define XkbAllocGeomPoints SrvXkbAllocGeomPoints +#define XkbAllocGeomProps SrvXkbAllocGeomProps +#define XkbAllocGeomRows SrvXkbAllocGeomRows +#define XkbAllocGeomSectionDoodads SrvXkbAllocGeomSectionDoodads +#define XkbAllocGeomSections SrvXkbAllocGeomSections +#define XkbAllocGeomOverlays SrvXkbAllocGeomOverlays +#define XkbAllocGeomOverlayRows SrvXkbAllocGeomOverlayRows +#define XkbAllocGeomOverlayKeys SrvXkbAllocGeomOverlayKeys +#define XkbAllocGeomShapes SrvXkbAllocGeomShapes +#define XkbAllocGeometry SrvXkbAllocGeometry +#define XkbFreeGeomKeyAliases SrvXkbFreeGeomKeyAliases +#define XkbFreeGeomColors SrvXkbFreeGeomColors +#define XkbFreeGeomDoodads SrvXkbFreeGeomDoodads +#define XkbFreeGeomProperties SrvXkbFreeGeomProperties +#define XkbFreeGeomOverlayKeys SrvXkbFreeGeomOverlayKeys +#define XkbFreeGeomOverlayRows SrvXkbFreeGeomOverlayRows +#define XkbFreeGeomOverlays SrvXkbFreeGeomOverlays +#define XkbFreeGeomKeys SrvXkbFreeGeomKeys +#define XkbFreeGeomRows SrvXkbFreeGeomRows +#define XkbFreeGeomSections SrvXkbFreeGeomSections +#define XkbFreeGeomPoints SrvXkbFreeGeomPoints +#define XkbFreeGeomOutlines SrvXkbFreeGeomOutlines +#define XkbFreeGeomShapes SrvXkbFreeGeomShapes +#define XkbFreeGeometry SrvXkbFreeGeometry + +typedef struct _XkbProperty { + char *name; + char *value; +} XkbPropertyRec,*XkbPropertyPtr; + +typedef struct _XkbColor { + unsigned int pixel; + char * spec; +} XkbColorRec,*XkbColorPtr; + +typedef struct _XkbPoint { + short x; + short y; +} XkbPointRec, *XkbPointPtr; + +typedef struct _XkbBounds { + short x1,y1; + short x2,y2; +} XkbBoundsRec, *XkbBoundsPtr; +#define XkbBoundsWidth(b) (((b)->x2)-((b)->x1)) +#define XkbBoundsHeight(b) (((b)->y2)-((b)->y1)) + +typedef struct _XkbOutline { + unsigned short num_points; + unsigned short sz_points; + unsigned short corner_radius; + XkbPointPtr points; +} XkbOutlineRec, *XkbOutlinePtr; + +typedef struct _XkbShape { + Atom name; + unsigned short num_outlines; + unsigned short sz_outlines; + XkbOutlinePtr outlines; + XkbOutlinePtr approx; + XkbOutlinePtr primary; + XkbBoundsRec bounds; +} XkbShapeRec, *XkbShapePtr; +#define XkbOutlineIndex(s,o) ((int)((o)-&(s)->outlines[0])) + +typedef struct _XkbShapeDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + unsigned short color_ndx; + unsigned short shape_ndx; +} XkbShapeDoodadRec, *XkbShapeDoodadPtr; +#define XkbShapeDoodadColor(g,d) (&(g)->colors[(d)->color_ndx]) +#define XkbShapeDoodadShape(g,d) (&(g)->shapes[(d)->shape_ndx]) +#define XkbSetShapeDoodadColor(g,d,c) ((d)->color_ndx= (c)-&(g)->colors[0]) +#define XkbSetShapeDoodadShape(g,d,s) ((d)->shape_ndx= (s)-&(g)->shapes[0]) + +typedef struct _XkbTextDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + short width; + short height; + unsigned short color_ndx; + char * text; + char * font; +} XkbTextDoodadRec, *XkbTextDoodadPtr; +#define XkbTextDoodadColor(g,d) (&(g)->colors[(d)->color_ndx]) +#define XkbSetTextDoodadColor(g,d,c) ((d)->color_ndx= (c)-&(g)->colors[0]) + +typedef struct _XkbIndicatorDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + unsigned short shape_ndx; + unsigned short on_color_ndx; + unsigned short off_color_ndx; +} XkbIndicatorDoodadRec, *XkbIndicatorDoodadPtr; +#define XkbIndicatorDoodadShape(g,d) (&(g)->shapes[(d)->shape_ndx]) +#define XkbIndicatorDoodadOnColor(g,d) (&(g)->colors[(d)->on_color_ndx]) +#define XkbIndicatorDoodadOffColor(g,d) (&(g)->colors[(d)->off_color_ndx]) +#define XkbSetIndicatorDoodadOnColor(g,d,c) \ + ((d)->on_color_ndx= (c)-&(g)->colors[0]) +#define XkbSetIndicatorDoodadOffColor(g,d,c) \ + ((d)->off_color_ndx= (c)-&(g)->colors[0]) +#define XkbSetIndicatorDoodadShape(g,d,s) \ + ((d)->shape_ndx= (s)-&(g)->shapes[0]) + +typedef struct _XkbLogoDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + unsigned short color_ndx; + unsigned short shape_ndx; + char * logo_name; +} XkbLogoDoodadRec, *XkbLogoDoodadPtr; +#define XkbLogoDoodadColor(g,d) (&(g)->colors[(d)->color_ndx]) +#define XkbLogoDoodadShape(g,d) (&(g)->shapes[(d)->shape_ndx]) +#define XkbSetLogoDoodadColor(g,d,c) ((d)->color_ndx= (c)-&(g)->colors[0]) +#define XkbSetLogoDoodadShape(g,d,s) ((d)->shape_ndx= (s)-&(g)->shapes[0]) + +typedef struct _XkbAnyDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; +} XkbAnyDoodadRec, *XkbAnyDoodadPtr; + +typedef union _XkbDoodad { + XkbAnyDoodadRec any; + XkbShapeDoodadRec shape; + XkbTextDoodadRec text; + XkbIndicatorDoodadRec indicator; + XkbLogoDoodadRec logo; +} XkbDoodadRec, *XkbDoodadPtr; + +#define XkbUnknownDoodad 0 +#define XkbOutlineDoodad 1 +#define XkbSolidDoodad 2 +#define XkbTextDoodad 3 +#define XkbIndicatorDoodad 4 +#define XkbLogoDoodad 5 + +typedef struct _XkbKey { + XkbKeyNameRec name; + short gap; + unsigned char shape_ndx; + unsigned char color_ndx; +} XkbKeyRec, *XkbKeyPtr; +#define XkbKeyShape(g,k) (&(g)->shapes[(k)->shape_ndx]) +#define XkbKeyColor(g,k) (&(g)->colors[(k)->color_ndx]) +#define XkbSetKeyShape(g,k,s) ((k)->shape_ndx= (s)-&(g)->shapes[0]) +#define XkbSetKeyColor(g,k,c) ((k)->color_ndx= (c)-&(g)->colors[0]) + +typedef struct _XkbRow { + short top; + short left; + unsigned short num_keys; + unsigned short sz_keys; + int vertical; + XkbKeyPtr keys; + XkbBoundsRec bounds; +} XkbRowRec, *XkbRowPtr; + +typedef struct _XkbSection { + Atom name; + unsigned char priority; + short top; + short left; + unsigned short width; + unsigned short height; + short angle; + unsigned short num_rows; + unsigned short num_doodads; + unsigned short num_overlays; + unsigned short sz_rows; + unsigned short sz_doodads; + unsigned short sz_overlays; + XkbRowPtr rows; + XkbDoodadPtr doodads; + XkbBoundsRec bounds; + struct _XkbOverlay *overlays; +} XkbSectionRec, *XkbSectionPtr; + +typedef struct _XkbOverlayKey { + XkbKeyNameRec over; + XkbKeyNameRec under; +} XkbOverlayKeyRec,*XkbOverlayKeyPtr; + +typedef struct _XkbOverlayRow { + unsigned short row_under; + unsigned short num_keys; + unsigned short sz_keys; + XkbOverlayKeyPtr keys; +} XkbOverlayRowRec,*XkbOverlayRowPtr; + +typedef struct _XkbOverlay { + Atom name; + XkbSectionPtr section_under; + unsigned short num_rows; + unsigned short sz_rows; + XkbOverlayRowPtr rows; + XkbBoundsPtr bounds; +} XkbOverlayRec,*XkbOverlayPtr; + +typedef struct _XkbGeometry { + Atom name; + unsigned short width_mm; + unsigned short height_mm; + char * label_font; + XkbColorPtr label_color; + XkbColorPtr base_color; + unsigned short sz_properties; + unsigned short sz_colors; + unsigned short sz_shapes; + unsigned short sz_sections; + unsigned short sz_doodads; + unsigned short sz_key_aliases; + unsigned short num_properties; + unsigned short num_colors; + unsigned short num_shapes; + unsigned short num_sections; + unsigned short num_doodads; + unsigned short num_key_aliases; + XkbPropertyPtr properties; + XkbColorPtr colors; + XkbShapePtr shapes; + XkbSectionPtr sections; + XkbDoodadPtr doodads; + XkbKeyAliasPtr key_aliases; +} XkbGeometryRec; +#define XkbGeomColorIndex(g,c) ((int)((c)-&(g)->colors[0])) + +#define XkbGeomPropertiesMask (1<<0) +#define XkbGeomColorsMask (1<<1) +#define XkbGeomShapesMask (1<<2) +#define XkbGeomSectionsMask (1<<3) +#define XkbGeomDoodadsMask (1<<4) +#define XkbGeomKeyAliasesMask (1<<5) +#define XkbGeomAllMask (0x3f) + +typedef struct _XkbGeometrySizes { + unsigned int which; + unsigned short num_properties; + unsigned short num_colors; + unsigned short num_shapes; + unsigned short num_sections; + unsigned short num_doodads; + unsigned short num_key_aliases; +} XkbGeometrySizesRec,*XkbGeometrySizesPtr; + +_XFUNCPROTOBEGIN + +extern XkbPropertyPtr +XkbAddGeomProperty( + XkbGeometryPtr /* geom */, + char * /* name */, + char * /* value */ +); + +extern XkbKeyAliasPtr +XkbAddGeomKeyAlias( + XkbGeometryPtr /* geom */, + char * /* alias */, + char * /* real */ +); + +extern XkbColorPtr +XkbAddGeomColor( + XkbGeometryPtr /* geom */, + char * /* spec */, + unsigned int /* pixel */ +); + +extern XkbOutlinePtr +XkbAddGeomOutline( + XkbShapePtr /* shape */, + int /* sz_points */ +); + +extern XkbShapePtr +XkbAddGeomShape( + XkbGeometryPtr /* geom */, + Atom /* name */, + int /* sz_outlines */ +); + +extern XkbKeyPtr +XkbAddGeomKey( + XkbRowPtr /* row */ +); + +extern XkbRowPtr +XkbAddGeomRow( + XkbSectionPtr /* section */, + int /* sz_keys */ +); + +extern XkbSectionPtr +XkbAddGeomSection( + XkbGeometryPtr /* geom */, + Atom /* name */, + int /* sz_rows */, + int /* sz_doodads */, + int /* sz_overlays */ +); + +extern XkbOverlayPtr +XkbAddGeomOverlay( + XkbSectionPtr /* section */, + Atom /* name */, + int /* sz_rows */ +); + +extern XkbOverlayRowPtr +XkbAddGeomOverlayRow( + XkbOverlayPtr /* overlay */, + int /* row_under */, + int /* sz_keys */ +); + +extern XkbOverlayKeyPtr +XkbAddGeomOverlayKey( + XkbOverlayPtr /* overlay */, + XkbOverlayRowPtr /* row */, + char * /* over */, + char * /* under */ +); + +extern XkbDoodadPtr +XkbAddGeomDoodad( + XkbGeometryPtr /* geom */, + XkbSectionPtr /* section */, + Atom /* name */ +); + + +extern void +XkbFreeGeomKeyAliases( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomColors( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomDoodads( + XkbDoodadPtr /* doodads */, + int /* nDoodads */, + Bool /* freeAll */ +); + + +extern void +XkbFreeGeomProperties( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomOverlayKeys( + XkbOverlayRowPtr /* row */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomOverlayRows( + XkbOverlayPtr /* overlay */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomOverlays( + XkbSectionPtr /* section */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomKeys( + XkbRowPtr /* row */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomRows( + XkbSectionPtr /* section */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomSections( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + + +extern void +XkbFreeGeomPoints( + XkbOutlinePtr /* outline */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomOutlines( + XkbShapePtr /* shape */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomShapes( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeometry( + XkbGeometryPtr /* geom */, + unsigned int /* which */, + Bool /* freeMap */ +); + +extern Status +XkbAllocGeomProps( + XkbGeometryPtr /* geom */, + int /* nProps */ +); + +extern Status +XkbAllocGeomKeyAliases( + XkbGeometryPtr /* geom */, + int /* nAliases */ +); + +extern Status +XkbAllocGeomColors( + XkbGeometryPtr /* geom */, + int /* nColors */ +); + +extern Status +XkbAllocGeomShapes( + XkbGeometryPtr /* geom */, + int /* nShapes */ +); + +extern Status +XkbAllocGeomSections( + XkbGeometryPtr /* geom */, + int /* nSections */ +); + +extern Status +XkbAllocGeomOverlays( + XkbSectionPtr /* section */, + int /* num_needed */ +); + +extern Status +XkbAllocGeomOverlayRows( + XkbOverlayPtr /* overlay */, + int /* num_needed */ +); + +extern Status +XkbAllocGeomOverlayKeys( + XkbOverlayRowPtr /* row */, + int /* num_needed */ +); + +extern Status +XkbAllocGeomDoodads( + XkbGeometryPtr /* geom */, + int /* nDoodads */ +); + +extern Status +XkbAllocGeomSectionDoodads( + XkbSectionPtr /* section */, + int /* nDoodads */ +); + +extern Status +XkbAllocGeomOutlines( + XkbShapePtr /* shape */, + int /* nOL */ +); + +extern Status +XkbAllocGeomRows( + XkbSectionPtr /* section */, + int /* nRows */ +); + +extern Status +XkbAllocGeomPoints( + XkbOutlinePtr /* ol */, + int /* nPts */ +); + +extern Status +XkbAllocGeomKeys( + XkbRowPtr /* row */, + int /* nKeys */ +); + +extern Status +XkbAllocGeometry( + XkbDescPtr /* xkb */, + XkbGeometrySizesPtr /* sizes */ +); + +extern Bool +XkbComputeShapeTop( + XkbShapePtr /* shape */, + XkbBoundsPtr /* bounds */ +); + +extern Bool +XkbComputeShapeBounds( + XkbShapePtr /* shape */ +); + +extern Bool +XkbComputeRowBounds( + XkbGeometryPtr /* geom */, + XkbSectionPtr /* section */, + XkbRowPtr /* row */ +); + +extern Bool +XkbComputeSectionBounds( + XkbGeometryPtr /* geom */, + XkbSectionPtr /* section */ +); + +extern char * +XkbFindOverlayForKey( + XkbGeometryPtr /* geom */, + XkbSectionPtr /* wanted */, + char * /* under */ +); + +_XFUNCPROTOEND + +#endif /* _XKBGEOM_H_ */ diff --git a/xorg-server/xkb/xkbout.c b/xorg-server/xkb/xkbout.c new file mode 100644 index 000000000..229cc9258 --- /dev/null +++ b/xorg-server/xkb/xkbout.c @@ -0,0 +1,895 @@ +/************************************************************ + Copyright (c) 1994 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 <dix-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <X11/Xfuncs.h> + +#include <X11/X.h> +#define NEED_EVENTS +#include <X11/keysym.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "xkbstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include <xkbsrv.h> + +#include "xkbgeom.h" +#include "xkbfile.h" + +#define VMOD_HIDE_VALUE 0 +#define VMOD_SHOW_VALUE 1 +#define VMOD_COMMENT_VALUE 2 + +static Bool +WriteXKBVModDecl(FILE *file,XkbDescPtr xkb,int showValue) +{ +register int i,nMods; +Atom * vmodNames; + + if (xkb==NULL) + return False; + if (xkb->names!=NULL) + vmodNames= xkb->names->vmods; + else vmodNames= NULL; + + for (i=nMods=0;i<XkbNumVirtualMods;i++) { + if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) { + if (nMods==0) fprintf(file," virtual_modifiers "); + else fprintf(file,","); + fprintf(file,"%s",XkbAtomText(vmodNames[i],XkbXKBFile)); + if ((showValue!=VMOD_HIDE_VALUE)&& + (xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) { + if (showValue==VMOD_COMMENT_VALUE) { + fprintf(file,"/* = %s */", + XkbModMaskText(xkb->server->vmods[i],XkbXKBFile)); + } + else { + fprintf(file,"= %s", + XkbModMaskText(xkb->server->vmods[i],XkbXKBFile)); + } + } + nMods++; + } + } + if (nMods>0) + fprintf(file,";\n\n"); + return True; +} + +/***====================================================================***/ + +static Bool +WriteXKBAction(FILE *file,XkbDescPtr xkb,XkbAnyAction *action) +{ + fprintf(file,"%s",XkbActionText(xkb,(XkbAction *)action,XkbXKBFile)); + return True; +} + +/***====================================================================***/ + +Bool +XkbWriteXKBKeycodes( FILE * file, + XkbDescPtr xkb, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +{ +Atom kcName; +register unsigned i; +char * alternate; + + if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) { + _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0); + return False; + } + kcName= xkb->names->keycodes; + if (kcName!=None) + fprintf(file,"xkb_keycodes \"%s\" {\n", + XkbAtomText(kcName,XkbXKBFile)); + else fprintf(file,"xkb_keycodes {\n"); + fprintf(file," minimum = %d;\n",xkb->min_key_code); + fprintf(file," maximum = %d;\n",xkb->max_key_code); + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (xkb->names->keys[i].name[0]!='\0') { + if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i) + alternate= "alternate "; + else alternate= ""; + fprintf(file," %s%6s = %d;\n",alternate, + XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile), + i); + } + } + if (xkb->indicators!=NULL) { + for (i=0;i<XkbNumIndicators;i++) { + char *type; + if (xkb->indicators->phys_indicators&(1<<i)) + type= " "; + else type= " virtual "; + if (xkb->names->indicators[i]!=None) { + fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1, + XkbAtomText(xkb->names->indicators[i],XkbXKBFile)); + } + } + } + if (xkb->names->key_aliases!=NULL) { + XkbKeyAliasPtr pAl; + pAl= xkb->names->key_aliases; + for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) { + fprintf(file," alias %6s = %6s;\n", + XkbKeyNameText(pAl->alias,XkbXKBFile), + XkbKeyNameText(pAl->real,XkbXKBFile)); + } + } + if (addOn) + (*addOn)(file,xkb,topLevel,showImplicit,XkmKeyNamesIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +Bool +XkbWriteXKBKeyTypes( FILE * file, + XkbDescPtr xkb, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +{ +register unsigned i,n; +XkbKeyTypePtr type; +XkbKTMapEntryPtr entry; + + if ((!xkb)||(!xkb->map)||(!xkb->map->types)) { + _XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0); + return False; + } + if (xkb->map->num_types<XkbNumRequiredTypes) { + _XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0); + return 0; + } + if ((xkb->names==NULL)||(xkb->names->types==None)) + fprintf(file,"xkb_types {\n\n"); + else fprintf(file,"xkb_types \"%s\" {\n\n", + XkbAtomText(xkb->names->types,XkbXKBFile)); + WriteXKBVModDecl(file,xkb, + (showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE)); + + type= xkb->map->types; + for (i=0;i<xkb->map->num_types;i++,type++) { + fprintf(file," type \"%s\" {\n", + XkbAtomText(type->name,XkbXKBFile)); + fprintf(file," modifiers= %s;\n", + XkbVModMaskText(xkb,type->mods.real_mods,type->mods.vmods, + XkbXKBFile)); + entry= type->map; + for (n=0;n<type->map_count;n++,entry++) { + char *str; + str=XkbVModMaskText(xkb,entry->mods.real_mods,entry->mods.vmods, + XkbXKBFile); + fprintf(file," map[%s]= Level%d;\n",str,entry->level+1); + if ((type->preserve)&&((type->preserve[n].real_mods)|| + (type->preserve[n].vmods))) { + fprintf(file," preserve[%s]= ",str); + fprintf(file,"%s;\n",XkbVModMaskText(xkb, + type->preserve[n].real_mods, + type->preserve[n].vmods, + XkbXKBFile)); + } + } + if (type->level_names!=NULL) { + Atom *name= type->level_names; + for (n=0;n<type->num_levels;n++,name++) { + if ((*name)==None) + continue; + fprintf(file," level_name[Level%d]= \"%s\";\n",n+1, + XkbAtomText(*name,XkbXKBFile)); + } + } + fprintf(file," };\n"); + } + if (addOn) + (*addOn)(file,xkb,topLevel,showImplicit,XkmTypesIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +static Bool +WriteXKBIndicatorMap( FILE * file, + XkbDescPtr xkb, + Atom name, + XkbIndicatorMapPtr led, + XkbFileAddOnFunc addOn, + void * priv) +{ + + fprintf(file," indicator \"%s\" {\n",XkbAtomGetString(name)); + if (led->flags&XkbIM_NoExplicit) + fprintf(file," !allowExplicit;\n"); + if (led->flags&XkbIM_LEDDrivesKB) + fprintf(file," indicatorDrivesKeyboard;\n"); + if (led->which_groups!=0) { + if (led->which_groups!=XkbIM_UseEffective) { + fprintf(file," whichGroupState= %s;\n", + XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile)); + } + fprintf(file," groups= 0x%02x;\n",led->groups); + } + if (led->which_mods!=0) { + if (led->which_mods!=XkbIM_UseEffective) { + fprintf(file," whichModState= %s;\n", + XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile)); + } + fprintf(file," modifiers= %s;\n", + XkbVModMaskText(xkb, + led->mods.real_mods,led->mods.vmods, + XkbXKBFile)); + } + if (led->ctrls!=0) { + fprintf(file," controls= %s;\n", + XkbControlsMaskText(led->ctrls,XkbXKBFile)); + } + if (addOn) + (*addOn)(file,xkb,False,True,XkmIndicatorsIndex,priv); + fprintf(file," };\n"); + return True; +} + +Bool +XkbWriteXKBCompatMap( FILE * file, + XkbDescPtr xkb, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +{ +register unsigned i; +XkbSymInterpretPtr interp; + + if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) { + _XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0); + return False; + } + if ((xkb->names==NULL)||(xkb->names->compat==None)) + fprintf(file,"xkb_compatibility {\n\n"); + else fprintf(file,"xkb_compatibility \"%s\" {\n\n", + XkbAtomText(xkb->names->compat,XkbXKBFile)); + WriteXKBVModDecl(file,xkb, + (showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE)); + + fprintf(file," interpret.useModMapMods= AnyLevel;\n"); + fprintf(file," interpret.repeat= False;\n"); + fprintf(file," interpret.locking= False;\n"); + interp= xkb->compat->sym_interpret; + for (i=0;i<xkb->compat->num_si;i++,interp++) { + fprintf(file," interpret %s+%s(%s) {\n", + ((interp->sym==NoSymbol)?"Any": + XkbKeysymText(interp->sym,XkbXKBFile)), + XkbSIMatchText(interp->match,XkbXKBFile), + XkbModMaskText(interp->mods,XkbXKBFile)); + if (interp->virtual_mod!=XkbNoModifier) { + fprintf(file," virtualModifier= %s;\n", + XkbVModIndexText(xkb,interp->virtual_mod,XkbXKBFile)); + } + if (interp->match&XkbSI_LevelOneOnly) + fprintf(file," useModMapMods=level1;\n"); + if (interp->flags&XkbSI_LockingKey) + fprintf(file," locking= True;\n"); + if (interp->flags&XkbSI_AutoRepeat) + fprintf(file," repeat= True;\n"); + fprintf(file," action= "); + WriteXKBAction(file,xkb,&interp->act); + fprintf(file,";\n"); + fprintf(file," };\n"); + } + for (i=0;i<XkbNumKbdGroups;i++) { + XkbModsPtr gc; + + gc= &xkb->compat->groups[i]; + if ((gc->real_mods==0)&&(gc->vmods==0)) + continue; + fprintf(file," group %d = %s;\n",i+1,XkbVModMaskText(xkb, + gc->real_mods,gc->vmods, + XkbXKBFile)); + } + if (xkb->indicators) { + for (i=0;i<XkbNumIndicators;i++) { + XkbIndicatorMapPtr map= &xkb->indicators->maps[i]; + if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)|| + (map->which_mods!=0)|| + (map->mods.real_mods!=0)||(map->mods.vmods!=0)|| + (map->ctrls!=0)) { + WriteXKBIndicatorMap(file,xkb,xkb->names->indicators[i],map, + addOn,priv); + } + } + } + if (addOn) + (*addOn)(file,xkb,topLevel,showImplicit,XkmCompatMapIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +Bool +XkbWriteXKBSymbols( FILE * file, + XkbDescPtr xkb, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +{ +register unsigned i,tmp; +XkbClientMapPtr map; +XkbServerMapPtr srv; +Bool showActions; + + map= xkb->map; + srv= xkb->server; + if ((!xkb)||(!map)||(!map->syms)||(!map->key_sym_map)) { + _XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0); + return False; + } + if ((!xkb->names)||(!xkb->names->keys)) { + _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0); + return False; + } + if ((xkb->names==NULL)||(xkb->names->symbols==None)) + fprintf(file,"xkb_symbols {\n\n"); + else fprintf(file,"xkb_symbols \"%s\" {\n\n", + XkbAtomText(xkb->names->symbols,XkbXKBFile)); + for (tmp=i=0;i<XkbNumKbdGroups;i++) { + if (xkb->names->groups[i]!=None) { + fprintf(file," name[group%d]=\"%s\";\n",i+1, + XkbAtomText(xkb->names->groups[i],XkbXKBFile)); + tmp++; + } + } + if (tmp>0) + fprintf(file,"\n"); + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + Bool simple; + if ((int)XkbKeyNumSyms(xkb,i)<1) + continue; + if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i) + continue; + simple= True; + fprintf(file," key %6s {", + XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile)); + if (srv->explicit) { + if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)|| + (showImplicit)) { + int typeNdx,g; + Bool multi; + char * comment=" "; + + if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0) + comment= "//"; + multi= False; + typeNdx= XkbKeyKeyTypeIndex(xkb,i,0); + for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) { + if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx) + multi= True; + } + if (multi) { + for (g=0;g<XkbKeyNumGroups(xkb,i);g++) { + typeNdx= XkbKeyKeyTypeIndex(xkb,i,g); + if (srv->explicit[i]&(1<<g)) { + fprintf(file,"\n%s type[group%d]= \"%s\",", + comment,g+1, + XkbAtomText(map->types[typeNdx].name, + XkbXKBFile)); + } + else if (showImplicit) { + fprintf(file,"\n// type[group%d]= \"%s\",",g+1, + XkbAtomText(map->types[typeNdx].name, + XkbXKBFile)); + } + } + } + else { + fprintf(file,"\n%s type= \"%s\",",comment, + XkbAtomText(map->types[typeNdx].name, + XkbXKBFile)); + } + simple= False; + } + if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&& + (xkb->ctrls!=NULL)) { + if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8))) + fprintf(file,"\n repeat= Yes,"); + else fprintf(file,"\n repeat= No,"); + simple= False; + } + if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&& + (xkb->server->vmodmap[i]!=0)) { + if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) { + fprintf(file,"\n virtualMods= %s,", + XkbVModMaskText(xkb,0, + xkb->server->vmodmap[i], + XkbXKBFile)); + } + else if (showImplicit) { + fprintf(file,"\n// virtualMods= %s,", + XkbVModMaskText(xkb,0, + xkb->server->vmodmap[i], + XkbXKBFile)); + } + } + } + switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) { + case XkbClampIntoRange: + fprintf(file,"\n groupsClamp,"); + break; + case XkbRedirectIntoRange: + fprintf(file,"\n groupsRedirect= Group%d,", + XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1); + break; + } + if (srv->behaviors!=NULL) { + unsigned type; + type= srv->behaviors[i].type&XkbKB_OpMask; + + if (type!=XkbKB_Default) { + simple= False; + fprintf(file,"\n %s,", + XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile)); + } + } + if ((srv->explicit==NULL) || showImplicit || + ((srv->explicit[i]&XkbExplicitInterpretMask)!=0)) + showActions= XkbKeyHasActions(xkb,i); + else showActions= False; + + if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions) + simple= False; + if (simple) { + KeySym *syms; + unsigned s; + + syms= XkbKeySymsPtr(xkb,i); + fprintf(file," [ "); + for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) { + if (s!=0) + fprintf(file,", "); + fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile)); + } + fprintf(file," ] };\n"); + } + else { + unsigned g,s; + KeySym *syms; + XkbAction *acts; + syms= XkbKeySymsPtr(xkb,i); + acts= XkbKeyActionsPtr(xkb,i); + for (g=0;g<XkbKeyNumGroups(xkb,i);g++) { + if (g!=0) + fprintf(file,","); + fprintf(file,"\n symbols[Group%d]= [ ",g+1); + for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) { + if (s!=0) + fprintf(file,", "); + fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile)); + } + fprintf(file," ]"); + syms+= XkbKeyGroupsWidth(xkb,i); + if (showActions) { + fprintf(file,",\n actions[Group%d]= [ ",g+1); + for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) { + if (s!=0) + fprintf(file,", "); + WriteXKBAction(file,xkb,(XkbAnyAction *)&acts[s]); + } + fprintf(file," ]"); + acts+= XkbKeyGroupsWidth(xkb,i); + } + } + fprintf(file,"\n };\n"); + } + } + if (map && map->modmap) { + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (map->modmap[i]!=0) { + register int n,bit; + for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) { + if (map->modmap[i]&bit) { + char buf[5]; + memcpy(buf,xkb->names->keys[i].name,4); + buf[4]= '\0'; + fprintf(file," modifier_map %s { <%s> };\n", + XkbModIndexText(n,XkbXKBFile),buf); + } + } + } + } + } + if (addOn) + (*addOn)(file,xkb,topLevel,showImplicit,XkmSymbolsIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +static Bool +WriteXKBOutline( FILE * file, + XkbShapePtr shape, + XkbOutlinePtr outline, + int lastRadius, + int first, + int indent) +{ +register int i; +XkbPointPtr pt; +char * iStr; + + fprintf(file,"%s",iStr= XkbIndentText(first)); + if (first!=indent) + iStr= XkbIndentText(indent); + if (outline->corner_radius!=lastRadius) { + fprintf(file,"corner= %s,", + XkbGeomFPText(outline->corner_radius,XkbMessage)); + if (shape!=NULL) { + fprintf(file,"\n%s",iStr); + } + } + if (shape) { + if (outline==shape->approx) + fprintf(file,"approx= "); + else if (outline==shape->primary) + fprintf(file,"primary= "); + } + fprintf(file,"{"); + for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) { + if (i==0) fprintf(file," "); + else if ((i%4)==0) fprintf(file,",\n%s ",iStr); + else fprintf(file,", "); + fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile), + XkbGeomFPText(pt->y,XkbXKBFile)); + } + fprintf(file," }"); + return True; +} + +static Bool +WriteXKBDoodad( FILE * file, + unsigned indent, + XkbGeometryPtr geom, + XkbDoodadPtr doodad) +{ +register char * i_str; +XkbShapePtr shape; +XkbColorPtr color; + + i_str= XkbIndentText(indent); + fprintf(file,"%s%s \"%s\" {\n",i_str, + XkbDoodadTypeText(doodad->any.type,XkbMessage), + XkbAtomText(doodad->any.name,XkbMessage)); + fprintf(file,"%s top= %s;\n",i_str, + XkbGeomFPText(doodad->any.top,XkbXKBFile)); + fprintf(file,"%s left= %s;\n",i_str, + XkbGeomFPText(doodad->any.left,XkbXKBFile)); + fprintf(file,"%s priority= %d;\n",i_str,doodad->any.priority); + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + if (doodad->shape.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->shape.angle,XkbXKBFile)); + } + if (doodad->shape.color_ndx!=0) { + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbShapeDoodadColor(geom,&doodad->shape)->spec); + } + shape= XkbShapeDoodadShape(geom,&doodad->shape); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(shape->name,XkbXKBFile)); + break; + case XkbTextDoodad: + if (doodad->text.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->text.angle,XkbXKBFile)); + } + if (doodad->text.width!=0) { + fprintf(file,"%s width= %s;\n",i_str, + XkbGeomFPText(doodad->text.width,XkbXKBFile)); + + } + if (doodad->text.height!=0) { + fprintf(file,"%s height= %s;\n",i_str, + XkbGeomFPText(doodad->text.height,XkbXKBFile)); + + } + if (doodad->text.color_ndx!=0) { + color= XkbTextDoodadColor(geom,&doodad->text); + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + } + fprintf(file,"%s XFont= \"%s\";\n",i_str, + XkbStringText(doodad->text.font,XkbXKBFile)); + fprintf(file,"%s text= \"%s\";\n",i_str, + XkbStringText(doodad->text.text,XkbXKBFile)); + break; + case XkbIndicatorDoodad: + shape= XkbIndicatorDoodadShape(geom,&doodad->indicator); + color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator); + fprintf(file,"%s onColor= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator); + fprintf(file,"%s offColor= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(shape->name,XkbXKBFile)); + break; + case XkbLogoDoodad: + fprintf(file,"%s logoName= \"%s\";\n",i_str, + XkbStringText(doodad->logo.logo_name,XkbXKBFile)); + if (doodad->shape.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->logo.angle,XkbXKBFile)); + } + if (doodad->shape.color_ndx!=0) { + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbLogoDoodadColor(geom,&doodad->logo)->spec); + } + shape= XkbLogoDoodadShape(geom,&doodad->logo); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(shape->name,XkbXKBFile)); + break; + } + fprintf(file,"%s};\n",i_str); + return True; +} + +/*ARGSUSED*/ +static Bool +WriteXKBOverlay( FILE * file, + unsigned indent, + XkbGeometryPtr geom, + XkbOverlayPtr ol) +{ +register char * i_str; +int r,k,nOut; +XkbOverlayRowPtr row; +XkbOverlayKeyPtr key; + + i_str= XkbIndentText(indent); + if (ol->name!=None) { + fprintf(file,"%soverlay \"%s\" {\n",i_str, + XkbAtomText(ol->name,XkbMessage)); + } + else fprintf(file,"%soverlay {\n",i_str); + for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) { + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + char *over,*under; + over= XkbKeyNameText(key->over.name,XkbXKBFile); + under= XkbKeyNameText(key->under.name,XkbXKBFile); + if (nOut==0) + fprintf(file,"%s %6s=%6s",i_str,under,over); + else if ((nOut%4)==0) + fprintf(file,",\n%s %6s=%6s",i_str,under,over); + else fprintf(file,", %6s=%6s",under,over); + nOut++; + } + } + fprintf(file,"\n%s};\n",i_str); + return True; +} + +static Bool +WriteXKBSection( FILE * file, + XkbSectionPtr s, + XkbGeometryPtr geom) +{ +register int i; +XkbRowPtr row; +int dfltKeyColor = 0; + + fprintf(file," section \"%s\" {\n", + XkbAtomText(s->name,XkbXKBFile)); + if (s->rows&&(s->rows->num_keys>0)) { + dfltKeyColor= s->rows->keys[0].color_ndx; + fprintf(file," key.color= \"%s\";\n", + XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile)); + } + fprintf(file," priority= %d;\n",s->priority); + fprintf(file," top= %s;\n",XkbGeomFPText(s->top,XkbXKBFile)); + fprintf(file," left= %s;\n",XkbGeomFPText(s->left,XkbXKBFile)); + fprintf(file," width= %s;\n",XkbGeomFPText(s->width,XkbXKBFile)); + fprintf(file," height= %s;\n", + XkbGeomFPText(s->height,XkbXKBFile)); + if (s->angle!=0) { + fprintf(file," angle= %s;\n", + XkbGeomFPText(s->angle,XkbXKBFile)); + } + for (i=0,row=s->rows;i<s->num_rows;i++,row++) { + fprintf(file," row {\n"); + fprintf(file," top= %s;\n", + XkbGeomFPText(row->top,XkbXKBFile)); + fprintf(file," left= %s;\n", + XkbGeomFPText(row->left,XkbXKBFile)); + if (row->vertical) + fprintf(file," vertical;\n"); + if (row->num_keys>0) { + register int k; + register XkbKeyPtr key; + int forceNL=0; + int nThisLine= 0; + fprintf(file," keys {\n"); + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + XkbShapePtr shape; + if (key->color_ndx!=dfltKeyColor) + forceNL= 1; + if (k==0) { + fprintf(file," "); + nThisLine= 0; + } + else if (((nThisLine%2)==1)||(forceNL)) { + fprintf(file,",\n "); + forceNL= nThisLine= 0; + } + else { + fprintf(file,", "); + nThisLine++; + } + shape= XkbKeyShape(geom,key); + fprintf(file,"{ %6s, \"%s\", %3s", + XkbKeyNameText(key->name.name,XkbXKBFile), + XkbAtomText(shape->name,XkbXKBFile), + XkbGeomFPText(key->gap,XkbXKBFile)); + if (key->color_ndx!=dfltKeyColor) { + fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec); + forceNL= 1; + } + fprintf(file," }"); + } + fprintf(file,"\n };\n"); + } + fprintf(file," };\n"); + } + if (s->doodads!=NULL) { + XkbDoodadPtr doodad; + for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) { + WriteXKBDoodad(file,8,geom,doodad); + } + } + if (s->overlays!=NULL) { + XkbOverlayPtr ol; + for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) { + WriteXKBOverlay(file,8,geom,ol); + } + } + fprintf(file," }; // End of \"%s\" section\n\n", + XkbAtomText(s->name,XkbXKBFile)); + return True; +} + +Bool +XkbWriteXKBGeometry( FILE * file, + XkbDescPtr xkb, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +{ +register unsigned i,n; +XkbGeometryPtr geom; + + if ((!xkb)||(!xkb->geom)) { + _XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0); + return False; + } + geom= xkb->geom; + if (geom->name==None) + fprintf(file,"xkb_geometry {\n\n"); + else fprintf(file,"xkb_geometry \"%s\" {\n\n", + XkbAtomText(geom->name,XkbXKBFile)); + fprintf(file," width= %s;\n", + XkbGeomFPText(geom->width_mm,XkbXKBFile)); + fprintf(file," height= %s;\n\n", + XkbGeomFPText(geom->height_mm,XkbXKBFile)); + + if (geom->key_aliases!=NULL) { + XkbKeyAliasPtr pAl; + pAl= geom->key_aliases; + for (i=0;i<geom->num_key_aliases;i++,pAl++) { + fprintf(file," alias %6s = %6s;\n", + XkbKeyNameText(pAl->alias,XkbXKBFile), + XkbKeyNameText(pAl->real,XkbXKBFile)); + } + fprintf(file,"\n"); + } + + if (geom->base_color!=NULL) + fprintf(file," baseColor= \"%s\";\n", + XkbStringText(geom->base_color->spec,XkbXKBFile)); + if (geom->label_color!=NULL) + fprintf(file," labelColor= \"%s\";\n", + XkbStringText(geom->label_color->spec,XkbXKBFile)); + if (geom->label_font!=NULL) + fprintf(file," xfont= \"%s\";\n", + XkbStringText(geom->label_font,XkbXKBFile)); + if ((geom->num_colors>0)&&(showImplicit)) { + XkbColorPtr color; + for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) { + fprintf(file,"// color[%d]= \"%s\"\n",i, + XkbStringText(color->spec,XkbXKBFile)); + } + fprintf(file,"\n"); + } + if (geom->num_properties>0) { + XkbPropertyPtr prop; + for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) { + fprintf(file," %s= \"%s\";\n",prop->name, + XkbStringText(prop->value,XkbXKBFile)); + } + fprintf(file,"\n"); + } + if (geom->num_shapes>0) { + XkbShapePtr shape; + XkbOutlinePtr outline; + int lastR; + for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) { + lastR=0; + fprintf(file," shape \"%s\" {", + XkbAtomText(shape->name,XkbXKBFile)); + outline= shape->outlines; + if (shape->num_outlines>1) { + for (n=0;n<shape->num_outlines;n++,outline++) { + if (n==0) fprintf(file,"\n"); + else fprintf(file,",\n"); + WriteXKBOutline(file,shape,outline,lastR,8,8); + lastR= outline->corner_radius; + } + fprintf(file,"\n };\n"); + } + else { + WriteXKBOutline(file,NULL,outline,lastR,1,8); + fprintf(file," };\n"); + } + } + } + if (geom->num_sections>0) { + XkbSectionPtr section; + for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){ + WriteXKBSection(file,section,geom); + } + } + if (geom->num_doodads>0) { + XkbDoodadPtr doodad; + for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) { + WriteXKBDoodad(file,4,geom,doodad); + } + } + if (addOn) + (*addOn)(file,xkb,topLevel,showImplicit,XkmGeometryIndex,priv); + fprintf(file,"};\n\n"); + return True; +} diff --git a/xorg-server/xkb/xkbtext.c b/xorg-server/xkb/xkbtext.c new file mode 100644 index 000000000..d08c91589 --- /dev/null +++ b/xorg-server/xkb/xkbtext.c @@ -0,0 +1,1227 @@ +/************************************************************ + Copyright (c) 1994 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 <dix-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#include <X11/Xos.h> + +#include <X11/X.h> +#define NEED_EVENTS +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "xkbstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include <xkbsrv.h> +#include "xkbgeom.h" + +/***====================================================================***/ + +#define BUFFER_SIZE 512 + +static char textBuffer[BUFFER_SIZE]; +static int tbNext= 0; + +static char * +tbGetBuffer(unsigned size) +{ +char *rtrn; + + if (size>=BUFFER_SIZE) + return NULL; + if ((BUFFER_SIZE-tbNext)<=size) + tbNext= 0; + rtrn= &textBuffer[tbNext]; + tbNext+= size; + return rtrn; +} + +/***====================================================================***/ + +char * +XkbAtomText(Atom atm,unsigned format) +{ +char *rtrn,*tmp; + + tmp= XkbAtomGetString(atm); + if (tmp!=NULL) { + int len; + len= strlen(tmp)+1; + if (len>BUFFER_SIZE) + len= BUFFER_SIZE-2; + rtrn= tbGetBuffer(len); + strncpy(rtrn,tmp,len); + rtrn[len]= '\0'; + } + else { + rtrn= tbGetBuffer(1); + rtrn[0]= '\0'; + } + if (format==XkbCFile) { + for (tmp=rtrn;*tmp!='\0';tmp++) { + if ((tmp==rtrn)&&(!isalpha(*tmp))) + *tmp= '_'; + else if (!isalnum(*tmp)) + *tmp= '_'; + } + } + return XkbStringText(rtrn,format); +} + +/***====================================================================***/ + +char * +XkbVModIndexText(XkbDescPtr xkb,unsigned ndx,unsigned format) +{ +register int len; +register Atom *vmodNames; +char *rtrn,*tmp; +char numBuf[20]; + + if (xkb && xkb->names) + vmodNames= xkb->names->vmods; + else vmodNames= NULL; + + tmp= NULL; + if (ndx>=XkbNumVirtualMods) + tmp= "illegal"; + else if (vmodNames&&(vmodNames[ndx]!=None)) + tmp= XkbAtomGetString(vmodNames[ndx]); + if (tmp==NULL) + sprintf(tmp=numBuf,"%d",ndx); + + len= strlen(tmp)+1; + if (format==XkbCFile) + len+= 4; + if (len>=BUFFER_SIZE) + len= BUFFER_SIZE-1; + rtrn= tbGetBuffer(len); + if (format==XkbCFile) { + strcpy(rtrn,"vmod_"); + strncpy(&rtrn[5],tmp,len-4); + } + else strncpy(rtrn,tmp,len); + return rtrn; +} + +char * +XkbVModMaskText( XkbDescPtr xkb, + unsigned modMask, + unsigned mask, + unsigned format) +{ +register int i,bit; +int len; +char *mm,*rtrn; +char *str,buf[BUFFER_SIZE]; + + if ((modMask==0)&&(mask==0)) { + rtrn= tbGetBuffer(5); + if (format==XkbCFile) + sprintf(rtrn,"0"); + else sprintf(rtrn,"none"); + return rtrn; + } + if (modMask!=0) + mm= XkbModMaskText(modMask,format); + else mm= NULL; + + str= buf; + buf[0]= '\0'; + if (mask) { + char *tmp; + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (mask&bit) { + tmp= XkbVModIndexText(xkb,i,format); + len= strlen(tmp)+1+(str==buf?0:1); + if (format==XkbCFile) + len+= 4; + if ((str-(buf+len))<=BUFFER_SIZE) { + if (str!=buf) { + if (format==XkbCFile) *str++= '|'; + else *str++= '+'; + len--; + } + } + if (format==XkbCFile) + sprintf(str,"%sMask",tmp); + else strcpy(str,tmp); + str= &str[len-1]; + } + } + str= buf; + } + else str= NULL; + if (mm) + len= strlen(mm); + else len= 0; + if (str) + len+= strlen(str)+(mm==NULL?0:1); + if (len>=BUFFER_SIZE) + len= BUFFER_SIZE-1; + rtrn= tbGetBuffer(len+1); + rtrn[0]= '\0'; + + if (mm!=NULL) { + i= strlen(mm); + if (i>len) + i= len; + strcpy(rtrn,mm); + } + else { + i=0; + } + if (str!=NULL) { + if (mm!=NULL) { + if (format==XkbCFile) strcat(rtrn,"|"); + else strcat(rtrn,"+"); + } + strncat(rtrn,str,len-i); + } + rtrn[len]= '\0'; + return rtrn; +} + +static char *modNames[XkbNumModifiers] = { + "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" +}; + +char * +XkbModIndexText(unsigned ndx,unsigned format) +{ +char * rtrn; +char buf[100]; + + if (format==XkbCFile) { + if (ndx<XkbNumModifiers) + sprintf(buf,"%sMapIndex",modNames[ndx]); + else if (ndx==XkbNoModifier) + sprintf(buf,"XkbNoModifier"); + else sprintf(buf,"0x%02x",ndx); + } + else { + if (ndx<XkbNumModifiers) + strcpy(buf,modNames[ndx]); + else if (ndx==XkbNoModifier) + strcpy(buf,"none"); + else sprintf(buf,"ILLEGAL_%02x",ndx); + } + rtrn= tbGetBuffer(strlen(buf)+1); + strcpy(rtrn,buf); + return rtrn; +} + +char * +XkbModMaskText(unsigned mask,unsigned format) +{ +register int i,bit; +char buf[64],*rtrn; + + if ((mask&0xff)==0xff) { + if (format==XkbCFile) strcpy(buf,"0xff"); + else strcpy(buf,"all"); + } + else if ((mask&0xff)==0) { + if (format==XkbCFile) strcpy(buf,"0"); + else strcpy(buf,"none"); + } + else { + char *str= buf; + buf[0]= '\0'; + for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { + if (mask&bit) { + if (str!=buf) { + if (format==XkbCFile) *str++= '|'; + else *str++= '+'; + } + strcpy(str,modNames[i]); + str= &str[strlen(str)]; + if (format==XkbCFile) { + strcpy(str,"Mask"); + str+= 4; + } + } + } + } + rtrn= tbGetBuffer(strlen(buf)+1); + strcpy(rtrn,buf); + return rtrn; +} + +/***====================================================================***/ + +/*ARGSUSED*/ +char * +XkbConfigText(unsigned config,unsigned format) +{ +static char *buf; + + buf= tbGetBuffer(32); + switch (config) { + case XkmSemanticsFile: + strcpy(buf,"Semantics"); + break; + case XkmLayoutFile: + strcpy(buf,"Layout"); + break; + case XkmKeymapFile: + strcpy(buf,"Keymap"); + break; + case XkmGeometryFile: + case XkmGeometryIndex: + strcpy(buf,"Geometry"); + break; + case XkmTypesIndex: + strcpy(buf,"Types"); + break; + case XkmCompatMapIndex: + strcpy(buf,"CompatMap"); + break; + case XkmSymbolsIndex: + strcpy(buf,"Symbols"); + break; + case XkmIndicatorsIndex: + strcpy(buf,"Indicators"); + break; + case XkmKeyNamesIndex: + strcpy(buf,"KeyNames"); + break; + case XkmVirtualModsIndex: + strcpy(buf,"VirtualMods"); + break; + default: + sprintf(buf,"unknown(%d)",config); + break; + } + return buf; +} + +/***====================================================================***/ + +char * +XkbKeysymText(KeySym sym,unsigned format) +{ +static char buf[32],*rtrn; + + if (sym==NoSymbol) + strcpy(rtrn=buf,"NoSymbol"); + else sprintf(rtrn=buf, "0x%lx", (long)sym); + return rtrn; +} + +char * +XkbKeyNameText(char *name,unsigned format) +{ +char *buf; + + if (format==XkbCFile) { + buf= tbGetBuffer(5); + memcpy(buf,name,4); + buf[4]= '\0'; + } + else { + int len; + buf= tbGetBuffer(7); + buf[0]= '<'; + memcpy(&buf[1],name,4); + buf[5]= '\0'; + len= strlen(buf); + buf[len++]= '>'; + buf[len]= '\0'; + } + return buf; +} + +/***====================================================================***/ + +static char *siMatchText[5] = { + "NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly" +}; + +char * +XkbSIMatchText(unsigned type,unsigned format) +{ +static char buf[40]; +char *rtrn; + + switch (type&XkbSI_OpMask) { + case XkbSI_NoneOf: rtrn= siMatchText[0]; break; + case XkbSI_AnyOfOrNone: rtrn= siMatchText[1]; break; + case XkbSI_AnyOf: rtrn= siMatchText[2]; break; + case XkbSI_AllOf: rtrn= siMatchText[3]; break; + case XkbSI_Exactly: rtrn= siMatchText[4]; break; + default: sprintf(buf,"0x%x",type&XkbSI_OpMask); + return buf; + } + if (format==XkbCFile) { + if (type&XkbSI_LevelOneOnly) + sprintf(buf,"XkbSI_LevelOneOnly|XkbSI_%s",rtrn); + else sprintf(buf,"XkbSI_%s",rtrn); + rtrn= buf; + } + return rtrn; +} + +/***====================================================================***/ + +static char *imWhichNames[]= { + "base", + "latched", + "locked", + "effective", + "compat" +}; + +char * +XkbIMWhichStateMaskText(unsigned use_which,unsigned format) +{ +int len; +unsigned i,bit,tmp; +char * buf; + + if (use_which==0) { + buf= tbGetBuffer(2); + strcpy(buf,"0"); + return buf; + } + tmp= use_which&XkbIM_UseAnyMods; + for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { + if (tmp&bit) { + tmp&= ~bit; + len+= strlen(imWhichNames[i])+1; + if (format==XkbCFile) + len+= 9; + } + } + buf= tbGetBuffer(len+1); + tmp= use_which&XkbIM_UseAnyMods; + for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { + if (tmp&bit) { + tmp&= ~bit; + if (format==XkbCFile) { + if (len!=0) + buf[len++]= '|'; + sprintf(&buf[len],"XkbIM_Use%s",imWhichNames[i]); + buf[len+9]= toupper(buf[len+9]); + } + else { + if (len!=0) + buf[len++]= '+'; + sprintf(&buf[len],"%s",imWhichNames[i]); + } + len+= strlen(&buf[len]); + } + } + return buf; +} + +static char *ctrlNames[] = { + "repeatKeys", + "slowKeys", + "bounceKeys", + "stickyKeys", + "mouseKeys", + "mouseKeysAccel", + "accessXKeys", + "accessXTimeout", + "accessXFeedback", + "audibleBell", + "overlay1", + "overlay2", + "ignoreGroupLock" +}; + +char * +XkbControlsMaskText(unsigned ctrls,unsigned format) +{ +int len; +unsigned i,bit,tmp; +char * buf; + + if (ctrls==0) { + buf= tbGetBuffer(5); + if (format==XkbCFile) + strcpy(buf,"0"); + else strcpy(buf,"none"); + return buf; + } + tmp= ctrls&XkbAllBooleanCtrlsMask; + for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { + if (tmp&bit) { + tmp&= ~bit; + len+= strlen(ctrlNames[i])+1; + if (format==XkbCFile) + len+= 7; + } + } + buf= tbGetBuffer(len+1); + tmp= ctrls&XkbAllBooleanCtrlsMask; + for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { + if (tmp&bit) { + tmp&= ~bit; + if (format==XkbCFile) { + if (len!=0) + buf[len++]= '|'; + sprintf(&buf[len],"Xkb%sMask",ctrlNames[i]); + buf[len+3]= toupper(buf[len+3]); + } + else { + if (len!=0) + buf[len++]= '+'; + sprintf(&buf[len],"%s",ctrlNames[i]); + } + len+= strlen(&buf[len]); + } + } + return buf; +} + +/***====================================================================***/ + +char * +XkbStringText(char *str,unsigned format) +{ +char * buf; +register char *in,*out; +int len; +Bool ok; + + if (str==NULL) { + buf= tbGetBuffer(2); + buf[0]='\0'; + return buf; + } + else if (format==XkbXKMFile) + return str; + for (ok= True,len=0,in=str;*in!='\0';in++,len++) { + if (!isprint(*in)) { + ok= False; + switch (*in) { + case '\n': case '\t': case '\v': + case '\b': case '\r': case '\f': + len++; + break; + default: + len+= 4; + break; + } + } + } + if (ok) + return str; + buf= tbGetBuffer(len+1); + for (in=str,out=buf;*in!='\0';in++) { + if (isprint(*in)) + *out++= *in; + else { + *out++= '\\'; + if (*in=='\n') *out++= 'n'; + else if (*in=='\t') *out++= 't'; + else if (*in=='\v') *out++= 'v'; + else if (*in=='\b') *out++= 'b'; + else if (*in=='\r') *out++= 'r'; + else if (*in=='\f') *out++= 'f'; + else if ((*in=='\033')&&(format==XkbXKMFile)) { + *out++= 'e'; + } + else { + *out++= '0'; + sprintf(out,"%o",*in); + while (*out!='\0') + out++; + } + } + } + *out++= '\0'; + return buf; +} + +/***====================================================================***/ + +char * +XkbGeomFPText(int val,unsigned format) +{ +int whole,frac; +char * buf; + + buf= tbGetBuffer(12); + if (format==XkbCFile) { + sprintf(buf,"%d",val); + } + else { + whole= val/XkbGeomPtsPerMM; + frac= val%XkbGeomPtsPerMM; + if (frac!=0) + sprintf(buf,"%d.%d",whole,frac); + else sprintf(buf,"%d",whole); + } + return buf; +} + +char * +XkbDoodadTypeText(unsigned type,unsigned format) +{ +char * buf; + if (format==XkbCFile) { + buf= tbGetBuffer(24); + if (type==XkbOutlineDoodad) strcpy(buf,"XkbOutlineDoodad"); + else if (type==XkbSolidDoodad) strcpy(buf,"XkbSolidDoodad"); + else if (type==XkbTextDoodad) strcpy(buf,"XkbTextDoodad"); + else if (type==XkbIndicatorDoodad) strcpy(buf,"XkbIndicatorDoodad"); + else if (type==XkbLogoDoodad) strcpy(buf,"XkbLogoDoodad"); + else sprintf(buf,"UnknownDoodad%d",type); + } + else { + buf= tbGetBuffer(12); + if (type==XkbOutlineDoodad) strcpy(buf,"outline"); + else if (type==XkbSolidDoodad) strcpy(buf,"solid"); + else if (type==XkbTextDoodad) strcpy(buf,"text"); + else if (type==XkbIndicatorDoodad) strcpy(buf,"indicator"); + else if (type==XkbLogoDoodad) strcpy(buf,"logo"); + else sprintf(buf,"unknown%d",type); + } + return buf; +} + +static char *actionTypeNames[XkbSA_NumActions]= { + "NoAction", + "SetMods", "LatchMods", "LockMods", + "SetGroup", "LatchGroup", "LockGroup", + "MovePtr", + "PtrBtn", "LockPtrBtn", + "SetPtrDflt", + "ISOLock", + "Terminate", "SwitchScreen", + "SetControls", "LockControls", + "ActionMessage", + "RedirectKey", + "DeviceBtn", "LockDeviceBtn" +}; + +char * +XkbActionTypeText(unsigned type,unsigned format) +{ +static char buf[32]; +char *rtrn; + + if (type<=XkbSA_LastAction) { + rtrn= actionTypeNames[type]; + if (format==XkbCFile) { + sprintf(buf,"XkbSA_%s",rtrn); + return buf; + } + return rtrn; + } + sprintf(buf,"Private"); + return buf; +} + +/***====================================================================***/ + +static int +TryCopyStr(char *to,char *from,int *pLeft) +{ +register int len; + if (*pLeft>0) { + len= strlen(from); + if (len<((*pLeft)-3)) { + strcat(to,from); + *pLeft-= len; + return True; + } + } + *pLeft= -1; + return False; +} + +/*ARGSUSED*/ +static Bool +CopyNoActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int*sz) +{ + return True; +} + +static Bool +CopyModActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf, + int* sz) +{ +XkbModAction * act; +unsigned tmp; + + act= &action->mods; + tmp= XkbModActionVMods(act); + TryCopyStr(buf,"modifiers=",sz); + if (act->flags&XkbSA_UseModMapMods) + TryCopyStr(buf,"modMapMods",sz); + else if (act->real_mods || tmp) { + TryCopyStr(buf, + XkbVModMaskText(xkb,act->real_mods,tmp,XkbXKBFile), + sz); + } + else TryCopyStr(buf,"none",sz); + if (act->type==XkbSA_LockMods) + return True; + if (act->flags&XkbSA_ClearLocks) + TryCopyStr(buf,",clearLocks",sz); + if (act->flags&XkbSA_LatchToLock) + TryCopyStr(buf,",latchToLock",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +CopyGroupActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +{ +XkbGroupAction * act; +char tbuf[32]; + + act= &action->group; + TryCopyStr(buf,"group=",sz); + if (act->flags&XkbSA_GroupAbsolute) + sprintf(tbuf,"%d",XkbSAGroup(act)+1); + else if (XkbSAGroup(act)<0) + sprintf(tbuf,"%d",XkbSAGroup(act)); + else sprintf(tbuf,"+%d",XkbSAGroup(act)); + TryCopyStr(buf,tbuf,sz); + if (act->type==XkbSA_LockGroup) + return True; + if (act->flags&XkbSA_ClearLocks) + TryCopyStr(buf,",clearLocks",sz); + if (act->flags&XkbSA_LatchToLock) + TryCopyStr(buf,",latchToLock",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +CopyMovePtrArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +{ +XkbPtrAction * act; +int x,y; +char tbuf[32]; + + act= &action->ptr; + x= XkbPtrActionX(act); + y= XkbPtrActionY(act); + if ((act->flags&XkbSA_MoveAbsoluteX)||(x<0)) + sprintf(tbuf,"x=%d",x); + else sprintf(tbuf,"x=+%d",x); + TryCopyStr(buf,tbuf,sz); + + if ((act->flags&XkbSA_MoveAbsoluteY)||(y<0)) + sprintf(tbuf,",y=%d",y); + else sprintf(tbuf,",y=+%d",y); + TryCopyStr(buf,tbuf,sz); + if (act->flags&XkbSA_NoAcceleration) + TryCopyStr(buf,",!accel",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +CopyPtrBtnArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +{ +XkbPtrBtnAction * act; +char tbuf[32]; + + act= &action->btn; + TryCopyStr(buf,"button=",sz); + if ((act->button>0)&&(act->button<6)) { + sprintf(tbuf,"%d",act->button); + TryCopyStr(buf,tbuf,sz); + } + else TryCopyStr(buf,"default",sz); + if (act->count>0) { + sprintf(tbuf,",count=%d",act->count); + TryCopyStr(buf,tbuf,sz); + } + if (action->type==XkbSA_LockPtrBtn) { + switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) { + case XkbSA_LockNoLock: + sprintf(tbuf,",affect=unlock"); break; + case XkbSA_LockNoUnlock: + sprintf(tbuf,",affect=lock"); break; + case XkbSA_LockNoUnlock|XkbSA_LockNoLock: + sprintf(tbuf,",affect=neither"); break; + default: + sprintf(tbuf,",affect=both"); break; + } + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +/*ARGSUSED*/ +static Bool +CopySetPtrDfltArgs(XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +{ +XkbPtrDfltAction * act; +char tbuf[32]; + + act= &action->dflt; + if (act->affect==XkbSA_AffectDfltBtn) { + TryCopyStr(buf,"affect=button,button=",sz); + if ((act->flags&XkbSA_DfltBtnAbsolute)||(XkbSAPtrDfltValue(act)<0)) + sprintf(tbuf,"%d",XkbSAPtrDfltValue(act)); + else sprintf(tbuf,"+%d",XkbSAPtrDfltValue(act)); + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +static Bool +CopyISOLockArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +{ +XkbISOAction * act; +char tbuf[64]; + + act= &action->iso; + if (act->flags&XkbSA_ISODfltIsGroup) { + TryCopyStr(tbuf,"group=",sz); + if (act->flags&XkbSA_GroupAbsolute) + sprintf(tbuf,"%d",XkbSAGroup(act)+1); + else if (XkbSAGroup(act)<0) + sprintf(tbuf,"%d",XkbSAGroup(act)); + else sprintf(tbuf,"+%d",XkbSAGroup(act)); + TryCopyStr(buf,tbuf,sz); + } + else { + unsigned tmp; + tmp= XkbModActionVMods(act); + TryCopyStr(buf,"modifiers=",sz); + if (act->flags&XkbSA_UseModMapMods) + TryCopyStr(buf,"modMapMods",sz); + else if (act->real_mods || tmp) { + if (act->real_mods) { + TryCopyStr(buf,XkbModMaskText(act->real_mods,XkbXKBFile),sz); + if (tmp) + TryCopyStr(buf,"+",sz); + } + if (tmp) + TryCopyStr(buf,XkbVModMaskText(xkb,0,tmp,XkbXKBFile),sz); + } + else TryCopyStr(buf,"none",sz); + } + TryCopyStr(buf,",affect=",sz); + if ((act->affect&XkbSA_ISOAffectMask)==0) + TryCopyStr(buf,"all",sz); + else { + int nOut= 0; + if ((act->affect&XkbSA_ISONoAffectMods)==0) { + TryCopyStr(buf,"mods",sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectGroup)==0) { + sprintf(tbuf,"%sgroups",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectPtr)==0) { + sprintf(tbuf,"%spointer",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectCtrls)==0) { + sprintf(tbuf,"%scontrols",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +CopySwitchScreenArgs(XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +{ +XkbSwitchScreenAction * act; +char tbuf[32]; + + act= &action->screen; + if ((act->flags&XkbSA_SwitchAbsolute)||(XkbSAScreen(act)<0)) + sprintf(tbuf,"screen=%d",XkbSAScreen(act)); + else sprintf(tbuf,"screen=+%d",XkbSAScreen(act)); + TryCopyStr(buf,tbuf,sz); + if (act->flags&XkbSA_SwitchApplication) + TryCopyStr(buf,",!same",sz); + else TryCopyStr(buf,",same",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +CopySetLockControlsArgs(XkbDescPtr xkb,XkbAction *action, + char *buf,int *sz) +{ +XkbCtrlsAction * act; +unsigned tmp; +char tbuf[32]; + + act= &action->ctrls; + tmp= XkbActionCtrls(act); + TryCopyStr(buf,"controls=",sz); + if (tmp==0) + TryCopyStr(buf,"none",sz); + else if ((tmp&XkbAllBooleanCtrlsMask)==XkbAllBooleanCtrlsMask) + TryCopyStr(buf,"all",sz); + else { + int nOut= 0; + if (tmp&XkbRepeatKeysMask) { + sprintf(tbuf,"%sRepeatKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbSlowKeysMask) { + sprintf(tbuf,"%sSlowKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbBounceKeysMask) { + sprintf(tbuf,"%sBounceKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbStickyKeysMask) { + sprintf(tbuf,"%sStickyKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbMouseKeysMask) { + sprintf(tbuf,"%sMouseKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbMouseKeysAccelMask) { + sprintf(tbuf,"%sMouseKeysAccel",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXKeysMask) { + sprintf(tbuf,"%sAccessXKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXTimeoutMask) { + sprintf(tbuf,"%sAccessXTimeout",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXFeedbackMask) { + sprintf(tbuf,"%sAccessXFeedback",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAudibleBellMask) { + sprintf(tbuf,"%sAudibleBell",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbOverlay1Mask) { + sprintf(tbuf,"%sOverlay1",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbOverlay2Mask) { + sprintf(tbuf,"%sOverlay2",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbIgnoreGroupLockMask) { + sprintf(tbuf,"%sIgnoreGroupLock",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +CopyActionMessageArgs(XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +{ +XkbMessageAction * act; +unsigned all; +char tbuf[32]; + + act= &action->msg; + all= XkbSA_MessageOnPress|XkbSA_MessageOnRelease; + TryCopyStr(buf,"report=",sz); + if ((act->flags&all)==0) + TryCopyStr(buf,"none",sz); + else if ((act->flags&all)==all) + TryCopyStr(buf,"all",sz); + else if (act->flags&XkbSA_MessageOnPress) + TryCopyStr(buf,"KeyPress",sz); + else TryCopyStr(buf,"KeyRelease",sz); + sprintf(tbuf,",data[0]=0x%02x",act->message[0]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[1]=0x%02x",act->message[1]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[2]=0x%02x",act->message[2]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[3]=0x%02x",act->message[3]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[4]=0x%02x",act->message[4]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[5]=0x%02x",act->message[5]); TryCopyStr(buf,tbuf,sz); + return True; +} + +static Bool +CopyRedirectKeyArgs(XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +{ +XkbRedirectKeyAction * act; +char tbuf[32],*tmp; +unsigned kc; +unsigned vmods,vmods_mask; + + act= &action->redirect; + kc= act->new_key; + vmods= XkbSARedirectVMods(act); + vmods_mask= XkbSARedirectVModsMask(act); + if (xkb && xkb->names && xkb->names->keys && (kc<=xkb->max_key_code) && + (xkb->names->keys[kc].name[0]!='\0')) { + char *kn; + kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile); + sprintf(tbuf,"key=%s",kn); + } + else sprintf(tbuf,"key=%d",kc); + TryCopyStr(buf,tbuf,sz); + if ((act->mods_mask==0)&&(vmods_mask==0)) + return True; + if ((act->mods_mask==XkbAllModifiersMask)&& + (vmods_mask==XkbAllVirtualModsMask)) { + tmp= XkbVModMaskText(xkb,act->mods,vmods,XkbXKBFile); + TryCopyStr(buf,",mods=",sz); + TryCopyStr(buf,tmp,sz); + } + else { + if ((act->mods_mask&act->mods)||(vmods_mask&vmods)) { + tmp= XkbVModMaskText(xkb,act->mods_mask&act->mods, + vmods_mask&vmods,XkbXKBFile); + TryCopyStr(buf,",mods= ",sz); + TryCopyStr(buf,tmp,sz); + } + if ((act->mods_mask&(~act->mods))||(vmods_mask&(~vmods))) { + tmp= XkbVModMaskText(xkb,act->mods_mask&(~act->mods), + vmods_mask&(~vmods),XkbXKBFile); + TryCopyStr(buf,",clearMods= ",sz); + TryCopyStr(buf,tmp,sz); + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +CopyDeviceBtnArgs(XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +{ +XkbDeviceBtnAction * act; +char tbuf[32]; + + act= &action->devbtn; + sprintf(tbuf,"device= %d",act->device); TryCopyStr(buf,tbuf,sz); + TryCopyStr(buf,",button=",sz); + sprintf(tbuf,"%d",act->button); + TryCopyStr(buf,tbuf,sz); + if (act->count>0) { + sprintf(tbuf,",count=%d",act->count); + TryCopyStr(buf,tbuf,sz); + } + if (action->type==XkbSA_LockDeviceBtn) { + switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) { + case XkbSA_LockNoLock: + sprintf(tbuf,",affect=unlock"); break; + case XkbSA_LockNoUnlock: + sprintf(tbuf,",affect=lock"); break; + case XkbSA_LockNoUnlock|XkbSA_LockNoLock: + sprintf(tbuf,",affect=neither"); break; + default: + sprintf(tbuf,",affect=both"); break; + } + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +/*ARGSUSED*/ +static Bool +CopyOtherArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +{ +XkbAnyAction * act; +char tbuf[32]; + + act= &action->any; + sprintf(tbuf,"type=0x%02x",act->type); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[0]=0x%02x",act->data[0]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[1]=0x%02x",act->data[1]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[2]=0x%02x",act->data[2]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[3]=0x%02x",act->data[3]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[4]=0x%02x",act->data[4]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[5]=0x%02x",act->data[5]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[6]=0x%02x",act->data[6]); TryCopyStr(buf,tbuf,sz); + return True; +} + +typedef Bool (*actionCopy)( + XkbDescPtr /* xkb */, + XkbAction * /* action */, + char * /* buf */, + int* /* sz */ +); +static actionCopy copyActionArgs[XkbSA_NumActions] = { + CopyNoActionArgs /* NoAction */, + CopyModActionArgs /* SetMods */, + CopyModActionArgs /* LatchMods */, + CopyModActionArgs /* LockMods */, + CopyGroupActionArgs /* SetGroup */, + CopyGroupActionArgs /* LatchGroup */, + CopyGroupActionArgs /* LockGroup */, + CopyMovePtrArgs /* MovePtr */, + CopyPtrBtnArgs /* PtrBtn */, + CopyPtrBtnArgs /* LockPtrBtn */, + CopySetPtrDfltArgs /* SetPtrDflt */, + CopyISOLockArgs /* ISOLock */, + CopyNoActionArgs /* Terminate */, + CopySwitchScreenArgs /* SwitchScreen */, + CopySetLockControlsArgs /* SetControls */, + CopySetLockControlsArgs /* LockControls */, + CopyActionMessageArgs /* ActionMessage*/, + CopyRedirectKeyArgs /* RedirectKey */, + CopyDeviceBtnArgs /* DeviceBtn */, + CopyDeviceBtnArgs /* LockDeviceBtn*/ +}; + +#define ACTION_SZ 256 + +char * +XkbActionText(XkbDescPtr xkb,XkbAction *action,unsigned format) +{ +char buf[ACTION_SZ],*tmp; +int sz; + + if (format==XkbCFile) { + sprintf(buf, + "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }", + XkbActionTypeText(action->type,XkbCFile), + action->any.data[0],action->any.data[1],action->any.data[2], + action->any.data[3],action->any.data[4],action->any.data[5], + action->any.data[6]); + } + else { + sprintf(buf,"%s(",XkbActionTypeText(action->type,XkbXKBFile)); + sz= ACTION_SZ-strlen(buf)+2; /* room for close paren and NULL */ + if (action->type<(unsigned)XkbSA_NumActions) + (*copyActionArgs[action->type])(xkb,action,buf,&sz); + else CopyOtherArgs(xkb,action,buf,&sz); + TryCopyStr(buf,")",&sz); + } + tmp= tbGetBuffer(strlen(buf)+1); + if (tmp!=NULL) + strcpy(tmp,buf); + return tmp; +} + +char * +XkbBehaviorText(XkbDescPtr xkb,XkbBehavior *behavior,unsigned format) +{ +char buf[256],*tmp; + + if (format==XkbCFile) { + if (behavior->type==XkbKB_Default) + sprintf(buf,"{ 0, 0 }"); + else sprintf(buf,"{ %3d, 0x%02x }",behavior->type,behavior->data); + } + else { + unsigned type,permanent; + type= behavior->type&XkbKB_OpMask; + permanent=((behavior->type&XkbKB_Permanent)!=0); + + if (type==XkbKB_Lock) { + sprintf(buf,"lock= %s",(permanent?"Permanent":"True")); + } + else if (type==XkbKB_RadioGroup) { + int g; + char *tmp; + g= ((behavior->data)&(~XkbKB_RGAllowNone))+1; + if (XkbKB_RGAllowNone&behavior->data) { + sprintf(buf,"allowNone,"); + tmp= &buf[strlen(buf)]; + } + else tmp= buf; + if (permanent) + sprintf(tmp,"permanentRadioGroup= %d",g); + else sprintf(tmp,"radioGroup= %d",g); + } + else if ((type==XkbKB_Overlay1)||(type==XkbKB_Overlay2)) { + int ndx,kc; + char *kn; + + ndx= ((type==XkbKB_Overlay1)?1:2); + kc= behavior->data; + if ((xkb)&&(xkb->names)&&(xkb->names->keys)) + kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile); + else { + static char tbuf[8]; + sprintf(tbuf,"%d",kc); + kn= tbuf; + } + if (permanent) + sprintf(buf,"permanentOverlay%d= %s",ndx,kn); + else sprintf(buf,"overlay%d= %s",ndx,kn); + } + } + tmp= tbGetBuffer(strlen(buf)+1); + if (tmp!=NULL) + strcpy(tmp,buf); + return tmp; +} + +/***====================================================================***/ + +char * +XkbIndentText(unsigned size) +{ +static char buf[32]; +register int i; + + if (size>31) + size= 31; + + for (i=0;i<size;i++) { + buf[i]= ' '; + } + buf[size]= '\0'; + return buf; +} diff --git a/xorg-server/xkb/xkmread.c b/xorg-server/xkb/xkmread.c new file mode 100644 index 000000000..b14a5beda --- /dev/null +++ b/xorg-server/xkb/xkmread.c @@ -0,0 +1,1148 @@ +/************************************************************ + Copyright (c) 1994 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 <dix-config.h> +#endif + +#include <stdio.h> + +#include <X11/Xos.h> +#include <X11/Xfuncs.h> + +#include <X11/X.h> +#define NEED_EVENTS +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "xkbstr.h" +#include "xkbsrv.h" +#include "xkbgeom.h" + +Atom +XkbInternAtom(char *str,Bool only_if_exists) +{ + if (str==NULL) + return None; + return MakeAtom(str,strlen(str),!only_if_exists); +} + +char * +_XkbDupString(char *str) +{ +char *new; + + if (str==NULL) + return NULL; + new= (char *)_XkbCalloc(strlen(str)+1,sizeof(char)); + if (new) + strcpy(new,str); + return new; +} + +/***====================================================================***/ + +static void * +XkmInsureSize(void *oldPtr,int oldCount,int *newCountRtrn,int elemSize) +{ +int newCount= *newCountRtrn; + + if (oldPtr==NULL) { + if (newCount==0) + return NULL; + oldPtr= _XkbCalloc(newCount,elemSize); + } + else if (oldCount<newCount) { + oldPtr= _XkbRealloc(oldPtr,newCount*elemSize); + if (oldPtr!=NULL) { + char *tmp= (char *)oldPtr; + bzero(&tmp[oldCount*elemSize],(newCount-oldCount)*elemSize); + } + } + else if (newCount<oldCount) { + *newCountRtrn= oldCount; + } + return oldPtr; +} + +#define XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t)))) + +static CARD8 +XkmGetCARD8(FILE *file,int *pNRead) +{ +int tmp; + tmp= getc(file); + if (pNRead&&(tmp!=EOF)) + (*pNRead)+= 1; + return tmp; +} + +static CARD16 +XkmGetCARD16(FILE *file,int *pNRead) +{ +CARD16 val; + + if ((fread(&val,2,1,file)==1)&&(pNRead)) + (*pNRead)+= 2; + return val; +} + +static CARD32 +XkmGetCARD32(FILE *file,int *pNRead) +{ +CARD32 val; + + if ((fread(&val,4,1,file)==1)&&(pNRead)) + (*pNRead)+= 4; + return val; +} + +static int +XkmSkipPadding(FILE *file,unsigned pad) +{ +register int i,nRead=0; + + for (i=0;i<pad;i++) { + if (getc(file)!=EOF) + nRead++; + } + return nRead; +} + +static int +XkmGetCountedString(FILE *file,char *str,int max_len) +{ +int count,nRead=0; + + count= XkmGetCARD16(file,&nRead); + if (count>0) { + int tmp; + if (count>max_len) { + tmp= fread(str,1,max_len,file); + while (tmp<count) { + if ((getc(file))!=EOF) + tmp++; + else break; + } + } + else { + tmp= fread(str,1,count,file); + } + nRead+= tmp; + } + if (count>=max_len) str[max_len-1]= '\0'; + else str[count]= '\0'; + count= XkbPaddedSize(nRead)-nRead; + if (count>0) + nRead+= XkmSkipPadding(file,count); + return nRead; +} + +/***====================================================================***/ + +static int +ReadXkmVirtualMods(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register unsigned int i,bit; +unsigned int bound,named,tmp; +int nRead=0; + + if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); + return -1; + } + bound= XkmGetCARD16(file,&nRead); + named= XkmGetCARD16(file,&nRead); + for (i=tmp=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (bound&bit) { + xkb->server->vmods[i]= XkmGetCARD8(file,&nRead); + if (changes) + changes->map.vmods|= bit; + tmp++; + } + } + if ((i= XkbPaddedSize(tmp)-tmp)>0) + nRead+= XkmSkipPadding(file,i); + if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); + return -1; + } + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + char name[100]; + if (named&bit) { + if (nRead+=XkmGetCountedString(file,name,100)) { + xkb->names->vmods[i]= XkbInternAtom(name,False); + if (changes) + changes->names.changed_vmods|= bit; + } + } + } + return nRead; +} + +/***====================================================================***/ + +static int +ReadXkmKeycodes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register int i; +unsigned minKC,maxKC,nAl; +int nRead=0; +char name[100]; +XkbKeyNamePtr pN; + + name[0]= '\0'; + nRead+= XkmGetCountedString(file,name,100); + minKC= XkmGetCARD8(file,&nRead); + maxKC= XkmGetCARD8(file,&nRead); + if (xkb->min_key_code==0) { + xkb->min_key_code= minKC; + xkb->max_key_code= maxKC; + } + else { + if (minKC<xkb->min_key_code) + xkb->min_key_code= minKC; + if (maxKC>xkb->max_key_code) { + _XkbLibError(_XkbErrBadValue,"ReadXkmKeycodes",maxKC); + return -1; + } + } + nAl= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,1); + +#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask) + if (XkbAllocNames(xkb,WANTED,0,nAl)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); + return -1; + } + if (name[0]!='\0') { + xkb->names->keycodes= XkbInternAtom(name,False); + } + + for (pN=&xkb->names->keys[minKC],i=minKC;i<=(int)maxKC;i++,pN++) { + if (fread(pN,1,XkbKeyNameLength,file)!=XkbKeyNameLength) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= XkbKeyNameLength; + } + if (nAl>0) { + XkbKeyAliasPtr pAl; + for (pAl= xkb->names->key_aliases,i=0;i<nAl;i++,pAl++) { + int tmp; + tmp= fread(pAl,1,2*XkbKeyNameLength,file); + if (tmp!=2*XkbKeyNameLength) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= 2*XkbKeyNameLength; + } + if (changes) + changes->names.changed|= XkbKeyAliasesMask; + } + if (changes) + changes->names.changed|= XkbKeyNamesMask; + return nRead; +} + +/***====================================================================***/ + +static int +ReadXkmKeyTypes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register unsigned i,n; +unsigned num_types; +int nRead=0; +int tmp; +XkbKeyTypePtr type; +xkmKeyTypeDesc wire; +XkbKTMapEntryPtr entry; +xkmKTMapEntryDesc wire_entry; +char buf[100]; + + if ((tmp= XkmGetCountedString(file,buf,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= tmp; + if (buf[0]!='\0') { + if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); + return -1; + } + xkb->names->types= XkbInternAtom(buf,False); + } + num_types= XkmGetCARD16(file,&nRead); + nRead+= XkmSkipPadding(file,2); + if (num_types<1) + return nRead; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_types)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); + return nRead; + } + xkb->map->num_types= num_types; + if (num_types<XkbNumRequiredTypes) { + _XkbLibError(_XkbErrMissingReqTypes,"ReadXkmKeyTypes",0); + return -1; + } + type= xkb->map->types; + for (i=0;i<num_types;i++,type++) { + if ((int)fread(&wire,SIZEOF(xkmKeyTypeDesc),1,file)<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= SIZEOF(xkmKeyTypeDesc); + if (((i==XkbOneLevelIndex)&&(wire.numLevels!=1))|| + (((i==XkbTwoLevelIndex)||(i==XkbAlphabeticIndex)|| + ((i)==XkbKeypadIndex))&&(wire.numLevels!=2))) { + _XkbLibError(_XkbErrBadTypeWidth,"ReadXkmKeyTypes",i); + return -1; + } + tmp= wire.nMapEntries; + XkmInsureTypedSize(type->map,type->map_count,&tmp,XkbKTMapEntryRec); + if ((wire.nMapEntries>0)&&(type->map==NULL)) { + _XkbLibError(_XkbErrBadValue,"ReadXkmKeyTypes",wire.nMapEntries); + return -1; + } + for (n=0,entry= type->map;n<wire.nMapEntries;n++,entry++) { + if (fread(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file)<(int)1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= SIZEOF(xkmKTMapEntryDesc); + entry->active= (wire_entry.virtualMods==0); + entry->level= wire_entry.level; + entry->mods.mask= wire_entry.realMods; + entry->mods.real_mods= wire_entry.realMods; + entry->mods.vmods= wire_entry.virtualMods; + } + nRead+= XkmGetCountedString(file,buf,100); + if (((i==XkbOneLevelIndex)&&(strcmp(buf,"ONE_LEVEL")!=0))|| + ((i==XkbTwoLevelIndex)&&(strcmp(buf,"TWO_LEVEL")!=0))|| + ((i==XkbAlphabeticIndex)&&(strcmp(buf,"ALPHABETIC")!=0))|| + ((i==XkbKeypadIndex)&&(strcmp(buf,"KEYPAD")!=0))) { + _XkbLibError(_XkbErrBadTypeName,"ReadXkmKeyTypes",0); + return -1; + } + if (buf[0]!='\0') { + type->name= XkbInternAtom(buf,False); + } + else type->name= None; + + if (wire.preserve) { + xkmModsDesc p_entry; + XkbModsPtr pre; + XkmInsureTypedSize(type->preserve,type->map_count,&tmp, + XkbModsRec); + if (type->preserve==NULL) { + _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); + return -1; + } + for (n=0,pre=type->preserve;n<wire.nMapEntries;n++,pre++) { + if (fread(&p_entry,SIZEOF(xkmModsDesc),1,file)<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= SIZEOF(xkmModsDesc); + pre->mask= p_entry.realMods; + pre->real_mods= p_entry.realMods; + pre->vmods= p_entry.virtualMods; + } + } + if (wire.nLevelNames>0) { + int width= wire.numLevels; + if (wire.nLevelNames>(unsigned)width) { + _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); + return -1; + } + XkmInsureTypedSize(type->level_names,type->num_levels,&width,Atom); + if (type->level_names!=NULL) { + for (n=0;n<wire.nLevelNames;n++) { + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + if (strlen(buf)==0) + type->level_names[n]= None; + else type->level_names[n]= XkbInternAtom(buf,0); + } + } + } + type->mods.mask= wire.realMods; + type->mods.real_mods= wire.realMods; + type->mods.vmods= wire.virtualMods; + type->num_levels= wire.numLevels; + type->map_count= wire.nMapEntries; + } + if (changes) { + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type= 0; + changes->map.num_types= xkb->map->num_types; + } + return nRead; +} + +/***====================================================================***/ + +static int +ReadXkmCompatMap(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register int i; +unsigned num_si,groups; +char name[100]; +XkbSymInterpretPtr interp; +xkmSymInterpretDesc wire; +unsigned tmp; +int nRead=0; +XkbCompatMapPtr compat; + + if ((tmp= XkmGetCountedString(file,name,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmCompatMap",0); + return -1; + } + nRead+= tmp; + if (name[0]!='\0') { + if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmCompatMap",0); + return -1; + } + xkb->names->compat= XkbInternAtom(name,False); + } + num_si= XkmGetCARD16(file,&nRead); + groups= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,1); + if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success) + return -1; + compat= xkb->compat; + compat->num_si= num_si; + interp= compat->sym_interpret; + for (i=0;i<num_si;i++,interp++) { + tmp= fread(&wire,SIZEOF(xkmSymInterpretDesc),1,file); + nRead+= tmp*SIZEOF(xkmSymInterpretDesc); + interp->sym= wire.sym; + interp->mods= wire.mods; + interp->match= wire.match; + interp->virtual_mod= wire.virtualMod; + interp->flags= wire.flags; + interp->act.type= wire.actionType; + interp->act.data[0]= wire.actionData[0]; + interp->act.data[1]= wire.actionData[1]; + interp->act.data[2]= wire.actionData[2]; + interp->act.data[3]= wire.actionData[3]; + interp->act.data[4]= wire.actionData[4]; + interp->act.data[5]= wire.actionData[5]; + interp->act.data[6]= wire.actionData[6]; + } + if ((num_si>0)&&(changes)) { + changes->compat.first_si= 0; + changes->compat.num_si= num_si; + } + if (groups) { + register unsigned bit; + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + xkmModsDesc md; + if (groups&bit) { + tmp= fread(&md,SIZEOF(xkmModsDesc),1,file); + nRead+= tmp*SIZEOF(xkmModsDesc); + xkb->compat->groups[i].real_mods= md.realMods; + xkb->compat->groups[i].vmods= md.virtualMods; + if (md.virtualMods != 0) { + unsigned mask; + if (XkbVirtualModsToReal(xkb,md.virtualMods,&mask)) + xkb->compat->groups[i].mask= md.realMods|mask; + } + else xkb->compat->groups[i].mask= md.realMods; + } + } + if (changes) + changes->compat.changed_groups|= groups; + } + return nRead; +} + +static int +ReadXkmIndicators(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register unsigned nLEDs; +xkmIndicatorMapDesc wire; +char buf[100]; +unsigned tmp; +int nRead=0; + + if ((xkb->indicators==NULL)&&(XkbAllocIndicatorMaps(xkb)!=Success)) { + _XkbLibError(_XkbErrBadAlloc,"indicator rec",0); + return -1; + } + if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"indicator names",0); + return -1; + } + nLEDs= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,3); + xkb->indicators->phys_indicators= XkmGetCARD32(file,&nRead); + while (nLEDs-->0) { + Atom name; + XkbIndicatorMapPtr map; + + if ((tmp=XkmGetCountedString(file,buf,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); + return -1; + } + nRead+= tmp; + if (buf[0]!='\0') + name= XkbInternAtom(buf,False); + else name= None; + if ((tmp=fread(&wire,SIZEOF(xkmIndicatorMapDesc),1,file))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); + return -1; + } + nRead+= tmp*SIZEOF(xkmIndicatorMapDesc); + if (xkb->names) { + xkb->names->indicators[wire.indicator-1]= name; + if (changes) + changes->names.changed_indicators|= (1<<(wire.indicator-1)); + } + map= &xkb->indicators->maps[wire.indicator-1]; + map->flags= wire.flags; + map->which_groups= wire.which_groups; + map->groups= wire.groups; + map->which_mods= wire.which_mods; + map->mods.mask= wire.real_mods; + map->mods.real_mods= wire.real_mods; + map->mods.vmods= wire.vmods; + map->ctrls= wire.ctrls; + } + return nRead; +} + +static XkbKeyTypePtr +FindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym *syms) +{ + if ((!xkb)||(!xkb->map)) + return NULL; + if (name!=None) { + register unsigned i; + for (i=0;i<xkb->map->num_types;i++) { + if (xkb->map->types[i].name==name) { + if (xkb->map->types[i].num_levels!=width) + DebugF("Group width mismatch between key and type\n"); + return &xkb->map->types[i]; + } + } + } + if ((width<2)||((syms!=NULL)&&(syms[1]==NoSymbol))) + return &xkb->map->types[XkbOneLevelIndex]; + if (syms!=NULL) { + if (XkbKSIsLower(syms[0])&&XkbKSIsUpper(syms[1])) + return &xkb->map->types[XkbAlphabeticIndex]; + else if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1])) + return &xkb->map->types[XkbKeypadIndex]; + } + return &xkb->map->types[XkbTwoLevelIndex]; +} + +static int +ReadXkmSymbols(FILE *file,XkbDescPtr xkb) +{ +register int i,g,s,totalVModMaps; +xkmKeySymMapDesc wireMap; +char buf[100]; +unsigned minKC,maxKC,groupNames,tmp; +int nRead=0; + + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + minKC= XkmGetCARD8(file,&nRead); + maxKC= XkmGetCARD8(file,&nRead); + groupNames= XkmGetCARD8(file,&nRead); + totalVModMaps= XkmGetCARD8(file,&nRead); + if (XkbAllocNames(xkb, + XkbSymbolsNameMask|XkbPhysSymbolsNameMask|XkbGroupNamesMask, + 0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"physical names",0); + return -1; + } + if ((buf[0]!='\0')&&(xkb->names)) { + Atom name; + name= XkbInternAtom(buf,0); + xkb->names->symbols= name; + xkb->names->phys_symbols= name; + } + for (i=0,g=1;i<XkbNumKbdGroups;i++,g<<=1) { + if (groupNames&g) { + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + if ((buf[0]!='\0')&&(xkb->names)) { + Atom name; + name= XkbInternAtom(buf,0); + xkb->names->groups[i]= name; + } + else xkb->names->groups[i]= None; + } + } + if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"server map",0); + return -1; + } + if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"client map",0); + return -1; + } + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"controls",0); + return -1; + } + if ((xkb->map==NULL)||(xkb->server==NULL)) + return -1; + if (xkb->min_key_code<8) xkb->min_key_code= minKC; + if (xkb->max_key_code<8) xkb->max_key_code= maxKC; + if ((minKC>=8)&&(minKC<xkb->min_key_code)) + xkb->min_key_code= minKC; + if ((maxKC>=8)&&(maxKC>xkb->max_key_code)) { + _XkbLibError(_XkbErrBadValue,"keys in symbol map",maxKC); + return -1; + } + for (i=minKC;i<=(int)maxKC;i++) { + Atom typeName[XkbNumKbdGroups]; + XkbKeyTypePtr type[XkbNumKbdGroups]; + if ((tmp=fread(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmSymbols",0); + return -1; + } + nRead+= tmp*SIZEOF(xkmKeySymMapDesc); + bzero((char *)typeName,XkbNumKbdGroups*sizeof(Atom)); + bzero((char *)type,XkbNumKbdGroups*sizeof(XkbKeyTypePtr)); + if (wireMap.flags&XkmKeyHasTypes) { + register int g; + for (g=0;g<XkbNumKbdGroups;g++) { + if ((wireMap.flags&(1<<g))&& + ((tmp=XkmGetCountedString(file,buf,100))>0)) { + typeName[g]= XkbInternAtom(buf,1); + nRead+= tmp; + } + type[g]=FindTypeForKey(xkb,typeName[g],wireMap.width,NULL); + if (type[g]==NULL) { + _XkbLibError(_XkbErrMissingTypes,"ReadXkmSymbols",0); + return -1; + } + if (typeName[g]==type[g]->name) + xkb->server->explicit[i]|= (1<<g); + } + } + if (wireMap.flags&XkmRepeatingKey) { + xkb->ctrls->per_key_repeat[i/8]|= (1<<(i%8)); + xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; + } + else if (wireMap.flags&XkmNonRepeatingKey) { + xkb->ctrls->per_key_repeat[i/8]&= ~(1<<(i%8)); + xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; + } + xkb->map->modmap[i]= wireMap.modifier_map; + if (XkbNumGroups(wireMap.num_groups)>0) { + KeySym *sym; + int nSyms; + + if (XkbNumGroups(wireMap.num_groups)>xkb->ctrls->num_groups) + xkb->ctrls->num_groups= wireMap.num_groups; + nSyms= XkbNumGroups(wireMap.num_groups)*wireMap.width; + sym= XkbResizeKeySyms(xkb,i,nSyms); + if (!sym) + return -1; + for (s=0;s<nSyms;s++) { + *sym++= XkmGetCARD32(file,&nRead); + } + if (wireMap.flags&XkmKeyHasActions) { + XkbAction * act; + act= XkbResizeKeyActions(xkb,i,nSyms); + for (s=0;s<nSyms;s++,act++) { + tmp=fread(act,SIZEOF(xkmActionDesc),1,file); + nRead+= tmp*SIZEOF(xkmActionDesc); + } + xkb->server->explicit[i]|= XkbExplicitInterpretMask; + } + } + for (g=0;g<XkbNumGroups(wireMap.num_groups);g++) { + if (((xkb->server->explicit[i]&(1<<g))==0)||(type[g]==NULL)) { + KeySym *tmpSyms; + tmpSyms= XkbKeySymsPtr(xkb,i)+(wireMap.width*g); + type[g]= FindTypeForKey(xkb,None,wireMap.width,tmpSyms); + } + xkb->map->key_sym_map[i].kt_index[g]= type[g]-(&xkb->map->types[0]); + } + xkb->map->key_sym_map[i].group_info= wireMap.num_groups; + xkb->map->key_sym_map[i].width= wireMap.width; + if (wireMap.flags&XkmKeyHasBehavior) { + xkmBehaviorDesc b; + tmp= fread(&b,SIZEOF(xkmBehaviorDesc),1,file); + nRead+= tmp*SIZEOF(xkmBehaviorDesc); + xkb->server->behaviors[i].type= b.type; + xkb->server->behaviors[i].data= b.data; + xkb->server->explicit[i]|= XkbExplicitBehaviorMask; + } + } + if (totalVModMaps>0) { + xkmVModMapDesc v; + for (i=0;i<totalVModMaps;i++) { + tmp= fread(&v,SIZEOF(xkmVModMapDesc),1,file); + nRead+= tmp*SIZEOF(xkmVModMapDesc); + if (tmp>0) + xkb->server->vmodmap[v.key]= v.vmods; + } + } + return nRead; +} + +static int +ReadXkmGeomDoodad( + FILE * file, + XkbGeometryPtr geom, + XkbSectionPtr section) +{ +XkbDoodadPtr doodad; +xkmDoodadDesc doodadWire; +char buf[100]; +unsigned tmp; +int nRead=0; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&doodadWire,SIZEOF(xkmDoodadDesc),1,file); + nRead+= SIZEOF(xkmDoodadDesc)*tmp; + doodad= XkbAddGeomDoodad(geom,section,XkbInternAtom(buf,False)); + if (!doodad) + return nRead; + doodad->any.type= doodadWire.any.type; + doodad->any.priority= doodadWire.any.priority; + doodad->any.top= doodadWire.any.top; + doodad->any.left= doodadWire.any.left; + switch (doodadWire.any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodad->shape.angle= doodadWire.shape.angle; + doodad->shape.color_ndx= doodadWire.shape.color_ndx; + doodad->shape.shape_ndx= doodadWire.shape.shape_ndx; + break; + case XkbTextDoodad: + doodad->text.angle= doodadWire.text.angle; + doodad->text.width= doodadWire.text.width; + doodad->text.height= doodadWire.text.height; + doodad->text.color_ndx= doodadWire.text.color_ndx; + nRead+= XkmGetCountedString(file,buf,100); + doodad->text.text= _XkbDupString(buf); + nRead+= XkmGetCountedString(file,buf,100); + doodad->text.font= _XkbDupString(buf); + break; + case XkbIndicatorDoodad: + doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx; + doodad->indicator.on_color_ndx= doodadWire.indicator.on_color_ndx; + doodad->indicator.off_color_ndx= doodadWire.indicator.off_color_ndx; + break; + case XkbLogoDoodad: + doodad->logo.angle= doodadWire.logo.angle; + doodad->logo.color_ndx= doodadWire.logo.color_ndx; + doodad->logo.shape_ndx= doodadWire.logo.shape_ndx; + nRead+= XkmGetCountedString(file,buf,100); + doodad->logo.logo_name= _XkbDupString(buf); + break; + default: + /* report error? */ + return nRead; + } + return nRead; +} + +static int +ReadXkmGeomOverlay( FILE * file, + XkbGeometryPtr geom, + XkbSectionPtr section) +{ +char buf[100]; +unsigned tmp; +int nRead=0; +XkbOverlayPtr ol; +XkbOverlayRowPtr row; +xkmOverlayDesc olWire; +xkmOverlayRowDesc rowWire; +register int r; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&olWire,SIZEOF(xkmOverlayDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayDesc); + ol= XkbAddGeomOverlay(section,XkbInternAtom(buf,False), + olWire.num_rows); + if (!ol) + return nRead; + for (r=0;r<olWire.num_rows;r++) { + int k; + xkmOverlayKeyDesc keyWire; + tmp= fread(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayRowDesc); + row= XkbAddGeomOverlayRow(ol,rowWire.row_under,rowWire.num_keys); + if (!row) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomOverlay",0); + return nRead; + } + for (k=0;k<rowWire.num_keys;k++) { + tmp= fread(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayKeyDesc); + memcpy(row->keys[k].over.name,keyWire.over,XkbKeyNameLength); + memcpy(row->keys[k].under.name,keyWire.under,XkbKeyNameLength); + } + row->num_keys= rowWire.num_keys; + } + return nRead; +} + +static int +ReadXkmGeomSection( FILE * file, + XkbGeometryPtr geom) +{ +register int i; +XkbSectionPtr section; +xkmSectionDesc sectionWire; +unsigned tmp; +int nRead= 0; +char buf[100]; +Atom nameAtom; + + nRead+= XkmGetCountedString(file,buf,100); + nameAtom= XkbInternAtom(buf,False); + tmp= fread(§ionWire,SIZEOF(xkmSectionDesc),1,file); + nRead+= SIZEOF(xkmSectionDesc)*tmp; + section= XkbAddGeomSection(geom,nameAtom,sectionWire.num_rows, + sectionWire.num_doodads, + sectionWire.num_overlays); + if (!section) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); + return nRead; + } + section->top= sectionWire.top; + section->left= sectionWire.left; + section->width= sectionWire.width; + section->height= sectionWire.height; + section->angle= sectionWire.angle; + section->priority= sectionWire.priority; + if (sectionWire.num_rows>0) { + register int k; + XkbRowPtr row; + xkmRowDesc rowWire; + XkbKeyPtr key; + xkmKeyDesc keyWire; + + for (i=0;i<sectionWire.num_rows;i++) { + tmp= fread(&rowWire,SIZEOF(xkmRowDesc),1,file); + nRead+= SIZEOF(xkmRowDesc)*tmp; + row= XkbAddGeomRow(section,rowWire.num_keys); + if (!row) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); + return nRead; + } + row->top= rowWire.top; + row->left= rowWire.left; + row->vertical= rowWire.vertical; + for (k=0;k<rowWire.num_keys;k++) { + tmp= fread(&keyWire,SIZEOF(xkmKeyDesc),1,file); + nRead+= SIZEOF(xkmKeyDesc)*tmp; + key= XkbAddGeomKey(row); + if (!key) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); + return nRead; + } + memcpy(key->name.name,keyWire.name,XkbKeyNameLength); + key->gap= keyWire.gap; + key->shape_ndx= keyWire.shape_ndx; + key->color_ndx= keyWire.color_ndx; + } + } + } + if (sectionWire.num_doodads>0) { + for (i=0;i<sectionWire.num_doodads;i++) { + tmp= ReadXkmGeomDoodad(file,geom,section); + nRead+= tmp; + if (tmp<1) + return nRead; + } + } + if (sectionWire.num_overlays>0) { + for (i=0;i<sectionWire.num_overlays;i++) { + tmp= ReadXkmGeomOverlay(file,geom,section); + nRead+= tmp; + if (tmp<1) + return nRead; + } + } + return nRead; +} + +static int +ReadXkmGeometry(FILE *file,XkbDescPtr xkb) +{ +register int i; +char buf[100]; +unsigned tmp; +int nRead= 0; +xkmGeometryDesc wireGeom; +XkbGeometryPtr geom; +XkbGeometrySizesRec sizes; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&wireGeom,SIZEOF(xkmGeometryDesc),1,file); + nRead+= tmp*SIZEOF(xkmGeometryDesc); + sizes.which= XkbGeomAllMask; + sizes.num_properties= wireGeom.num_properties; + sizes.num_colors= wireGeom.num_colors; + sizes.num_shapes= wireGeom.num_shapes; + sizes.num_sections= wireGeom.num_sections; + sizes.num_doodads= wireGeom.num_doodads; + sizes.num_key_aliases= wireGeom.num_key_aliases; + if (XkbAllocGeometry(xkb,&sizes)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + geom= xkb->geom; + geom->name= XkbInternAtom(buf,False); + geom->width_mm= wireGeom.width_mm; + geom->height_mm= wireGeom.height_mm; + nRead+= XkmGetCountedString(file,buf,100); + geom->label_font= _XkbDupString(buf); + if (wireGeom.num_properties>0) { + char val[1024]; + for (i=0;i<wireGeom.num_properties;i++) { + nRead+= XkmGetCountedString(file,buf,100); + nRead+= XkmGetCountedString(file,val,1024); + if (XkbAddGeomProperty(geom,buf,val)==NULL) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + } + } + if (wireGeom.num_colors>0) { + for (i=0;i<wireGeom.num_colors;i++) { + nRead+= XkmGetCountedString(file,buf,100); + if (XkbAddGeomColor(geom,buf,i)==NULL) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + } + } + geom->base_color= &geom->colors[wireGeom.base_color_ndx]; + geom->label_color= &geom->colors[wireGeom.label_color_ndx]; + if (wireGeom.num_shapes>0) { + XkbShapePtr shape; + xkmShapeDesc shapeWire; + Atom nameAtom; + for (i=0;i<wireGeom.num_shapes;i++) { + register int n; + XkbOutlinePtr ol; + xkmOutlineDesc olWire; + nRead+= XkmGetCountedString(file,buf,100); + nameAtom= XkbInternAtom(buf,False); + tmp= fread(&shapeWire,SIZEOF(xkmShapeDesc),1,file); + nRead+= tmp*SIZEOF(xkmShapeDesc); + shape= XkbAddGeomShape(geom,nameAtom,shapeWire.num_outlines); + if (!shape) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + for (n=0;n<shapeWire.num_outlines;n++) { + register int p; + xkmPointDesc ptWire; + tmp= fread(&olWire,SIZEOF(xkmOutlineDesc),1,file); + nRead+= tmp*SIZEOF(xkmOutlineDesc); + ol= XkbAddGeomOutline(shape,olWire.num_points); + if (!ol) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + ol->num_points= olWire.num_points; + ol->corner_radius= olWire.corner_radius; + for (p=0;p<olWire.num_points;p++) { + tmp= fread(&ptWire,SIZEOF(xkmPointDesc),1,file); + nRead+= tmp*SIZEOF(xkmPointDesc); + ol->points[p].x= ptWire.x; + ol->points[p].y= ptWire.y; + if (ptWire.x<shape->bounds.x1) shape->bounds.x1= ptWire.x; + if (ptWire.x>shape->bounds.x2) shape->bounds.x2= ptWire.x; + if (ptWire.y<shape->bounds.y1) shape->bounds.y1= ptWire.y; + if (ptWire.y>shape->bounds.y2) shape->bounds.y2= ptWire.y; + } + } + if (shapeWire.primary_ndx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire.primary_ndx]; + if (shapeWire.approx_ndx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire.approx_ndx]; + } + } + if (wireGeom.num_sections>0) { + for (i=0;i<wireGeom.num_sections;i++) { + tmp= ReadXkmGeomSection(file,geom); + nRead+= tmp; + if (tmp==0) + return nRead; + } + } + if (wireGeom.num_doodads>0) { + for (i=0;i<wireGeom.num_doodads;i++) { + tmp= ReadXkmGeomDoodad(file,geom,NULL); + nRead+= tmp; + if (tmp==0) + return nRead; + } + } + if ((wireGeom.num_key_aliases>0)&&(geom->key_aliases)) { + int sz= XkbKeyNameLength*2; + int num= wireGeom.num_key_aliases; + if (fread(geom->key_aliases,sz,num,file)!=num) { + _XkbLibError(_XkbErrBadLength,"ReadXkmGeometry",0); + return -1; + } + nRead+= (num*sz); + geom->num_key_aliases= num; + } + return nRead; +} + +Bool +XkmProbe(FILE *file) +{ +unsigned hdr,tmp; +int nRead=0; + + hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); + tmp= XkmGetCARD32(file,&nRead); + if (tmp!=hdr) { + if ((tmp&(~0xff))==(hdr&(~0xff))) { + _XkbLibError(_XkbErrBadFileVersion,"XkmProbe",tmp&0xff); + } + return 0; + } + return 1; +} + +static Bool +XkmReadTOC(FILE *file,xkmFileInfo* file_info,int max_toc,xkmSectionInfo *toc) +{ +unsigned hdr,tmp; +int nRead=0; +unsigned i,size_toc; + + hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); + tmp= XkmGetCARD32(file,&nRead); + if (tmp!=hdr) { + if ((tmp&(~0xff))==(hdr&(~0xff))) { + _XkbLibError(_XkbErrBadFileVersion,"XkmReadTOC",tmp&0xff); + } + else { + _XkbLibError(_XkbErrBadFileType,"XkmReadTOC",tmp); + } + return 0; + } + fread(file_info,SIZEOF(xkmFileInfo),1,file); + size_toc= file_info->num_toc; + if (size_toc>max_toc) { + DebugF("Warning! Too many TOC entries; last %d ignored\n", + size_toc-max_toc); + size_toc= max_toc; + } + for (i=0;i<size_toc;i++) { + fread(&toc[i],SIZEOF(xkmSectionInfo),1,file); + } + return 1; +} + +/***====================================================================***/ + +#define MAX_TOC 16 +unsigned +XkmReadFile(FILE *file,unsigned need,unsigned want,XkbDescPtr *xkb) +{ +register unsigned i; +xkmSectionInfo toc[MAX_TOC],tmpTOC; +xkmFileInfo fileInfo; +unsigned tmp,nRead=0; +unsigned which= need|want; + + if (!XkmReadTOC(file,&fileInfo,MAX_TOC,toc)) + return which; + if ((fileInfo.present&need)!=need) { + _XkbLibError(_XkbErrIllegalContents,"XkmReadFile", + need&(~fileInfo.present)); + return which; + } + if (*xkb==NULL) + *xkb= XkbAllocKeyboard(); + for (i=0;i<fileInfo.num_toc;i++) { + fseek(file,toc[i].offset,SEEK_SET); + tmp= fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file); + nRead= tmp*SIZEOF(xkmSectionInfo); + if ((tmpTOC.type!=toc[i].type)||(tmpTOC.format!=toc[i].format)|| + (tmpTOC.size!=toc[i].size)||(tmpTOC.offset!=toc[i].offset)) { + return which; + } + if ((which&(1<<tmpTOC.type))==0) { + continue; + } + switch (tmpTOC.type) { + case XkmVirtualModsIndex: + tmp= ReadXkmVirtualMods(file,*xkb,NULL); + break; + case XkmTypesIndex: + tmp= ReadXkmKeyTypes(file,*xkb,NULL); + break; + case XkmCompatMapIndex: + tmp= ReadXkmCompatMap(file,*xkb,NULL); + break; + case XkmKeyNamesIndex: + tmp= ReadXkmKeycodes(file,*xkb,NULL); + break; + case XkmIndicatorsIndex: + tmp= ReadXkmIndicators(file,*xkb,NULL); + break; + case XkmSymbolsIndex: + tmp= ReadXkmSymbols(file,*xkb); + break; + case XkmGeometryIndex: + tmp= ReadXkmGeometry(file,*xkb); + break; + default: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(tmpTOC.type,XkbMessage),0); + tmp= 0; + break; + } + if (tmp>0) { + nRead+= tmp; + which&= ~(1<<toc[i].type); + (*xkb)->defined|= (1<<toc[i].type); + } + if (nRead!=tmpTOC.size) { + _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage), + nRead-tmpTOC.size); + } + } + return which; +} |