diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 18:19:47 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 18:19:47 +0000 |
commit | 04f51aaa1f5b0cac419d2891812446c790b9c581 (patch) | |
tree | 7d104a653aff8d7488bc039ba435118115c18807 /xserver/dix | |
parent | 4a168ba45f33263ee86fc398ff32f108cffb1330 (diff) |
Importing xserver from X.Org 7.2RC2
Diffstat (limited to 'xserver/dix')
32 files changed, 30714 insertions, 0 deletions
diff --git a/xserver/dix/BuiltInAtoms b/xserver/dix/BuiltInAtoms new file mode 100644 index 000000000..910c62706 --- /dev/null +++ b/xserver/dix/BuiltInAtoms @@ -0,0 +1,329 @@ +File: .../x11/server/dix/BuiltInAtoms + +This file is of a fixed format and is used to generate both the file +include/XAtom.h and dix/initatoms.c. Neither of those files should be +edited directly. Changing the atoms in this file, or even the order in +which they occur, is equivalent to forcing a new (minor) version number +on the server. Take care. + +The format of the file is that each built in atom starts in column 1 +with no text, other than spaces and tabs, on that line other than a +mandatory trailing "@" at the end of the line. For each atom (Foo) +below the defines will be of the form + #define XA_Foo <n> +and the string value of the atom will be "Foo". + +The comment lines in this file are not guaranteed to be accurate. To see the +current truth, look at the Xlib documentation as well as the protocol spec. + +Atoms occur in five distinct name spaces within the protocol. Any particular +atom may or may not have some client interpretation within each of the name +spaces. For each of the built in atoms, the intended semantics and the space +within which it is defined is indicated. + +Those name spaces are + Property names + Property types + Selections + Font properties + Type of a ClientMessage event (none built into server) + +For the font properties mentioned here, see the spec for more information. + + -- Selections -- + +PRIMARY @ + Selection. +SECONDARY @ + Selection. + + -- Property types and names -- + +ARC @ + Property type: + x, y: INT16 + width, height: CARD16, + angle1, angle2: INT16 +ATOM @ + Property type: + atom: ATOM +BITMAP @ + Property type: + bitmap: PIXMAP + This is asserted to be of depth 1. +CARDINAL @ + Property type: + card: CARD32 or CARD16 or CARD8 + the datum size is dependent on the property format +COLORMAP @ + Property type: + colormap: COLORMAP +CURSOR @ + Property type: + cursor: CURSOR +CUT_BUFFER0 @ +CUT_BUFFER1 @ +CUT_BUFFER2 @ +CUT_BUFFER3 @ +CUT_BUFFER4 @ +CUT_BUFFER5 @ +CUT_BUFFER6 @ +CUT_BUFFER7 @ + Property name: (type: STRING) + Used to implement cut buffer ring, in particular Andrew uses + this mechanism. Anyone else using this sort of IPC mechanism + should use these properties. + + Data is normally fetched and stored out of CUT_BUFFER0; the + RotateProperties request is used to rotate these buffers. +DRAWABLE @ + Property type: + drawable: DRAWABLE +FONT @ + Property type: + font: FONT +INTEGER @ + Property type: + card: INT32 or INT16 or INT8 + the datum size is dependent on the property format +PIXMAP @ + Property type: + pixmap: PIXMAP +POINT @ + Property type: + x, y: INT16 +RECTANGLE @ + Property type: + x, y: INT16 + width, height: CARD16 +RESOURCE_MANAGER @ + Property name: (type: STRING) + Contents of the user's resource manager data base. +RGB_COLOR_MAP @ + Property type: + colormap: COLORMAP + red-max: CARD32 + red-mult: CARD32 + green-max: CARD32 + green-mult: CARD32 + blue-max: CARD32 + blue-mult: CARD32 + base-pixel: CARD32 + + The fields `red_max', `green_max', and `blue_max' give the maximum + red, green, and blue values, respectively. Each color + coefficient ranges from 0 to its max, inclusive. For example, + a common colormap allocation is 3/3/2: 3 planes for red, 3 + planes for green, and 2 planes for blue. Such a colormap would + have red_max == 7, green_max = 7, and blue_max = 3. An alternate + allocation that uses only 216 colors is red_max = 5, green_max = + 5, and blue_max = 5. + + The fields `red_mult', `green_mult', and `blue_mult' give the + scale factors used to compose a full pixel value. (See next + paragraph.) For a 3/3/2 allocation red_mult might be 32, + green_mult might be 4, and blue_mult might be 1. For a + 6-colors-each allocation, red_mult might be 36, green_mult might + be 6, and blue_mult might be 1. + + The field `base_pixel' gives the base pixel value used to + compose a full pixel value. Normally base_pixel is obtained + from a call to XAllocColorPlanes(). Given integer red, green, + and blue coefficients in their appropriate ranges, one can + compute a corresponding pixel value with the expression: + + r * red_mult + g * green_mult + b * blue_mult + base_pixel + + For gray-scale colormaps, only the colormap, red_max, red_mult, + and base_pixel fields are defined; the other fields are + ignored. To compute a gray-scale pixel value, use: + + gray * red_mult + base_pixel + + This is provided to allow applications to share color maps. + +RGB_BEST_MAP @ +RGB_BLUE_MAP @ +RGB_DEFAULT_MAP @ +RGB_GRAY_MAP @ +RGB_GREEN_MAP @ +RGB_RED_MAP @ + Property name: (type: RGB_COLOR_MAP) + The needs of most applications can be met with five colormaps. + Polite applications may need only a small RGB space, and can + use a portion of the default color map. Applications doing + high-quality RGB rendering will need an entire colormap, + filled with as large an RGB space as possible, e.g. 332. For + color separations, an application may need maximum device + resolution for each of red, green, and blue, even if this + requires three renderings with three colormaps. + + Each of the above five names would be used for sharing color + maps. +STRING @ + Property type: + sequence of Bytes +VISUALID @ + Property type: + visual: VISUALID +WINDOW @ + Property type: + window: WINDOW +WM_COMMAND @ + Property name: (type: STRING) + Command line arguments used to invoke this application. The + arguments are delimited by null characters (ASCII 0). +WM_HINTS @ + Property type: + flags: CARD32 + input: BOOL32 + initial-state: CARD32 + icon-pixmap: PIXMAP + icon-window: WINDOW + icon_mask: BITMAP + icon-x, icon-y: INT32 + flags contains the following bits + 0x00000001 input hint + 0x00000002 state hint + 0x00000004 icon pixmap hint + 0x00000008 icon window hint + 0x00000010 icon position hint + values for initial-state + 0 unspecified -> application does not + care and WM should pick one. + 1 normal + 2 zoomed + 3 iconic + 4 inactive -> application believes + itself to be seldomly used. WM may wish to + place it on an inactive menu. + This type is potentially extensible. The order is critical; + append to the end only. + Property name: (type: WM_HINTS) + Additional hints set by the client for use by the window + manager. +WM_CLIENT_MACHINE @ + Property name: (type: STRING) + used to communicate with the window manager. The host name + of the machine the client is running on may be set here. +WM_ICON_NAME @ + Property name: (type: STRING) + what the application would like the label to be for + the iconic form of the window. +WM_ICON_SIZE @ + Property type: + minWidth, min-height: CARD32 + maxWidth, max-height: CARD32 + widthInc, height-inc: CARD32 + Property name: (type: ICON_SIZE) + The window manager may set this property on the root window + to specify the icon sizes it allows. +WM_NAME @ + Property name: (type: STRING) + used to communicate with the window manager. This is + what the application would like the label for the window. +WM_NORMAL_HINTS @ + Property name: (type: SIZE_HINTS) + used to communicate with the window manager. This is size + hints for a window in its "normal" state. +WM_SIZE_HINTS @ + Property type: + flags: CARD32 + x, y: INT32 + width, height: CARD32 + min-width, min-height: CARD32 + max-width, max-height: CARD32 + width-inc, height-inc: CARD32 + min-aspect-x, min-aspect-y: CARD32 + max-aspect-x, max-aspect-y: CARD32 + flags contains the following bits + 0x00000001 user specified x and y + 0x00000002 user specified width and height + 0x00000004 program specified position + 0x00000008 program specified size + 0x00000010 program specified minimum size + 0x00000020 program specified maximum size + 0x00000040 program specified resize increment + 0x00000080 program specified aspect ratio + This type is potentially extensible. The order is critical; + append to the end only. +WM_ZOOM_HINTS @ + Property name: (type: SIZE_HINTS) + used to communicate with the window manager. This is size + hints for a window in its "zoomed" state. + + -- Font properties -- + +MIN_SPACE @ + Font property: CARD32 +NORM_SPACE @ + Font property: CARD32 +MAX_SPACE @ + Font property: CARD32 +END_SPACE @ + Font property: CARD32 +SUPERSCRIPT_X @ + Font property: INT32 +SUPERSCRIPT_Y @ + Font property: INT32 +SUBSCRIPT_X @ + Font property: INT32 +SUBSCRIPT_Y @ + Font property: INT32 +UNDERLINE_POSITION @ + Font property: INT32 +UNDERLINE_THICKNESS @ + Font property: CARD32 +STRIKEOUT_ASCENT @ + Font property: INT32 +STRIKEOUT_DESCENT @ + Font property: INT32 +ITALIC_ANGLE @ + Font property: INT32 +X_HEIGHT @ + Font property: INT32 +QUAD_WIDTH @ + Font property: INT32 +WEIGHT @ + Font property: CARD32 +POINT_SIZE @ + Font property: CARD32 +RESOLUTION @ + Font property: CARD32 + +The following optional properties on fonts have values that are atoms. The +atom print name is the useful information. + +COPYRIGHT @ + of the font distribution +NOTICE @ + trademark/copyright of the character shapes +FONT_NAME @ + name of this particular instance of a font +FAMILY_NAME @ + name of the 'font family' to which it belongs +FULL_NAME @ + full text name of the font + +The following aren't in order but putting them at the end avoids encoding +changes. + +CAP_HEIGHT @ + Font property: CARD32 + + +WM_CLASS @ + Property name: (type: STRING) + Used (possibly by some window managers; definitely by + session managers) to look up resources in the resource + data base on behalf of the client who set this property. + There are 2 elements: + {char *resource_name; char *resource_class;} + delimited by a null character (ascii 0) + +WM_TRANSIENT_FOR @ + Property name: (type: WINDOW) + Used by transient top-level windows, such as dialog + boxes, to point to their logical "parents". The window + manager can then take down the dialog boxes when the + "parent" gets iconified, for instance. diff --git a/xserver/dix/CHANGES b/xserver/dix/CHANGES new file mode 100644 index 000000000..d8fb7c31a --- /dev/null +++ b/xserver/dix/CHANGES @@ -0,0 +1,17 @@ +The following changes have been made to this directory since R3 (for +a full description, see doc/Server/r4.tbl.ms): + + o Windows restructured (memory reduction, devPrivates and speedups) + o GCs restructured (memory reduction, devPrivates and wrappers) + o Screens restructured (window ops merged in, devPrivates) + o Pixmaps restructured (drawable changes mostly) + o Cursors restructured (shares glyph bits now) + o Visuals restructured (screen index removed, fields rearranged) + o Devices restructured (input extension changes) + o Out of memory changes. Many interfaces now return OutOfMemory + status. + o Synchronous grab code rewritten. Should conform to our + understanding of the protocol now. Be careful when time + stamping events (don't allow time to run backwards). + o Resource types redesigned and rewritten. + o Internal fake color allocation routine for software cursors. diff --git a/xserver/dix/Makefile.am b/xserver/dix/Makefile.am new file mode 100644 index 000000000..d26d9ea7a --- /dev/null +++ b/xserver/dix/Makefile.am @@ -0,0 +1,40 @@ +noinst_LTLIBRARIES = libdix.la libxpstubs.la + +AM_CFLAGS = $(DIX_CFLAGS) \ + -DVENDOR_STRING=\""@VENDOR_STRING@"\" \ + -DVENDOR_RELEASE="@VENDOR_RELEASE@" + +libdix_la_SOURCES = \ + atom.c \ + colormap.c \ + cursor.c \ + devices.c \ + dispatch.c \ + dispatch.h \ + dixfonts.c \ + dixutils.c \ + events.c \ + extension.c \ + ffs.c \ + gc.c \ + globals.c \ + glyphcurs.c \ + grabs.c \ + initatoms.c \ + main.c \ + pixmap.c \ + privates.c \ + property.c \ + resource.c \ + swaprep.c \ + swapreq.c \ + tables.c \ + window.c \ + strcasecmp.c + +libxpstubs_la_SOURCES = \ + xpstubs.c + +INCLUDES = -I$(top_srcdir)/Xprint + +EXTRA_DIST = buildatoms BuiltInAtoms CHANGES diff --git a/xserver/dix/Makefile.in b/xserver/dix/Makefile.in new file mode 100644 index 000000000..e3f3a7bd7 --- /dev/null +++ b/xserver/dix/Makefile.in @@ -0,0 +1,853 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = dix +DIST_COMMON = $(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) +libdix_la_LIBADD = +am_libdix_la_OBJECTS = atom.lo colormap.lo cursor.lo devices.lo \ + dispatch.lo dixfonts.lo dixutils.lo events.lo extension.lo \ + ffs.lo gc.lo globals.lo glyphcurs.lo grabs.lo initatoms.lo \ + main.lo pixmap.lo privates.lo property.lo resource.lo \ + swaprep.lo swapreq.lo tables.lo window.lo strcasecmp.lo +libdix_la_OBJECTS = $(am_libdix_la_OBJECTS) +libxpstubs_la_LIBADD = +am_libxpstubs_la_OBJECTS = xpstubs.lo +libxpstubs_la_OBJECTS = $(am_libxpstubs_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -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 --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libdix_la_SOURCES) $(libxpstubs_la_SOURCES) +DIST_SOURCES = $(libdix_la_SOURCES) $(libxpstubs_la_SOURCES) +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@ +AFB_FALSE = @AFB_FALSE@ +AFB_TRUE = @AFB_TRUE@ +AGP_FALSE = @AGP_FALSE@ +AGP_TRUE = @AGP_TRUE@ +AIGLX_FALSE = @AIGLX_FALSE@ +AIGLX_TRUE = @AIGLX_TRUE@ +ALLOCA = @ALLOCA@ +ALPHA_VIDEO_FALSE = @ALPHA_VIDEO_FALSE@ +ALPHA_VIDEO_TRUE = @ALPHA_VIDEO_TRUE@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +APPDEFAULTDIR = @APPDEFAULTDIR@ +APPGROUP_FALSE = @APPGROUP_FALSE@ +APPGROUP_TRUE = @APPGROUP_TRUE@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +ARM_VIDEO_FALSE = @ARM_VIDEO_FALSE@ +ARM_VIDEO_TRUE = @ARM_VIDEO_TRUE@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASE_FONT_PATH = @BASE_FONT_PATH@ +BSD_KBD_MODE_FALSE = @BSD_KBD_MODE_FALSE@ +BSD_KBD_MODE_TRUE = @BSD_KBD_MODE_TRUE@ +BUILDDOCS_FALSE = @BUILDDOCS_FALSE@ +BUILDDOCS_TRUE = @BUILDDOCS_TRUE@ +BUILD_DATE = @BUILD_DATE@ +BUILD_KBD_MODE_FALSE = @BUILD_KBD_MODE_FALSE@ +BUILD_KBD_MODE_TRUE = @BUILD_KBD_MODE_TRUE@ +BUILD_LINUXDOC_FALSE = @BUILD_LINUXDOC_FALSE@ +BUILD_LINUXDOC_TRUE = @BUILD_LINUXDOC_TRUE@ +BUILD_PDFDOC_FALSE = @BUILD_PDFDOC_FALSE@ +BUILD_PDFDOC_TRUE = @BUILD_PDFDOC_TRUE@ +BUILD_XORGCFG_FALSE = @BUILD_XORGCFG_FALSE@ +BUILD_XORGCFG_TRUE = @BUILD_XORGCFG_TRUE@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFB_FALSE = @CFB_FALSE@ +CFB_TRUE = @CFB_TRUE@ +CFLAGS = @CFLAGS@ +COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@ +COMPOSITE_FALSE = @COMPOSITE_FALSE@ +COMPOSITE_TRUE = @COMPOSITE_TRUE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CUP_FALSE = @CUP_FALSE@ +CUP_TRUE = @CUP_TRUE@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBE_FALSE = @DBE_FALSE@ +DBE_TRUE = @DBE_TRUE@ +DEBUG_FALSE = @DEBUG_FALSE@ +DEBUG_TRUE = @DEBUG_TRUE@ +DEFAULT_LOGPREFIX = @DEFAULT_LOGPREFIX@ +DEFAULT_MODULE_PATH = @DEFAULT_MODULE_PATH@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DGA_FALSE = @DGA_FALSE@ +DGA_TRUE = @DGA_TRUE@ +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@ +DMX_BUILD_LNX_FALSE = @DMX_BUILD_LNX_FALSE@ +DMX_BUILD_LNX_TRUE = @DMX_BUILD_LNX_TRUE@ +DMX_BUILD_USB_FALSE = @DMX_BUILD_USB_FALSE@ +DMX_BUILD_USB_TRUE = @DMX_BUILD_USB_TRUE@ +DMX_FALSE = @DMX_FALSE@ +DMX_TRUE = @DMX_TRUE@ +DPMSExtension_FALSE = @DPMSExtension_FALSE@ +DPMSExtension_TRUE = @DPMSExtension_TRUE@ +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@ +DRI_FALSE = @DRI_FALSE@ +DRI_TRUE = @DRI_TRUE@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EVI_FALSE = @EVI_FALSE@ +EVI_TRUE = @EVI_TRUE@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FBDEVHW_FALSE = @FBDEVHW_FALSE@ +FBDEVHW_TRUE = @FBDEVHW_TRUE@ +FFLAGS = @FFLAGS@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +FONTCACHE_FALSE = @FONTCACHE_FALSE@ +FONTCACHE_TRUE = @FONTCACHE_TRUE@ +FREEBSD_KLDLOAD_FALSE = @FREEBSD_KLDLOAD_FALSE@ +FREEBSD_KLDLOAD_TRUE = @FREEBSD_KLDLOAD_TRUE@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_REQUIRES = @FREETYPE_REQUIRES@ +GLX_DEFINES = @GLX_DEFINES@ +GLX_FALSE = @GLX_FALSE@ +GLX_TRUE = @GLX_TRUE@ +GL_CFLAGS = @GL_CFLAGS@ +GL_LIBS = @GL_LIBS@ +H3600_TS_FALSE = @H3600_TS_FALSE@ +H3600_TS_TRUE = @H3600_TS_TRUE@ +I386_VIDEO_FALSE = @I386_VIDEO_FALSE@ +I386_VIDEO_TRUE = @I386_VIDEO_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_LIBXF86CONFIG_FALSE = @INSTALL_LIBXF86CONFIG_FALSE@ +INSTALL_LIBXF86CONFIG_TRUE = @INSTALL_LIBXF86CONFIG_TRUE@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_SETUID_FALSE = @INSTALL_SETUID_FALSE@ +INSTALL_SETUID_TRUE = @INSTALL_SETUID_TRUE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INT10_STUB_FALSE = @INT10_STUB_FALSE@ +INT10_STUB_TRUE = @INT10_STUB_TRUE@ +INT10_VM86_FALSE = @INT10_VM86_FALSE@ +INT10_VM86_TRUE = @INT10_VM86_TRUE@ +INT10_X86EMU_FALSE = @INT10_X86EMU_FALSE@ +INT10_X86EMU_TRUE = @INT10_X86EMU_TRUE@ +KDRIVEFBDEV_FALSE = @KDRIVEFBDEV_FALSE@ +KDRIVEFBDEV_TRUE = @KDRIVEFBDEV_TRUE@ +KDRIVEVESA_FALSE = @KDRIVEVESA_FALSE@ +KDRIVEVESA_TRUE = @KDRIVEVESA_TRUE@ +KDRIVE_CFLAGS = @KDRIVE_CFLAGS@ +KDRIVE_FALSE = @KDRIVE_FALSE@ +KDRIVE_HW_FALSE = @KDRIVE_HW_FALSE@ +KDRIVE_HW_TRUE = @KDRIVE_HW_TRUE@ +KDRIVE_INCS = @KDRIVE_INCS@ +KDRIVE_LIBS = @KDRIVE_LIBS@ +KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@ +KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@ +KDRIVE_TRUE = @KDRIVE_TRUE@ +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@ +LINUX_ALPHA_FALSE = @LINUX_ALPHA_FALSE@ +LINUX_ALPHA_TRUE = @LINUX_ALPHA_TRUE@ +LINUX_IA64_FALSE = @LINUX_IA64_FALSE@ +LINUX_IA64_TRUE = @LINUX_IA64_TRUE@ +LNXACPI_FALSE = @LNXACPI_FALSE@ +LNXACPI_TRUE = @LNXACPI_TRUE@ +LNXAPM_FALSE = @LNXAPM_FALSE@ +LNXAPM_TRUE = @LNXAPM_TRUE@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MAKE_HTML = @MAKE_HTML@ +MAKE_PDF = @MAKE_PDF@ +MAKE_PS = @MAKE_PS@ +MAKE_TEXT = @MAKE_TEXT@ +MESA_SOURCE = @MESA_SOURCE@ +MFB_FALSE = @MFB_FALSE@ +MFB_TRUE = @MFB_TRUE@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MITSHM_FALSE = @MITSHM_FALSE@ +MITSHM_TRUE = @MITSHM_TRUE@ +MKFONTDIR = @MKFONTDIR@ +MKFONTSCALE = @MKFONTSCALE@ +MMX_CAPABLE_FALSE = @MMX_CAPABLE_FALSE@ +MMX_CAPABLE_TRUE = @MMX_CAPABLE_TRUE@ +MULTIBUFFER_FALSE = @MULTIBUFFER_FALSE@ +MULTIBUFFER_TRUE = @MULTIBUFFER_TRUE@ +NEED_STRLCAT_FALSE = @NEED_STRLCAT_FALSE@ +NEED_STRLCAT_TRUE = @NEED_STRLCAT_TRUE@ +NEED_VSNPRINTF_FALSE = @NEED_VSNPRINTF_FALSE@ +NEED_VSNPRINTF_TRUE = @NEED_VSNPRINTF_TRUE@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +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@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PPC_VIDEO_FALSE = @PPC_VIDEO_FALSE@ +PPC_VIDEO_TRUE = @PPC_VIDEO_TRUE@ +PROJECTROOT = @PROJECTROOT@ +PS2PDF = @PS2PDF@ +RANLIB = @RANLIB@ +RAWCPP = @RAWCPP@ +RAWCPPFLAGS = @RAWCPPFLAGS@ +RECORD_FALSE = @RECORD_FALSE@ +RECORD_TRUE = @RECORD_TRUE@ +RES_FALSE = @RES_FALSE@ +RES_TRUE = @RES_TRUE@ +RGB_DB = @RGB_DB@ +SCREENSAVER_FALSE = @SCREENSAVER_FALSE@ +SCREENSAVER_TRUE = @SCREENSAVER_TRUE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@ +SOLARIS_ASM_INLINE_FALSE = @SOLARIS_ASM_INLINE_FALSE@ +SOLARIS_ASM_INLINE_TRUE = @SOLARIS_ASM_INLINE_TRUE@ +SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@ +SOLARIS_USL_CONSOLE_FALSE = @SOLARIS_USL_CONSOLE_FALSE@ +SOLARIS_USL_CONSOLE_TRUE = @SOLARIS_USL_CONSOLE_TRUE@ +SPARC64_VIDEO_FALSE = @SPARC64_VIDEO_FALSE@ +SPARC64_VIDEO_TRUE = @SPARC64_VIDEO_TRUE@ +STRIP = @STRIP@ +SUN_KBD_MODE_FALSE = @SUN_KBD_MODE_FALSE@ +SUN_KBD_MODE_TRUE = @SUN_KBD_MODE_TRUE@ +SYS_LIBS = @SYS_LIBS@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_FALSE = @TSLIB_FALSE@ +TSLIB_LIBS = @TSLIB_LIBS@ +TSLIB_TRUE = @TSLIB_TRUE@ +USE_CURSES_FALSE = @USE_CURSES_FALSE@ +USE_CURSES_TRUE = @USE_CURSES_TRUE@ +USE_RGB_BUILTIN_FALSE = @USE_RGB_BUILTIN_FALSE@ +USE_RGB_BUILTIN_TRUE = @USE_RGB_BUILTIN_TRUE@ +VENDOR_MAN_VERSION = @VENDOR_MAN_VERSION@ +VENDOR_RELEASE = @VENDOR_RELEASE@ +VENDOR_STRING = @VENDOR_STRING@ +VENDOR_STRING_SHORT = @VENDOR_STRING_SHORT@ +VERSION = @VERSION@ +X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@ +X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@ +XACE_FALSE = @XACE_FALSE@ +XACE_TRUE = @XACE_TRUE@ +XCALIBRATE_FALSE = @XCALIBRATE_FALSE@ +XCALIBRATE_TRUE = @XCALIBRATE_TRUE@ +XCSECURITY_FALSE = @XCSECURITY_FALSE@ +XCSECURITY_TRUE = @XCSECURITY_TRUE@ +XDMAUTH_FALSE = @XDMAUTH_FALSE@ +XDMAUTH_TRUE = @XDMAUTH_TRUE@ +XDMCP_CFLAGS = @XDMCP_CFLAGS@ +XDMCP_FALSE = @XDMCP_FALSE@ +XDMCP_LIBS = @XDMCP_LIBS@ +XDMCP_TRUE = @XDMCP_TRUE@ +XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@ +XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@ +XDMX_LIBS = @XDMX_LIBS@ +XEGLMODULES_CFLAGS = @XEGLMODULES_CFLAGS@ +XEGLMODULES_LIBS = @XEGLMODULES_LIBS@ +XEGL_FALSE = @XEGL_FALSE@ +XEGL_LIBS = @XEGL_LIBS@ +XEGL_TRUE = @XEGL_TRUE@ +XEPHYR_CFLAGS = @XEPHYR_CFLAGS@ +XEPHYR_FALSE = @XEPHYR_FALSE@ +XEPHYR_INCS = @XEPHYR_INCS@ +XEPHYR_LIBS = @XEPHYR_LIBS@ +XEPHYR_TRUE = @XEPHYR_TRUE@ +XEVIE_FALSE = @XEVIE_FALSE@ +XEVIE_TRUE = @XEVIE_TRUE@ +XF86BIGFONT_FALSE = @XF86BIGFONT_FALSE@ +XF86BIGFONT_TRUE = @XF86BIGFONT_TRUE@ +XF86CONFIGFILE = @XF86CONFIGFILE@ +XF86UTILS_FALSE = @XF86UTILS_FALSE@ +XF86UTILS_TRUE = @XF86UTILS_TRUE@ +XGLMODULES_CFLAGS = @XGLMODULES_CFLAGS@ +XGLMODULES_LIBS = @XGLMODULES_LIBS@ +XGLXMODULES_CFLAGS = @XGLXMODULES_CFLAGS@ +XGLXMODULES_LIBS = @XGLXMODULES_LIBS@ +XGLX_FALSE = @XGLX_FALSE@ +XGLX_LIBS = @XGLX_LIBS@ +XGLX_TRUE = @XGLX_TRUE@ +XGL_FALSE = @XGL_FALSE@ +XGL_LIBS = @XGL_LIBS@ +XGL_MODULE_PATH = @XGL_MODULE_PATH@ +XGL_TRUE = @XGL_TRUE@ +XINERAMA_FALSE = @XINERAMA_FALSE@ +XINERAMA_TRUE = @XINERAMA_TRUE@ +XINPUT_FALSE = @XINPUT_FALSE@ +XINPUT_TRUE = @XINPUT_TRUE@ +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_FALSE = @XNEST_FALSE@ +XNEST_LIBS = @XNEST_LIBS@ +XNEST_TRUE = @XNEST_TRUE@ +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_BUS_FREEBSDPCI_FALSE = @XORG_BUS_FREEBSDPCI_FALSE@ +XORG_BUS_FREEBSDPCI_TRUE = @XORG_BUS_FREEBSDPCI_TRUE@ +XORG_BUS_IX86PCI_FALSE = @XORG_BUS_IX86PCI_FALSE@ +XORG_BUS_IX86PCI_TRUE = @XORG_BUS_IX86PCI_TRUE@ +XORG_BUS_LINUXPCI_FALSE = @XORG_BUS_LINUXPCI_FALSE@ +XORG_BUS_LINUXPCI_TRUE = @XORG_BUS_LINUXPCI_TRUE@ +XORG_BUS_NETBSDPCI_FALSE = @XORG_BUS_NETBSDPCI_FALSE@ +XORG_BUS_NETBSDPCI_TRUE = @XORG_BUS_NETBSDPCI_TRUE@ +XORG_BUS_PPCPCI_FALSE = @XORG_BUS_PPCPCI_FALSE@ +XORG_BUS_PPCPCI_TRUE = @XORG_BUS_PPCPCI_TRUE@ +XORG_BUS_SPARCPCI_FALSE = @XORG_BUS_SPARCPCI_FALSE@ +XORG_BUS_SPARCPCI_TRUE = @XORG_BUS_SPARCPCI_TRUE@ +XORG_BUS_SPARC_FALSE = @XORG_BUS_SPARC_FALSE@ +XORG_BUS_SPARC_TRUE = @XORG_BUS_SPARC_TRUE@ +XORG_CFLAGS = @XORG_CFLAGS@ +XORG_CORE_LIBS = @XORG_CORE_LIBS@ +XORG_FALSE = @XORG_FALSE@ +XORG_INCS = @XORG_INCS@ +XORG_LIBS = @XORG_LIBS@ +XORG_LOADER_SPARC_FALSE = @XORG_LOADER_SPARC_FALSE@ +XORG_LOADER_SPARC_TRUE = @XORG_LOADER_SPARC_TRUE@ +XORG_OS = @XORG_OS@ +XORG_OS_KBD = @XORG_OS_KBD@ +XORG_OS_SUBDIR = @XORG_OS_SUBDIR@ +XORG_TRUE = @XORG_TRUE@ +XPRINTPROTO_CFLAGS = @XPRINTPROTO_CFLAGS@ +XPRINTPROTO_LIBS = @XPRINTPROTO_LIBS@ +XPRINT_CFLAGS = @XPRINT_CFLAGS@ +XPRINT_FALSE = @XPRINT_FALSE@ +XPRINT_LIBS = @XPRINT_LIBS@ +XPRINT_TRUE = @XPRINT_TRUE@ +XP_USE_FREETYPE_FALSE = @XP_USE_FREETYPE_FALSE@ +XP_USE_FREETYPE_TRUE = @XP_USE_FREETYPE_TRUE@ +XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ +XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ +XSDLSERVER_FALSE = @XSDLSERVER_FALSE@ +XSDLSERVER_TRUE = @XSDLSERVER_TRUE@ +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@ +XTRAP_FALSE = @XTRAP_FALSE@ +XTRAP_TRUE = @XTRAP_TRUE@ +XTSTEXAMPLES_DEP_CFLAGS = @XTSTEXAMPLES_DEP_CFLAGS@ +XTSTEXAMPLES_DEP_LIBS = @XTSTEXAMPLES_DEP_LIBS@ +XVFB_FALSE = @XVFB_FALSE@ +XVFB_LIBS = @XVFB_LIBS@ +XVFB_TRUE = @XVFB_TRUE@ +XVMC_FALSE = @XVMC_FALSE@ +XVMC_TRUE = @XVMC_TRUE@ +XV_FALSE = @XV_FALSE@ +XV_TRUE = @XV_TRUE@ +XWINMODULES_CFLAGS = @XWINMODULES_CFLAGS@ +XWINMODULES_LIBS = @XWINMODULES_LIBS@ +XWIN_CLIPBOARD_FALSE = @XWIN_CLIPBOARD_FALSE@ +XWIN_CLIPBOARD_TRUE = @XWIN_CLIPBOARD_TRUE@ +XWIN_FALSE = @XWIN_FALSE@ +XWIN_GLX_WINDOWS_FALSE = @XWIN_GLX_WINDOWS_FALSE@ +XWIN_GLX_WINDOWS_TRUE = @XWIN_GLX_WINDOWS_TRUE@ +XWIN_LIBS = @XWIN_LIBS@ +XWIN_MULTIWINDOWEXTWM_FALSE = @XWIN_MULTIWINDOWEXTWM_FALSE@ +XWIN_MULTIWINDOWEXTWM_TRUE = @XWIN_MULTIWINDOWEXTWM_TRUE@ +XWIN_MULTIWINDOW_FALSE = @XWIN_MULTIWINDOW_FALSE@ +XWIN_MULTIWINDOW_TRUE = @XWIN_MULTIWINDOW_TRUE@ +XWIN_NATIVEGDI_FALSE = @XWIN_NATIVEGDI_FALSE@ +XWIN_NATIVEGDI_TRUE = @XWIN_NATIVEGDI_TRUE@ +XWIN_PRIMARYFB_FALSE = @XWIN_PRIMARYFB_FALSE@ +XWIN_PRIMARYFB_TRUE = @XWIN_PRIMARYFB_TRUE@ +XWIN_RANDR_FALSE = @XWIN_RANDR_FALSE@ +XWIN_RANDR_TRUE = @XWIN_RANDR_TRUE@ +XWIN_SERVER_NAME = @XWIN_SERVER_NAME@ +XWIN_SYSTEM_LIBS = @XWIN_SYSTEM_LIBS@ +XWIN_TRUE = @XWIN_TRUE@ +XWIN_XV_FALSE = @XWIN_XV_FALSE@ +XWIN_XV_TRUE = @XWIN_XV_TRUE@ +YACC = @YACC@ +__XCONFIGFILE__ = @__XCONFIGFILE__@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_AS = @ac_ct_AS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DLLTOOL = @ac_ct_DLLTOOL@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_OBJDUMP = @ac_ct_OBJDUMP@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +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@ +datadir = @datadir@ +driverdir = @driverdir@ +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@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +logdir = @logdir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sdkdir = @sdkdir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +xglmoduledir = @xglmoduledir@ +xpconfigdir = @xpconfigdir@ +noinst_LTLIBRARIES = libdix.la libxpstubs.la +AM_CFLAGS = $(DIX_CFLAGS) \ + -DVENDOR_STRING=\""@VENDOR_STRING@"\" \ + -DVENDOR_RELEASE="@VENDOR_RELEASE@" + +libdix_la_SOURCES = \ + atom.c \ + colormap.c \ + cursor.c \ + devices.c \ + dispatch.c \ + dispatch.h \ + dixfonts.c \ + dixutils.c \ + events.c \ + extension.c \ + ffs.c \ + gc.c \ + globals.c \ + glyphcurs.c \ + grabs.c \ + initatoms.c \ + main.c \ + pixmap.c \ + privates.c \ + property.c \ + resource.c \ + swaprep.c \ + swapreq.c \ + tables.c \ + window.c \ + strcasecmp.c + +libxpstubs_la_SOURCES = \ + xpstubs.c + +INCLUDES = -I$(top_srcdir)/Xprint +EXTRA_DIST = buildatoms BuiltInAtoms CHANGES +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 dix/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign dix/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 +libdix.la: $(libdix_la_OBJECTS) $(libdix_la_DEPENDENCIES) + $(LINK) $(libdix_la_LDFLAGS) $(libdix_la_OBJECTS) $(libdix_la_LIBADD) $(LIBS) +libxpstubs.la: $(libxpstubs_la_OBJECTS) $(libxpstubs_la_DEPENDENCIES) + $(LINK) $(libxpstubs_la_LDFLAGS) $(libxpstubs_la_OBJECTS) $(libxpstubs_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colormap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cursor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devices.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dispatch.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dixfonts.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dixutils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/events.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extension.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ffs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globals.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glyphcurs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grabs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initatoms.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pixmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/privates.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/property.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasecmp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swaprep.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swapreq.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/window.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xpstubs.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@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@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@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@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@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 + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +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; } \ + END { 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; } \ + END { 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=; \ + 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; } \ + END { 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)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + 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) +installdirs: +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-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +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-info-am + +.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-exec \ + install-exec-am install-info install-info-am install-man \ + 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-info-am + +# 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/xserver/dix/atom.c b/xserver/dix/atom.c new file mode 100644 index 000000000..d9d74f1da --- /dev/null +++ b/xserver/dix/atom.c @@ -0,0 +1,213 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#include <X11/Xatom.h> +#include <stdio.h> +#include <string.h> +#include "misc.h" +#include "resource.h" +#include "dix.h" + +#define InitialTableSize 100 + +typedef struct _Node { + struct _Node *left, *right; + Atom a; + unsigned int fingerPrint; + char *string; +} NodeRec, *NodePtr; + +static Atom lastAtom = None; +static NodePtr atomRoot = (NodePtr)NULL; +static unsigned long tableLength; +static NodePtr *nodeTable; + +void FreeAtom(NodePtr patom); + +_X_EXPORT Atom +MakeAtom(char *string, unsigned len, Bool makeit) +{ + register NodePtr * np; + unsigned i; + int comp; + register unsigned int fp = 0; + + np = &atomRoot; + for (i = 0; i < (len+1)/2; i++) + { + fp = fp * 27 + string[i]; + fp = fp * 27 + string[len - 1 - i]; + } + while (*np != (NodePtr) NULL) + { + if (fp < (*np)->fingerPrint) + np = &((*np)->left); + else if (fp > (*np)->fingerPrint) + np = &((*np)->right); + else + { /* now start testing the strings */ + comp = strncmp(string, (*np)->string, (int)len); + if ((comp < 0) || ((comp == 0) && (len < strlen((*np)->string)))) + np = &((*np)->left); + else if (comp > 0) + np = &((*np)->right); + else + return(*np)->a; + } + } + if (makeit) + { + register NodePtr nd; + + nd = (NodePtr) xalloc(sizeof(NodeRec)); + if (!nd) + return BAD_RESOURCE; + if (lastAtom < XA_LAST_PREDEFINED) + { + nd->string = string; + } + else + { + nd->string = (char *) xalloc(len + 1); + if (!nd->string) { + xfree(nd); + return BAD_RESOURCE; + } + strncpy(nd->string, string, (int)len); + nd->string[len] = 0; + } + if ((lastAtom + 1) >= tableLength) { + NodePtr *table; + + table = (NodePtr *) xrealloc(nodeTable, + tableLength * (2 * sizeof(NodePtr))); + if (!table) { + if (nd->string != string) + xfree(nd->string); + xfree(nd); + return BAD_RESOURCE; + } + tableLength <<= 1; + nodeTable = table; + } + *np = nd; + nd->left = nd->right = (NodePtr) NULL; + nd->fingerPrint = fp; + nd->a = (++lastAtom); + *(nodeTable+lastAtom) = nd; + return nd->a; + } + else + return None; +} + +_X_EXPORT Bool +ValidAtom(Atom atom) +{ + return (atom != None) && (atom <= lastAtom); +} + +_X_EXPORT char * +NameForAtom(Atom atom) +{ + NodePtr node; + if (atom > lastAtom) return 0; + if ((node = nodeTable[atom]) == (NodePtr)NULL) return 0; + return node->string; +} + +void +AtomError() +{ + FatalError("initializing atoms"); +} + +void +FreeAtom(NodePtr patom) +{ + if(patom->left) + FreeAtom(patom->left); + if(patom->right) + FreeAtom(patom->right); + if (patom->a > XA_LAST_PREDEFINED) + xfree(patom->string); + xfree(patom); +} + +void +FreeAllAtoms() +{ + if(atomRoot == (NodePtr)NULL) + return; + FreeAtom(atomRoot); + atomRoot = (NodePtr)NULL; + xfree(nodeTable); + nodeTable = (NodePtr *)NULL; + lastAtom = None; +} + +void +InitAtoms() +{ + FreeAllAtoms(); + tableLength = InitialTableSize; + nodeTable = (NodePtr *)xalloc(InitialTableSize*sizeof(NodePtr)); + if (!nodeTable) + AtomError(); + nodeTable[None] = (NodePtr)NULL; + MakePredeclaredAtoms(); + if (lastAtom != XA_LAST_PREDEFINED) + AtomError (); +} + + diff --git a/xserver/dix/buildatoms b/xserver/dix/buildatoms new file mode 100644 index 000000000..dfbbca8a9 --- /dev/null +++ b/xserver/dix/buildatoms @@ -0,0 +1,43 @@ +#!/bin/sh +hfile=../../../include/Xatom.h +cfile=initatoms.c +rm -f $hfile $cfile +umask 222 +awk ' +BEGIN { + hfile = "'$hfile'"; + cfile = "'$cfile'"; + hformat = "#define XA_%s ((Atom) %d)\n"; + printf("#ifndef XATOM_H\n") > hfile; + printf("#define XATOM_H 1\n\n") > hfile; + printf("/* THIS IS A GENERATED FILE\n") > hfile; + printf(" *\n") > hfile; + printf(" * Do not change! Changing this file implies a protocol change!\n") > hfile; + printf(" */\n\n") > hfile; + + printf("/* THIS IS A GENERATED FILE\n") > cfile; + printf(" *\n") > cfile; + printf(" * Do not change! Changing this file implies a protocol change!\n") > cfile; + printf(" */\n\n") > cfile; + printf("#include \"X.h\"\n") > cfile; + printf("#include \"Xatom.h\"\n") > cfile; + printf("#include \"misc.h\"\n") > cfile; + printf("#include \"dix.h\"\n") > cfile; + printf("void MakePredeclaredAtoms()\n") > cfile; + printf("{\n") > cfile; + + } + +NF == 2 && $2 == "@" { + printf(hformat, $1, ++atomno) > hfile ; + printf(" if (MakeAtom(\"%s\", %d, 1) != XA_%s) AtomError();\n", $1, length($1), $1) > cfile ; + } + +END { + printf("\n") > hfile; + printf(hformat, "LAST_PREDEFINED", atomno) > hfile ; + printf("#endif /* XATOM_H */\n") > hfile; + printf("}\n") > cfile ; + } +' BuiltInAtoms +exit 0 diff --git a/xserver/dix/colormap.c b/xserver/dix/colormap.c new file mode 100644 index 000000000..b8f2f4af6 --- /dev/null +++ b/xserver/dix/colormap.c @@ -0,0 +1,2699 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#define NEED_EVENTS +#include <X11/Xproto.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include "misc.h" +#include "dix.h" +#include "colormapst.h" +#include "os.h" +#include "scrnintstr.h" +#include "resource.h" +#include "windowstr.h" + +extern XID clientErrorValue; +extern int colormapPrivateCount; + +static Pixel FindBestPixel( + EntryPtr /*pentFirst*/, + int /*size*/, + xrgb * /*prgb*/, + int /*channel*/ +); + +static int AllComp( + EntryPtr /*pent*/, + xrgb * /*prgb*/ +); + +static int RedComp( + EntryPtr /*pent*/, + xrgb * /*prgb*/ +); + +static int GreenComp( + EntryPtr /*pent*/, + xrgb * /*prgb*/ +); + +static int BlueComp( + EntryPtr /*pent*/, + xrgb * /*prgb*/ +); + +static void FreePixels( + register ColormapPtr /*pmap*/, + register int /*client*/ +); + +static void CopyFree( + int /*channel*/, + int /*client*/, + ColormapPtr /*pmapSrc*/, + ColormapPtr /*pmapDst*/ +); + +static void FreeCell( + ColormapPtr /*pmap*/, + Pixel /*i*/, + int /*channel*/ +); + +static void UpdateColors( + ColormapPtr /*pmap*/ +); + +static int AllocDirect( + int /*client*/, + ColormapPtr /*pmap*/, + int /*c*/, + int /*r*/, + int /*g*/, + int /*b*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*prmask*/, + Pixel * /*pgmask*/, + Pixel * /*pbmask*/ +); + +static int AllocPseudo( + int /*client*/, + ColormapPtr /*pmap*/, + int /*c*/, + int /*r*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*pmask*/, + Pixel ** /*pppixFirst*/ +); + +static Bool AllocCP( + ColormapPtr /*pmap*/, + EntryPtr /*pentFirst*/, + int /*count*/, + int /*planes*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*pMask*/ +); + +static Bool AllocShared( + ColormapPtr /*pmap*/, + Pixel * /*ppix*/, + int /*c*/, + int /*r*/, + int /*g*/, + int /*b*/, + Pixel /*rmask*/, + Pixel /*gmask*/, + Pixel /*bmask*/, + Pixel * /*ppixFirst*/ +); + +static int FreeCo( + ColormapPtr /*pmap*/, + int /*client*/, + int /*color*/, + int /*npixIn*/, + Pixel * /*ppixIn*/, + Pixel /*mask*/ +); + +static int TellNoMap( + WindowPtr /*pwin*/, + Colormap * /*pmid*/ +); + +static void FindColorInRootCmap ( + ColormapPtr /* pmap */, + EntryPtr /* pentFirst */, + int /* size */, + xrgb* /* prgb */, + Pixel* /* pPixel */, + int /* channel */, + ColorCompareProcPtr /* comp */ +); + +#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1) +#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1) +#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1) +#if COMPOSITE +#define ALPHAMASK(vis) ((vis)->nplanes < 32 ? 0 : \ + (CARD32) ~((vis)->redMask|(vis)->greenMask|(vis)->blueMask)) +#else +#define ALPHAMASK(vis) 0 +#endif + +#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis)) + +/* GetNextBitsOrBreak(bits, mask, base) -- + * (Suggestion: First read the macro, then read this explanation. + * + * Either generate the next value to OR in to a pixel or break out of this + * while loop + * + * This macro is used when we're trying to generate all 2^n combinations of + * bits in mask. What we're doing here is counting in binary, except that + * the bits we use to count may not be contiguous. This macro will be + * called 2^n times, returning a different value in bits each time. Then + * it will cause us to break out of a surrounding loop. (It will always be + * called from within a while loop.) + * On call: mask is the value we want to find all the combinations for + * base has 1 bit set where the least significant bit of mask is set + * + * For example,if mask is 01010, base should be 0010 and we count like this: + * 00010 (see this isn't so hard), + * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so + * we add that to bits getting (0100 + 0100) = + * 01000 for our next value. + * then we add 0010 to get + * 01010 and we're done (easy as 1, 2, 3) + */ +#define GetNextBitsOrBreak(bits, mask, base) \ + if((bits) == (mask)) \ + break; \ + (bits) += (base); \ + while((bits) & ~(mask)) \ + (bits) += ((bits) & ~(mask)); +/* ID of server as client */ +#define SERVER_ID 0 + +typedef struct _colorResource +{ + Colormap mid; + int client; +} colorResource; + +/* Invariants: + * refcnt == 0 means entry is empty + * refcnt > 0 means entry is useable by many clients, so it can't be changed + * refcnt == AllocPrivate means entry owned by one client only + * fShared should only be set if refcnt == AllocPrivate, and only in red map + */ + + +/** + * Create and initialize the color map + * + * \param mid resource to use for this colormap + * \param alloc 1 iff all entries are allocated writable + */ +_X_EXPORT int +CreateColormap (Colormap mid, ScreenPtr pScreen, VisualPtr pVisual, + ColormapPtr *ppcmap, int alloc, int client) +{ + int class, size; + unsigned long sizebytes; + ColormapPtr pmap; + register EntryPtr pent; + int i; + register Pixel *ppix, **pptr; + + class = pVisual->class; + if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID)) + return (BadMatch); + + size = pVisual->ColormapEntries; + sizebytes = (size * sizeof(Entry)) + + (MAXCLIENTS * sizeof(Pixel *)) + + (MAXCLIENTS * sizeof(int)); + if ((class | DynamicClass) == DirectColor) + sizebytes *= 3; + sizebytes += sizeof(ColormapRec); + pmap = (ColormapPtr) xalloc(sizebytes); + if (!pmap) + return (BadAlloc); +#if defined(_XSERVER64) + pmap->pad0 = 0; + pmap->pad1 = 0; +#if (X_BYTE_ORDER == X_LITTLE_ENDIAN) + pmap->pad2 = 0; +#endif +#endif + pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec)); + sizebytes = size * sizeof(Entry); + pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes); + pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed + + (MAXCLIENTS * sizeof(Pixel *))); + pmap->mid = mid; + pmap->flags = 0; /* start out with all flags clear */ + if(mid == pScreen->defColormap) + pmap->flags |= IsDefault; + pmap->pScreen = pScreen; + pmap->pVisual = pVisual; + pmap->class = class; + if ((class | DynamicClass) == DirectColor) + size = NUMRED(pVisual); + pmap->freeRed = size; + bzero ((char *) pmap->red, (int)sizebytes); + bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int)); + for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; ) + *pptr = (Pixel *)NULL; + if (alloc == AllocAll) + { + if (class & DynamicClass) + pmap->flags |= AllAllocated; + for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--) + pent->refcnt = AllocPrivate; + pmap->freeRed = 0; + ppix = (Pixel *)xalloc(size * sizeof(Pixel)); + if (!ppix) + { + xfree(pmap); + return (BadAlloc); + } + pmap->clientPixelsRed[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsRed[client] = size; + } + + if ((class | DynamicClass) == DirectColor) + { + pmap->freeGreen = NUMGREEN(pVisual); + pmap->green = (EntryPtr)((char *)pmap->numPixelsRed + + (MAXCLIENTS * sizeof(int))); + pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes); + pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen + + (MAXCLIENTS * sizeof(Pixel *))); + pmap->freeBlue = NUMBLUE(pVisual); + pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen + + (MAXCLIENTS * sizeof(int))); + pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes); + pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue + + (MAXCLIENTS * sizeof(Pixel *))); + + bzero ((char *) pmap->green, (int)sizebytes); + bzero ((char *) pmap->blue, (int)sizebytes); + + memmove((char *) pmap->clientPixelsGreen, + (char *) pmap->clientPixelsRed, + MAXCLIENTS * sizeof(Pixel *)); + memmove((char *) pmap->clientPixelsBlue, + (char *) pmap->clientPixelsRed, + MAXCLIENTS * sizeof(Pixel *)); + bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int)); + bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int)); + + /* If every cell is allocated, mark its refcnt */ + if (alloc == AllocAll) + { + size = pmap->freeGreen; + for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--) + pent->refcnt = AllocPrivate; + pmap->freeGreen = 0; + ppix = (Pixel *) xalloc(size * sizeof(Pixel)); + if (!ppix) + { + xfree(pmap->clientPixelsRed[client]); + xfree(pmap); + return(BadAlloc); + } + pmap->clientPixelsGreen[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsGreen[client] = size; + + size = pmap->freeBlue; + for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--) + pent->refcnt = AllocPrivate; + pmap->freeBlue = 0; + ppix = (Pixel *) xalloc(size * sizeof(Pixel)); + if (!ppix) + { + xfree(pmap->clientPixelsGreen[client]); + xfree(pmap->clientPixelsRed[client]); + xfree(pmap); + return(BadAlloc); + } + pmap->clientPixelsBlue[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsBlue[client] = size; + } + } + if (!AddResource(mid, RT_COLORMAP, (pointer)pmap)) + return (BadAlloc); + /* If the device wants a chance to initialize the colormap in any way, + * this is it. In specific, if this is a Static colormap, this is the + * time to fill in the colormap's values */ + pmap->flags |= BeingCreated; + + + /* + * Allocate the array of devPrivate's for this colormap. + */ + + if (colormapPrivateCount == 0) + pmap->devPrivates = NULL; + else + { + pmap->devPrivates = (DevUnion *) xcalloc ( + sizeof(DevUnion), colormapPrivateCount); + if (!pmap->devPrivates) + { + FreeResource (mid, RT_NONE); + return BadAlloc; + } + } + + if (!(*pScreen->CreateColormap)(pmap)) + { + FreeResource (mid, RT_NONE); + return BadAlloc; + } + pmap->flags &= ~BeingCreated; + *ppcmap = pmap; + return (Success); +} + +/** + * + * \param value must conform to DeleteType + */ +int +FreeColormap (pointer value, XID mid) +{ + int i; + register EntryPtr pent; + ColormapPtr pmap = (ColormapPtr)value; + + if(CLIENT_ID(mid) != SERVER_ID) + { + (*pmap->pScreen->UninstallColormap) (pmap); + WalkTree(pmap->pScreen, (VisitWindowProcPtr)TellNoMap, (pointer) &mid); + } + + /* This is the device's chance to undo anything it needs to, especially + * to free any storage it allocated */ + (*pmap->pScreen->DestroyColormap)(pmap); + + if(pmap->clientPixelsRed) + { + for(i = 0; i < MAXCLIENTS; i++) + xfree(pmap->clientPixelsRed[i]); + } + + if ((pmap->class == PseudoColor) || (pmap->class == GrayScale)) + { + for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1]; + pent >= pmap->red; + pent--) + { + if(pent->fShared) + { + if (--pent->co.shco.red->refcnt == 0) + xfree(pent->co.shco.red); + if (--pent->co.shco.green->refcnt == 0) + xfree(pent->co.shco.green); + if (--pent->co.shco.blue->refcnt == 0) + xfree(pent->co.shco.blue); + } + } + } + if((pmap->class | DynamicClass) == DirectColor) + { + for(i = 0; i < MAXCLIENTS; i++) + { + xfree(pmap->clientPixelsGreen[i]); + xfree(pmap->clientPixelsBlue[i]); + } + } + + if (pmap->devPrivates) + xfree(pmap->devPrivates); + + xfree(pmap); + return(Success); +} + +/* Tell window that pmid has disappeared */ +static int +TellNoMap (WindowPtr pwin, Colormap *pmid) +{ + xEvent xE; + + if (wColormap(pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = None; + xE.u.colormap.new = TRUE; + xE.u.colormap.state = ColormapUninstalled; +#ifdef PANORAMIX + if(noPanoramiXExtension || !pwin->drawable.pScreen->myNum) +#endif + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + if (pwin->optional) { + pwin->optional->colormap = None; + CheckWindowOptionalNeed (pwin); + } + } + + return (WT_WALKCHILDREN); +} + +/* Tell window that pmid got uninstalled */ +_X_EXPORT int +TellLostMap (WindowPtr pwin, pointer value) +{ + Colormap *pmid = (Colormap *)value; + xEvent xE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum) + return WT_STOPWALKING; +#endif + if (wColormap(pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = *pmid; + xE.u.colormap.new = FALSE; + xE.u.colormap.state = ColormapUninstalled; + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + } + + return (WT_WALKCHILDREN); +} + +/* Tell window that pmid got installed */ +_X_EXPORT int +TellGainedMap (WindowPtr pwin, pointer value) +{ + Colormap *pmid = (Colormap *)value; + xEvent xE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum) + return WT_STOPWALKING; +#endif + if (wColormap (pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = *pmid; + xE.u.colormap.new = FALSE; + xE.u.colormap.state = ColormapInstalled; + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + } + + return (WT_WALKCHILDREN); +} + + +int +CopyColormapAndFree (Colormap mid, ColormapPtr pSrc, int client) +{ + ColormapPtr pmap = (ColormapPtr) NULL; + int result, alloc, size; + Colormap midSrc; + ScreenPtr pScreen; + VisualPtr pVisual; + + pScreen = pSrc->pScreen; + pVisual = pSrc->pVisual; + midSrc = pSrc->mid; + alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ? + AllocAll : AllocNone; + size = pVisual->ColormapEntries; + + /* If the create returns non-0, it failed */ + result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client); + if(result != Success) + return(result); + if(alloc == AllocAll) + { + memmove((char *)pmap->red, (char *)pSrc->red, size * sizeof(Entry)); + if((pmap->class | DynamicClass) == DirectColor) + { + memmove((char *)pmap->green, (char *)pSrc->green, size * sizeof(Entry)); + memmove((char *)pmap->blue, (char *)pSrc->blue, size * sizeof(Entry)); + } + pSrc->flags &= ~AllAllocated; + FreePixels(pSrc, client); + UpdateColors(pmap); + return(Success); + } + + CopyFree(REDMAP, client, pSrc, pmap); + if ((pmap->class | DynamicClass) == DirectColor) + { + CopyFree(GREENMAP, client, pSrc, pmap); + CopyFree(BLUEMAP, client, pSrc, pmap); + } + if (pmap->class & DynamicClass) + UpdateColors(pmap); + /* XXX should worry about removing any RT_CMAPENTRY resource */ + return(Success); +} + +/* Helper routine for freeing large numbers of cells from a map */ +static void +CopyFree (int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst) +{ + int z, npix; + EntryPtr pentSrcFirst, pentDstFirst; + EntryPtr pentSrc, pentDst; + Pixel *ppix; + int nalloc; + + switch(channel) + { + default: /* so compiler can see that everything gets initialized */ + case REDMAP: + ppix = (pmapSrc->clientPixelsRed)[client]; + npix = (pmapSrc->numPixelsRed)[client]; + pentSrcFirst = pmapSrc->red; + pentDstFirst = pmapDst->red; + break; + case GREENMAP: + ppix = (pmapSrc->clientPixelsGreen)[client]; + npix = (pmapSrc->numPixelsGreen)[client]; + pentSrcFirst = pmapSrc->green; + pentDstFirst = pmapDst->green; + break; + case BLUEMAP: + ppix = (pmapSrc->clientPixelsBlue)[client]; + npix = (pmapSrc->numPixelsBlue)[client]; + pentSrcFirst = pmapSrc->blue; + pentDstFirst = pmapDst->blue; + break; + } + nalloc = 0; + if (pmapSrc->class & DynamicClass) + { + for(z = npix; --z >= 0; ppix++) + { + /* Copy entries */ + pentSrc = pentSrcFirst + *ppix; + pentDst = pentDstFirst + *ppix; + if (pentDst->refcnt > 0) + { + pentDst->refcnt++; + } + else + { + *pentDst = *pentSrc; + nalloc++; + if (pentSrc->refcnt > 0) + pentDst->refcnt = 1; + else + pentSrc->fShared = FALSE; + } + FreeCell(pmapSrc, *ppix, channel); + } + } + + /* Note that FreeCell has already fixed pmapSrc->free{Color} */ + switch(channel) + { + case REDMAP: + pmapDst->freeRed -= nalloc; + (pmapDst->clientPixelsRed)[client] = + (pmapSrc->clientPixelsRed)[client]; + (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL; + (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client]; + (pmapSrc->numPixelsRed)[client] = 0; + break; + case GREENMAP: + pmapDst->freeGreen -= nalloc; + (pmapDst->clientPixelsGreen)[client] = + (pmapSrc->clientPixelsGreen)[client]; + (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL; + (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client]; + (pmapSrc->numPixelsGreen)[client] = 0; + break; + case BLUEMAP: + pmapDst->freeBlue -= nalloc; + pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client]; + pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL; + pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client]; + pmapSrc->numPixelsBlue[client] = 0; + break; + } +} + +/* Free the ith entry in a color map. Must handle freeing of + * colors allocated through AllocColorPlanes */ +static void +FreeCell (ColormapPtr pmap, Pixel i, int channel) +{ + EntryPtr pent; + int *pCount; + + + switch (channel) + { + default: /* so compiler can see that everything gets initialized */ + case PSEUDOMAP: + case REDMAP: + pent = (EntryPtr) &pmap->red[i]; + pCount = &pmap->freeRed; + break; + case GREENMAP: + pent = (EntryPtr) &pmap->green[i]; + pCount = &pmap->freeGreen; + break; + case BLUEMAP: + pent = (EntryPtr) &pmap->blue[i]; + pCount = &pmap->freeBlue; + break; + } + /* If it's not privately allocated and it's not time to free it, just + * decrement the count */ + if (pent->refcnt > 1) + pent->refcnt--; + else + { + /* If the color type is shared, find the sharedcolor. If decremented + * refcnt is 0, free the shared cell. */ + if (pent->fShared) + { + if(--pent->co.shco.red->refcnt == 0) + xfree(pent->co.shco.red); + if(--pent->co.shco.green->refcnt == 0) + xfree(pent->co.shco.green); + if(--pent->co.shco.blue->refcnt == 0) + xfree(pent->co.shco.blue); + pent->fShared = FALSE; + } + pent->refcnt = 0; + *pCount += 1; + } +} + +static void +UpdateColors (ColormapPtr pmap) +{ + xColorItem *defs; + register xColorItem *pdef; + register EntryPtr pent; + register VisualPtr pVisual; + int i, n, size; + + pVisual = pmap->pVisual; + size = pVisual->ColormapEntries; + defs = (xColorItem *)ALLOCATE_LOCAL(size * sizeof(xColorItem)); + if (!defs) + return; + n = 0; + pdef = defs; + if (pmap->class == DirectColor) + { + for (i = 0; i < size; i++) + { + if (!pmap->red[i].refcnt && + !pmap->green[i].refcnt && + !pmap->blue[i].refcnt) + continue; + pdef->pixel = ((Pixel)i << pVisual->offsetRed) | + ((Pixel)i << pVisual->offsetGreen) | + ((Pixel)i << pVisual->offsetBlue); + pdef->red = pmap->red[i].co.local.red; + pdef->green = pmap->green[i].co.local.green; + pdef->blue = pmap->blue[i].co.local.blue; + pdef->flags = DoRed|DoGreen|DoBlue; + pdef++; + n++; + } + } + else + { + for (i = 0, pent = pmap->red; i < size; i++, pent++) + { + if (!pent->refcnt) + continue; + pdef->pixel = i; + if(pent->fShared) + { + pdef->red = pent->co.shco.red->color; + pdef->green = pent->co.shco.green->color; + pdef->blue = pent->co.shco.blue->color; + } + else + { + pdef->red = pent->co.local.red; + pdef->green = pent->co.local.green; + pdef->blue = pent->co.local.blue; + } + pdef->flags = DoRed|DoGreen|DoBlue; + pdef++; + n++; + } + } + if (n) + (*pmap->pScreen->StoreColors)(pmap, n, defs); + DEALLOCATE_LOCAL(defs); +} + +/* Get a read-only color from a ColorMap (probably slow for large maps) + * Returns by changing the value in pred, pgreen, pblue and pPix + */ +_X_EXPORT int +AllocColor (ColormapPtr pmap, + unsigned short *pred, unsigned short *pgreen, unsigned short *pblue, + Pixel *pPix, int client) +{ + Pixel pixR, pixG, pixB; + int entries; + xrgb rgb; + int class; + VisualPtr pVisual; + int npix; + Pixel *ppix; + + pVisual = pmap->pVisual; + (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual); + rgb.red = *pred; + rgb.green = *pgreen; + rgb.blue = *pblue; + class = pmap->class; + entries = pVisual->ColormapEntries; + + /* If the colormap is being created, then we want to be able to change + * the colormap, even if it's a static type. Otherwise, we'd never be + * able to initialize static colormaps + */ + if(pmap->flags & BeingCreated) + class |= DynamicClass; + + /* If this is one of the static storage classes, and we're not initializing + * it, the best we can do is to find the closest color entry to the + * requested one and return that. + */ + switch (class) { + case StaticColor: + case StaticGray: + /* Look up all three components in the same pmap */ + *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP); + *pred = pmap->red[pixR].co.local.red; + *pgreen = pmap->red[pixR].co.local.green; + *pblue = pmap->red[pixR].co.local.blue; + npix = pmap->numPixelsRed[client]; + ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixR; + pmap->clientPixelsRed[client] = ppix; + pmap->numPixelsRed[client]++; + break; + + case TrueColor: + /* Look up each component in its own map, then OR them together */ + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP); + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP); + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP); + *pPix = (pixR << pVisual->offsetRed) | + (pixG << pVisual->offsetGreen) | + (pixB << pVisual->offsetBlue) | + ALPHAMASK(pVisual); + + *pred = pmap->red[pixR].co.local.red; + *pgreen = pmap->green[pixG].co.local.green; + *pblue = pmap->blue[pixB].co.local.blue; + npix = pmap->numPixelsRed[client]; + ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixR; + pmap->clientPixelsRed[client] = ppix; + npix = pmap->numPixelsGreen[client]; + ppix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixG; + pmap->clientPixelsGreen[client] = ppix; + npix = pmap->numPixelsBlue[client]; + ppix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixB; + pmap->clientPixelsBlue[client] = ppix; + pmap->numPixelsRed[client]++; + pmap->numPixelsGreen[client]++; + pmap->numPixelsBlue[client]++; + break; + + case GrayScale: + case PseudoColor: + if (pmap->mid != pmap->pScreen->defColormap && + pmap->pVisual->vid == pmap->pScreen->rootVisual) + { + ColormapPtr prootmap = (ColormapPtr) + SecurityLookupIDByType (clients[client], pmap->pScreen->defColormap, + RT_COLORMAP, SecurityReadAccess); + + if (pmap->class == prootmap->class) + FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, + pPix, PSEUDOMAP, AllComp); + } + if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP, + client, AllComp) != Success) + return (BadAlloc); + break; + + case DirectColor: + if (pmap->mid != pmap->pScreen->defColormap && + pmap->pVisual->vid == pmap->pScreen->rootVisual) + { + ColormapPtr prootmap = (ColormapPtr) + SecurityLookupIDByType (clients[client], pmap->pScreen->defColormap, + RT_COLORMAP, SecurityReadAccess); + + if (pmap->class == prootmap->class) + { + pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; + FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, + &pixR, REDMAP, RedComp); + pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; + FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb, + &pixG, GREENMAP, GreenComp); + pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; + FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb, + &pixB, BLUEMAP, BlueComp); + *pPix = pixR | pixG | pixB; + } + } + + pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; + if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP, + client, RedComp) != Success) + return (BadAlloc); + pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; + if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG, + GREENMAP, client, GreenComp) != Success) + { + (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0); + return (BadAlloc); + } + pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; + if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP, + client, BlueComp) != Success) + { + (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0); + (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0); + return (BadAlloc); + } + *pPix = pixR | pixG | pixB | ALPHAMASK(pVisual); + + break; + } + + /* if this is the client's first pixel in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((pmap->numPixelsRed[client] == 1) && + (CLIENT_ID(pmap->mid) != client) && + !(pmap->flags & BeingCreated)) + { + colorResource *pcr; + + pcr = (colorResource *) xalloc(sizeof(colorResource)); + if (!pcr) + { + (void)FreeColors(pmap, client, 1, pPix, (Pixel)0); + return (BadAlloc); + } + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + return (BadAlloc); + } + return (Success); +} + +/* + * FakeAllocColor -- fake an AllocColor request by + * returning a free pixel if availible, otherwise returning + * the closest matching pixel. This is used by the mi + * software sprite code to recolor cursors. A nice side-effect + * is that this routine will never return failure. + */ + +_X_EXPORT void +FakeAllocColor (register ColormapPtr pmap, register xColorItem *item) +{ + Pixel pixR, pixG, pixB; + Pixel temp; + int entries; + xrgb rgb; + int class; + register VisualPtr pVisual; + + pVisual = pmap->pVisual; + rgb.red = item->red; + rgb.green = item->green; + rgb.blue = item->blue; + (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual); + class = pmap->class; + entries = pVisual->ColormapEntries; + + switch (class) { + case GrayScale: + case PseudoColor: + item->pixel = 0; + if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP, + -1, AllComp) == Success) { + item->pixel = temp; + break; + } + /* fall through ... */ + case StaticColor: + case StaticGray: + item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP); + break; + + case DirectColor: + /* Look up each component in its own map, then OR them together */ + pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed; + pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen; + pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP, + -1, RedComp) != Success) + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP) + << pVisual->offsetRed; + if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG, + GREENMAP, -1, GreenComp) != Success) + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, + GREENMAP) << pVisual->offsetGreen; + if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP, + -1, BlueComp) != Success) + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP) + << pVisual->offsetBlue; + item->pixel = pixR | pixG | pixB; + break; + + case TrueColor: + /* Look up each component in its own map, then OR them together */ + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP); + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP); + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP); + item->pixel = (pixR << pVisual->offsetRed) | + (pixG << pVisual->offsetGreen) | + (pixB << pVisual->offsetBlue); + break; + } +} + +/* free a pixel value obtained from FakeAllocColor */ +_X_EXPORT void +FakeFreeColor(register ColormapPtr pmap, Pixel pixel) +{ + register VisualPtr pVisual; + Pixel pixR, pixG, pixB; + + switch (pmap->class) { + case GrayScale: + case PseudoColor: + if (pmap->red[pixel].refcnt == AllocTemporary) + pmap->red[pixel].refcnt = 0; + break; + case DirectColor: + pVisual = pmap->pVisual; + pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed; + pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; + pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (pmap->red[pixR].refcnt == AllocTemporary) + pmap->red[pixR].refcnt = 0; + if (pmap->green[pixG].refcnt == AllocTemporary) + pmap->green[pixG].refcnt = 0; + if (pmap->blue[pixB].refcnt == AllocTemporary) + pmap->blue[pixB].refcnt = 0; + break; + } +} + +typedef unsigned short BigNumUpper; +typedef unsigned long BigNumLower; + +#define BIGNUMLOWERBITS 24 +#define BIGNUMUPPERBITS 16 +#define BIGNUMLOWER (1 << BIGNUMLOWERBITS) +#define BIGNUMUPPER (1 << BIGNUMUPPERBITS) +#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS) +#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1)) + +typedef struct _bignum { + BigNumUpper upper; + BigNumLower lower; +} BigNumRec, *BigNumPtr; + +#define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\ + ((x)->upper == (y)->upper && (x)->lower > (y)->lower)) + +#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \ + ((r)->lower = LOWERPART(u))) + +#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \ + ((r)->lower = BIGNUMLOWER-1)) + +static void +BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r) +{ + BigNumLower lower, carry = 0; + + lower = x->lower + y->lower; + if (lower >= BIGNUMLOWER) { + lower -= BIGNUMLOWER; + carry = 1; + } + r->lower = lower; + r->upper = x->upper + y->upper + carry; +} + +static Pixel +FindBestPixel(EntryPtr pentFirst, int size, xrgb *prgb, int channel) +{ + EntryPtr pent; + Pixel pixel, final; + long dr, dg, db; + unsigned long sq; + BigNumRec minval, sum, temp; + + final = 0; + MaxBigNum(&minval); + /* look for the minimal difference */ + for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++) + { + dr = dg = db = 0; + switch(channel) + { + case PSEUDOMAP: + dg = (long) pent->co.local.green - prgb->green; + db = (long) pent->co.local.blue - prgb->blue; + case REDMAP: + dr = (long) pent->co.local.red - prgb->red; + break; + case GREENMAP: + dg = (long) pent->co.local.green - prgb->green; + break; + case BLUEMAP: + db = (long) pent->co.local.blue - prgb->blue; + break; + } + sq = dr * dr; + UnsignedToBigNum (sq, &sum); + sq = dg * dg; + UnsignedToBigNum (sq, &temp); + BigNumAdd (&sum, &temp, &sum); + sq = db * db; + UnsignedToBigNum (sq, &temp); + BigNumAdd (&sum, &temp, &sum); + if (BigNumGreater (&minval, &sum)) + { + final = pixel; + minval = sum; + } + } + return(final); +} + +static void +FindColorInRootCmap (ColormapPtr pmap, EntryPtr pentFirst, int size, + xrgb *prgb, Pixel *pPixel, int channel, + ColorCompareProcPtr comp) +{ + EntryPtr pent; + Pixel pixel; + int count; + + if ((pixel = *pPixel) >= size) + pixel = 0; + for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++) + { + if (pent->refcnt > 0 && (*comp) (pent, prgb)) + { + switch (channel) + { + case REDMAP: + pixel <<= pmap->pVisual->offsetRed; + break; + case GREENMAP: + pixel <<= pmap->pVisual->offsetGreen; + break; + case BLUEMAP: + pixel <<= pmap->pVisual->offsetBlue; + break; + default: /* PSEUDOMAP */ + break; + } + *pPixel = pixel; + } + } +} + +/* Tries to find a color in pmap that exactly matches the one requested in prgb + * if it can't it allocates one. + * Starts looking at pentFirst + *pPixel, so if you want a specific pixel, + * load *pPixel with that value, otherwise set it to 0 + */ +int +FindColor (ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb *prgb, + Pixel *pPixel, int channel, int client, + ColorCompareProcPtr comp) +{ + EntryPtr pent; + Bool foundFree; + Pixel pixel, Free = 0; + int npix, count, *nump = NULL; + Pixel **pixp = NULL, *ppix; + xColorItem def; + + foundFree = FALSE; + + if((pixel = *pPixel) >= size) + pixel = 0; + /* see if there is a match, and also look for a free entry */ + for (pent = pentFirst + pixel, count = size; --count >= 0; ) + { + if (pent->refcnt > 0) + { + if ((*comp) (pent, prgb)) + { + if (client >= 0) + pent->refcnt++; + *pPixel = pixel; + switch(channel) + { + case REDMAP: + *pPixel <<= pmap->pVisual->offsetRed; + case PSEUDOMAP: + break; + case GREENMAP: + *pPixel <<= pmap->pVisual->offsetGreen; + break; + case BLUEMAP: + *pPixel <<= pmap->pVisual->offsetBlue; + break; + } + goto gotit; + } + } + else if (!foundFree && pent->refcnt == 0) + { + Free = pixel; + foundFree = TRUE; + /* If we're initializing the colormap, then we are looking for + * the first free cell we can find, not to minimize the number + * of entries we use. So don't look any further. */ + if(pmap->flags & BeingCreated) + break; + } + pixel++; + if(pixel >= size) + { + pent = pentFirst; + pixel = 0; + } + else + pent++; + } + + /* If we got here, we didn't find a match. If we also didn't find + * a free entry, we're out of luck. Otherwise, we'll usurp a free + * entry and fill it in */ + if (!foundFree) + return (BadAlloc); + pent = pentFirst + Free; + pent->fShared = FALSE; + pent->refcnt = (client >= 0) ? 1 : AllocTemporary; + + switch (channel) + { + case PSEUDOMAP: + pent->co.local.red = prgb->red; + pent->co.local.green = prgb->green; + pent->co.local.blue = prgb->blue; + def.red = prgb->red; + def.green = prgb->green; + def.blue = prgb->blue; + def.flags = (DoRed|DoGreen|DoBlue); + if (client >= 0) + pmap->freeRed--; + def.pixel = Free; + break; + + case REDMAP: + pent->co.local.red = prgb->red; + def.red = prgb->red; + def.green = pmap->green[0].co.local.green; + def.blue = pmap->blue[0].co.local.blue; + def.flags = DoRed; + if (client >= 0) + pmap->freeRed--; + def.pixel = Free << pmap->pVisual->offsetRed; + break; + + case GREENMAP: + pent->co.local.green = prgb->green; + def.red = pmap->red[0].co.local.red; + def.green = prgb->green; + def.blue = pmap->blue[0].co.local.blue; + def.flags = DoGreen; + if (client >= 0) + pmap->freeGreen--; + def.pixel = Free << pmap->pVisual->offsetGreen; + break; + + case BLUEMAP: + pent->co.local.blue = prgb->blue; + def.red = pmap->red[0].co.local.red; + def.green = pmap->green[0].co.local.green; + def.blue = prgb->blue; + def.flags = DoBlue; + if (client >= 0) + pmap->freeBlue--; + def.pixel = Free << pmap->pVisual->offsetBlue; + break; + } + (*pmap->pScreen->StoreColors) (pmap, 1, &def); + pixel = Free; + *pPixel = def.pixel; + +gotit: + if (pmap->flags & BeingCreated || client == -1) + return(Success); + /* Now remember the pixel, for freeing later */ + switch (channel) + { + case PSEUDOMAP: + case REDMAP: + nump = pmap->numPixelsRed; + pixp = pmap->clientPixelsRed; + break; + + case GREENMAP: + nump = pmap->numPixelsGreen; + pixp = pmap->clientPixelsGreen; + break; + + case BLUEMAP: + nump = pmap->numPixelsBlue; + pixp = pmap->clientPixelsBlue; + break; + } + npix = nump[client]; + ppix = (Pixel *) xrealloc (pixp[client], (npix + 1) * sizeof(Pixel)); + if (!ppix) + { + pent->refcnt--; + if (!pent->fShared) + switch (channel) + { + case PSEUDOMAP: + case REDMAP: + pmap->freeRed++; + break; + case GREENMAP: + pmap->freeGreen++; + break; + case BLUEMAP: + pmap->freeBlue++; + break; + } + return(BadAlloc); + } + ppix[npix] = pixel; + pixp[client] = ppix; + nump[client]++; + + return(Success); +} + +/* Comparison functions -- passed to FindColor to determine if an + * entry is already the color we're looking for or not */ +static int +AllComp (EntryPtr pent, xrgb *prgb) +{ + if((pent->co.local.red == prgb->red) && + (pent->co.local.green == prgb->green) && + (pent->co.local.blue == prgb->blue) ) + return (1); + return (0); +} + +static int +RedComp (EntryPtr pent, xrgb *prgb) +{ + if (pent->co.local.red == prgb->red) + return (1); + return (0); +} + +static int +GreenComp (EntryPtr pent, xrgb *prgb) +{ + if (pent->co.local.green == prgb->green) + return (1); + return (0); +} + +static int +BlueComp (EntryPtr pent, xrgb *prgb) +{ + if (pent->co.local.blue == prgb->blue) + return (1); + return (0); +} + + +/* Read the color value of a cell */ + +_X_EXPORT int +QueryColors (ColormapPtr pmap, int count, Pixel *ppixIn, xrgb *prgbList) +{ + Pixel *ppix, pixel; + xrgb *prgb; + VisualPtr pVisual; + EntryPtr pent; + Pixel i; + int errVal = Success; + + pVisual = pmap->pVisual; + if ((pmap->class | DynamicClass) == DirectColor) + { + int numred, numgreen, numblue; + Pixel rgbbad; + + numred = NUMRED(pVisual); + numgreen = NUMGREEN(pVisual); + numblue = NUMBLUE(pVisual); + rgbbad = ~RGBMASK(pVisual); + for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) + { + pixel = *ppix; + if (pixel & rgbbad) { + clientErrorValue = pixel; + errVal = BadValue; + continue; + } + i = (pixel & pVisual->redMask) >> pVisual->offsetRed; + if (i >= numred) + { + clientErrorValue = pixel; + errVal = BadValue; + continue; + } + prgb->red = pmap->red[i].co.local.red; + i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; + if (i >= numgreen) + { + clientErrorValue = pixel; + errVal = BadValue; + continue; + } + prgb->green = pmap->green[i].co.local.green; + i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (i >= numblue) + { + clientErrorValue = pixel; + errVal = BadValue; + continue; + } + prgb->blue = pmap->blue[i].co.local.blue; + } + } + else + { + for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) + { + pixel = *ppix; + if (pixel >= pVisual->ColormapEntries) + { + clientErrorValue = pixel; + errVal = BadValue; + } + else + { + pent = (EntryPtr)&pmap->red[pixel]; + if (pent->fShared) + { + prgb->red = pent->co.shco.red->color; + prgb->green = pent->co.shco.green->color; + prgb->blue = pent->co.shco.blue->color; + } + else + { + prgb->red = pent->co.local.red; + prgb->green = pent->co.local.green; + prgb->blue = pent->co.local.blue; + } + } + } + } + return (errVal); +} + +static void +FreePixels(register ColormapPtr pmap, register int client) +{ + register Pixel *ppix, *ppixStart; + register int n; + int class; + + class = pmap->class; + ppixStart = pmap->clientPixelsRed[client]; + if (class & DynamicClass) + { + n = pmap->numPixelsRed[client]; + for (ppix = ppixStart; --n >= 0; ) + { + FreeCell(pmap, *ppix, REDMAP); + ppix++; + } + } + + xfree(ppixStart); + pmap->clientPixelsRed[client] = (Pixel *) NULL; + pmap->numPixelsRed[client] = 0; + if ((class | DynamicClass) == DirectColor) + { + ppixStart = pmap->clientPixelsGreen[client]; + if (class & DynamicClass) + for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;) + FreeCell(pmap, *ppix++, GREENMAP); + xfree(ppixStart); + pmap->clientPixelsGreen[client] = (Pixel *) NULL; + pmap->numPixelsGreen[client] = 0; + + ppixStart = pmap->clientPixelsBlue[client]; + if (class & DynamicClass) + for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; ) + FreeCell(pmap, *ppix++, BLUEMAP); + xfree(ppixStart); + pmap->clientPixelsBlue[client] = (Pixel *) NULL; + pmap->numPixelsBlue[client] = 0; + } +} + +/** + * Frees all of a client's colors and cells. + * + * \param value must conform to DeleteType + * \unused fakeid + */ +int +FreeClientPixels (pointer value, XID fakeid) +{ + ColormapPtr pmap; + colorResource *pcr = (colorResource *)value; + + pmap = (ColormapPtr) LookupIDByType(pcr->mid, RT_COLORMAP); + if (pmap) + FreePixels(pmap, pcr->client); + xfree(pcr); + return Success; +} + +int +AllocColorCells (int client, ColormapPtr pmap, int colors, int planes, + Bool contig, Pixel *ppix, Pixel *masks) +{ + Pixel rmask, gmask, bmask, *ppixFirst, r, g, b; + int n, class; + int ok; + int oldcount; + colorResource *pcr = (colorResource *)NULL; + + class = pmap->class; + if (!(class & DynamicClass)) + return (BadAlloc); /* Shouldn't try on this type */ + oldcount = pmap->numPixelsRed[client]; + if (pmap->class == DirectColor) + oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client]; + if (!oldcount && (CLIENT_ID(pmap->mid) != client)) + { + pcr = (colorResource *) xalloc(sizeof(colorResource)); + if (!pcr) + return (BadAlloc); + } + + if (pmap->class == DirectColor) + { + ok = AllocDirect (client, pmap, colors, planes, planes, planes, + contig, ppix, &rmask, &gmask, &bmask); + if(ok == Success) + { + for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b) + { + while(!(rmask & r)) + r += r; + while(!(gmask & g)) + g += g; + while(!(bmask & b)) + b += b; + *masks++ = r | g | b; + } + } + } + else + { + ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask, + &ppixFirst); + if(ok == Success) + { + for (r = 1, n = planes; --n >= 0; r += r) + { + while(!(rmask & r)) + r += r; + *masks++ = r; + } + } + } + + /* if this is the client's first pixels in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((ok == Success) && pcr) + { + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + ok = BadAlloc; + } else if (pcr) + xfree(pcr); + + return (ok); +} + + +int +AllocColorPlanes (int client, ColormapPtr pmap, int colors, + int r, int g, int b, Bool contig, Pixel *pixels, + Pixel *prmask, Pixel *pgmask, Pixel *pbmask) +{ + int ok; + Pixel mask, *ppixFirst; + register Pixel shift; + register int i; + int class; + int oldcount; + colorResource *pcr = (colorResource *)NULL; + + class = pmap->class; + if (!(class & DynamicClass)) + return (BadAlloc); /* Shouldn't try on this type */ + oldcount = pmap->numPixelsRed[client]; + if (class == DirectColor) + oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client]; + if (!oldcount && (CLIENT_ID(pmap->mid) != client)) + { + pcr = (colorResource *) xalloc(sizeof(colorResource)); + if (!pcr) + return (BadAlloc); + } + + if (class == DirectColor) + { + ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels, + prmask, pgmask, pbmask); + } + else + { + /* Allocate the proper pixels */ + /* XXX This is sort of bad, because of contig is set, we force all + * r + g + b bits to be contiguous. Should only force contiguity + * per mask + */ + ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels, + &mask, &ppixFirst); + + if(ok == Success) + { + /* now split that mask into three */ + *prmask = *pgmask = *pbmask = 0; + shift = 1; + for (i = r; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *prmask |= shift; + } + for (i = g; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *pgmask |= shift; + } + for (i = b; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *pbmask |= shift; + } + + /* set up the shared color cells */ + if (!AllocShared(pmap, pixels, colors, r, g, b, + *prmask, *pgmask, *pbmask, ppixFirst)) + { + (void)FreeColors(pmap, client, colors, pixels, mask); + ok = BadAlloc; + } + } + } + + /* if this is the client's first pixels in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((ok == Success) && pcr) + { + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + ok = BadAlloc; + } else if (pcr) + xfree(pcr); + + return (ok); +} + +static int +AllocDirect (int client, ColormapPtr pmap, int c, int r, int g, int b, Bool contig, + Pixel *pixels, Pixel *prmask, Pixel *pgmask, Pixel *pbmask) +{ + Pixel *ppixRed, *ppixGreen, *ppixBlue; + Pixel *ppix, *pDst, *p; + int npix, npixR, npixG, npixB; + Bool okR, okG, okB; + Pixel *rpix = 0, *gpix = 0, *bpix = 0; + + npixR = c << r; + npixG = c << g; + npixB = c << b; + if ((r >= 32) || (g >= 32) || (b >= 32) || + (npixR > pmap->freeRed) || (npixR < c) || + (npixG > pmap->freeGreen) || (npixG < c) || + (npixB > pmap->freeBlue) || (npixB < c)) + return BadAlloc; + + /* start out with empty pixels */ + for(p = pixels; p < pixels + c; p++) + *p = 0; + + ppixRed = (Pixel *)ALLOCATE_LOCAL(npixR * sizeof(Pixel)); + ppixGreen = (Pixel *)ALLOCATE_LOCAL(npixG * sizeof(Pixel)); + ppixBlue = (Pixel *)ALLOCATE_LOCAL(npixB * sizeof(Pixel)); + if (!ppixRed || !ppixGreen || !ppixBlue) + { + if (ppixBlue) DEALLOCATE_LOCAL(ppixBlue); + if (ppixGreen) DEALLOCATE_LOCAL(ppixGreen); + if (ppixRed) DEALLOCATE_LOCAL(ppixRed); + return(BadAlloc); + } + + okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask); + okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask); + okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask); + + if (okR && okG && okB) + { + rpix = (Pixel *) xrealloc(pmap->clientPixelsRed[client], + (pmap->numPixelsRed[client] + (c << r)) * + sizeof(Pixel)); + if (rpix) + pmap->clientPixelsRed[client] = rpix; + gpix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client], + (pmap->numPixelsGreen[client] + (c << g)) * + sizeof(Pixel)); + if (gpix) + pmap->clientPixelsGreen[client] = gpix; + bpix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client], + (pmap->numPixelsBlue[client] + (c << b)) * + sizeof(Pixel)); + if (bpix) + pmap->clientPixelsBlue[client] = bpix; + } + + if (!okR || !okG || !okB || !rpix || !gpix || !bpix) + { + if (okR) + for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++) + pmap->red[*ppix].refcnt = 0; + if (okG) + for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++) + pmap->green[*ppix].refcnt = 0; + if (okB) + for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++) + pmap->blue[*ppix].refcnt = 0; + DEALLOCATE_LOCAL(ppixBlue); + DEALLOCATE_LOCAL(ppixGreen); + DEALLOCATE_LOCAL(ppixRed); + return(BadAlloc); + } + + *prmask <<= pmap->pVisual->offsetRed; + *pgmask <<= pmap->pVisual->offsetGreen; + *pbmask <<= pmap->pVisual->offsetBlue; + + ppix = rpix + pmap->numPixelsRed[client]; + for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++) + { + *ppix++ = *p; + if(p < ppixRed + c) + *pDst++ |= *p << pmap->pVisual->offsetRed; + } + pmap->numPixelsRed[client] += npixR; + pmap->freeRed -= npixR; + + ppix = gpix + pmap->numPixelsGreen[client]; + for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++) + { + *ppix++ = *p; + if(p < ppixGreen + c) + *pDst++ |= *p << pmap->pVisual->offsetGreen; + } + pmap->numPixelsGreen[client] += npixG; + pmap->freeGreen -= npixG; + + ppix = bpix + pmap->numPixelsBlue[client]; + for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++) + { + *ppix++ = *p; + if(p < ppixBlue + c) + *pDst++ |= *p << pmap->pVisual->offsetBlue; + } + pmap->numPixelsBlue[client] += npixB; + pmap->freeBlue -= npixB; + + + for (pDst = pixels; pDst < pixels + c; pDst++) + *pDst |= ALPHAMASK(pmap->pVisual); + + DEALLOCATE_LOCAL(ppixBlue); + DEALLOCATE_LOCAL(ppixGreen); + DEALLOCATE_LOCAL(ppixRed); + + return (Success); +} + +static int +AllocPseudo (int client, ColormapPtr pmap, int c, int r, Bool contig, + Pixel *pixels, Pixel *pmask, Pixel **pppixFirst) +{ + Pixel *ppix, *p, *pDst, *ppixTemp; + int npix; + Bool ok; + + npix = c << r; + if ((r >= 32) || (npix > pmap->freeRed) || (npix < c)) + return(BadAlloc); + if(!(ppixTemp = (Pixel *)ALLOCATE_LOCAL(npix * sizeof(Pixel)))) + return(BadAlloc); + ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask); + + if (ok) + { + + /* all the allocated pixels are added to the client pixel list, + * but only the unique ones are returned to the client */ + ppix = (Pixel *)xrealloc(pmap->clientPixelsRed[client], + (pmap->numPixelsRed[client] + npix) * sizeof(Pixel)); + if (!ppix) + { + for (p = ppixTemp; p < ppixTemp + npix; p++) + pmap->red[*p].refcnt = 0; + return (BadAlloc); + } + pmap->clientPixelsRed[client] = ppix; + ppix += pmap->numPixelsRed[client]; + *pppixFirst = ppix; + pDst = pixels; + for (p = ppixTemp; p < ppixTemp + npix; p++) + { + *ppix++ = *p; + if(p < ppixTemp + c) + *pDst++ = *p; + } + pmap->numPixelsRed[client] += npix; + pmap->freeRed -= npix; + } + DEALLOCATE_LOCAL(ppixTemp); + return (ok ? Success : BadAlloc); +} + +/* Allocates count << planes pixels from colormap pmap for client. If + * contig, then the plane mask is made of consecutive bits. Returns + * all count << pixels in the array pixels. The first count of those + * pixels are the unique pixels. *pMask has the mask to Or with the + * unique pixels to get the rest of them. + * + * Returns True iff all pixels could be allocated + * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE + * (see AllocShared for why we care) + */ +static Bool +AllocCP (ColormapPtr pmap, EntryPtr pentFirst, int count, int planes, + Bool contig, Pixel *pixels, Pixel *pMask) +{ + EntryPtr ent; + Pixel pixel, base, entries, maxp, save; + int dplanes, found; + Pixel *ppix; + Pixel mask; + Pixel finalmask; + + dplanes = pmap->pVisual->nplanes; + + /* Easy case. Allocate pixels only */ + if (planes == 0) + { + /* allocate writable entries */ + ppix = pixels; + ent = pentFirst; + pixel = 0; + while (--count >= 0) + { + /* Just find count unallocated cells */ + while (ent->refcnt) + { + ent++; + pixel++; + } + ent->refcnt = AllocPrivate; + *ppix++ = pixel; + ent->fShared = FALSE; + } + *pMask = 0; + return (TRUE); + } + else if (planes > dplanes) + { + return (FALSE); + } + + /* General case count pixels * 2 ^ planes cells to be allocated */ + + /* make room for new pixels */ + ent = pentFirst; + + /* first try for contiguous planes, since it's fastest */ + for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1); + --dplanes >= 0; + mask += mask, base += base) + { + ppix = pixels; + found = 0; + pixel = 0; + entries = pmap->pVisual->ColormapEntries - mask; + while (pixel < entries) + { + save = pixel; + maxp = pixel + mask + base; + /* check if all are free */ + while (pixel != maxp && ent[pixel].refcnt == 0) + pixel += base; + if (pixel == maxp) + { + /* this one works */ + *ppix++ = save; + found++; + if (found == count) + { + /* found enough, allocate them all */ + while (--count >= 0) + { + pixel = pixels[count]; + maxp = pixel + mask; + while (1) + { + ent[pixel].refcnt = AllocPrivate; + ent[pixel].fShared = FALSE; + if (pixel == maxp) + break; + pixel += base; + *ppix++ = pixel; + } + } + *pMask = mask; + return (TRUE); + } + } + pixel = save + 1; + if (pixel & mask) + pixel += mask; + } + } + + dplanes = pmap->pVisual->nplanes; + if (contig || planes == 1 || dplanes < 3) + return (FALSE); + + /* this will be very slow for large maps, need a better algorithm */ + + /* + we can generate the smallest and largest numbers that fits in dplanes + bits and contain exactly planes bits set as follows. First, we need to + check that it is possible to generate such a mask at all. + (Non-contiguous masks need one more bit than contiguous masks). Then + the smallest such mask consists of the rightmost planes-1 bits set, then + a zero, then a one in position planes + 1. The formula is + (3 << (planes-1)) -1 + The largest such masks consists of the leftmost planes-1 bits set, then + a zero, then a one bit in position dplanes-planes-1. If dplanes is + smaller than 32 (the number of bits in a word) then the formula is: + (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1) + If dplanes = 32, then we can't calculate (1<<dplanes) and we have + to use: + ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1)) + + << Thank you, Loretta>>> + + */ + + finalmask = + (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) + + (((Pixel)1)<<(dplanes-planes-1)); + for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++) + { + /* next 3 magic statements count number of ones (HAKMEM #169) */ + pixel = (mask >> 1) & 033333333333; + pixel = mask - pixel - ((pixel >> 1) & 033333333333); + if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes) + continue; + ppix = pixels; + found = 0; + entries = pmap->pVisual->ColormapEntries - mask; + base = lowbit (mask); + for (pixel = 0; pixel < entries; pixel++) + { + if (pixel & mask) + continue; + maxp = 0; + /* check if all are free */ + while (ent[pixel + maxp].refcnt == 0) + { + GetNextBitsOrBreak(maxp, mask, base); + } + if ((maxp < mask) || (ent[pixel + mask].refcnt != 0)) + continue; + /* this one works */ + *ppix++ = pixel; + found++; + if (found < count) + continue; + /* found enough, allocate them all */ + while (--count >= 0) + { + pixel = (pixels)[count]; + maxp = 0; + while (1) + { + ent[pixel + maxp].refcnt = AllocPrivate; + ent[pixel + maxp].fShared = FALSE; + GetNextBitsOrBreak(maxp, mask, base); + *ppix++ = pixel + maxp; + } + } + + *pMask = mask; + return (TRUE); + } + } + return (FALSE); +} + +/** + * + * \param ppixFirst First of the client's new pixels + */ +static Bool +AllocShared (ColormapPtr pmap, Pixel *ppix, int c, int r, int g, int b, + Pixel rmask, Pixel gmask, Pixel bmask, Pixel *ppixFirst) +{ + Pixel *pptr, *cptr; + int npix, z, npixClientNew, npixShared; + Pixel basemask, base, bits, common; + SHAREDCOLOR *pshared, **ppshared, **psharedList; + + npixClientNew = c << (r + g + b); + npixShared = (c << r) + (c << g) + (c << b); + psharedList = (SHAREDCOLOR **)ALLOCATE_LOCAL(npixShared * + sizeof(SHAREDCOLOR *)); + if (!psharedList) + return FALSE; + ppshared = psharedList; + for (z = npixShared; --z >= 0; ) + { + if (!(ppshared[z] = (SHAREDCOLOR *)xalloc(sizeof(SHAREDCOLOR)))) + { + for (z++ ; z < npixShared; z++) + xfree(ppshared[z]); + return FALSE; + } + } + for(pptr = ppix, npix = c; --npix >= 0; pptr++) + { + basemask = ~(gmask | bmask); + common = *pptr & basemask; + if (rmask) + { + bits = 0; + base = lowbit (rmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].fShared = TRUE; + pmap->red[*cptr].co.shco.red = pshared; + } + } + GetNextBitsOrBreak(bits, rmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].fShared = TRUE; + pmap->red[*cptr].co.shco.red = pshared; + } + } + } + basemask = ~(rmask | bmask); + common = *pptr & basemask; + if (gmask) + { + bits = 0; + base = lowbit (gmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (r + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].co.shco.green = pshared; + } + } + GetNextBitsOrBreak(bits, gmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].co.shco.green = pshared; + } + } + } + basemask = ~(rmask | gmask); + common = *pptr & basemask; + if (bmask) + { + bits = 0; + base = lowbit (bmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (r + g); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].co.shco.blue = pshared; + } + } + GetNextBitsOrBreak(bits, bmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].co.shco.blue = pshared; + } + } + } + } + DEALLOCATE_LOCAL(psharedList); + return TRUE; +} + + +/** FreeColors + * Free colors and/or cells (probably slow for large numbers) + */ +_X_EXPORT int +FreeColors (ColormapPtr pmap, int client, int count, Pixel *pixels, Pixel mask) +{ + int rval, result, class; + Pixel rmask; + + class = pmap->class; + if (pmap->flags & AllAllocated) + return(BadAccess); + if ((class | DynamicClass) == DirectColor) + { + rmask = mask & RGBMASK(pmap->pVisual); + result = FreeCo(pmap, client, REDMAP, count, pixels, + mask & pmap->pVisual->redMask); + /* If any of the three calls fails, we must report that, if more + * than one fails, it's ok that we report the last one */ + rval = FreeCo(pmap, client, GREENMAP, count, pixels, + mask & pmap->pVisual->greenMask); + if(rval != Success) + result = rval; + rval = FreeCo(pmap, client, BLUEMAP, count, pixels, + mask & pmap->pVisual->blueMask); + if(rval != Success) + result = rval; + } + else + { + rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1); + result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask); + } + if ((mask != rmask) && count) + { + clientErrorValue = *pixels | mask; + result = BadValue; + } + /* XXX should worry about removing any RT_CMAPENTRY resource */ + return (result); +} + +/** + * Helper for FreeColors -- frees all combinations of *newpixels and mask bits + * which the client has allocated in channel colormap cells of pmap. + * doesn't change newpixels if it doesn't need to + * + * \param pmap which colormap head + * \param color which sub-map, eg, RED, BLUE, PSEUDO + * \param npixIn number of pixels passed in + * \param ppixIn number of base pixels + * \param mask mask client gave us + */ +static int +FreeCo (ColormapPtr pmap, int client, int color, int npixIn, Pixel *ppixIn, Pixel mask) +{ + Pixel *ppixClient, pixTest; + int npixClient, npixNew, npix; + Pixel bits, base, cmask, rgbbad; + Pixel *pptr, *cptr; + int n, zapped; + int errVal = Success; + int offset, numents; + + if (npixIn == 0) + return (errVal); + bits = 0; + zapped = 0; + base = lowbit (mask); + + switch(color) + { + case REDMAP: + cmask = pmap->pVisual->redMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetRed; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsRed[client]; + npixClient = pmap->numPixelsRed[client]; + break; + case GREENMAP: + cmask = pmap->pVisual->greenMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetGreen; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsGreen[client]; + npixClient = pmap->numPixelsGreen[client]; + break; + case BLUEMAP: + cmask = pmap->pVisual->blueMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetBlue; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsBlue[client]; + npixClient = pmap->numPixelsBlue[client]; + break; + default: /* so compiler can see that everything gets initialized */ + case PSEUDOMAP: + cmask = ~((Pixel)0); + rgbbad = 0; + offset = 0; + numents = pmap->pVisual->ColormapEntries; + ppixClient = pmap->clientPixelsRed[client]; + npixClient = pmap->numPixelsRed[client]; + break; + } + + + /* zap all pixels which match */ + while (1) + { + /* go through pixel list */ + for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++) + { + pixTest = ((*pptr | bits) & cmask) >> offset; + if ((pixTest >= numents) || (*pptr & rgbbad)) + { + clientErrorValue = *pptr | bits; + errVal = BadValue; + continue; + } + + /* find match in client list */ + for (cptr = ppixClient, npix = npixClient; + --npix >= 0 && *cptr != pixTest; + cptr++) ; + + if (npix >= 0) + { + if (pmap->class & DynamicClass) + { + FreeCell(pmap, pixTest, color); + } + *cptr = ~((Pixel)0); + zapped++; + } + else + errVal = BadAccess; + } + /* generate next bits value */ + GetNextBitsOrBreak(bits, mask, base); + } + + /* delete freed pixels from client pixel list */ + if (zapped) + { + npixNew = npixClient - zapped; + if (npixNew) + { + /* Since the list can only get smaller, we can do a copy in + * place and then realloc to a smaller size */ + pptr = cptr = ppixClient; + + /* If we have all the new pixels, we don't have to examine the + * rest of the old ones */ + for(npix = 0; npix < npixNew; cptr++) + { + if (*cptr != ~((Pixel)0)) + { + *pptr++ = *cptr; + npix++; + } + } + pptr = (Pixel *)xrealloc(ppixClient, npixNew * sizeof(Pixel)); + if (pptr) + ppixClient = pptr; + npixClient = npixNew; + } + else + { + npixClient = 0; + xfree(ppixClient); + ppixClient = (Pixel *)NULL; + } + switch(color) + { + case PSEUDOMAP: + case REDMAP: + pmap->clientPixelsRed[client] = ppixClient; + pmap->numPixelsRed[client] = npixClient; + break; + case GREENMAP: + pmap->clientPixelsGreen[client] = ppixClient; + pmap->numPixelsGreen[client] = npixClient; + break; + case BLUEMAP: + pmap->clientPixelsBlue[client] = ppixClient; + pmap->numPixelsBlue[client] = npixClient; + break; + } + } + return (errVal); +} + + + +/* Redefine color values */ +_X_EXPORT int +StoreColors (ColormapPtr pmap, int count, xColorItem *defs) +{ + register Pixel pix; + register xColorItem *pdef; + register EntryPtr pent, pentT, pentLast; + register VisualPtr pVisual; + SHAREDCOLOR *pred, *pgreen, *pblue; + int n, ChgRed, ChgGreen, ChgBlue, idef; + int class, errVal = Success; + int ok; + + + class = pmap->class; + if(!(class & DynamicClass) && !(pmap->flags & BeingCreated)) + { + return(BadAccess); + } + pVisual = pmap->pVisual; + + idef = 0; + if((class | DynamicClass) == DirectColor) + { + int numred, numgreen, numblue; + Pixel rgbbad; + + numred = NUMRED(pVisual); + numgreen = NUMGREEN(pVisual); + numblue = NUMBLUE(pVisual); + rgbbad = ~RGBMASK(pVisual); + for (pdef = defs, n = 0; n < count; pdef++, n++) + { + ok = TRUE; + (*pmap->pScreen->ResolveColor) + (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual); + + if (pdef->pixel & rgbbad) + { + errVal = BadValue; + clientErrorValue = pdef->pixel; + continue; + } + pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed; + if (pix >= numred) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->red[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoRed) + { + pmap->red[pix].co.local.red = pdef->red; + } + else + { + pdef->red = pmap->red[pix].co.local.red; + } + + pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen; + if (pix >= numgreen) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->green[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoGreen) + { + pmap->green[pix].co.local.green = pdef->green; + } + else + { + pdef->green = pmap->green[pix].co.local.green; + } + + pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (pix >= numblue) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->blue[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoBlue) + { + pmap->blue[pix].co.local.blue = pdef->blue; + } + else + { + pdef->blue = pmap->blue[pix].co.local.blue; + } + /* If this is an o.k. entry, then it gets added to the list + * to be sent to the hardware. If not, skip it. Once we've + * skipped one, we have to copy all the others. + */ + if(ok) + { + if(idef != n) + defs[idef] = defs[n]; + idef++; + } else + clientErrorValue = pdef->pixel; + } + } + else + { + for (pdef = defs, n = 0; n < count; pdef++, n++) + { + + ok = TRUE; + if (pdef->pixel >= pVisual->ColormapEntries) + { + clientErrorValue = pdef->pixel; + errVal = BadValue; + ok = FALSE; + } + else if (pmap->red[pdef->pixel].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + + /* If this is an o.k. entry, then it gets added to the list + * to be sent to the hardware. If not, skip it. Once we've + * skipped one, we have to copy all the others. + */ + if(ok) + { + if(idef != n) + defs[idef] = defs[n]; + idef++; + } + else + continue; + + (*pmap->pScreen->ResolveColor) + (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual); + + pent = &pmap->red[pdef->pixel]; + + if(pdef->flags & DoRed) + { + if(pent->fShared) + { + pent->co.shco.red->color = pdef->red; + if (pent->co.shco.red->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.red = pdef->red; + } + else + { + if(pent->fShared) + pdef->red = pent->co.shco.red->color; + else + pdef->red = pent->co.local.red; + } + if(pdef->flags & DoGreen) + { + if(pent->fShared) + { + pent->co.shco.green->color = pdef->green; + if (pent->co.shco.green->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.green = pdef->green; + } + else + { + if(pent->fShared) + pdef->green = pent->co.shco.green->color; + else + pdef->green = pent->co.local.green; + } + if(pdef->flags & DoBlue) + { + if(pent->fShared) + { + pent->co.shco.blue->color = pdef->blue; + if (pent->co.shco.blue->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.blue = pdef->blue; + } + else + { + if(pent->fShared) + pdef->blue = pent->co.shco.blue->color; + else + pdef->blue = pent->co.local.blue; + } + + if(!ok) + { + /* have to run through the colormap and change anybody who + * shares this value */ + pred = pent->co.shco.red; + pgreen = pent->co.shco.green; + pblue = pent->co.shco.blue; + ChgRed = pdef->flags & DoRed; + ChgGreen = pdef->flags & DoGreen; + ChgBlue = pdef->flags & DoBlue; + pentLast = pmap->red + pVisual->ColormapEntries; + + for(pentT = pmap->red; pentT < pentLast; pentT++) + { + if(pentT->fShared && (pentT != pent)) + { + xColorItem defChg; + + /* There are, alas, devices in this world too dumb + * to read their own hardware colormaps. Sick, but + * true. So we're going to be really nice and load + * the xColorItem with the proper value for all the + * fields. We will only set the flags for those + * fields that actually change. Smart devices can + * arrange to change only those fields. Dumb devices + * can rest assured that we have provided for them, + * and can change all three fields */ + + defChg.flags = 0; + if(ChgRed && pentT->co.shco.red == pred) + { + defChg.flags |= DoRed; + } + if(ChgGreen && pentT->co.shco.green == pgreen) + { + defChg.flags |= DoGreen; + } + if(ChgBlue && pentT->co.shco.blue == pblue) + { + defChg.flags |= DoBlue; + } + if(defChg.flags != 0) + { + defChg.pixel = pentT - pmap->red; + defChg.red = pentT->co.shco.red->color; + defChg.green = pentT->co.shco.green->color; + defChg.blue = pentT->co.shco.blue->color; + (*pmap->pScreen->StoreColors) (pmap, 1, &defChg); + } + } + } + + } + } + } + /* Note that we use idef, the count of acceptable entries, and not + * count, the count of proposed entries */ + if (idef != 0) + ( *pmap->pScreen->StoreColors) (pmap, idef, defs); + return (errVal); +} + +int +IsMapInstalled(Colormap map, WindowPtr pWin) +{ + Colormap *pmaps; + int imap, nummaps, found; + + pmaps = (Colormap *) ALLOCATE_LOCAL( + pWin->drawable.pScreen->maxInstalledCmaps * sizeof(Colormap)); + if(!pmaps) + return(FALSE); + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, pmaps); + found = FALSE; + for(imap = 0; imap < nummaps; imap++) + { + if(pmaps[imap] == map) + { + found = TRUE; + break; + } + } + DEALLOCATE_LOCAL(pmaps); + return (found); +} diff --git a/xserver/dix/cursor.c b/xserver/dix/cursor.c new file mode 100644 index 000000000..b9ede1f76 --- /dev/null +++ b/xserver/dix/cursor.c @@ -0,0 +1,457 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#include <X11/Xmd.h> +#include "servermd.h" +#include "scrnintstr.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "dixfontstr.h" +#include "opaque.h" + +typedef struct _GlyphShare { + FontPtr font; + unsigned short sourceChar; + unsigned short maskChar; + CursorBitsPtr bits; + struct _GlyphShare *next; +} GlyphShare, *GlyphSharePtr; + +static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL; + +#ifdef XFIXES +static CARD32 cursorSerial; +#endif + +static void +FreeCursorBits(CursorBitsPtr bits) +{ + if (--bits->refcnt > 0) + return; + xfree(bits->source); + xfree(bits->mask); +#ifdef ARGB_CURSOR + xfree(bits->argb); +#endif + if (bits->refcnt == 0) + { + register GlyphSharePtr *prev, this; + + for (prev = &sharedGlyphs; + (this = *prev) && (this->bits != bits); + prev = &this->next) + ; + if (this) + { + *prev = this->next; + CloseFont(this->font, (Font)0); + xfree(this); + } + xfree(bits); + } +} + +/** + * To be called indirectly by DeleteResource; must use exactly two args. + * + * \param value must conform to DeleteType + */ +_X_EXPORT int +FreeCursor(pointer value, XID cid) +{ + int nscr; + CursorPtr pCurs = (CursorPtr)value; + + ScreenPtr pscr; + + if ( --pCurs->refcnt > 0) + return(Success); + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + (void)( *pscr->UnrealizeCursor)( pscr, pCurs); + } + FreeCursorBits(pCurs->bits); + xfree( pCurs); + return(Success); +} + + +/* + * We check for empty cursors so that we won't have to display them + */ +static void +CheckForEmptyMask(CursorBitsPtr bits) +{ + register unsigned char *msk = bits->mask; + int n = BitmapBytePad(bits->width) * bits->height; + + bits->emptyMask = FALSE; + while(n--) + if(*(msk++) != 0) return; +#ifdef ARGB_CURSOR + if (bits->argb) + { + CARD32 *argb = bits->argb; + int n = bits->width * bits->height; + while (n--) + if (*argb++ & 0xff000000) return; + } +#endif + bits->emptyMask = TRUE; +} + +/** + * does nothing about the resource table, just creates the data structure. + * does not copy the src and mask bits + * + * \param psrcbits server-defined padding + * \param pmaskbits server-defined padding + * \param argb no padding + */ +CursorPtr +AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb, + CursorMetricPtr cm, + unsigned foreRed, unsigned foreGreen, unsigned foreBlue, + unsigned backRed, unsigned backGreen, unsigned backBlue) +{ + CursorBitsPtr bits; + CursorPtr pCurs; + int nscr; + ScreenPtr pscr; + + pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); + if (!pCurs) + { + xfree(psrcbits); + xfree(pmaskbits); + return (CursorPtr)NULL; + } + bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec)); + bits->source = psrcbits; + bits->mask = pmaskbits; +#ifdef ARGB_CURSOR + bits->argb = argb; +#endif + bits->width = cm->width; + bits->height = cm->height; + bits->xhot = cm->xhot; + bits->yhot = cm->yhot; + bits->refcnt = -1; + CheckForEmptyMask(bits); + + pCurs->bits = bits; + pCurs->refcnt = 1; +#ifdef XFIXES + pCurs->serialNumber = ++cursorSerial; + pCurs->name = None; +#endif + + pCurs->foreRed = foreRed; + pCurs->foreGreen = foreGreen; + pCurs->foreBlue = foreBlue; + + pCurs->backRed = backRed; + pCurs->backGreen = backGreen; + pCurs->backBlue = backBlue; + + /* + * realize the cursor for every screen + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + if (!( *pscr->RealizeCursor)( pscr, pCurs)) + { + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + ( *pscr->UnrealizeCursor)( pscr, pCurs); + } + FreeCursorBits(bits); + xfree(pCurs); + return (CursorPtr)NULL; + } + } + return pCurs; +} + +/** + * + * \param psrcbits server-defined padding + * \param pmaskbits server-defined padding + */ +CursorPtr +AllocCursor(unsigned char *psrcbits, unsigned char *pmaskbits, + CursorMetricPtr cm, + unsigned foreRed, unsigned foreGreen, unsigned foreBlue, + unsigned backRed, unsigned backGreen, unsigned backBlue) +{ + return AllocCursorARGB (psrcbits, pmaskbits, (CARD32 *) 0, cm, + foreRed, foreGreen, foreBlue, + backRed, backGreen, backBlue); +} + +int +AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, + unsigned foreRed, unsigned foreGreen, unsigned foreBlue, + unsigned backRed, unsigned backGreen, unsigned backBlue, + CursorPtr *ppCurs, ClientPtr client) +{ + FontPtr sourcefont, maskfont; + unsigned char *srcbits; + unsigned char *mskbits; + CursorMetricRec cm; + int res; + CursorBitsPtr bits; + CursorPtr pCurs; + int nscr; + ScreenPtr pscr; + GlyphSharePtr pShare; + + sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT, + SecurityReadAccess); + maskfont = (FontPtr) SecurityLookupIDByType(client, mask, RT_FONT, + SecurityReadAccess); + + if (!sourcefont) + { + client->errorValue = source; + return(BadFont); + } + if (!maskfont && (mask != None)) + { + client->errorValue = mask; + return(BadFont); + } + if (sourcefont != maskfont) + pShare = (GlyphSharePtr)NULL; + else + { + for (pShare = sharedGlyphs; + pShare && + ((pShare->font != sourcefont) || + (pShare->sourceChar != sourceChar) || + (pShare->maskChar != maskChar)); + pShare = pShare->next) + ; + } + if (pShare) + { + pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); + if (!pCurs) + return BadAlloc; + bits = pShare->bits; + bits->refcnt++; + } + else + { + if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm)) + { + client->errorValue = sourceChar; + return BadValue; + } + if (!maskfont) + { + register long n; + register unsigned char *mskptr; + + n = BitmapBytePad(cm.width)*(long)cm.height; + mskptr = mskbits = (unsigned char *)xalloc(n); + if (!mskptr) + return BadAlloc; + while (--n >= 0) + *mskptr++ = ~0; + } + else + { + if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm)) + { + client->errorValue = maskChar; + return BadValue; + } + if ((res = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)) != 0) + return res; + } + if ((res = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits)) != 0) + { + xfree(mskbits); + return res; + } + if (sourcefont != maskfont) + { + pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); + if (pCurs) + bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec)); + else + bits = (CursorBitsPtr)NULL; + } + else + { + pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); + if (pCurs) + bits = (CursorBitsPtr)xalloc(sizeof(CursorBits)); + else + bits = (CursorBitsPtr)NULL; + } + if (!bits) + { + xfree(pCurs); + xfree(mskbits); + xfree(srcbits); + return BadAlloc; + } + bits->source = srcbits; + bits->mask = mskbits; +#ifdef ARGB_CURSOR + bits->argb = 0; +#endif + bits->width = cm.width; + bits->height = cm.height; + bits->xhot = cm.xhot; + bits->yhot = cm.yhot; + if (sourcefont != maskfont) + bits->refcnt = -1; + else + { + bits->refcnt = 1; + pShare = (GlyphSharePtr)xalloc(sizeof(GlyphShare)); + if (!pShare) + { + FreeCursorBits(bits); + return BadAlloc; + } + pShare->font = sourcefont; + sourcefont->refcnt++; + pShare->sourceChar = sourceChar; + pShare->maskChar = maskChar; + pShare->bits = bits; + pShare->next = sharedGlyphs; + sharedGlyphs = pShare; + } + } + CheckForEmptyMask(bits); + pCurs->bits = bits; + pCurs->refcnt = 1; +#ifdef XFIXES + pCurs->serialNumber = ++cursorSerial; + pCurs->name = None; +#endif + + pCurs->foreRed = foreRed; + pCurs->foreGreen = foreGreen; + pCurs->foreBlue = foreBlue; + + pCurs->backRed = backRed; + pCurs->backGreen = backGreen; + pCurs->backBlue = backBlue; + + /* + * realize the cursor for every screen + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + if (!( *pscr->RealizeCursor)( pscr, pCurs)) + { + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + ( *pscr->UnrealizeCursor)( pscr, pCurs); + } + FreeCursorBits(pCurs->bits); + xfree(pCurs); + return BadAlloc; + } + } + *ppCurs = pCurs; + return Success; +} + +/** CreateRootCursor + * + * look up the name of a font + * open the font + * add the font to the resource table + * make a cursor from the glyphs + * add the cursor to the resource table + *************************************************************/ + +CursorPtr +CreateRootCursor(char *pfilename, unsigned glyph) +{ + CursorPtr curs; + FontPtr cursorfont; + int err; + XID fontID; + + fontID = FakeClientID(0); + err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync, + (unsigned)strlen( pfilename), pfilename); + if (err != Success) + return NullCursor; + + cursorfont = (FontPtr)LookupIDByType(fontID, RT_FONT); + if (!cursorfont) + return NullCursor; + if (AllocGlyphCursor(fontID, glyph, fontID, glyph + 1, + 0, 0, 0, ~0, ~0, ~0, &curs, serverClient) != Success) + return NullCursor; + + if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs)) + return NullCursor; + + return curs; +} diff --git a/xserver/dix/devices.c b/xserver/dix/devices.c new file mode 100644 index 000000000..607510203 --- /dev/null +++ b/xserver/dix/devices.c @@ -0,0 +1,1613 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "site.h" +#ifndef XKB_IN_SERVER +#define XKB_IN_SERVER +#endif +#ifdef XKB +#include <X11/extensions/XKBsrv.h> +#endif +#ifdef XACE +#include "xace.h" +#endif + +#include "dispatch.h" +#include "swaprep.h" +#include "dixevents.h" + +DeviceIntPtr +AddInputDevice(DeviceProc deviceProc, Bool autoStart) +{ + register DeviceIntPtr dev; + + if (inputInfo.numDevices >= MAX_DEVICES) + return (DeviceIntPtr)NULL; + dev = (DeviceIntPtr) xalloc(sizeof(DeviceIntRec)); + if (!dev) + return (DeviceIntPtr)NULL; + dev->name = (char *)NULL; + dev->type = 0; + dev->id = inputInfo.numDevices; + inputInfo.numDevices++; + dev->public.on = FALSE; + dev->public.processInputProc = (ProcessInputProc)NoopDDA; + dev->public.realInputProc = (ProcessInputProc)NoopDDA; + dev->public.enqueueInputProc = EnqueueEvent; + dev->deviceProc = deviceProc; + dev->startup = autoStart; + dev->sync.frozen = FALSE; + dev->sync.other = NullGrab; + dev->sync.state = NOT_GRABBED; + dev->sync.event = (xEvent *) NULL; + dev->sync.evcount = 0; + dev->grab = NullGrab; + dev->grabTime = currentTime; + dev->fromPassiveGrab = FALSE; + dev->key = (KeyClassPtr)NULL; + dev->valuator = (ValuatorClassPtr)NULL; + dev->button = (ButtonClassPtr)NULL; + dev->focus = (FocusClassPtr)NULL; + dev->proximity = (ProximityClassPtr)NULL; + dev->kbdfeed = (KbdFeedbackPtr)NULL; + dev->ptrfeed = (PtrFeedbackPtr)NULL; + dev->intfeed = (IntegerFeedbackPtr)NULL; + dev->stringfeed = (StringFeedbackPtr)NULL; + dev->bell = (BellFeedbackPtr)NULL; + dev->leds = (LedFeedbackPtr)NULL; + dev->next = inputInfo.off_devices; +#ifdef XKB + dev->xkb_interest= NULL; +#endif + dev->nPrivates = 0; + dev->devPrivates = NULL; + dev->unwrapProc = NULL; + inputInfo.off_devices = dev; + return dev; +} + +Bool +EnableDevice(register DeviceIntPtr dev) +{ + register DeviceIntPtr *prev; + + for (prev = &inputInfo.off_devices; + *prev && (*prev != dev); + prev = &(*prev)->next) + ; + if ((*prev != dev) || !dev->inited || + ((*dev->deviceProc)(dev, DEVICE_ON) != Success)) + return FALSE; + *prev = dev->next; + dev->next = inputInfo.devices; + inputInfo.devices = dev; + return TRUE; +} + +Bool +DisableDevice(register DeviceIntPtr dev) +{ + register DeviceIntPtr *prev; + + for (prev = &inputInfo.devices; + *prev && (*prev != dev); + prev = &(*prev)->next) + ; + if (*prev != dev) + return FALSE; + (void)(*dev->deviceProc)(dev, DEVICE_OFF); + *prev = dev->next; + dev->next = inputInfo.off_devices; + inputInfo.off_devices = dev; + return TRUE; +} + +int +InitAndStartDevices() +{ + register DeviceIntPtr dev, next; + + for (dev = inputInfo.off_devices; dev; dev = dev->next) + dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success); + for (dev = inputInfo.off_devices; dev; dev = next) + { + next = dev->next; + if (dev->inited && dev->startup) + (void)EnableDevice(dev); + } + for (dev = inputInfo.devices; + dev && (dev != inputInfo.keyboard); + dev = dev->next) + ; + if (!dev || (dev != inputInfo.keyboard)) { + ErrorF("No core keyboard\n"); + return BadImplementation; + } + for (dev = inputInfo.devices; + dev && (dev != inputInfo.pointer); + dev = dev->next) + ; + if (!dev || (dev != inputInfo.pointer)) { + ErrorF("No core pointer\n"); + return BadImplementation; + } + return Success; +} + +static void +CloseDevice(register DeviceIntPtr dev) +{ + KbdFeedbackPtr k, knext; + PtrFeedbackPtr p, pnext; + IntegerFeedbackPtr i, inext; + StringFeedbackPtr s, snext; + BellFeedbackPtr b, bnext; + LedFeedbackPtr l, lnext; + + if (dev->inited) + (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); + xfree(dev->name); + if (dev->key) + { +#ifdef XKB + if (dev->key->xkbInfo) + XkbFreeInfo(dev->key->xkbInfo); +#endif + xfree(dev->key->curKeySyms.map); + xfree(dev->key->modifierKeyMap); + xfree(dev->key); + } + xfree(dev->valuator); +#ifdef XKB + if ((dev->button)&&(dev->button->xkb_acts)) + xfree(dev->button->xkb_acts); +#endif + xfree(dev->button); + if (dev->focus) + { + xfree(dev->focus->trace); + xfree(dev->focus); + } + xfree(dev->proximity); + for (k=dev->kbdfeed; k; k=knext) + { + knext = k->next; +#ifdef XKB + if (k->xkb_sli) + XkbFreeSrvLedInfo(k->xkb_sli); +#endif + xfree(k); + } + for (p=dev->ptrfeed; p; p=pnext) + { + pnext = p->next; + xfree(p); + } + for (i=dev->intfeed; i; i=inext) + { + inext = i->next; + xfree(i); + } + for (s=dev->stringfeed; s; s=snext) + { + snext = s->next; + xfree(s->ctrl.symbols_supported); + xfree(s->ctrl.symbols_displayed); + xfree(s); + } + for (b=dev->bell; b; b=bnext) + { + bnext = b->next; + xfree(b); + } + for (l=dev->leds; l; l=lnext) + { + lnext = l->next; +#ifdef XKB + if (l->xkb_sli) + XkbFreeSrvLedInfo(l->xkb_sli); +#endif + xfree(l); + } +#ifdef XKB + while (dev->xkb_interest) { + XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); + } +#endif + xfree(dev->sync.event); + xfree(dev); +} + +void +CloseDownDevices() +{ + register DeviceIntPtr dev, next; + + for (dev = inputInfo.devices; dev; dev = next) + { + next = dev->next; + CloseDevice(dev); + } + for (dev = inputInfo.off_devices; dev; dev = next) + { + next = dev->next; + CloseDevice(dev); + } + inputInfo.devices = NULL; + inputInfo.off_devices = NULL; + inputInfo.keyboard = NULL; + inputInfo.pointer = NULL; +} + +void +RemoveDevice(register DeviceIntPtr dev) +{ + register DeviceIntPtr prev,tmp,next; + + prev= NULL; + for (tmp= inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { + next = tmp->next; + if (tmp==dev) { + CloseDevice(tmp); + if (prev==NULL) + inputInfo.devices = next; + else + prev->next = next; + inputInfo.numDevices--; + if (inputInfo.keyboard == tmp) + inputInfo.keyboard = NULL; + else if (inputInfo.pointer == tmp) + inputInfo.pointer = NULL; + return; + } + } + + prev= NULL; + for (tmp= inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) { + next = tmp->next; + if (tmp==dev) { + CloseDevice(tmp); + if (prev==NULL) + inputInfo.off_devices = next; + else + prev->next = next; + inputInfo.numDevices--; + if (inputInfo.keyboard == tmp) + inputInfo.keyboard = NULL; + else if (inputInfo.pointer == tmp) + inputInfo.pointer = NULL; + return; + } + } + ErrorF("Internal Error! Attempt to remove a non-existent device\n"); + return; +} + +int +NumMotionEvents() +{ + return inputInfo.pointer->valuator->numMotionEvents; +} + +void +RegisterPointerDevice(DeviceIntPtr device) +{ + inputInfo.pointer = device; +#ifdef XKB + device->public.processInputProc = CoreProcessPointerEvent; + device->public.realInputProc = CoreProcessPointerEvent; + if (!noXkbExtension) + XkbSetExtension(device,ProcessPointerEvent); +#else + device->public.processInputProc = ProcessPointerEvent; + device->public.realInputProc = ProcessPointerEvent; +#endif + device->ActivateGrab = ActivatePointerGrab; + device->DeactivateGrab = DeactivatePointerGrab; + if (!device->name) + { + char *p = "pointer"; + device->name = (char *)xalloc(strlen(p) + 1); + strcpy(device->name, p); + } +} + +void +RegisterKeyboardDevice(DeviceIntPtr device) +{ + inputInfo.keyboard = device; +#ifdef XKB + device->public.processInputProc = CoreProcessKeyboardEvent; + device->public.realInputProc = CoreProcessKeyboardEvent; + if (!noXkbExtension) + XkbSetExtension(device,ProcessKeyboardEvent); +#else + device->public.processInputProc = ProcessKeyboardEvent; + device->public.realInputProc = ProcessKeyboardEvent; +#endif + device->ActivateGrab = ActivateKeyboardGrab; + device->DeactivateGrab = DeactivateKeyboardGrab; + if (!device->name) + { + char *k = "keyboard"; + device->name = (char *)xalloc(strlen(k) + 1); + strcpy(device->name, k); + } +} + +_X_EXPORT DevicePtr +LookupKeyboardDevice() +{ + return inputInfo.keyboard ? &inputInfo.keyboard->public : NULL; +} + +_X_EXPORT DevicePtr +LookupPointerDevice() +{ + return inputInfo.pointer ? &inputInfo.pointer->public : NULL; +} + +DevicePtr +LookupDevice(int id) +{ + DeviceIntPtr dev; + + for (dev=inputInfo.devices; dev; dev=dev->next) { + if (dev->id == (CARD8)id) + return (DevicePtr)dev; + } + for (dev=inputInfo.off_devices; dev; dev=dev->next) { + if (dev->id == (CARD8)id) + return (DevicePtr)dev; + } + return NULL; +} + +void +QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode) +{ + if (inputInfo.keyboard) { + *minCode = inputInfo.keyboard->key->curKeySyms.minKeyCode; + *maxCode = inputInfo.keyboard->key->curKeySyms.maxKeyCode; + } +} + +Bool +SetKeySymsMap(register KeySymsPtr dst, register KeySymsPtr src) +{ + int i, j; + int rowDif = src->minKeyCode - dst->minKeyCode; + /* if keysym map size changes, grow map first */ + + if (src->mapWidth < dst->mapWidth) + { + for (i = src->minKeyCode; i <= src->maxKeyCode; i++) + { +#define SI(r, c) (((r-src->minKeyCode)*src->mapWidth) + (c)) +#define DI(r, c) (((r - dst->minKeyCode)*dst->mapWidth) + (c)) + for (j = 0; j < src->mapWidth; j++) + dst->map[DI(i, j)] = src->map[SI(i, j)]; + for (j = src->mapWidth; j < dst->mapWidth; j++) + dst->map[DI(i, j)] = NoSymbol; +#undef SI +#undef DI + } + return TRUE; + } + else if (src->mapWidth > dst->mapWidth) + { + KeySym *map; + int bytes = sizeof(KeySym) * src->mapWidth * + (dst->maxKeyCode - dst->minKeyCode + 1); + map = (KeySym *)xalloc(bytes); + if (!map) + return FALSE; + bzero((char *)map, bytes); + if (dst->map) + { + for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) + memmove((char *)&map[i*src->mapWidth], + (char *)&dst->map[i*dst->mapWidth], + dst->mapWidth * sizeof(KeySym)); + xfree(dst->map); + } + dst->mapWidth = src->mapWidth; + dst->map = map; + } + memmove((char *)&dst->map[rowDif * dst->mapWidth], + (char *)src->map, + (int)(src->maxKeyCode - src->minKeyCode + 1) * + dst->mapWidth * sizeof(KeySym)); + return TRUE; +} + +static Bool +InitModMap(register KeyClassPtr keyc) +{ + int i, j; + CARD8 keysPerModifier[8]; + CARD8 mask; + + keyc->maxKeysPerModifier = 0; + for (i = 0; i < 8; i++) + keysPerModifier[i] = 0; + for (i = 8; i < MAP_LENGTH; i++) + { + for (j = 0, mask = 1; j < 8; j++, mask <<= 1) + { + if (mask & keyc->modifierMap[i]) + { + if (++keysPerModifier[j] > keyc->maxKeysPerModifier) + keyc->maxKeysPerModifier = keysPerModifier[j]; + } + } + } + keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier); + if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier) + return (FALSE); + bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier); + for (i = 0; i < 8; i++) + keysPerModifier[i] = 0; + for (i = 8; i < MAP_LENGTH; i++) + { + for (j = 0, mask = 1; j < 8; j++, mask <<= 1) + { + if (mask & keyc->modifierMap[i]) + { + keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) + + keysPerModifier[j]] = i; + keysPerModifier[j]++; + } + } + } + return TRUE; +} + +_X_EXPORT Bool +InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers[]) +{ + int i; + register KeyClassPtr keyc; + + keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec)); + if (!keyc) + return FALSE; + keyc->curKeySyms.map = (KeySym *)NULL; + keyc->curKeySyms.mapWidth = 0; + keyc->curKeySyms.minKeyCode = pKeySyms->minKeyCode; + keyc->curKeySyms.maxKeyCode = pKeySyms->maxKeyCode; + keyc->modifierKeyMap = (KeyCode *)NULL; + keyc->state = 0; + keyc->prev_state = 0; + if (pModifiers) + memmove((char *)keyc->modifierMap, (char *)pModifiers, MAP_LENGTH); + else + bzero((char *)keyc->modifierMap, MAP_LENGTH); + bzero((char *)keyc->down, DOWN_LENGTH); + for (i = 0; i < 8; i++) + keyc->modifierKeyCount[i] = 0; + if (!SetKeySymsMap(&keyc->curKeySyms, pKeySyms) || !InitModMap(keyc)) + { + xfree(keyc->curKeySyms.map); + xfree(keyc->modifierKeyMap); + xfree(keyc); + return FALSE; + } + dev->key = keyc; +#ifdef XKB + dev->key->xkbInfo= NULL; + if (!noXkbExtension) XkbInitDevice(dev); +#endif + return TRUE; +} + +_X_EXPORT Bool +InitButtonClassDeviceStruct(register DeviceIntPtr dev, int numButtons, + CARD8 *map) +{ + register ButtonClassPtr butc; + int i; + + butc = (ButtonClassPtr)xalloc(sizeof(ButtonClassRec)); + if (!butc) + return FALSE; + butc->numButtons = numButtons; + for (i = 1; i <= numButtons; i++) + butc->map[i] = map[i]; + butc->buttonsDown = 0; + butc->state = 0; + butc->motionMask = 0; + bzero((char *)butc->down, DOWN_LENGTH); +#ifdef XKB + butc->xkb_acts= NULL; +#endif + dev->button = butc; + return TRUE; +} + +_X_EXPORT Bool +InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, + ValuatorMotionProcPtr motionProc, + int numMotionEvents, int mode) +{ + int i; + register ValuatorClassPtr valc; + + valc = (ValuatorClassPtr)xalloc(sizeof(ValuatorClassRec) + + numAxes * sizeof(AxisInfo) + + numAxes * sizeof(unsigned int)); + if (!valc) + return FALSE; + valc->GetMotionProc = motionProc; + valc->numMotionEvents = numMotionEvents; + valc->motionHintWindow = NullWindow; + valc->numAxes = numAxes; + valc->mode = mode; + valc->axes = (AxisInfoPtr)(valc + 1); + valc->axisVal = (int *)(valc->axes + numAxes); + for (i=0; i<numAxes; i++) + valc->axisVal[i]=0; + dev->valuator = valc; + return TRUE; +} + +_X_EXPORT Bool +InitFocusClassDeviceStruct(DeviceIntPtr dev) +{ + register FocusClassPtr focc; + + focc = (FocusClassPtr)xalloc(sizeof(FocusClassRec)); + if (!focc) + return FALSE; + focc->win = PointerRootWin; + focc->revert = None; + focc->time = currentTime; + focc->trace = (WindowPtr *)NULL; + focc->traceSize = 0; + focc->traceGood = 0; + dev->focus = focc; + return TRUE; +} + +_X_EXPORT Bool +InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, + KbdCtrlProcPtr controlProc) +{ + register KbdFeedbackPtr feedc; + + feedc = (KbdFeedbackPtr)xalloc(sizeof(KbdFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->BellProc = bellProc; + feedc->CtrlProc = controlProc; +#ifdef XKB + defaultKeyboardControl.autoRepeat = TRUE; +#endif + feedc->ctrl = defaultKeyboardControl; + feedc->ctrl.id = 0; + if ((feedc->next = dev->kbdfeed) != 0) + feedc->ctrl.id = dev->kbdfeed->ctrl.id + 1; + dev->kbdfeed = feedc; +#ifdef XKB + feedc->xkb_sli= NULL; + if (!noXkbExtension) + XkbFinishDeviceInit(dev); +#endif + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + return TRUE; +} + +_X_EXPORT Bool +InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc) +{ + register PtrFeedbackPtr feedc; + + feedc = (PtrFeedbackPtr)xalloc(sizeof(PtrFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultPointerControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->ptrfeed) ) + feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1; + dev->ptrfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + + +LedCtrl defaultLedControl = { + DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0}; + +BellCtrl defaultBellControl = { + DEFAULT_BELL, + DEFAULT_BELL_PITCH, + DEFAULT_BELL_DURATION, + 0}; + +IntegerCtrl defaultIntegerControl = { + DEFAULT_INT_RESOLUTION, + DEFAULT_INT_MIN_VALUE, + DEFAULT_INT_MAX_VALUE, + DEFAULT_INT_DISPLAYED, + 0}; + +_X_EXPORT Bool +InitStringFeedbackClassDeviceStruct ( + DeviceIntPtr dev, StringCtrlProcPtr controlProc, + int max_symbols, int num_symbols_supported, KeySym *symbols) +{ + int i; + register StringFeedbackPtr feedc; + + feedc = (StringFeedbackPtr)xalloc(sizeof(StringFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl.num_symbols_supported = num_symbols_supported; + feedc->ctrl.num_symbols_displayed = 0; + feedc->ctrl.max_symbols = max_symbols; + feedc->ctrl.symbols_supported = (KeySym *) + xalloc (sizeof (KeySym) * num_symbols_supported); + feedc->ctrl.symbols_displayed = (KeySym *) + xalloc (sizeof (KeySym) * max_symbols); + if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) + { + if (feedc->ctrl.symbols_supported) + xfree(feedc->ctrl.symbols_supported); + if (feedc->ctrl.symbols_displayed) + xfree(feedc->ctrl.symbols_displayed); + xfree(feedc); + return FALSE; + } + for (i=0; i<num_symbols_supported; i++) + *(feedc->ctrl.symbols_supported+i) = *symbols++; + for (i=0; i<max_symbols; i++) + *(feedc->ctrl.symbols_displayed+i) = (KeySym) NULL; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->stringfeed) ) + feedc->ctrl.id = dev->stringfeed->ctrl.id + 1; + dev->stringfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +_X_EXPORT Bool +InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, + BellCtrlProcPtr controlProc) +{ + register BellFeedbackPtr feedc; + + feedc = (BellFeedbackPtr)xalloc(sizeof(BellFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->BellProc = bellProc; + feedc->ctrl = defaultBellControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->bell) ) + feedc->ctrl.id = dev->bell->ctrl.id + 1; + dev->bell = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +_X_EXPORT Bool +InitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc) +{ + register LedFeedbackPtr feedc; + + feedc = (LedFeedbackPtr)xalloc(sizeof(LedFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultLedControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->leds) ) + feedc->ctrl.id = dev->leds->ctrl.id + 1; +#ifdef XKB + feedc->xkb_sli= NULL; +#endif + dev->leds = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +_X_EXPORT Bool +InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc) +{ + register IntegerFeedbackPtr feedc; + + feedc = (IntegerFeedbackPtr)xalloc(sizeof(IntegerFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultIntegerControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->intfeed) ) + feedc->ctrl.id = dev->intfeed->ctrl.id + 1; + dev->intfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +_X_EXPORT Bool +InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, + ValuatorMotionProcPtr motionProc, + PtrCtrlProcPtr controlProc, int numMotionEvents) +{ + DeviceIntPtr dev = (DeviceIntPtr)device; + + return(InitButtonClassDeviceStruct(dev, numButtons, map) && + InitValuatorClassDeviceStruct(dev, 2, motionProc, + numMotionEvents, 0) && + InitPtrFeedbackClassDeviceStruct(dev, controlProc)); +} + +_X_EXPORT Bool +InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, + CARD8 pModifiers[], BellProcPtr bellProc, + KbdCtrlProcPtr controlProc) +{ + DeviceIntPtr dev = (DeviceIntPtr)device; + + return(InitKeyClassDeviceStruct(dev, pKeySyms, pModifiers) && + InitFocusClassDeviceStruct(dev) && + InitKbdFeedbackClassDeviceStruct(dev, bellProc, controlProc)); +} + +_X_EXPORT void +SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, + ClientPtr client) +{ + int i; + xEvent event; + + event.u.u.type = MappingNotify; + event.u.mappingNotify.request = request; + if (request == MappingKeyboard) + { + event.u.mappingNotify.firstKeyCode = firstKeyCode; + event.u.mappingNotify.count = count; + } +#ifdef XKB + if (!noXkbExtension && + ((request == MappingKeyboard) || (request == MappingModifier))) { + XkbApplyMappingChange(inputInfo.keyboard,request,firstKeyCode,count, + client); + } +#endif + + /* 0 is the server client */ + for (i=1; i<currentMaxClients; i++) + { + if (clients[i] && clients[i]->clientState == ClientStateRunning) + { +#ifdef XKB + if (!noXkbExtension && + (request == MappingKeyboard) && + (clients[i]->xkbClientFlags != 0) && + (clients[i]->mapNotifyMask&XkbKeySymsMask)) + continue; +#endif + event.u.u.sequenceNumber = clients[i]->sequence; + WriteEventsToClient(clients[i], 1, &event); + } + } +} + +/* + * n-squared algorithm. n < 255 and don't want to copy the whole thing and + * sort it to do the checking. How often is it called? Just being lazy? + */ +Bool +BadDeviceMap(register BYTE *buff, int length, unsigned low, unsigned high, XID *errval) +{ + register int i, j; + + for (i = 0; i < length; i++) + if (buff[i]) /* only check non-zero elements */ + { + if ((low > buff[i]) || (high < buff[i])) + { + *errval = buff[i]; + return TRUE; + } + for (j = i + 1; j < length; j++) + if (buff[i] == buff[j]) + { + *errval = buff[i]; + return TRUE; + } + } + return FALSE; +} + +Bool +AllModifierKeysAreUp(dev, map1, per1, map2, per2) + register DeviceIntPtr dev; + register CARD8 *map1, *map2; + int per1, per2; +{ + register int i, j, k; + register CARD8 *down = dev->key->down; + + for (i = 8; --i >= 0; map2 += per2) + { + for (j = per1; --j >= 0; map1++) + { + if (*map1 && BitIsOn(down, *map1)) + { + for (k = per2; (--k >= 0) && (*map1 != map2[k]);) + ; + if (k < 0) + return FALSE; + } + } + } + return TRUE; +} + +int +ProcSetModifierMapping(ClientPtr client) +{ + xSetModifierMappingReply rep; + REQUEST(xSetModifierMappingReq); + KeyCode *inputMap; + int inputMapLen; + register int i; + DeviceIntPtr keybd = inputInfo.keyboard; + register KeyClassPtr keyc = keybd->key; + + REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq); + + if (client->req_len != ((stuff->numKeyPerModifier<<1) + + (sizeof (xSetModifierMappingReq)>>2))) + return BadLength; + + inputMapLen = 8*stuff->numKeyPerModifier; + inputMap = (KeyCode *)&stuff[1]; + + /* + * Now enforce the restriction that "all of the non-zero keycodes must be + * in the range specified by min-keycode and max-keycode in the + * connection setup (else a Value error)" + */ + i = inputMapLen; + while (i--) + { + if (inputMap[i] + && (inputMap[i] < keyc->curKeySyms.minKeyCode + || inputMap[i] > keyc->curKeySyms.maxKeyCode)) + { + client->errorValue = inputMap[i]; + return BadValue; + } + } + +#ifdef XACE + if (!XaceHook(XACE_DEVICE_ACCESS, client, keybd, TRUE)) + return BadAccess; +#endif + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.success = MappingSuccess; + + /* + * Now enforce the restriction that none of the old or new + * modifier keys may be down while we change the mapping, and + * that the DDX layer likes the choice. + */ + if (!AllModifierKeysAreUp(keybd, keyc->modifierKeyMap, + (int)keyc->maxKeysPerModifier, + inputMap, (int)stuff->numKeyPerModifier) + || + !AllModifierKeysAreUp(keybd, inputMap, (int)stuff->numKeyPerModifier, + keyc->modifierKeyMap, + (int)keyc->maxKeysPerModifier)) + { + rep.success = MappingBusy; + } + else + { + for (i = 0; i < inputMapLen; i++) + { + if (inputMap[i] && !LegalModifier(inputMap[i], (DevicePtr)keybd)) + { + rep.success = MappingFailed; + break; + } + } + } + + if (rep.success == MappingSuccess) + { + KeyCode *map; + /* + * Now build the keyboard's modifier bitmap from the + * list of keycodes. + */ + map = (KeyCode *)xalloc(inputMapLen); + if (!map && inputMapLen) + return BadAlloc; + if (keyc->modifierKeyMap) + xfree(keyc->modifierKeyMap); + keyc->modifierKeyMap = map; + memmove((char *)map, (char *)inputMap, inputMapLen); + + keyc->maxKeysPerModifier = stuff->numKeyPerModifier; + for (i = 0; i < MAP_LENGTH; i++) + keyc->modifierMap[i] = 0; + for (i = 0; i < inputMapLen; i++) + { + if (inputMap[i]) + keyc->modifierMap[inputMap[i]] |= + (1<<(((unsigned int)i)/keyc->maxKeysPerModifier)); + } + } + + if (rep.success == MappingSuccess) + SendMappingNotify(MappingModifier, 0, 0, client); + + WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); + + return(client->noClientException); +} + +int +ProcGetModifierMapping(ClientPtr client) +{ + xGetModifierMappingReply rep; + register KeyClassPtr keyc = inputInfo.keyboard->key; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.numKeyPerModifier = keyc->maxKeysPerModifier; + rep.sequenceNumber = client->sequence; + /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ + rep.length = keyc->maxKeysPerModifier << 1; + + WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); + + /* Use the (modified by DDX) map that SetModifierMapping passed in */ + (void)WriteToClient(client, (int)(keyc->maxKeysPerModifier << 3), + (char *)keyc->modifierKeyMap); + return client->noClientException; +} + +int +ProcChangeKeyboardMapping(ClientPtr client) +{ + REQUEST(xChangeKeyboardMappingReq); + unsigned len; + KeySymsRec keysyms; + register KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); + + len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2); + if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) + return BadLength; + if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || + (stuff->firstKeyCode > curKeySyms->maxKeyCode)) + { + client->errorValue = stuff->firstKeyCode; + return BadValue; + } + if ( ((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) > + curKeySyms->maxKeyCode) || + (stuff->keySymsPerKeyCode == 0)) + { + client->errorValue = stuff->keySymsPerKeyCode; + return BadValue; + } +#ifdef XACE + if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE)) + return BadAccess; +#endif + keysyms.minKeyCode = stuff->firstKeyCode; + keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1; + keysyms.mapWidth = stuff->keySymsPerKeyCode; + keysyms.map = (KeySym *)&stuff[1]; + if (!SetKeySymsMap(curKeySyms, &keysyms)) + return BadAlloc; + SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes, + client); + return client->noClientException; + +} + +int +ProcSetPointerMapping(ClientPtr client) +{ + REQUEST(xSetPointerMappingReq); + BYTE *map; + xSetPointerMappingReply rep; + register unsigned int i; + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); + if (client->req_len != (sizeof(xSetPointerMappingReq)+stuff->nElts+3) >> 2) + return BadLength; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.success = MappingSuccess; + map = (BYTE *)&stuff[1]; + if (stuff->nElts != mouse->button->numButtons) + { + client->errorValue = stuff->nElts; + return BadValue; + } + if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue)) + return BadValue; + for (i=0; i < stuff->nElts; i++) + if ((mouse->button->map[i + 1] != map[i]) && + BitIsOn(mouse->button->down, i + 1)) + { + rep.success = MappingBusy; + WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); + return Success; + } + for (i = 0; i < stuff->nElts; i++) + mouse->button->map[i + 1] = map[i]; + SendMappingNotify(MappingPointer, 0, 0, client); + WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); + return Success; +} + +int +ProcGetKeyboardMapping(ClientPtr client) +{ + xGetKeyboardMappingReply rep; + REQUEST(xGetKeyboardMappingReq); + KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + + REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); + + if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || + (stuff->firstKeyCode > curKeySyms->maxKeyCode)) + { + client->errorValue = stuff->firstKeyCode; + return BadValue; + } + if (stuff->firstKeyCode + stuff->count > + (unsigned)(curKeySyms->maxKeyCode + 1)) + { + client->errorValue = stuff->count; + return BadValue; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.keySymsPerKeyCode = curKeySyms->mapWidth; + /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ + rep.length = (curKeySyms->mapWidth * stuff->count); + WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep); + client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; + WriteSwappedDataToClient( + client, + curKeySyms->mapWidth * stuff->count * sizeof(KeySym), + &curKeySyms->map[(stuff->firstKeyCode - curKeySyms->minKeyCode) * + curKeySyms->mapWidth]); + + return client->noClientException; +} + +int +ProcGetPointerMapping(ClientPtr client) +{ + xGetPointerMappingReply rep; + ButtonClassPtr butc = inputInfo.pointer->button; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.nElts = butc->numButtons; + rep.length = ((unsigned)rep.nElts + (4-1))/4; + WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); + (void)WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]); + return Success; +} + +void +NoteLedState(DeviceIntPtr keybd, int led, Bool on) +{ + KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl; + if (on) + ctrl->leds |= ((Leds)1 << (led - 1)); + else + ctrl->leds &= ~((Leds)1 << (led - 1)); +} + +_X_EXPORT int +Ones(unsigned long mask) /* HACKMEM 169 */ +{ + register unsigned long y; + + y = (mask >> 1) &033333333333; + y = mask - y - ((y >>1) & 033333333333); + return (((y + (y >> 3)) & 030707070707) % 077); +} + +int +ProcChangeKeyboardControl (ClientPtr client) +{ +#define DO_ALL (-1) + KeybdCtrl ctrl; + DeviceIntPtr keybd = inputInfo.keyboard; + XID *vlist; + int t; + int led = DO_ALL; + int key = DO_ALL; + BITS32 vmask, index2; + int mask, i; + REQUEST(xChangeKeyboardControlReq); + + REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); + vmask = stuff->mask; + if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask)) + return BadLength; +#ifdef XACE + if (!XaceHook(XACE_DEVICE_ACCESS, client, keybd, TRUE)) + return BadAccess; +#endif + vlist = (XID *)&stuff[1]; /* first word of values */ + ctrl = keybd->kbdfeed->ctrl; + while (vmask) + { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + switch (index2) + { + case KBKeyClickPercent: + t = (INT8)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.click; + else if (t < 0 || t > 100) + { + client->errorValue = t; + return BadValue; + } + ctrl.click = t; + break; + case KBBellPercent: + t = (INT8)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.bell; + else if (t < 0 || t > 100) + { + client->errorValue = t; + return BadValue; + } + ctrl.bell = t; + break; + case KBBellPitch: + t = (INT16)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.bell_pitch; + else if (t < 0) + { + client->errorValue = t; + return BadValue; + } + ctrl.bell_pitch = t; + break; + case KBBellDuration: + t = (INT16)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.bell_duration; + else if (t < 0) + { + client->errorValue = t; + return BadValue; + } + ctrl.bell_duration = t; + break; + case KBLed: + led = (CARD8)*vlist; + vlist++; + if (led < 1 || led > 32) + { + client->errorValue = led; + return BadValue; + } + if (!(stuff->mask & KBLedMode)) + return BadMatch; + break; + case KBLedMode: + t = (CARD8)*vlist; + vlist++; + if (t == LedModeOff) + { + if (led == DO_ALL) + ctrl.leds = 0x0; + else + ctrl.leds &= ~(((Leds)(1)) << (led - 1)); + } + else if (t == LedModeOn) + { + if (led == DO_ALL) + ctrl.leds = ~0L; + else + ctrl.leds |= (((Leds)(1)) << (led - 1)); + } + else + { + client->errorValue = t; + return BadValue; + } +#ifdef XKB + if (!noXkbExtension) { + XkbEventCauseRec cause; + XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client); + XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))), + ctrl.leds, &cause); + ctrl.leds = keybd->kbdfeed->ctrl.leds; + } +#endif + break; + case KBKey: + key = (KeyCode)*vlist; + vlist++; + if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode || + (KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) + { + client->errorValue = key; + return BadValue; + } + if (!(stuff->mask & KBAutoRepeatMode)) + return BadMatch; + break; + case KBAutoRepeatMode: + i = (key >> 3); + mask = (1 << (key & 7)); + t = (CARD8)*vlist; + vlist++; +#ifdef XKB + if (!noXkbExtension && key != DO_ALL) + XkbDisableComputedAutoRepeats(keybd,key); +#endif + if (t == AutoRepeatModeOff) + { + if (key == DO_ALL) + ctrl.autoRepeat = FALSE; + else + ctrl.autoRepeats[i] &= ~mask; + } + else if (t == AutoRepeatModeOn) + { + if (key == DO_ALL) + ctrl.autoRepeat = TRUE; + else + ctrl.autoRepeats[i] |= mask; + } + else if (t == AutoRepeatModeDefault) + { + if (key == DO_ALL) + ctrl.autoRepeat = defaultKeyboardControl.autoRepeat; + else + ctrl.autoRepeats[i] = + (ctrl.autoRepeats[i] & ~mask) | + (defaultKeyboardControl.autoRepeats[i] & mask); + } + else + { + client->errorValue = t; + return BadValue; + } + break; + default: + client->errorValue = stuff->mask; + return BadValue; + } + } + keybd->kbdfeed->ctrl = ctrl; +#ifdef XKB + /* The XKB RepeatKeys control and core protocol global autorepeat */ + /* value are linked */ + if (!noXkbExtension) { + XkbSetRepeatKeys(keybd,key,keybd->kbdfeed->ctrl.autoRepeat); + } + else +#endif + (*keybd->kbdfeed->CtrlProc)(keybd, &keybd->kbdfeed->ctrl); + return Success; +#undef DO_ALL +} + +int +ProcGetKeyboardControl (ClientPtr client) +{ + int i; + register KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl; + xGetKeyboardControlReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 5; + rep.sequenceNumber = client->sequence; + rep.globalAutoRepeat = ctrl->autoRepeat; + rep.keyClickPercent = ctrl->click; + rep.bellPercent = ctrl->bell; + rep.bellPitch = ctrl->bell_pitch; + rep.bellDuration = ctrl->bell_duration; + rep.ledMask = ctrl->leds; + for (i = 0; i < 32; i++) + rep.map[i] = ctrl->autoRepeats[i]; + WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); + return Success; +} + +int +ProcBell(ClientPtr client) +{ + register DeviceIntPtr keybd = inputInfo.keyboard; + int base = keybd->kbdfeed->ctrl.bell; + int newpercent; + REQUEST(xBellReq); + REQUEST_SIZE_MATCH(xBellReq); + if (stuff->percent < -100 || stuff->percent > 100) + { + client->errorValue = stuff->percent; + return BadValue; + } + newpercent = (base * stuff->percent) / 100; + if (stuff->percent < 0) + newpercent = base + newpercent; + else + newpercent = base - newpercent + stuff->percent; +#ifdef XKB + if (!noXkbExtension) + XkbHandleBell(FALSE,FALSE, keybd, newpercent, &keybd->kbdfeed->ctrl, 0, + None, NULL, client); + else +#endif + (*keybd->kbdfeed->BellProc)(newpercent, keybd, + (pointer) &keybd->kbdfeed->ctrl, 0); + return Success; +} + +int +ProcChangePointerControl(ClientPtr client) +{ + DeviceIntPtr mouse = inputInfo.pointer; + PtrCtrl ctrl; /* might get BadValue part way through */ + REQUEST(xChangePointerControlReq); + + REQUEST_SIZE_MATCH(xChangePointerControlReq); + ctrl = mouse->ptrfeed->ctrl; + if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) + { + client->errorValue = stuff->doAccel; + return(BadValue); + } + if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) + { + client->errorValue = stuff->doThresh; + return(BadValue); + } + if (stuff->doAccel) + { + if (stuff->accelNum == -1) + ctrl.num = defaultPointerControl.num; + else if (stuff->accelNum < 0) + { + client->errorValue = stuff->accelNum; + return BadValue; + } + else ctrl.num = stuff->accelNum; + if (stuff->accelDenum == -1) + ctrl.den = defaultPointerControl.den; + else if (stuff->accelDenum <= 0) + { + client->errorValue = stuff->accelDenum; + return BadValue; + } + else ctrl.den = stuff->accelDenum; + } + if (stuff->doThresh) + { + if (stuff->threshold == -1) + ctrl.threshold = defaultPointerControl.threshold; + else if (stuff->threshold < 0) + { + client->errorValue = stuff->threshold; + return BadValue; + } + else ctrl.threshold = stuff->threshold; + } + mouse->ptrfeed->ctrl = ctrl; + (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl); + return Success; +} + +int +ProcGetPointerControl(ClientPtr client) +{ + register PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl; + xGetPointerControlReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.threshold = ctrl->threshold; + rep.accelNumerator = ctrl->num; + rep.accelDenominator = ctrl->den; + WriteReplyToClient(client, sizeof(xGenericReply), &rep); + return Success; +} + +void +MaybeStopHint(register DeviceIntPtr dev, ClientPtr client) +{ + GrabPtr grab = dev->grab; + + if ((grab && SameClient(grab, client) && + ((grab->eventMask & PointerMotionHintMask) || + (grab->ownerEvents && + (EventMaskForClient(dev->valuator->motionHintWindow, client) & + PointerMotionHintMask)))) || + (!grab && + (EventMaskForClient(dev->valuator->motionHintWindow, client) & + PointerMotionHintMask))) + dev->valuator->motionHintWindow = NullWindow; +} + +int +ProcGetMotionEvents(ClientPtr client) +{ + WindowPtr pWin; + xTimecoord * coords = (xTimecoord *) NULL; + xGetMotionEventsReply rep; + int i, count, xmin, xmax, ymin, ymax; + unsigned long nEvents; + DeviceIntPtr mouse = inputInfo.pointer; + TimeStamp start, stop; + REQUEST(xGetMotionEventsReq); + + REQUEST_SIZE_MATCH(xGetMotionEventsReq); + pWin = SecurityLookupWindow(stuff->window, client, TRUE); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + nEvents = 0; + start = ClientTimeToServerTime(stuff->start); + stop = ClientTimeToServerTime(stuff->stop); + if ((CompareTimeStamps(start, stop) != LATER) && + (CompareTimeStamps(start, currentTime) != LATER) && + mouse->valuator->numMotionEvents) + { + if (CompareTimeStamps(stop, currentTime) == LATER) + stop = currentTime; + coords = (xTimecoord *)ALLOCATE_LOCAL(mouse->valuator->numMotionEvents + * sizeof(xTimecoord)); + if (!coords) + return BadAlloc; + count = (*mouse->valuator->GetMotionProc) (mouse, coords, + start.milliseconds, + stop.milliseconds, + pWin->drawable.pScreen); + xmin = pWin->drawable.x - wBorderWidth (pWin); + xmax = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + ymin = pWin->drawable.y - wBorderWidth (pWin); + ymax = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + for (i = 0; i < count; i++) + if ((xmin <= coords[i].x) && (coords[i].x < xmax) && + (ymin <= coords[i].y) && (coords[i].y < ymax)) + { + coords[nEvents].time = coords[i].time; + coords[nEvents].x = coords[i].x - pWin->drawable.x; + coords[nEvents].y = coords[i].y - pWin->drawable.y; + nEvents++; + } + } + rep.length = nEvents * (sizeof(xTimecoord) >> 2); + rep.nEvents = nEvents; + WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep); + if (nEvents) + { + client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite; + WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord), + (char *)coords); + } + if (coords) + DEALLOCATE_LOCAL(coords); + return Success; +} + +int +ProcQueryKeymap(ClientPtr client) +{ + xQueryKeymapReply rep; + int i; + CARD8 *down = inputInfo.keyboard->key->down; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 2; +#ifdef XACE + if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE)) + { + bzero((char *)&rep.map[0], 32); + } + else +#endif + for (i = 0; i<32; i++) + rep.map[i] = down[i]; + WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); + return Success; +} diff --git a/xserver/dix/dispatch.c b/xserver/dix/dispatch.c new file mode 100644 index 000000000..05795407f --- /dev/null +++ b/xserver/dix/dispatch.c @@ -0,0 +1,3992 @@ +/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifdef PANORAMIX_DEBUG +#include <stdio.h> +int ProcInitialConnection(); +#endif + +#include "windowstr.h" +#include <X11/fonts/fontstruct.h> +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#include "dispatch.h" +#include "swaprep.h" +#include "swapreq.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef XACE +#include "xace.h" +#endif +#ifdef XAPPGROUP +#include "appgroup.h" +#endif +#ifdef XKB +#ifndef XKB_IN_SERVER +#define XKB_IN_SERVER +#endif +#include "inputstr.h" +#include <X11/extensions/XKBsrv.h> +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1U << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; + +_X_EXPORT Selection *CurrentSelections; +_X_EXPORT int NumCurrentSelections; +CallbackListPtr SelectionCallback = NULL; + +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +_X_EXPORT CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +extern int connBlockScreenStart; + +static void KillAllClients(void); + +static void DeleteClientFromAnySelections(ClientPtr client); + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +_X_EXPORT CallbackListPtr ClientStateCallback; + +/* dispatchException & isItTimeToYield must be declared volatile since they + * are modified by signal handlers - otherwise optimizer may assume it doesn't + * need to actually check value in memory when used and may miss changes from + * signal handlers. + */ +_X_EXPORT volatile char dispatchException = 0; +_X_EXPORT volatile char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +_X_EXPORT void +SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +_X_EXPORT void +UpdateCurrentTime() +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +_X_EXPORT void +UpdateCurrentTimeIf() +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + +void +InitSelections() +{ + if (CurrentSelections) + xfree(CurrentSelections); + CurrentSelections = (Selection *)NULL; + NumCurrentSelections = 0; +} + +void +FlushClientCaches(XID id) +{ + int i; + register ClientPtr client; + + client = clients[CLIENT_ID(id)]; + if (client == NullClient) + return ; + for (i=0; i<currentMaxClients; i++) + { + client = clients[i]; + if (client != NullClient) + { + if (client->lastDrawableID == id) + { + client->lastDrawableID = WindowTable[0]->drawable.id; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + } + else if (client->lastGCID == id) + { + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + } + } +} +#ifdef SMART_SCHEDULE + +#undef SMART_DEBUG + +#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ + +Bool SmartScheduleDisable = FALSE; +long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; +long SmartScheduleTime; +ClientPtr SmartLastClient; +int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; +int SmartScheduleClient(int *clientReady, int nready); + +#ifdef SMART_DEBUG +long SmartLastPrint; +#endif + +void Dispatch(void); +void InitProcVectors(void); + +int +SmartScheduleClient (int *clientReady, int nready) +{ + ClientPtr pClient; + int i; + int client; + int bestPrio, best = 0; + int bestRobin, robin; + long now = SmartScheduleTime; + long idle; + + bestPrio = -0x7fffffff; + bestRobin = 0; + idle = 2 * SmartScheduleSlice; + for (i = 0; i < nready; i++) + { + client = clientReady[i]; + pClient = clients[client]; + /* Praise clients which are idle */ + if ((now - pClient->smart_check_tick) >= idle) + { + if (pClient->smart_priority < 0) + pClient->smart_priority++; + } + pClient->smart_check_tick = now; + + /* check priority to select best client */ + robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; + if (pClient->smart_priority > bestPrio || + (pClient->smart_priority == bestPrio && robin > bestRobin)) + { + bestPrio = pClient->smart_priority; + bestRobin = robin; + best = client; + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); +#endif + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + { + fprintf (stderr, " use %2d\n", best); + SmartLastPrint = now; + } +#endif + pClient = clients[best]; + SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + /* + * Set current client pointer + */ + if (SmartLastClient != pClient) + { + pClient->smart_start_tick = now; + SmartLastClient = pClient; + } + /* + * Adjust slice + */ + if (nready == 1) + { + /* + * If it's been a long time since another client + * has run, bump the slice up to get maximal + * performance from a single client + */ + if ((now - pClient->smart_start_tick) > 1000 && + SmartScheduleSlice < SmartScheduleMaxSlice) + { + SmartScheduleSlice += SmartScheduleInterval; + } + } + else + { + SmartScheduleSlice = SmartScheduleInterval; + } + return best; +} +#endif + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch(void) +{ + register int *clientReady; /* array of request ready clients */ + register int result; + register ClientPtr client; + register int nready; + register HWEventQueuePtr* icheck = checkForInput; +#ifdef SMART_SCHEDULE + long start_tick; +#endif + + nextFreeClientID = 1; + InitSelections(); + nClients = 0; + + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); + if (!clientReady) + return; + + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + nready = WaitForSomething(clientReady); + +#ifdef SMART_SCHEDULE + if (nready && !SmartScheduleDisable) + { + clientReady[0] = SmartScheduleClient (clientReady, nready); + nready = 1; + } +#endif + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + requestingClient = client; +#ifdef SMART_SCHEDULE + start_tick = SmartScheduleTime; +#endif + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable && + (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + { + /* Penalize clients which consume ticks */ + if (client->smart_priority > SMART_MIN_PRIORITY) + client->smart_priority--; + break; + } +#endif + /* now, finally, deal with client requests */ + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } + + client->sequence++; +#ifdef DEBUG + if (client->requestLogIndex == MAX_REQUEST_LOG) + client->requestLogIndex = 0; + client->requestLog[client->requestLogIndex] = MAJOROP; + client->requestLogIndex++; +#endif + if (result > (maxBigRequestSize << 2)) + result = BadLength; + else +#ifdef XACE + { + XaceHook(XACE_AUDIT_BEGIN, client); + result = (* client->requestVector[MAJOROP])(client); + XaceHook(XACE_AUDIT_END, client, result); + } +#else + result = (* client->requestVector[MAJOROP])(client); +#endif /* XACE */ + + if (result != Success) + { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } +#ifdef DAMAGEEXT + FlushIfCriticalOutputPending (); +#endif + } + FlushAllOutput(); +#ifdef SMART_SCHEDULE + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; +#endif + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } +#if defined(DDXBEFORERESET) + ddxBeforeReset (); +#endif + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; +} + +#undef MAJOROP + +_X_EXPORT int +ProcBadRequest(ClientPtr client) +{ + return (BadRequest); +} + +int +ProcCreateWindow(ClientPtr client) +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result; + int len; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + if (!(pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess))) + return BadWindow; + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &result); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcChangeWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + result = ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcGetWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return(client->noClientException); +} + +int +ProcDestroyWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + if (pWin->parent) + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcDestroySubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + DestroySubwindows(pWin, client); + return(client->noClientException); +} + +int +ProcChangeSaveSet(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + register int result; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + { + result = AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->mode; + return( BadValue ); + } +} + +int +ProcReparentWindow(register ClientPtr client) +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess); + if (!pParent) + return(BadWindow); + if (SAME_SCREENS(pWin->drawable, pParent->drawable)) + { + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + result = ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + return (BadMatch); +} + +int +ProcMapWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcMapSubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapSubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapSubwindows(pWin); + return(client->noClientException); +} + +int +ProcConfigureWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcCirculateWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + CirculateWindow(pWin, (int)stuff->direction, client); + return(client->noClientException); +} + +int +GetGeometry(register ClientPtr client, xGetGeometryReply *rep) +{ + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->id, client, SecurityReadAccess); + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) + { + register WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(register ClientPtr client) +{ + xGetGeometryReply rep; + int status; + + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return(client->noClientException); +} + + +int +ProcQueryTree(register ClientPtr client) +{ + xQueryTreeReply reply; + int numChildren = 0; + register WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + reply.type = X_Reply; + reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + numChildren++; + if (numChildren) + { + int curChild = 0; + + childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + childIDs[curChild++] = pChild->drawable.id; + } + + reply.nChildren = numChildren; + reply.length = (numChildren * sizeof(Window)) >> 2; + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + DEALLOCATE_LOCAL(childIDs); + } + + return(client->noClientException); +} + +int +ProcInternAtom(register ClientPtr client) +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return(BadValue); + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return(client->noClientException); + } + else + return (BadAlloc); +} + +int +ProcGetAtomName(register ClientPtr client) +{ + char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +#ifdef K5AUTH +extern int k5_bad(); +#endif + +int +ProcSetSelectionOwner(register ClientPtr client) +{ + WindowPtr pWin; + TimeStamp time; + REQUEST(xSetSelectionOwnerReq); + + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + UpdateCurrentTime(); + time = ClientTimeToServerTime(stuff->time); + + /* If the client's time stamp is in the future relative to the server's + time stamp, do not set the selection, just return success. */ + if (CompareTimeStamps(time, currentTime) == LATER) + return Success; + if (stuff->window != None) + { + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + } + else + pWin = (WindowPtr)None; + if (ValidAtom(stuff->selection)) + { + int i = 0; + + /* + * First, see if the selection is already set... + */ + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) + i++; + if (i < NumCurrentSelections) + { + xEvent event; + + /* If the timestamp in client's request is in the past relative + to the time stamp indicating the last time the owner of the + selection was set, do not set the selection, just return + success. */ + if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) + == EARLIER) + return Success; + if (CurrentSelections[i].client && + (!pWin || (CurrentSelections[i].client != client))) + { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = time.milliseconds; + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, &event, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + } + } + else + { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return BadAlloc; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = stuff->selection; + } + CurrentSelections[i].lastTimeChanged = time; + CurrentSelections[i].window = stuff->window; + CurrentSelections[i].pWin = pWin; + CurrentSelections[i].client = (pWin ? client : NullClient); + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind= SelectionSetOwner; + CallCallbacks(&SelectionCallback, &info); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->selection; + return (BadAtom); + } +} + +int +ProcGetSelectionOwner(register ClientPtr client) +{ + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if (ValidAtom(stuff->id)) + { + int i; + xGetSelectionOwnerReply reply; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->id) i++; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + if (i < NumCurrentSelections) + reply.owner = CurrentSelections[i].window; + else + reply.owner = None; + WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +int +ProcConvertSelection(register ClientPtr client) +{ + Bool paramsOkay; + xEvent event; + WindowPtr pWin; + REQUEST(xConvertSelectionReq); + + REQUEST_SIZE_MATCH(xConvertSelectionReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); + if (stuff->property != None) + paramsOkay &= ValidAtom(stuff->property); + if (paramsOkay) + { + int i; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + if ((i < NumCurrentSelections) && + (CurrentSelections[i].window != None) +#ifdef XACE + && XaceHook(XACE_RESOURCE_ACCESS, client, + CurrentSelections[i].window, RT_WINDOW, + SecurityReadAccess, CurrentSelections[i].pWin) +#endif + ) + { + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = + CurrentSelections[i].window; + event.u.selectionRequest.requestor = stuff->requestor; + event.u.selectionRequest.selection = stuff->selection; + event.u.selectionRequest.target = stuff->target; + event.u.selectionRequest.property = stuff->property; + if (TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab)) + return (client->noClientException); + } + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = stuff->time; + event.u.selectionNotify.requestor = stuff->requestor; + event.u.selectionNotify.selection = stuff->selection; + event.u.selectionNotify.target = stuff->target; + event.u.selectionNotify.property = None; + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + return (client->noClientException); + } + else + { + client->errorValue = stuff->property; + return (BadAtom); + } +} + +int +ProcGrabServer(register ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return(client->noClientException); + } + OnlyListenToOneClient(client); + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return(client->noClientException); +} + +static void +UngrabServer(ClientPtr client) +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(register ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return(client->noClientException); +} + +int +ProcTranslateCoords(register ClientPtr client) +{ + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) + + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int +ProcOpenFont(register ClientPtr client) +{ + int err; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcCloseFont(register ClientPtr client) +{ + FontPtr pFont; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityDestroyAccess); + if ( pFont != (FontPtr)NULL) /* id was valid */ + { + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadFont); + } +} + +int +ProcQueryFont(register ClientPtr client) +{ + xQueryFontReply *reply; + FontPtr pFont; + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + client->errorValue = stuff->id; /* EITHER font or gc */ + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->id; + return(BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); + if(!reply) + { + return(BadAlloc); + } + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + DEALLOCATE_LOCAL(reply); + return(client->noClientException); + } +} + +int +ProcQueryTextExtents(register ClientPtr client) +{ + REQUEST(xQueryTextExtentsReq); + xQueryTextExtentsReply reply; + FontPtr pFont; + GC *pGC; + ExtentInfoRec info; + unsigned long length; + + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->fid; + return(BadFont); + } + pFont = pGC->font; + } + length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return(BadLength); + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return(BadAlloc); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return(client->noClientException); +} + +int +ProcListFonts(register ClientPtr client) +{ + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(register ClientPtr client) +{ + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/** + * + * \param value must conform to DeleteType + */ +int +dixDestroyPixmap(pointer value, XID pid) +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + register int i; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->width > 32767 || stuff->height > 32767) + { + /* It is allowed to try and allocate a pixmap which is larger than + * 32767 in either dimension. However, all of the framebuffer code + * is buggy and does not reliably draw to such big pixmaps, basically + * because the Region data structure operates with signed shorts + * for the rectangles in it. + * + * Furthermore, several places in the X server computes the + * size in bytes of the pixmap and tries to store it in an + * integer. This integer can overflow and cause the allocated size + * to be much smaller. + * + * So, such big pixmaps are rejected here with a BadAlloc + */ + return BadAlloc; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return(client->noClientException); + } + return (BadAlloc); +} + +int +ProcFreePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, + SecurityDestroyAccess); + if (pMap) + { + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadPixmap); + } +} + +int +ProcCreateGC(register ClientPtr client) +{ + int error; + GC *pGC; + register DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + SECURITY_VERIFY_DRAWABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, + (XID *) &stuff[1], &error); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return (BadAlloc); + return(client->noClientException); +} + +int +ProcChangeGC(register ClientPtr client) +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result; + unsigned len; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + + result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcCopyGC(register ClientPtr client) +{ + register GC *dstGC; + register GC *pGC; + int result; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + SECURITY_VERIFY_GC( pGC, stuff->srcGC, client, SecurityReadAccess); + SECURITY_VERIFY_GC( dstGC, stuff->dstGC, client, SecurityWriteAccess); + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return (BadMatch); + result = CopyGC(pGC, dstGC, stuff->mask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetDashes(register ClientPtr client) +{ + register GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetClipRectangles(register ClientPtr client) +{ + int nr; + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return(BadLength); + nr >>= 3; + result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcFreeGC(register ClientPtr client) +{ + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GC(pGC, stuff->id, client, SecurityDestroyAccess); + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcClearToBackground(register ClientPtr client) +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + + REQUEST_SIZE_MATCH(xClearAreaReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return (BadMatch); + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return(client->noClientException); +} + +int +ProcCopyArea(register ClientPtr client) +{ + register DrawablePtr pDst; + register DrawablePtr pSrc; + register GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + pSrc = pDst; + + SET_DBE_SRCBUF(pSrc, stuff->srcDrawable); + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + REGION_DESTROY(pDst->pScreen, pRgn); + } + + return(client->noClientException); +} + +int +ProcCopyPlane(register ClientPtr client) +{ + register DrawablePtr psrcDraw, pdstDraw; + register GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + psrcDraw = pdstDraw; + + SET_DBE_SRCBUF(psrcDraw, stuff->srcDrawable); + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + REGION_DESTROY(pdstDraw->pScreen, pRgn); + } + return(client->noClientException); +} + +int +ProcPolyPoint(register ClientPtr client) +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint) + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyLine(register ClientPtr client) +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 1) + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolySegment(register ClientPtr client) +{ + int nsegs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return(BadLength); + nsegs >>= 3; + if (nsegs) + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyRectangle (register ClientPtr client) +{ + int nrects; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return(BadLength); + nrects >>= 3; + if (nrects) + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolyArc(register ClientPtr client) +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + return (client->noClientException); +} + +int +ProcFillPoly(register ClientPtr client) +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (things) + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolyFillRectangle(register ClientPtr client) +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return(BadLength); + things >>= 3; + + if (things) + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyFillArc(register ClientPtr client) +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + return (client->noClientException); +} + +#ifdef MATCH_CLIENT_ENDIAN + +int +ServerOrder (void) +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + return MSBFirst; +} + +#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) + +void +ReformatImage (char *base, int nbytes, int bpp, int order) +{ + switch (bpp) { + case 1: /* yuck */ + if (BITMAP_BIT_ORDER != order) + BitOrderInvert ((unsigned char *) base, nbytes); +#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); +#endif + break; + case 4: + break; /* yuck */ + case 8: + break; + case 16: + if (IMAGE_BYTE_ORDER != order) + TwoByteSwap ((unsigned char *) base, nbytes); + break; + case 32: + if (IMAGE_BYTE_ORDER != order) + FourByteSwap ((unsigned char *) base, nbytes); + break; + } +} +#else +#define ReformatImage(b,n,bpp,o) +#endif + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(register ClientPtr client) +{ + register GC *pGC; + register DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + tmpImage = (char *)&stuff[1]; + lengthProto = length; + + if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + + (sizeof(xPutImageReq) >> 2)) != client->req_len) + return BadLength; + + ReformatImage (tmpImage, lengthProto * stuff->height, + stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, + ClientOrder(client)); + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + + return (client->noClientException); +} + + +int +DoGetImage(register ClientPtr client, int format, Drawable drawable, + int x, int y, int width, int height, + Mask planemask, xGetImageReply **im_return) +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int linesDone; + long widthBytesLine, length; + Mask plane = 0; + char *pBuf; + xGetImageReply xgi; +#ifdef XACE + RegionPtr pVisibleRegion = NULL; +#endif + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return(BadValue); + } + SECURITY_VERIFY_DRAWABLE(pDraw, drawable, client, SecurityReadAccess); + if(pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + x < 0 || + pDraw->x + x + width > pDraw->pScreen->width || + pDraw->y + y < 0 || + pDraw->y + y + height > pDraw->pScreen->height || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual (((WindowPtr) pDraw)); + } + else + { + if(x < 0 || + x+width > (int)pDraw->width || + y < 0 || + y+height > (int)pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + + SET_DBE_SRCBUF(pDraw, drawable); + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = length; + + if (im_return) { + pBuf = (char *)xalloc(sz_xGetImageReply + length); + if (!pBuf) + return (BadAlloc); + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = (xgi.length + 3) >> 2; + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + +#ifdef XACE + if (pDraw->type == DRAWABLE_WINDOW && + !XaceHook(XACE_DRAWABLE_ACCESS, client, pDraw)) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + REGION_TRANSLATE(pDraw->pScreen, pVisibleRegion, -pDraw->x, -pDraw->y); + } + } +#endif + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); +#ifdef XACE + if (pVisibleRegion) + XaceCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) + { + ReformatImage (pBuf, (int)(nlines * widthBytesLine), + BitsPerPixel (pDraw->depth), + ClientOrder(client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); +#ifdef XACE + if (pVisibleRegion) + XaceCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { + pBuf += nlines * widthBytesLine; + } else { + ReformatImage (pBuf, + (int)(nlines * widthBytesLine), + 1, + ClientOrder (client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + } + } +#ifdef XACE + if (pVisibleRegion) + REGION_DESTROY(pDraw->pScreen, pVisibleRegion); +#endif + if (!im_return) + DEALLOCATE_LOCAL(pBuf); + return (client->noClientException); +} + +int +ProcGetImage(register ClientPtr client) +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(register ClientPtr client) +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText8(register ClientPtr client) +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText16(register ClientPtr client) +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + + +int +ProcCreateColormap(register ClientPtr client) +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return(BadValue); + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + result = CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + client->errorValue = stuff->visual; + return(BadMatch); +} + +int +ProcFreeColormap(register ClientPtr client) +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, + SecurityDestroyAccess); + if (pmap) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + + +int +ProcCopyColormapAndFree(register ClientPtr client) +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int result; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, + RT_COLORMAP, SecurityReadAccess|SecurityWriteAccess)) ) + { + result = CopyColormapAndFree(mid, pSrcMap, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->srcCmap; + return(BadColor); + } +} + +int +ProcInstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcUninstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcListInstalledColormaps(register ClientPtr client) +{ + xListInstalledColormapsReply *preply; + int nummaps; + WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + + if (!pWin) + return(BadWindow); + + preply = (xListInstalledColormapsReply *) + ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return(BadAlloc); + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + DEALLOCATE_LOCAL(preply); + return(client->noClientException); +} + +int +ProcAllocColor (register ClientPtr client) +{ + ColormapPtr pmap; + int retval; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pmap) + { + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return (retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pmap->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return (client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocNamedColor (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int retval; + + xAllocNamedColorReply ancr; + + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (retval = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return (client->noClientException); + } + else + return(BadName); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorCells (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorCellsReply accr; + int npixels, nmasks, retval; + long length; + Pixel *ppixels, *pmasks; + + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + pmasks = ppixels + npixels; + + if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + accr.type = X_Reply; + accr.length = length >> 2; + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorPlanes(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorPlanesReply acpr; + int npixels, retval; + long length; + Pixel *ppixels; + + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + if( (retval = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + acpr.length = length >> 2; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcFreeColors(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + if(pcmp->flags & AllAllocated) + return(BadAccess); + count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; + retval = FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreColors (ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return(BadLength); + count /= sizeof(xColorItem); + retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreNamedColor (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xColorItem def; + int retval; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + retval = StoreColors(pcmp, 1, &def); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcQueryColors(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + int count, retval; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); + if(!prgbs && count) + return(BadAlloc); + if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) + { + if (prgbs) DEALLOCATE_LOCAL(prgbs); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return (retval); + } + } + qcr.type = X_Reply; + qcr.length = (count * sizeof(xrgb)) >> 2; + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + if (prgbs) DEALLOCATE_LOCAL(prgbs); + return(client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcLookupColor(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return(client->noClientException); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcCreateCursor (register ClientPtr client) +{ + CursorPtr pCursor; + + register PixmapPtr src; + register PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, + RT_PIXMAP, SecurityReadAccess); + msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, + RT_PIXMAP, SecurityReadAccess); + if ( src == (PixmapPtr)NULL) + { + client->errorValue = stuff->source; + return (BadPixmap); + } + if ( msk == (PixmapPtr)NULL) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return (BadPixmap); + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return (BadMatch); + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + + n = BitmapBytePad(width)*height; + srcbits = (unsigned char *)xalloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = (unsigned char *)xalloc(n); + if (!mskbits) + { + xfree(srcbits); + return (BadAlloc); + } + + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)srcbits, n); + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + register unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)mskbits, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursor( srcbits, mskbits, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue); + + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +int +ProcCreateGlyphCursor (register ClientPtr client) +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + + +int +ProcFreeCursor (register ClientPtr client) +{ + CursorPtr pCursor; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, + RT_CURSOR, SecurityDestroyAccess); + if (pCursor) + { + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadCursor); + } +} + +int +ProcQueryBestSize (register ClientPtr client) +{ + xQueryBestSizeReply reply; + register DrawablePtr pDraw; + ScreenPtr pScreen; + REQUEST(xQueryBestSizeReq); + + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return(BadValue); + } + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return (BadMatch); + pScreen = pDraw->pScreen; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return (client->noClientException); +} + + +int +ProcSetScreenSaver (register ClientPtr client) +{ + int blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + if (blankingOption == DefaultBlanking) + ScreenSaverBlanking = defaultScreenSaverBlanking; + else + ScreenSaverBlanking = blankingOption; + if (exposureOption == DefaultExposures) + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + else + ScreenSaverAllowExposures = exposureOption; + + if (stuff->timeout >= 0) + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + else + ScreenSaverTime = defaultScreenSaverTime; + if (stuff->interval >= 0) + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + else + ScreenSaverInterval = defaultScreenSaverInterval; + + SetScreenSaverTimer(); + return (client->noClientException); +} + +int +ProcGetScreenSaver(register ClientPtr client) +{ + xGetScreenSaverReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return (client->noClientException); +} + +int +ProcChangeHosts(register ClientPtr client) +{ + REQUEST(xChangeHostsReq); + int result; + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + result = AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else if (stuff->mode == HostDelete) + result = RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else + { + client->errorValue = stuff->mode; + return BadValue; + } + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcListHosts(register ClientPtr client) +{ + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + /* REQUEST(xListHostsReq); */ + + REQUEST_SIZE_MATCH(xListHostsReq); +#ifdef XACE + /* untrusted clients can't list hosts */ + if (!XaceHook(XACE_HOSTLIST_ACCESS, client, SecurityReadAccess)) + { + return BadAccess; + } +#endif + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return(result); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = len >> 2; + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + xfree(pdata); + return (client->noClientException); +} + +int +ProcChangeAccessControl(register ClientPtr client) +{ + int result; + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + result = ChangeAccessControl(client, stuff->mode == EnableAccess); + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcKillClient(register ClientPtr client) +{ + REQUEST(xResourceReq); + ClientPtr killclient; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return (client->noClientException); + } + + if ((killclient = LookupClient(stuff->id, client))) + { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return (Success); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadValue); + } +} + +int +ProcSetFontPath(register ClientPtr client) +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n, result; + int error; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return(BadLength); + total -= n; + ptr += n; + } + if (total >= 4) + return(BadLength); + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], + &error); + if (!result) + { + result = client->noClientException; + client->errorValue = error; + } + return (result); +} + +int +ProcGetFontPath(register ClientPtr client) +{ + xGetFontPathReply reply; + int stringLens, numpaths; + unsigned char *bufferStart; + /* REQUEST (xReq); */ + + REQUEST_SIZE_MATCH(xReq); + bufferStart = GetFontPath(&numpaths, &stringLens); + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = (stringLens + numpaths + 3) >> 2; + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return(client->noClientException); +} + +int +ProcChangeCloseDownMode(register ClientPtr client) +{ + REQUEST(xSetCloseDownModeReq); + + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return (client->noClientException); + } + else + { + client->errorValue = stuff->mode; + return (BadValue); + } +} + +int ProcForceScreenSaver(register ClientPtr client) +{ + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + return client->noClientException; +} + +int ProcNoOperation(register ClientPtr client) +{ + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return(client->noClientException); +} + +void +InitProcVectors(void) +{ + int i; + for (i = 0; i<256; i++) + { + if(!ProcVector[i]) + { + ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; + ReplySwapVector[i] = ReplyNotSwappd; + } +#ifdef K5AUTH + if (!k5_Vector[i]) + { + k5_Vector[i] = k5_bad; + } +#endif + } + for(i = LASTEvent; i < 128; i++) + { + EventSwapVector[i] = NotImplemented; + } + +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +char dispatchExceptionAtReset = DE_RESET; + +void +CloseDownClient(register ClientPtr client) +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + dispatchException |= dispatchExceptionAtReset; + + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; +#ifdef SMART_SCHEDULE + SmartLastClient = NullClient; +#endif + xfree(client); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients() +{ + int i; + for (i=1; i<currentMaxClients; i++) + if (clients[i]) { + /* Make sure Retained clients are released. */ + clients[i]->closeDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +void +CloseDownRetainedResources() +{ + register int i; + register ClientPtr client; + + for (i=1; i<currentMaxClients; i++) + { + client = clients[i]; + if (client && (client->closeDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +extern int clientPrivateLen; +extern unsigned *clientPrivateSizes; +extern unsigned totalClientSize; + +void InitClient(ClientPtr client, int i, pointer ospriv) +{ + client->index = i; + client->sequence = 0; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->clientGone = FALSE; + if (i) + { + client->closeDownMode = DestroyAll; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + client->lastDrawableID = WindowTable[0]->drawable.id; + } + else + { + client->closeDownMode = RetainPermanent; + client->lastDrawable = (DrawablePtr)NULL; + client->lastDrawableID = INVALID; + } + client->lastGC = (GCPtr) NULL; + client->lastGCID = INVALID; + client->numSaved = 0; + client->saveSet = (SaveSetElt *)NULL; + client->noClientException = Success; +#ifdef DEBUG + client->requestLogIndex = 0; +#endif + client->requestVector = InitialVector; + client->osPrivate = ospriv; + client->swapped = FALSE; + client->big_requests = FALSE; + client->priority = 0; + client->clientState = ClientStateInitial; +#ifdef XKB + if (!noXkbExtension) { + client->xkbClientFlags = 0; + client->mapNotifyMask = 0; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + } +#endif + client->replyBytesRemaining = 0; +#ifdef XAPPGROUP + client->appgroup = NULL; +#endif + client->fontResFunc = NULL; +#ifdef SMART_SCHEDULE + client->smart_priority = 0; + client->smart_start_tick = SmartScheduleTime; + client->smart_stop_tick = SmartScheduleTime; + client->smart_check_tick = SmartScheduleTime; +#endif +} + +int +InitClientPrivates(ClientPtr client) +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *)NULL; + else if (client->index) + ppriv = (DevUnion *)(client + 1); + else + { + ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); + if (!ppriv) + return 0; + } + client->devPrivates = ppriv; + sizes = clientPrivateSizes; + ptr = (char *)(ppriv + clientPrivateLen); + for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + + /* Allow registrants to initialize the serverClient devPrivates */ + if (!client->index && ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return 1; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr NextAvailableClient(pointer ospriv) +{ + register int i; + register ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = (ClientPtr)xalloc(totalClientSize); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) + { + xfree(client); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + xfree(client); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return(client); +} + +int +ProcInitialConnection(register ClientPtr client) +{ + REQUEST(xReq); + register xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return (client->noClientException = -1); + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + + ((prefix->nbytesAuthString + (unsigned)3) >> 2); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +int +SendConnSetup(register ClientPtr client, char *reason) +{ + register xWindowRoot *root; + register int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = (csp.lengthReason + (unsigned)3) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return (client->noClientException = -1); + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; +#ifdef XAPPGROUP + XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); +#endif + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; +#ifdef MATCH_CLIENT_ENDIAN + ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); + ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); +#endif + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#endif + + for (i=0; i<numScreens; i++) + { + register unsigned int j; + register xDepth *pDepth; + + root->currentInputMask = WindowTable[i]->eventMask | + wOtherEventMasks (WindowTable[i]); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return (client->noClientException); +} + +int +ProcEstablishConnection(register ClientPtr client) +{ + char *reason, *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return(client->noClientException); +} + +_X_EXPORT void +SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, + XID resId, int errorCode) +{ + xError rep; + + rep.type = X_Error; + rep.sequenceNumber = client->sequence; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +DeleteWindowFromAnySelections(WindowPtr pWin) +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].pWin == pWin) + { + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind = SelectionWindowDestroy; + CallCallbacks(&SelectionCallback, &info); + } + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +static void +DeleteClientFromAnySelections(ClientPtr client) +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].client == client) + { + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind = SelectionWindowDestroy; + CallCallbacks(&SelectionCallback, &info); + } + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +void +MarkClientException(ClientPtr client) +{ + client->noClientException = -1; +} diff --git a/xserver/dix/dispatch.h b/xserver/dix/dispatch.h new file mode 100644 index 000000000..dd07096af --- /dev/null +++ b/xserver/dix/dispatch.h @@ -0,0 +1,146 @@ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey <dickey@clark.net> + + All Rights Reserved + +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 the above listed +copyright holder(s) not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + +********************************************************/ + +/* + * This prototypes the dispatch.c module (except for functions declared in + * global headers), plus related dispatch procedures from devices.c, events.c, + * extension.c, property.c. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef DISPATCH_H +#define DISPATCH_H 1 + +DISPATCH_PROC(InitClientPrivates); +DISPATCH_PROC(ProcAllocColor); +DISPATCH_PROC(ProcAllocColorCells); +DISPATCH_PROC(ProcAllocColorPlanes); +DISPATCH_PROC(ProcAllocNamedColor); +DISPATCH_PROC(ProcBell); +DISPATCH_PROC(ProcChangeAccessControl); +DISPATCH_PROC(ProcChangeCloseDownMode); +DISPATCH_PROC(ProcChangeGC); +DISPATCH_PROC(ProcChangeHosts); +DISPATCH_PROC(ProcChangeKeyboardControl); +DISPATCH_PROC(ProcChangeKeyboardMapping); +DISPATCH_PROC(ProcChangePointerControl); +DISPATCH_PROC(ProcChangeProperty); +DISPATCH_PROC(ProcChangeSaveSet); +DISPATCH_PROC(ProcChangeWindowAttributes); +DISPATCH_PROC(ProcCirculateWindow); +DISPATCH_PROC(ProcClearToBackground); +DISPATCH_PROC(ProcCloseFont); +DISPATCH_PROC(ProcConfigureWindow); +DISPATCH_PROC(ProcConvertSelection); +DISPATCH_PROC(ProcCopyArea); +DISPATCH_PROC(ProcCopyColormapAndFree); +DISPATCH_PROC(ProcCopyGC); +DISPATCH_PROC(ProcCopyPlane); +DISPATCH_PROC(ProcCreateColormap); +DISPATCH_PROC(ProcCreateCursor); +DISPATCH_PROC(ProcCreateGC); +DISPATCH_PROC(ProcCreateGlyphCursor); +DISPATCH_PROC(ProcCreatePixmap); +DISPATCH_PROC(ProcCreateWindow); +DISPATCH_PROC(ProcDeleteProperty); +DISPATCH_PROC(ProcDestroySubwindows); +DISPATCH_PROC(ProcDestroyWindow); +DISPATCH_PROC(ProcEstablishConnection); +DISPATCH_PROC(ProcFillPoly); +DISPATCH_PROC(ProcForceScreenSaver); +DISPATCH_PROC(ProcFreeColormap); +DISPATCH_PROC(ProcFreeColors); +DISPATCH_PROC(ProcFreeCursor); +DISPATCH_PROC(ProcFreeGC); +DISPATCH_PROC(ProcFreePixmap); +DISPATCH_PROC(ProcGetAtomName); +DISPATCH_PROC(ProcGetFontPath); +DISPATCH_PROC(ProcGetGeometry); +DISPATCH_PROC(ProcGetImage); +DISPATCH_PROC(ProcGetKeyboardControl); +DISPATCH_PROC(ProcGetKeyboardMapping); +DISPATCH_PROC(ProcGetModifierMapping); +DISPATCH_PROC(ProcGetMotionEvents); +DISPATCH_PROC(ProcGetPointerControl); +DISPATCH_PROC(ProcGetPointerMapping); +DISPATCH_PROC(ProcGetProperty); +DISPATCH_PROC(ProcGetScreenSaver); +DISPATCH_PROC(ProcGetSelectionOwner); +DISPATCH_PROC(ProcGetWindowAttributes); +DISPATCH_PROC(ProcGrabServer); +DISPATCH_PROC(ProcImageText16); +DISPATCH_PROC(ProcImageText8); +DISPATCH_PROC(ProcInitialConnection); +DISPATCH_PROC(ProcInstallColormap); +DISPATCH_PROC(ProcInternAtom); +DISPATCH_PROC(ProcKillClient); +DISPATCH_PROC(ProcListExtensions); +DISPATCH_PROC(ProcListFonts); +DISPATCH_PROC(ProcListFontsWithInfo); +DISPATCH_PROC(ProcListHosts); +DISPATCH_PROC(ProcListInstalledColormaps); +DISPATCH_PROC(ProcListProperties); +DISPATCH_PROC(ProcLookupColor); +DISPATCH_PROC(ProcMapSubwindows); +DISPATCH_PROC(ProcMapWindow); +DISPATCH_PROC(ProcNoOperation); +DISPATCH_PROC(ProcOpenFont); +DISPATCH_PROC(ProcPolyArc); +DISPATCH_PROC(ProcPolyFillArc); +DISPATCH_PROC(ProcPolyFillRectangle); +DISPATCH_PROC(ProcPolyLine); +DISPATCH_PROC(ProcPolyPoint); +DISPATCH_PROC(ProcPolyRectangle); +DISPATCH_PROC(ProcPolySegment); +DISPATCH_PROC(ProcPolyText); +DISPATCH_PROC(ProcPutImage); +DISPATCH_PROC(ProcQueryBestSize); +DISPATCH_PROC(ProcQueryColors); +DISPATCH_PROC(ProcQueryExtension); +DISPATCH_PROC(ProcQueryFont); +DISPATCH_PROC(ProcQueryKeymap); +DISPATCH_PROC(ProcQueryTextExtents); +DISPATCH_PROC(ProcQueryTree); +DISPATCH_PROC(ProcReparentWindow); +DISPATCH_PROC(ProcRotateProperties); +DISPATCH_PROC(ProcSetClipRectangles); +DISPATCH_PROC(ProcSetDashes); +DISPATCH_PROC(ProcSetFontPath); +DISPATCH_PROC(ProcSetModifierMapping); +DISPATCH_PROC(ProcSetPointerMapping); +DISPATCH_PROC(ProcSetScreenSaver); +DISPATCH_PROC(ProcSetSelectionOwner); +DISPATCH_PROC(ProcStoreColors); +DISPATCH_PROC(ProcStoreNamedColor); +DISPATCH_PROC(ProcTranslateCoords); +DISPATCH_PROC(ProcUngrabServer); +DISPATCH_PROC(ProcUninstallColormap); +DISPATCH_PROC(ProcUnmapSubwindows); +DISPATCH_PROC(ProcUnmapWindow); + +#endif /* DISPATCH_H */ diff --git a/xserver/dix/dixfonts.c b/xserver/dix/dixfonts.c new file mode 100644 index 000000000..f10011e4b --- /dev/null +++ b/xserver/dix/dixfonts.c @@ -0,0 +1,2133 @@ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +************************************************************************/ +/* The panoramix components contained the following notice */ +/* +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "misc.h" +#include "opaque.h" +#include "dixfontstr.h" +#include "closestr.h" + +#ifdef DEBUG +#include <stdio.h> +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#endif + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include <X11/extensions/xf86bigfont.h> +#endif + +#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics + +extern pointer fosNaturalParams; +extern FontPtr defaultFont; + +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; +static int num_fpes = 0; +_X_EXPORT FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static int num_fpe_types = 0; + +static unsigned char *font_path_string; + +static int num_slept_fpes = 0; +static int size_slept_fpes = 0; +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; +static FontPatternCachePtr patternCache; + +_X_EXPORT int +FontToXError(err) + int err; +{ + switch (err) { + case Successful: + return Success; + case AllocError: + return BadAlloc; + case BadFontName: + return BadName; + case BadFontPath: + case BadFontFormat: /* is there something better? */ + case BadCharRange: + return BadValue; + default: + return err; + } +} + + +/* + * adding RT_FONT prevents conflict with default cursor font + */ +Bool +SetDefaultFont(char *defaultfontname) +{ + int err; + FontPtr pf; + XID fid; + + fid = FakeClientID(0); + err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, + (unsigned) strlen(defaultfontname), defaultfontname); + if (err != Success) + return FALSE; + pf = (FontPtr) LookupIDByType(fid, RT_FONT); + if (pf == (FontPtr) NULL) + return FALSE; + defaultFont = pf; + return TRUE; +} + +/* + * note that the font wakeup queue is not refcounted. this is because + * an fpe needs to be added when it's inited, and removed when it's finally + * freed, in order to handle any data that isn't requested, like FS events. + * + * since the only thing that should call these routines is the renderer's + * init_fpe() and free_fpe(), there shouldn't be any problem in using + * freed data. + */ +void +QueueFontWakeup(FontPathElementPtr fpe) +{ + int i; + FontPathElementPtr *new; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + +#ifdef DEBUG + fprintf(stderr, "re-queueing fpe wakeup\n"); +#endif + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + xrealloc(slept_fpes, + sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); + if (!new) + return; + slept_fpes = new; + size_slept_fpes += 4; + } + slept_fpes[num_slept_fpes] = fpe; + num_slept_fpes++; +} + +void +RemoveFontWakeup(FontPathElementPtr fpe) +{ + int i, + j; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + for (j = i; j < num_slept_fpes; j++) { + slept_fpes[j] = slept_fpes[j + 1]; + } + num_slept_fpes--; + return; + } + } +} + +void +FontWakeup(pointer data, int count, pointer LastSelectMask) +{ + int i; + FontPathElementPtr fpe; + + if (count < 0) + return; + /* wake up any fpe's that may be waiting for information */ + for (i = 0; i < num_slept_fpes; i++) { + fpe = slept_fpes[i]; + (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); + } +} + +/* XXX -- these two funcs may want to be broken into macros */ +static void +UseFPE(FontPathElementPtr fpe) +{ + fpe->refcount++; +} + +static void +FreeFPE (FontPathElementPtr fpe) +{ + fpe->refcount--; + if (fpe->refcount == 0) { + (*fpe_functions[fpe->type].free_fpe) (fpe); + xfree(fpe->name); + xfree(fpe); + } +} + +static Bool +doOpenFont(ClientPtr client, OFclosurePtr c) +{ + FontPtr pfont = NullFont; + FontPathElementPtr fpe = NULL; + ScreenPtr pScr; + int err = Successful; + int i; + char *alias, + *newname; + int newlen; + int aliascount = 20; + /* + * Decide at runtime what FontFormat to use. + */ + Mask FontFormat = + + ((screenInfo.imageByteOrder == LSBFirst) ? + BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | + + ((screenInfo.bitmapBitOrder == LSBFirst) ? + BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | + + BitmapFormatImageRectMin | + +#if GLYPHPADBYTES == 1 + BitmapFormatScanlinePad8 | +#endif + +#if GLYPHPADBYTES == 2 + BitmapFormatScanlinePad16 | +#endif + +#if GLYPHPADBYTES == 4 + BitmapFormatScanlinePad32 | +#endif + +#if GLYPHPADBYTES == 8 + BitmapFormatScanlinePad64 | +#endif + + BitmapFormatScanlineUnit8; + + if (client->clientGone) + { + if (c->current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + while (c->current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current_fpe]; + err = (*fpe_functions[fpe->type].open_font) + ((pointer) client, fpe, c->flags, + c->fontname, c->fnamelen, FontFormat, + BitmapFormatMaskByte | + BitmapFormatMaskBit | + BitmapFormatMaskImageRectangle | + BitmapFormatMaskScanLinePad | + BitmapFormatMaskScanLineUnit, + c->fontid, &pfont, &alias, + c->non_cachable_font && c->non_cachable_font->fpe == fpe ? + c->non_cachable_font : + (FontPtr)0); + + if (err == FontNameAlias && alias) { + newlen = strlen(alias); + newname = (char *) xrealloc(c->fontname, newlen); + if (!newname) { + err = AllocError; + break; + } + memmove(newname, alias, newlen); + c->fontname = newname; + c->fnamelen = newlen; + c->current_fpe = 0; + if (--aliascount <= 0) + break; + continue; + } + if (err == BadFontName) { + c->current_fpe++; + continue; + } + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); + } + return TRUE; + } + break; + } + + if (err != Successful) + goto bail; + if (!pfont) { + err = BadFontName; + goto bail; + } + if (!pfont->fpe) + pfont->fpe = fpe; + pfont->refcnt++; + if (pfont->refcnt == 1) { + UseFPE(pfont->fpe); + for (i = 0; i < screenInfo.numScreens; i++) { + pScr = screenInfo.screens[i]; + if (pScr->RealizeFont) + { + if (!(*pScr->RealizeFont) (pScr, pfont)) + { + CloseFont (pfont, (Font) 0); + err = AllocError; + goto bail; + } + } + } + } + if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { + err = AllocError; + goto bail; + } + if (patternCache && pfont != c->non_cachable_font) + CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, + pfont); +bail: + if (err != Successful && c->client != serverClient) { + SendErrorToClient(c->client, X_OpenFont, 0, + c->fontid, FontToXError(err)); + } + if (c->slept) + ClientWakeup(c->client); + for (i = 0; i < c->num_fpes; i++) { + FreeFPE(c->fpe_list[i]); + } + xfree(c->fpe_list); + xfree(c->fontname); + xfree(c); + return TRUE; +} + +int +OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname) +{ + OFclosurePtr c; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + c = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = (char *) xalloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + xfree(c); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c->fontname); + xfree(c); + return BadAlloc; + } + memmove(c->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->fontid = fid; + c->current_fpe = 0; + c->num_fpes = num_fpes; + c->fnamelen = lenfname; + c->slept = FALSE; + c->flags = flags; + c->non_cachable_font = cached; + + (void) doOpenFont(client, c); + return Success; +} + +/** + * Decrement font's ref count, and free storage if ref count equals zero + * + * \param value must conform to DeleteType + */ +_X_EXPORT int +CloseFont(pointer value, XID fid) +{ + int nscr; + ScreenPtr pscr; + FontPathElementPtr fpe; + FontPtr pfont = (FontPtr)value; + + if (pfont == NullFont) + return (Success); + if (--pfont->refcnt == 0) { + if (patternCache) + RemoveCachedFontPattern (patternCache, pfont); + /* + * since the last reference is gone, ask each screen to free any + * storage it may have allocated locally for it. + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + if (pscr->UnrealizeFont) + (*pscr->UnrealizeFont) (pscr, pfont); + } + if (pfont == defaultFont) + defaultFont = NULL; +#ifdef XF86BIGFONT + XF86BigfontFreeFontShm(pfont); +#endif + fpe = pfont->fpe; + (*fpe_functions[fpe->type].close_font) (fpe, pfont); + FreeFPE(fpe); + } + return (Success); +} + + +/***====================================================================***/ + +/** + * Sets up pReply as the correct QueryFontReply for pFont with the first + * nProtoCCIStructs char infos. + * + * \param pReply caller must allocate this storage + */ +void +QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs) +{ + FontPropPtr pFP; + int r, + c, + i; + xFontProp *prFP; + xCharInfo *prCI; + xCharInfo *charInfos[256]; + unsigned char chars[512]; + int ninfos; + unsigned long ncols; + unsigned long count; + + /* pr->length set in dispatch */ + pReply->minCharOrByte2 = pFont->info.firstCol; + pReply->defaultChar = pFont->info.defaultCh; + pReply->maxCharOrByte2 = pFont->info.lastCol; + pReply->drawDirection = pFont->info.drawDirection; + pReply->allCharsExist = pFont->info.allExist; + pReply->minByte1 = pFont->info.firstRow; + pReply->maxByte1 = pFont->info.lastRow; + pReply->fontAscent = pFont->info.fontAscent; + pReply->fontDescent = pFont->info.fontDescent; + + pReply->minBounds = pFont->info.ink_minbounds; + pReply->maxBounds = pFont->info.ink_maxbounds; + + pReply->nFontProps = pFont->info.nprops; + pReply->nCharInfos = nProtoCCIStructs; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); + i < pFont->info.nprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + } + + ninfos = 0; + ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); + prCI = (xCharInfo *) (prFP); + for (r = pFont->info.firstRow; + ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; + r++) { + i = 0; + for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { + chars[i++] = r; + chars[i++] = c; + } + (*pFont->get_metrics) (pFont, ncols, chars, + TwoD16Bit, &count, charInfos); + i = 0; + for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { + *prCI = *charInfos[i]; + prCI++; + ninfos++; + } + } + return; +} + +static Bool +doListFontsAndAliases(ClientPtr client, LFclosurePtr c) +{ + FontPathElementPtr fpe; + int err = Successful; + FontNamesPtr names = NULL; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int nnames; + int stringLens; + int i; + xListFontsReply reply; + char *bufptr; + char *bufferStart; + int aliascount = 0; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + memmove(resolved, tmpname, resolvedlen + 1); + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + (void)AddFontNamesName(c->names, c->savedName, + c->savedNameLen); + } + else + (void)AddFontNamesName(c->names, name, namelen); + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ + if (err != Successful) { + SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); + goto bail; + } + +finish: + + names = c->names; + nnames = names->nnames; + client = c->client; + stringLens = 0; + for (i = 0; i < nnames; i++) + stringLens += (names->length[i] <= 255) ? names->length[i] : 0; + + reply.type = X_Reply; + reply.length = (stringLens + nnames + 3) >> 2; + reply.nFonts = nnames; + reply.sequenceNumber = client->sequence; + + bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); + + if (!bufptr && reply.length) { + SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); + goto bail; + } + /* + * since WriteToClient long word aligns things, copy to temp buffer and + * write all at once + */ + for (i = 0; i < nnames; i++) { + if (names->length[i] > 255) + reply.nFonts--; + else + { + *bufptr++ = names->length[i]; + memmove( bufptr, names->names[i], names->length[i]); + bufptr += names->length[i]; + } + } + nnames = reply.nFonts; + reply.length = (stringLens + nnames + 3) >> 2; + client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; + WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); + (void) WriteToClient(client, stringLens + nnames, bufferStart); + DEALLOCATE_LOCAL(bufferStart); + +bail: + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(names); + xfree(c); + if (resolved) xfree(resolved); + return TRUE; +} + +int +ListFonts(ClientPtr client, unsigned char *pattern, unsigned length, + unsigned max_names) +{ + int i; + LFclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + return BadAlloc; + } + memmove( c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsAndAliases(client, c); + return Success; +} + +int +doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) +{ + FontPathElementPtr fpe; + int err = Successful; + char *name; + int namelen; + int numFonts; + FontInfoRec fontInfo, + *pFontInfo; + xListFontsWithInfoReply *reply; + int length; + xFontProp *pFP; + int i; + int aliascount = 0; + xListFontsWithInfoReply finalReply; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; + if (!c->current.patlen) + goto finish; + while (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + if (!c->current.list_started) + { + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) + { + name = 0; + pFontInfo = &fontInfo; + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &name, &namelen, &pFontInfo, + &numFonts, c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsWithInfo, + c); + c->slept = TRUE; + } + return TRUE; + } + } + /* + * When we get an alias back, save our state and reset back to the + * start of the FPE looking for the specified name. As soon as a real + * font is found for the alias, pop back to the old state + */ + if (err == FontNameAlias) + { + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + FontInfoPtr tmpFontInfo; + + tmpname = 0; + tmpFontInfo = &fontInfo; + (void) (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, + &numFonts, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + c->savedNumFonts = numFonts; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + aliascount = 20; + } + memmove(c->current.pattern, name, namelen); + c->current.patlen = namelen; + c->current.max_names = 1; + c->current.current_fpe = 0; + c->current.private = 0; + c->current.list_started = FALSE; + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've sent enough font + * names, quit. Always wait for BadFontName to let the FPE + * have a chance to clean up. + */ + else if (err == BadFontName) + { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->current.max_names == 0 || + c->current.current_fpe == c->num_fpes) + { + c->haveSaved = FALSE; + c->saved.max_names -= (1 - c->current.max_names); + c->current = c->saved; + } + } + else if (c->current.max_names == 0) + break; + } + else if (err == Successful) + { + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); + reply = c->reply; + if (c->length < length) + { + reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); + if (!reply) + { + err = AllocError; + break; + } + c->reply = reply; + c->length = length; + } + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + reply->type = X_Reply; + reply->length = (sizeof *reply - sizeof(xGenericReply) + + pFontInfo->nprops * sizeof(xFontProp) + + namelen + 3) >> 2; + reply->sequenceNumber = client->sequence; + reply->nameLength = namelen; + reply->minBounds = pFontInfo->ink_minbounds; + reply->maxBounds = pFontInfo->ink_maxbounds; + reply->minCharOrByte2 = pFontInfo->firstCol; + reply->maxCharOrByte2 = pFontInfo->lastCol; + reply->defaultChar = pFontInfo->defaultCh; + reply->nFontProps = pFontInfo->nprops; + reply->drawDirection = pFontInfo->drawDirection; + reply->minByte1 = pFontInfo->firstRow; + reply->maxByte1 = pFontInfo->lastRow; + reply->allCharsExist = pFontInfo->allExist; + reply->fontAscent = pFontInfo->fontAscent; + reply->fontDescent = pFontInfo->fontDescent; + reply->nReplies = numFonts; + pFP = (xFontProp *) (reply + 1); + for (i = 0; i < pFontInfo->nprops; i++) + { + pFP->name = pFontInfo->props[i].name; + pFP->value = pFontInfo->props[i].value; + pFP++; + } + WriteSwappedDataToClient(client, length, reply); + (void) WriteToClient(client, namelen, name); + if (pFontInfo == &fontInfo) + { + xfree(fontInfo.props); + xfree(fontInfo.isStringProp); + } + --c->current.max_names; + } + } +finish: + length = sizeof(xListFontsWithInfoReply); + bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); + finalReply.type = X_Reply; + finalReply.sequenceNumber = client->sequence; + finalReply.length = (sizeof(xListFontsWithInfoReply) + - sizeof(xGenericReply)) >> 2; + WriteSwappedDataToClient(client, length, &finalReply); +bail: + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->reply); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + xfree(c); + return TRUE; +} + +int +StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, + int max_names) +{ + int i; + LFWIclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFWIclosurePtr) xalloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) + { + xfree(c); + goto badAlloc; + } + memmove(c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) + { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->reply = 0; + c->length = 0; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->savedNumFonts = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsWithInfo(client, c); + return Success; +badAlloc: + return BadAlloc; +} + +#define TextEltHeader 2 +#define FontShiftSize 5 +static XID clearGC[] = { CT_NONE }; +#define clearGCmask (GCClipMask) + +int +doPolyText(ClientPtr client, register PTclosurePtr c) +{ + register FontPtr pFont = c->pGC->font, oldpFont; + Font fid, oldfid; + int err = Success, lgerr; /* err is in X error, not font error, space */ + enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; + FontPathElementPtr fpe; + GC *origGC = NULL; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + + if (c->slept) + { + /* Client has died, but we cannot bail out right now. We + need to clean up after the work we did when going to + sleep. Setting the drawable pointer to 0 makes this + happen without any attempts to render or perform other + unnecessary activities. */ + c->pDraw = (DrawablePtr)0; + } + else + { + err = Success; + goto bail; + } + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client and avoid further + rendering while we clean up after ourself. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + c->pDraw = (DrawablePtr)0; + } + + client_state = c->slept ? SLEEPING : NEVER_SLEPT; + + while (c->endReq - c->pElt > TextEltHeader) + { + if (*c->pElt == FontChange) + { + if (c->endReq - c->pElt < FontShiftSize) + { + err = BadLength; + goto bail; + } + + oldpFont = pFont; + oldfid = fid; + + fid = ((Font)*(c->pElt+4)) /* big-endian */ + | ((Font)*(c->pElt+3)) << 8 + | ((Font)*(c->pElt+2)) << 16 + | ((Font)*(c->pElt+1)) << 24; + pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + client->errorValue = fid; + err = BadFont; + /* restore pFont and fid for step 4 (described below) */ + pFont = oldpFont; + fid = oldfid; + + /* If we're in START_SLEEP mode, the following step + shortens the request... in the unlikely event that + the fid somehow becomes valid before we come through + again to actually execute the polytext, which would + then mess up our refcounting scheme badly. */ + c->err = err; + c->endReq = c->pElt; + + goto bail; + } + + /* Step 3 (described below) on our new font */ + if (client_state == START_SLEEP) + pFont->refcnt++; + else + { + if (pFont != c->pGC->font && c->pDraw) + { + ChangeGC( c->pGC, GCFont, &fid); + ValidateGC(c->pDraw, c->pGC); + if (c->reqType == X_PolyText8) + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; + else + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; + } + + /* Undo the refcnt++ we performed when going to sleep */ + if (client_state == SLEEPING) + (void)CloseFont(c->pGC->font, (Font)0); + } + c->pElt += FontShiftSize; + } + else /* print a string */ + { + unsigned char *pNextElt; + pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; + if ( pNextElt > c->endReq) + { + err = BadLength; + goto bail; + } + if (client_state == START_SLEEP) + { + c->pElt = pNextElt; + continue; + } + if (c->pDraw) + { + lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, + c->pElt + TextEltHeader); + } + else lgerr = Successful; + + if (lgerr == Suspended) + { + if (!c->slept) { + int len; + GC *pGC; + PTclosurePtr new_closure; + + /* We're putting the client to sleep. We need to do a few things + to ensure successful and atomic-appearing execution of the + remainder of the request. First, copy the remainder of the + request into a safe malloc'd area. Second, create a scratch GC + to use for the remainder of the request. Third, mark all fonts + referenced in the remainder of the request to prevent their + deallocation. Fourth, make the original GC look like the + request has completed... set its font to the final font value + from this request. These GC manipulations are for the unlikely + (but possible) event that some other client is using the GC. + Steps 3 and 4 are performed by running this procedure through + the remainder of the request in a special no-render mode + indicated by client_state = START_SLEEP. */ + + /* Step 1 */ + /* Allocate a malloc'd closure structure to replace + the local one we were passed */ + new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + len = c->endReq - c->pElt; + c->data = (unsigned char *)xalloc(len); + if (!c->data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(c->data, c->pElt, len); + c->pElt = c->data; + c->endReq = c->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(c->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != + Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + origGC = c->pGC; + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doPolyText, + (pointer) c); + + /* Set up to perform steps 3 and 4 */ + client_state = START_SLEEP; + continue; /* on to steps 3 and 4 */ + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ + c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, + *c->pElt, c->pElt + TextEltHeader); + } + c->pElt = pNextElt; + } + } + +bail: + + if (client_state == START_SLEEP) + { + /* Step 4 */ + if (pFont != origGC->font) + { + ChangeGC(origGC, GCFont, &fid); + ValidateGC(c->pDraw, origGC); + } + + /* restore pElt pointer for execution of remainder of the request */ + c->pElt = c->data; + return TRUE; + } + + if (c->err != Success) err = c->err; + if (err != Success && c->client != serverClient) { +#ifdef PANORAMIX + if (noPanoramiXExtension || !c->pGC->pScreen->myNum) +#endif + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt, + unsigned char *endReq, int xorg, int yorg, int reqType, XID did) +{ + PTclosureRec local_closure; + + local_closure.pElt = pElt; + local_closure.endReq = endReq; + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_PolyText8) + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; + local_closure.itemSize = 1; + } + else + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16; + local_closure.itemSize = 2; + } + local_closure.pGC = pGC; + local_closure.did = did; + local_closure.err = Success; + local_closure.slept = FALSE; + + (void) doPolyText(client, &local_closure); + return Success; +} + + +#undef TextEltHeader +#undef FontShiftSize + +int +doImageText(ClientPtr client, register ITclosurePtr c) +{ + int err = Success, lgerr; /* err is in X error, not font error, space */ + FontPathElementPtr fpe; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); + if (lgerr == Suspended) + { + if (!c->slept) { + GC *pGC; + unsigned char *data; + ITclosurePtr new_closure; + + /* We're putting the client to sleep. We need to + save some state. Similar problem to that handled + in doPolyText, but much simpler because the + request structure is much simpler. */ + + new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + data = (unsigned char *)xalloc(c->nChars * c->itemSize); + if (!data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(data, c->data, c->nChars * c->itemSize); + c->data = data; + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | + GCForeground | GCBackground | GCFillStyle | + GCTile | GCStipple | GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, + c->nChars, c->data); + } + +bail: + + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, + unsigned char *data, int xorg, int yorg, int reqType, XID did) +{ + ITclosureRec local_closure; + + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.pGC = pGC; + local_closure.nChars = nChars; + local_closure.data = data; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_ImageText8) + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; + local_closure.itemSize = 1; + } + else + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; + local_closure.itemSize = 2; + } + local_closure.did = did; + local_closure.slept = FALSE; + + (void) doImageText(client, &local_closure); + return Success; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +DetermineFPEType(char *pathname) +{ + int i; + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static void +FreeFontPath(FontPathElementPtr *list, int n, Bool force) +{ + int i; + + for (i = 0; i < n; i++) { + if (force) { + /* Sanity check that all refcounts will be 0 by the time + we get to the end of the list. */ + int found = 1; /* the first reference is us */ + int j; + for (j = i+1; j < n; j++) { + if (list[j] == list[i]) + found++; + } + if (list[i]->refcount != found) { + ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n", + list[i]->name_length, list[i]->name, + list[i]->refcount, found); + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + xfree((char *) list); +} + +static FontPathElementPtr +find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) +{ + FontPathElementPtr fpe; + int i; + + for (i = 0; i < num; i++) { + fpe = list[i]; + if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) + return fpe; + } + return (FontPathElementPtr) 0; +} + + +static int +SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) +{ + int i, err = 0; + int valid_paths = 0; + unsigned int len; + unsigned char *cp = paths; + FontPathElementPtr fpe = NULL, *fplist; + + fplist = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * npaths); + if (!fplist) { + *bad = 0; + return BadAlloc; + } + for (i = 0; i < num_fpe_types; i++) { + if (fpe_functions[i].set_path_hook) + (*fpe_functions[i].set_path_hook) (); + } + for (i = 0; i < npaths; i++) + { + len = (unsigned int) (*cp++); + + if (len == 0) + { + if (persist) + ErrorF ("Removing empty element from the valid list of fontpaths\n"); + err = BadValue; + } + else + { + /* if it's already in our active list, just reset it */ + /* + * note that this can miss FPE's in limbo -- may be worth catching + * them, though it'd muck up refcounting + */ + fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); + if (fpe) + { + err = (*fpe_functions[fpe->type].reset_fpe) (fpe); + if (err == Successful) + { + UseFPE(fpe);/* since it'll be decref'd later when freed + * from the old list */ + } + else + fpe = 0; + } + /* if error or can't do it, act like it's a new one */ + if (!fpe) + { + fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec)); + if (!fpe) + { + err = BadAlloc; + goto bail; + } + fpe->name = (char *) xalloc(len + 1); + if (!fpe->name) + { + xfree(fpe); + err = BadAlloc; + goto bail; + } + fpe->refcount = 1; + + strncpy(fpe->name, (char *) cp, (int) len); + fpe->name[len] = '\0'; + fpe->name_length = len; + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) + err = BadValue; + else + err = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (err != Successful) + { + if (persist) + { + ErrorF("Could not init font path element %s, removing from list!\n", + fpe->name); + } + xfree (fpe->name); + xfree (fpe); + } + } + } + if (err != Successful) + { + if (!persist) + goto bail; + } + else + { + fplist[valid_paths++] = fpe; + } + cp += len; + } + + FreeFontPath(font_path_elements, num_fpes, FALSE); + font_path_elements = fplist; + if (patternCache) + EmptyFontPatternCache(patternCache); + num_fpes = valid_paths; + + return Success; +bail: + *bad = i; + while (--valid_paths >= 0) + FreeFPE(fplist[valid_paths]); + xfree(fplist); + return FontToXError(err); +} + +/* XXX -- do we need to pass error down to each renderer? */ +int +SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error) +{ + int err = Success; + + if (npaths == 0) { + if (SetDefaultFontPath(defaultFontPath) != Success) + return BadValue; + } else { + err = SetFontPathElements(npaths, paths, error, FALSE); + } + return err; +} + +int +SetDefaultFontPath(char *path) +{ + unsigned char *cp, + *pp, + *nump, + *newpath; + int num = 1, + len, + err, + size = 0, + bad; + + /* get enough for string, plus values -- use up commas */ + len = strlen(path) + 1; + nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); + if (!newpath) + return BadAlloc; + pp = (unsigned char *) path; + cp++; + while (*pp) { + if (*pp == ',') { + *nump = (unsigned char) size; + nump = cp++; + pp++; + num++; + size = 0; + } else { + *cp++ = *pp++; + size++; + } + } + *nump = (unsigned char) size; + + err = SetFontPathElements(num, newpath, &bad, TRUE); + + DEALLOCATE_LOCAL(newpath); + + return err; +} + +unsigned char * +GetFontPath(int *count, int *length) +{ + int i; + unsigned char *c; + int len; + FontPathElementPtr fpe; + + len = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + len += fpe->name_length + 1; + } + font_path_string = (unsigned char *) xrealloc(font_path_string, len); + if (!font_path_string) + return NULL; + + c = font_path_string; + *length = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + *c = fpe->name_length; + *length += *c++; + memmove(c, fpe->name, fpe->name_length); + c += fpe->name_length; + } + *count = num_fpes; + return font_path_string; +} + +_X_EXPORT int +LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, unsigned char *data) +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} + +void +DeleteClientFontStuff(ClientPtr client) +{ + int i; + FontPathElementPtr fpe; + + for (i = 0; i < num_fpes; i++) + { + fpe = font_path_elements[i]; + if (fpe_functions[fpe->type].client_died) + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } +} + +void +InitFonts () +{ + patternCache = MakeFontPatternCache(); + +#ifndef KDRIVESERVER + if (screenInfo.numScreens > screenInfo.numVideoScreens) { + PrinterFontRegisterFpeFunctions(); + FontFileCheckRegisterFpeFunctions(); + check_fs_register_fpe_functions(); + } else +#endif + { +#ifdef KDRIVESERVER + BuiltinRegisterFpeFunctions(); +#endif + FontFileRegisterFpeFunctions(); +#ifndef NOFONTSERVERACCESS + fs_register_fpe_functions(); +#endif + } +} + +int +GetDefaultPointSize () +{ + return 120; +} + + +FontResolutionPtr +GetClientResolutions (int *num) +{ + if (requestingClient && requestingClient->fontResFunc != NULL && + !requestingClient->clientGone) + { + return (*requestingClient->fontResFunc)(requestingClient, num); + } + else { + static struct _FontResolution res; + ScreenPtr pScreen; + + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; + } +} + +/* + * returns the type index of the new fpe + * + * should be called (only once!) by each type of fpe when initialized + */ + +int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + FPEFunctions *new; + + /* grow the list */ + new = (FPEFunctions *) xrealloc(fpe_functions, + (num_fpe_types + 1) * sizeof(FPEFunctions)); + if (!new) + return -1; + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = + start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = + next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = + next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +void +FreeFonts() +{ + if (patternCache) { + FreeFontPatternCache(patternCache); + patternCache = 0; + } + FreeFontPath(font_path_elements, num_fpes, TRUE); + font_path_elements = 0; + num_fpes = 0; + xfree(fpe_functions); + num_fpe_types = 0; + fpe_functions = (FPEFunctions *) 0; +} + +/* convenience functions for FS interface */ + +FontPtr +find_old_font(XID id) +{ + return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE, + SecurityUnknownAccess); +} + +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +int +StoreFontClientFont(FontPtr pfont, Font id) +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +void +DeleteFontClientID(Font id) +{ + FreeResource(id, RT_NONE); +} + +int +client_auth_generation(ClientPtr client) +{ + return 0; +} + +static int fs_handlers_installed = 0; +static unsigned int last_server_gen; + +int +init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) +{ + /* if server has reset, make sure the b&w handlers are reinstalled */ + if (last_server_gen < serverGeneration) { + last_server_gen = serverGeneration; + fs_handlers_installed = 0; + } + if (fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "adding FS b & w handlers\n"); +#endif + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +void +remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) +{ + if (all) { + /* remove the handlers if no one else is using them */ + if (--fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "removing FS b & w handlers\n"); +#endif + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + +#ifdef DEBUG +#define GLWIDTHBYTESPADDED(bits,nbytes) \ + ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \ + :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \ + :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \ + :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \ + : 0) + +#define GLYPH_SIZE(ch, nbytes) \ + GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \ + (ch)->metrics.leftSideBearing, (nbytes)) +void +dump_char_ascii(CharInfoPtr cip) +{ + int r, + l; + int bpr; + int byte; + static unsigned maskTab[] = { + (1 << 7), (1 << 6), (1 << 5), (1 << 4), + (1 << 3), (1 << 2), (1 << 1), (1 << 0), + }; + + bpr = GLYPH_SIZE(cip, 4); + for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) { + pointer row = (pointer) cip->bits + r * bpr; + + byte = 0; + for (l = 0; l <= (cip->metrics.rightSideBearing - + cip->metrics.leftSideBearing); l++) { + if (maskTab[l & 7] & row[l >> 3]) + putchar('X'); + else + putchar('.'); + } + putchar('\n'); + } +} + +#endif diff --git a/xserver/dix/dixutils.c b/xserver/dix/dixutils.c new file mode 100644 index 000000000..a395d4474 --- /dev/null +++ b/xserver/dix/dixutils.c @@ -0,0 +1,938 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ + +/* + +(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved. + +Permission to use, copy, modify, distribute, and sublicense this software and its +documentation for any purpose and without fee is hereby granted, provided that +the above copyright notices appear in all copies and that both those copyright +notices and this permission notice appear in supporting documentation and that +the name of Adobe Systems Incorporated not be used in advertising or publicity +pertaining to distribution of the software without specific, written prior +permission. No trademark license to use the Adobe trademarks is hereby +granted. If the Adobe trademark "Display PostScript"(tm) is used to describe +this software, its functionality or for any other purpose, such use shall be +limited to a statement that this software works in conjunction with the Display +PostScript system. Proper trademark attribution to reflect Adobe's ownership +of the trademark shall be given whenever any such reference to the Display +PostScript system is made. + +ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY +PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE +DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- +INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU +OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT +LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER +SUPPORT FOR THE SOFTWARE. + +Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems +Incorporated which may be registered in certain jurisdictions. + +Author: Adobe Systems Incorporated + +*/ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xmd.h> +#include "misc.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#define XK_LATIN1 +#include <X11/keysymdef.h> +#ifdef XACE +#include "xace.h" +#endif + +/* + * CompareTimeStamps returns -1, 0, or +1 depending on if the first + * argument is less than, equal to or greater than the second argument. + */ + +_X_EXPORT int +CompareTimeStamps(TimeStamp a, TimeStamp b) +{ + if (a.months < b.months) + return EARLIER; + if (a.months > b.months) + return LATER; + if (a.milliseconds < b.milliseconds) + return EARLIER; + if (a.milliseconds > b.milliseconds) + return LATER; + return SAMETIME; +} + +/* + * convert client times to server TimeStamps + */ + +#define HALFMONTH ((unsigned long) 1<<31) +_X_EXPORT TimeStamp +ClientTimeToServerTime(CARD32 c) +{ + TimeStamp ts; + if (c == CurrentTime) + return currentTime; + ts.months = currentTime.months; + ts.milliseconds = c; + if (c > currentTime.milliseconds) + { + if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH) + ts.months -= 1; + } + else if (c < currentTime.milliseconds) + { + if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH) + ts.months += 1; + } + return ts; +} + +/* + * ISO Latin-1 case conversion routine + * + * this routine always null-terminates the result, so + * beware of too-small buffers + */ + +static unsigned char +ISOLatin1ToLower (unsigned char source) +{ + unsigned char dest; + if ((source >= XK_A) && (source <= XK_Z)) + dest = source + (XK_a - XK_A); + else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis)) + dest = source + (XK_agrave - XK_Agrave); + else if ((source >= XK_Ooblique) && (source <= XK_Thorn)) + dest = source + (XK_oslash - XK_Ooblique); + else + dest = source; + return dest; +} + + +_X_EXPORT void +CopyISOLatin1Lowered(unsigned char *dest, unsigned char *source, int length) +{ + register int i; + + for (i = 0; i < length; i++, source++, dest++) + *dest = ISOLatin1ToLower (*source); + *dest = '\0'; +} + +int +CompareISOLatin1Lowered(unsigned char *s1, int s1len, + unsigned char *s2, int s2len) +{ + unsigned char c1, c2; + + for (;;) + { + /* note -- compare against zero so that -1 ignores len */ + c1 = s1len-- ? *s1++ : '\0'; + c2 = s2len-- ? *s2++ : '\0'; + if (!c1 || + (c1 != c2 && + (c1 = ISOLatin1ToLower (c1)) != (c2 = ISOLatin1ToLower (c2)))) + break; + } + return (int) c1 - (int) c2; +} + +#ifdef XACE + +/* SecurityLookupWindow and SecurityLookupDrawable: + * Look up the window/drawable taking into account the client doing + * the lookup and the type of access desired. Return the window/drawable + * if it exists and the client is allowed access, else return NULL. + * Most Proc* functions should be calling these instead of + * LookupWindow and LookupDrawable, which do no access checks. + * XACE note: need to see if client->lastDrawableID can still be used here. + */ + +_X_EXPORT WindowPtr +SecurityLookupWindow(XID rid, ClientPtr client, Mask access_mode) +{ + client->errorValue = rid; + if(rid == INVALID) + return NULL; + return (WindowPtr)SecurityLookupIDByType(client, rid, RT_WINDOW, access_mode); +} + + +_X_EXPORT pointer +SecurityLookupDrawable(XID rid, ClientPtr client, Mask access_mode) +{ + register DrawablePtr pDraw; + + if(rid == INVALID) + return (pointer) NULL; + pDraw = (DrawablePtr)SecurityLookupIDByClass(client, rid, RC_DRAWABLE, + access_mode); + if (pDraw && (pDraw->type != UNDRAWABLE_WINDOW)) + return (pointer)pDraw; + return (pointer)NULL; +} + +/* We can't replace the LookupWindow and LookupDrawable functions with + * macros because of compatibility with loadable servers. + */ + +_X_EXPORT WindowPtr +LookupWindow(XID rid, ClientPtr client) +{ + return SecurityLookupWindow(rid, client, SecurityUnknownAccess); +} + +_X_EXPORT pointer +LookupDrawable(XID rid, ClientPtr client) +{ + return SecurityLookupDrawable(rid, client, SecurityUnknownAccess); +} + +#else /* not XACE */ + +WindowPtr +LookupWindow(XID rid, ClientPtr client) +{ + WindowPtr pWin; + + client->errorValue = rid; + if(rid == INVALID) + return NULL; + if (client->lastDrawableID == rid) + { + if (client->lastDrawable->type == DRAWABLE_WINDOW) + return ((WindowPtr) client->lastDrawable); + return (WindowPtr) NULL; + } + pWin = (WindowPtr)LookupIDByType(rid, RT_WINDOW); + if (pWin && pWin->drawable.type == DRAWABLE_WINDOW) { + client->lastDrawable = (DrawablePtr) pWin; + client->lastDrawableID = rid; + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + return pWin; +} + + +pointer +LookupDrawable(XID rid, ClientPtr client) +{ + register DrawablePtr pDraw; + + if(rid == INVALID) + return (pointer) NULL; + if (client->lastDrawableID == rid) + return ((pointer) client->lastDrawable); + pDraw = (DrawablePtr)LookupIDByClass(rid, RC_DRAWABLE); + if (pDraw && (pDraw->type != UNDRAWABLE_WINDOW)) + return (pointer)pDraw; + return (pointer)NULL; +} + +#endif /* XACE */ + +_X_EXPORT ClientPtr +LookupClient(XID rid, ClientPtr client) +{ + pointer pRes = (pointer)SecurityLookupIDByClass(client, rid, RC_ANY, + SecurityReadAccess); + int clientIndex = CLIENT_ID(rid); + + if (clientIndex && pRes && clients[clientIndex] && !(rid & SERVER_BIT)) + { + return clients[clientIndex]; + } + return (ClientPtr)NULL; +} + + +int +AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode, + Bool toRoot, Bool remap) +{ + int numnow; + SaveSetElt *pTmp = NULL; + int j; + + numnow = client->numSaved; + j = 0; + if (numnow) + { + pTmp = client->saveSet; + while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (pointer)pWin)) + j++; + } + if (mode == SetModeInsert) + { + if (j < numnow) /* duplicate */ + return(Success); + numnow++; + pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow); + if (!pTmp) + return(BadAlloc); + client->saveSet = pTmp; + client->numSaved = numnow; + SaveSetAssignWindow(client->saveSet[numnow - 1], pWin); + SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot); + SaveSetAssignRemap(client->saveSet[numnow - 1], remap); + return(Success); + } + else if ((mode == SetModeDelete) && (j < numnow)) + { + while (j < numnow-1) + { + pTmp[j] = pTmp[j+1]; + j++; + } + numnow--; + if (numnow) + { + pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow); + if (pTmp) + client->saveSet = pTmp; + } + else + { + xfree(client->saveSet); + client->saveSet = (SaveSetElt *)NULL; + } + client->numSaved = numnow; + return(Success); + } + return(Success); +} + +void +DeleteWindowFromAnySaveSet(WindowPtr pWin) +{ + register int i; + register ClientPtr client; + + for (i = 0; i< currentMaxClients; i++) + { + client = clients[i]; + if (client && client->numSaved) + (void)AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE, TRUE); + } +} + +/* No-op Don't Do Anything : sometimes we need to be able to call a procedure + * that doesn't do anything. For example, on screen with only static + * colormaps, if someone calls install colormap, it's easier to have a dummy + * procedure to call than to check if there's a procedure + */ +_X_EXPORT void +NoopDDA(void) +{ +} + +typedef struct _BlockHandler { + BlockHandlerProcPtr BlockHandler; + WakeupHandlerProcPtr WakeupHandler; + pointer blockData; + Bool deleted; +} BlockHandlerRec, *BlockHandlerPtr; + +static BlockHandlerPtr handlers; +static int numHandlers; +static int sizeHandlers; +static Bool inHandler; +static Bool handlerDeleted; + +/** + * + * \param pTimeout DIX doesn't want to know how OS represents time + * \param pReadMask nor how it represents the det of descriptors + */ +void +BlockHandler(pointer pTimeout, pointer pReadmask) +{ + register int i, j; + + ++inHandler; + for (i = 0; i < screenInfo.numScreens; i++) + (* screenInfo.screens[i]->BlockHandler)(i, + screenInfo.screens[i]->blockData, + pTimeout, pReadmask); + for (i = 0; i < numHandlers; i++) + (*handlers[i].BlockHandler) (handlers[i].blockData, + pTimeout, pReadmask); + if (handlerDeleted) + { + for (i = 0; i < numHandlers;) + if (handlers[i].deleted) + { + for (j = i; j < numHandlers - 1; j++) + handlers[j] = handlers[j+1]; + numHandlers--; + } + else + i++; + handlerDeleted = FALSE; + } + --inHandler; +} + +/** + * + * \param result 32 bits of undefined result from the wait + * \param pReadmask the resulting descriptor mask + */ +void +WakeupHandler(int result, pointer pReadmask) +{ + register int i, j; + + ++inHandler; + for (i = numHandlers - 1; i >= 0; i--) + (*handlers[i].WakeupHandler) (handlers[i].blockData, + result, pReadmask); + for (i = 0; i < screenInfo.numScreens; i++) + (* screenInfo.screens[i]->WakeupHandler)(i, + screenInfo.screens[i]->wakeupData, + result, pReadmask); + if (handlerDeleted) + { + for (i = 0; i < numHandlers;) + if (handlers[i].deleted) + { + for (j = i; j < numHandlers - 1; j++) + handlers[j] = handlers[j+1]; + numHandlers--; + } + else + i++; + handlerDeleted = FALSE; + } + --inHandler; +} + +/** + * Reentrant with BlockHandler and WakeupHandler, except wakeup won't + * get called until next time + */ +_X_EXPORT Bool +RegisterBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler, + WakeupHandlerProcPtr wakeupHandler, + pointer blockData) +{ + BlockHandlerPtr new; + + if (numHandlers >= sizeHandlers) + { + new = (BlockHandlerPtr) xrealloc (handlers, (numHandlers + 1) * + sizeof (BlockHandlerRec)); + if (!new) + return FALSE; + handlers = new; + sizeHandlers = numHandlers + 1; + } + handlers[numHandlers].BlockHandler = blockHandler; + handlers[numHandlers].WakeupHandler = wakeupHandler; + handlers[numHandlers].blockData = blockData; + handlers[numHandlers].deleted = FALSE; + numHandlers = numHandlers + 1; + return TRUE; +} + +_X_EXPORT void +RemoveBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler, + WakeupHandlerProcPtr wakeupHandler, + pointer blockData) +{ + int i; + + for (i = 0; i < numHandlers; i++) + if (handlers[i].BlockHandler == blockHandler && + handlers[i].WakeupHandler == wakeupHandler && + handlers[i].blockData == blockData) + { + if (inHandler) + { + handlerDeleted = TRUE; + handlers[i].deleted = TRUE; + } + else + { + for (; i < numHandlers - 1; i++) + handlers[i] = handlers[i+1]; + numHandlers--; + } + break; + } +} + +void +InitBlockAndWakeupHandlers () +{ + xfree (handlers); + handlers = (BlockHandlerPtr) 0; + numHandlers = 0; + sizeHandlers = 0; +} + +/* + * A general work queue. Perform some task before the server + * sleeps for input. + */ + +WorkQueuePtr workQueue; +static WorkQueuePtr *workQueueLast = &workQueue; + +void +ProcessWorkQueue(void) +{ + WorkQueuePtr q, *p; + + p = &workQueue; + /* + * Scan the work queue once, calling each function. Those + * which return TRUE are removed from the queue, otherwise + * they will be called again. This must be reentrant with + * QueueWorkProc. + */ + while ((q = *p)) + { + if ((*q->function) (q->client, q->closure)) + { + /* remove q from the list */ + *p = q->next; /* don't fetch until after func called */ + xfree (q); + } + else + { + p = &q->next; /* don't fetch until after func called */ + } + } + workQueueLast = p; +} + +void +ProcessWorkQueueZombies(void) +{ + WorkQueuePtr q, *p; + + p = &workQueue; + while ((q = *p)) + { + if (q->client && q->client->clientGone) + { + (void) (*q->function) (q->client, q->closure); + /* remove q from the list */ + *p = q->next; /* don't fetch until after func called */ + xfree (q); + } + else + { + p = &q->next; /* don't fetch until after func called */ + } + } + workQueueLast = p; +} + +_X_EXPORT Bool +QueueWorkProc ( + Bool (*function)(ClientPtr /* pClient */, pointer /* closure */), + ClientPtr client, pointer closure) +{ + WorkQueuePtr q; + + q = (WorkQueuePtr) xalloc (sizeof *q); + if (!q) + return FALSE; + q->function = function; + q->client = client; + q->closure = closure; + q->next = NULL; + *workQueueLast = q; + workQueueLast = &q->next; + return TRUE; +} + +/* + * Manage a queue of sleeping clients, awakening them + * when requested, by using the OS functions IgnoreClient + * and AttendClient. Note that this *ignores* the troubles + * with request data interleaving itself with events, but + * we'll leave that until a later time. + */ + +typedef struct _SleepQueue { + struct _SleepQueue *next; + ClientPtr client; + ClientSleepProcPtr function; + pointer closure; +} SleepQueueRec, *SleepQueuePtr; + +static SleepQueuePtr sleepQueue = NULL; + +_X_EXPORT Bool +ClientSleep (ClientPtr client, ClientSleepProcPtr function, pointer closure) +{ + SleepQueuePtr q; + + q = (SleepQueuePtr) xalloc (sizeof *q); + if (!q) + return FALSE; + + IgnoreClient (client); + q->next = sleepQueue; + q->client = client; + q->function = function; + q->closure = closure; + sleepQueue = q; + return TRUE; +} + +Bool +ClientSignal (ClientPtr client) +{ + SleepQueuePtr q; + + for (q = sleepQueue; q; q = q->next) + if (q->client == client) + { + return QueueWorkProc (q->function, q->client, q->closure); + } + return FALSE; +} + +_X_EXPORT void +ClientWakeup (ClientPtr client) +{ + SleepQueuePtr q, *prev; + + prev = &sleepQueue; + while ( (q = *prev) ) + { + if (q->client == client) + { + *prev = q->next; + xfree (q); + if (client->clientGone) + /* Oops -- new zombie cleanup code ensures this only + * happens from inside CloseDownClient; don't want to + * recurse here... + */ + /* CloseDownClient(client) */; + else + AttendClient (client); + break; + } + prev = &q->next; + } +} + +Bool +ClientIsAsleep (ClientPtr client) +{ + SleepQueuePtr q; + + for (q = sleepQueue; q; q = q->next) + if (q->client == client) + return TRUE; + return FALSE; +} + +/* + * Generic Callback Manager + */ + +/* ===== Private Procedures ===== */ + +static int numCallbackListsToCleanup = 0; +static CallbackListPtr **listsToCleanup = NULL; + +static Bool +_AddCallback( + CallbackListPtr *pcbl, + CallbackProcPtr callback, + pointer data) +{ + CallbackPtr cbr; + + cbr = (CallbackPtr) xalloc(sizeof(CallbackRec)); + if (!cbr) + return FALSE; + cbr->proc = callback; + cbr->data = data; + cbr->next = (*pcbl)->list; + cbr->deleted = FALSE; + (*pcbl)->list = cbr; + return TRUE; +} + +static Bool +_DeleteCallback( + CallbackListPtr *pcbl, + CallbackProcPtr callback, + pointer data) +{ + CallbackListPtr cbl = *pcbl; + CallbackPtr cbr, pcbr; + + for (pcbr = NULL, cbr = cbl->list; + cbr != NULL; + pcbr = cbr, cbr = cbr->next) + { + if ((cbr->proc == callback) && (cbr->data == data)) + break; + } + if (cbr != NULL) + { + if (cbl->inCallback) + { + ++(cbl->numDeleted); + cbr->deleted = TRUE; + } + else + { + if (pcbr == NULL) + cbl->list = cbr->next; + else + pcbr->next = cbr->next; + xfree(cbr); + } + return TRUE; + } + return FALSE; +} + +static void +_CallCallbacks( + CallbackListPtr *pcbl, + pointer call_data) +{ + CallbackListPtr cbl = *pcbl; + CallbackPtr cbr, pcbr; + + ++(cbl->inCallback); + for (cbr = cbl->list; cbr != NULL; cbr = cbr->next) + { + (*(cbr->proc)) (pcbl, cbr->data, call_data); + } + --(cbl->inCallback); + + if (cbl->inCallback) return; + + /* Was the entire list marked for deletion? */ + + if (cbl->deleted) + { + DeleteCallbackList(pcbl); + return; + } + + /* Were some individual callbacks on the list marked for deletion? + * If so, do the deletions. + */ + + if (cbl->numDeleted) + { + for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; ) + { + if (cbr->deleted) + { + if (pcbr) + { + cbr = cbr->next; + xfree(pcbr->next); + pcbr->next = cbr; + } else + { + cbr = cbr->next; + xfree(cbl->list); + cbl->list = cbr; + } + cbl->numDeleted--; + } + else /* this one wasn't deleted */ + { + pcbr = cbr; + cbr = cbr->next; + } + } + } +} + +static void +_DeleteCallbackList( + CallbackListPtr *pcbl) +{ + CallbackListPtr cbl = *pcbl; + CallbackPtr cbr, nextcbr; + int i; + + if (cbl->inCallback) + { + cbl->deleted = TRUE; + return; + } + + for (i = 0; i < numCallbackListsToCleanup; i++) + { + if ((listsToCleanup[i] = pcbl) != 0) + { + listsToCleanup[i] = NULL; + break; + } + } + + for (cbr = cbl->list; cbr != NULL; cbr = nextcbr) + { + nextcbr = cbr->next; + xfree(cbr); + } + xfree(cbl); + *pcbl = NULL; +} + +static CallbackFuncsRec default_cbfuncs = +{ + _AddCallback, + _DeleteCallback, + _CallCallbacks, + _DeleteCallbackList +}; + +/* ===== Public Procedures ===== */ + +Bool +CreateCallbackList(CallbackListPtr *pcbl, CallbackFuncsPtr cbfuncs) +{ + CallbackListPtr cbl; + int i; + + if (!pcbl) return FALSE; + cbl = (CallbackListPtr) xalloc(sizeof(CallbackListRec)); + if (!cbl) return FALSE; + cbl->funcs = cbfuncs ? *cbfuncs : default_cbfuncs; + cbl->inCallback = 0; + cbl->deleted = FALSE; + cbl->numDeleted = 0; + cbl->list = NULL; + *pcbl = cbl; + + for (i = 0; i < numCallbackListsToCleanup; i++) + { + if (!listsToCleanup[i]) + { + listsToCleanup[i] = pcbl; + return TRUE; + } + } + + listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup, + sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1)); + listsToCleanup[numCallbackListsToCleanup] = pcbl; + numCallbackListsToCleanup++; + return TRUE; +} + +_X_EXPORT Bool +AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data) +{ + if (!pcbl) return FALSE; + if (!*pcbl) + { /* list hasn't been created yet; go create it */ + if (!CreateCallbackList(pcbl, (CallbackFuncsPtr)NULL)) + return FALSE; + } + return ((*(*pcbl)->funcs.AddCallback) (pcbl, callback, data)); +} + +_X_EXPORT Bool +DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data) +{ + if (!pcbl || !*pcbl) return FALSE; + return ((*(*pcbl)->funcs.DeleteCallback) (pcbl, callback, data)); +} + +void +CallCallbacks(CallbackListPtr *pcbl, pointer call_data) +{ + if (!pcbl || !*pcbl) return; + (*(*pcbl)->funcs.CallCallbacks) (pcbl, call_data); +} + +void +DeleteCallbackList(CallbackListPtr *pcbl) +{ + if (!pcbl || !*pcbl) return; + (*(*pcbl)->funcs.DeleteCallbackList) (pcbl); +} + +void +InitCallbackManager() +{ + int i; + + for (i = 0; i < numCallbackListsToCleanup; i++) + { + DeleteCallbackList(listsToCleanup[i]); + } + if (listsToCleanup) xfree(listsToCleanup); + + numCallbackListsToCleanup = 0; + listsToCleanup = NULL; +} diff --git a/xserver/dix/events.c b/xserver/dix/events.c new file mode 100644 index 000000000..c57a30ed8 --- /dev/null +++ b/xserver/dix/events.c @@ -0,0 +1,4599 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/***************************************************************** + +Copyright 2003-2005 Sun Microsystems, Inc. + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +******************************************************************/ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "globals.h" + +#ifdef XKB +#include <X11/extensions/XKBsrv.h> +extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); +#endif + +#ifdef XACE +#include "xace.h" +#endif + +#ifdef XEVIE +extern WindowPtr *WindowTable; +extern int xevieFlag; +extern int xevieClientIndex; +extern DeviceIntPtr xeviemouse; +extern DeviceIntPtr xeviekb; +extern Mask xevieMask; +extern Mask xevieFilters[128]; +extern int xevieEventSent; +extern int xevieKBEventSent; +int xeviegrabState = 0; +xEvent *xeviexE; +#endif + +#include <X11/extensions/XIproto.h> +#include "exevents.h" +#include "extnsionst.h" + +#include "dixevents.h" +#include "dixgrabs.h" +#include "dispatch.h" + +#define EXTENSION_EVENT_BASE 64 + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define MotionMask ( \ + PointerMotionMask | Button1MotionMask | \ + Button2MotionMask | Button3MotionMask | Button4MotionMask | \ + Button5MotionMask | ButtonMotionMask ) +#define PropagateMask ( \ + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ + MotionMask ) +#define PointerGrabMask ( \ + ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask | \ + PointerMotionHintMask | KeymapStateMask | \ + MotionMask ) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllEventMasks (lastEventMask|(lastEventMask-1)) +/* + * The following relies on the fact that the Button<n>MotionMasks are equal + * to the corresponding Button<n>Masks from the current modifier/button state. + */ +#define Motion_Filter(class) (PointerMotionMask | \ + (class)->state | (class)->motionMask) + + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) + +#define XE_KBPTR (xE->u.keyButtonPointer) + + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +_X_EXPORT CallbackListPtr EventCallback; +_X_EXPORT CallbackListPtr DeviceEventCallback; + +#define DNPMCOUNT 8 + +Mask DontPropagateMasks[DNPMCOUNT]; +static int DontPropagateRefCnts[DNPMCOUNT]; + +#ifdef DEBUG +static debug_events = 0; +#endif +_X_EXPORT InputInfo inputInfo; + +static struct { + QdEventPtr pending, *pendtail; + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + WindowPtr replayWin; /* ComputeFreezes */ + Bool playingEvents; + TimeStamp time; +} syncEvents; + +/* + * The window trace information is used to avoid having to compute all the + * windows between the root and the current pointer window each time a button + * or key goes down. The grabs on each of those windows must be checked. + */ +static WindowPtr *spriteTrace = (WindowPtr *)NULL; +#define ROOT spriteTrace[0] +static int spriteTraceSize = 0; +static int spriteTraceGood; + +static struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#if defined(SHAPE) || defined(PANORAMIX) + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif +} sprite; /* info about the cursor sprite */ + +#ifdef XEVIE +_X_EXPORT WindowPtr xeviewin; +_X_EXPORT HotSpot xeviehot; +#endif + +static void DoEnterLeaveEvents( + WindowPtr fromWin, + WindowPtr toWin, + int mode +); + +static WindowPtr XYToWindow( + int x, + int y +); + +extern int lastEvent; + +static Mask lastEventMask; + +#ifdef XINPUT +extern int DeviceMotionNotify; +#endif + +#define CantBeFiltered NoEventMask +static Mask filters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ + EnterWindowMask, /* EnterNotify */ + LeaveWindowMask, /* LeaveNotify */ + FocusChangeMask, /* FocusIn */ + FocusChangeMask, /* FocusOut */ + KeymapStateMask, /* KeymapNotify */ + ExposureMask, /* Expose */ + CantBeFiltered, /* GraphicsExpose */ + CantBeFiltered, /* NoExpose */ + VisibilityChangeMask, /* VisibilityNotify */ + SubstructureNotifyMask, /* CreateNotify */ + StructureAndSubMask, /* DestroyNotify */ + StructureAndSubMask, /* UnmapNotify */ + StructureAndSubMask, /* MapNotify */ + SubstructureRedirectMask, /* MapRequest */ + StructureAndSubMask, /* ReparentNotify */ + StructureAndSubMask, /* ConfigureNotify */ + SubstructureRedirectMask, /* ConfigureRequest */ + StructureAndSubMask, /* GravityNotify */ + ResizeRedirectMask, /* ResizeRequest */ + StructureAndSubMask, /* CirculateNotify */ + SubstructureRedirectMask, /* CirculateRequest */ + PropertyChangeMask, /* PropertyNotify */ + CantBeFiltered, /* SelectionClear */ + CantBeFiltered, /* SelectionRequest */ + CantBeFiltered, /* SelectionNotify */ + ColormapChangeMask, /* ColormapNotify */ + CantBeFiltered, /* ClientMessage */ + CantBeFiltered /* MappingNotify */ +}; + +static CARD8 criticalEvents[32] = +{ + 0x7c /* key and button events */ +}; + +#ifdef PANORAMIX + +static void ConfineToShape(RegionPtr shape, int *px, int *py); +static void SyntheticMotion(int x, int y); +static void PostNewCursor(void); + +static Bool +XineramaSetCursorPosition( + int x, + int y, + Bool generateEvent +){ + ScreenPtr pScreen; + BoxRec box; + int i; + + /* x,y are in Screen 0 coordinates. We need to decide what Screen + to send the message too and what the coordinates relative to + that screen are. */ + + pScreen = sprite.screen; + x += panoramiXdataPtr[0].x; + y += panoramiXdataPtr[0].y; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) + { + FOR_NSCREENS(i) + { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) + { + pScreen = screenInfo.screens[i]; + break; + } + } + } + + sprite.screen = pScreen; + sprite.hotPhys.x = x - panoramiXdataPtr[0].x; + sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + x -= panoramiXdataPtr[pScreen->myNum].x; + y -= panoramiXdataPtr[pScreen->myNum].y; + + return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); +} + + +static void +XineramaConstrainCursor(void) +{ + ScreenPtr pScreen = sprite.screen; + BoxRec newBox = sprite.physLimits; + + /* Translate the constraining box to the screen + the sprite is actually on */ + newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + + (* pScreen->ConstrainCursor)(pScreen, &newBox); +} + +static void +XineramaCheckPhysLimits( + CursorPtr cursor, + Bool generateEvents +){ + HotSpot new; + + if (!cursor) + return; + + new = sprite.hotPhys; + + /* I don't care what the DDX has to say about it */ + sprite.physLimits = sprite.hotLimits; + + /* constrain the pointer to those limits */ + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) /* more work if the shape is a mess */ + ConfineToShape(sprite.hotShape, &new.x, &new.y); + + if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + XineramaSetCursorPosition (new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } + + /* Tell DDX what the limits are */ + XineramaConstrainCursor(); +} + + +static Bool +XineramaSetWindowPntrs(WindowPtr pWin) +{ + if(pWin == WindowTable[0]) { + memcpy(sprite.windows, WindowTable, + PanoramiXNumScreens*sizeof(WindowPtr)); + } else { + PanoramiXRes *win; + int i; + + win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); + + if(!win) + return FALSE; + + for(i = 0; i < PanoramiXNumScreens; i++) { + sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!sprite.windows[i]) /* window is being unmapped */ + return FALSE; + } + } + return TRUE; +} + +static void +XineramaCheckVirtualMotion( + QdEventPtr qe, + WindowPtr pWin +){ + + if (qe) + { + sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + int x, y, off_x, off_y, i; + BoxRec lims; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg2, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; + + if (REGION_NUM_RECTS(&sprite.Reg2) > 1) + ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } +#ifdef XEVIE + xeviehot.x = sprite.hot.x; + xeviehot.y = sprite.hot.y; +#endif +} + + +static Bool +XineramaCheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + + if (xE && !syncEvents.playingEvents) + { + /* Motion events entering DIX get translated to Screen 0 + coordinates. Replayed events have already been + translated since they've entered DIX before */ + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + sprite.hot.x = XE_KBPTR.rootX; + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); + + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + XineramaSetCursorPosition( + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + +#ifdef XEVIE + xeviehot.x = sprite.hot.x; + xeviehot.y = sprite.hot.y; + xeviewin = +#endif + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + + +static void +XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +{ + + if (syncEvents.playingEvents) + { + XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + int x, y, off_x, off_y, i; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg1, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + + if(REGION_NUM_RECTS(&sprite.Reg1) > 1) + sprite.hotShape = &sprite.Reg1; + else + sprite.hotShape = NullRegion; + + sprite.confined = FALSE; + sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + + XineramaCheckPhysLimits(sprite.current, generateEvents); + } +} + + +static void +XineramaChangeToCursor(CursorPtr cursor) +{ + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(cursor, FALSE); + (*sprite.screen->DisplayCursor)(sprite.screen, cursor); + FreeCursor(sprite.current, (Cursor)0); + sprite.current = cursor; + sprite.current->refcnt++; + } +} + + +#endif /* PANORAMIX */ + +void +SetMaskForEvent(Mask mask, int event) +{ + if ((event < LASTEvent) || (event >= 128)) + FatalError("SetMaskForEvent: bogus event number"); + filters[event] = mask; +} + +_X_EXPORT void +SetCriticalEvent(int event) +{ + if (event >= 128) + FatalError("SetCriticalEvent: bogus event number"); + criticalEvents[event >> 3] |= 1 << (event & 7); +} + +static void +SyntheticMotion(int x, int y) +{ + xEvent xE; + +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x; + y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + if (syncEvents.playingEvents) + xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; + else + xE.u.keyButtonPointer.time = currentTime.milliseconds; + xE.u.u.type = MotionNotify; + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +} + +#ifdef SHAPE +static void +ConfineToShape(RegionPtr shape, int *px, int *py) +{ + BoxRec box; + int x = *px, y = *py; + int incx = 1, incy = 1; + + if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + return; + box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + /* this is rather crude */ + do { + x += incx; + if (x >= box.x2) + { + incx = -1; + x = *px - 1; + } + else if (x < box.x1) + { + incx = 1; + x = *px; + y += incy; + if (y >= box.y2) + { + incy = -1; + y = *py - 1; + } + else if (y < box.y1) + return; /* should never get here! */ + } + } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + *px = x; + *py = y; +} +#endif + +static void +CheckPhysLimits( + CursorPtr cursor, + Bool generateEvents, + Bool confineToScreen, + ScreenPtr pScreen) +{ + HotSpot new; + + if (!cursor) + return; + new = sprite.hotPhys; + if (pScreen) + new.pScreen = pScreen; + else + pScreen = new.pScreen; + (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = confineToScreen; + (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); +#endif + if ((pScreen != sprite.hotPhys.pScreen) || + (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + if (pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys = new; + (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } +} + +static void +CheckVirtualMotion( + register QdEventPtr qe, + register WindowPtr pWin) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaCheckVirtualMotion(qe, pWin); + return; + } +#endif + if (qe) + { + sprite.hot.pScreen = qe->pScreen; + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + BoxRec lims; + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + sprite.hot.pScreen = pWin->drawable.pScreen; + sprite.hot.x = sprite.hot.y = 0; + } + lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; +#ifdef SHAPE + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); +#endif + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } +#ifdef XEVIE + xeviehot.x = sprite.hot.x; + xeviehot.y = sprite.hot.y; +#endif + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +static void +ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaConfineCursorToWindow(pWin, generateEvents); + return; + } +#endif + + if (syncEvents.playingEvents) + { + CheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); +#ifdef SHAPE + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + : NullRegion; +#endif + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +_X_EXPORT Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +ChangeToCursor(CursorPtr cursor) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaChangeToCursor(cursor); + return; + } +#endif + + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(cursor, FALSE, sprite.confined, + (ScreenPtr)NULL); + (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, + cursor); + FreeCursor(sprite.current, (Cursor)0); + sprite.current = cursor; + sprite.current->refcnt++; + } +} + +/* returns true if b is a descendent of a */ +Bool +IsParent(register WindowPtr a, register WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (b == a) return TRUE; + return FALSE; +} + +static void +PostNewCursor(void) +{ + register WindowPtr win; + register GrabPtr grab = inputInfo.pointer->grab; + + if (syncEvents.playingEvents) + return; + if (grab) + { + if (grab->cursor) + { + ChangeToCursor(grab->cursor); + return; + } + if (IsParent(grab->window, sprite.win)) + win = sprite.win; + else + win = grab->window; + } + else + win = sprite.win; + for (; win; win = win->parent) + if (win->optional && win->optional->cursor != NullCursor) + { + ChangeToCursor(win->optional->cursor); + return; + } +} + +_X_EXPORT WindowPtr +GetCurrentRootWindow() +{ + return ROOT; +} + +_X_EXPORT WindowPtr +GetSpriteWindow() +{ + return sprite.win; +} + +_X_EXPORT CursorPtr +GetSpriteCursor() +{ + return sprite.current; +} + +_X_EXPORT void +GetSpritePosition(int *px, int *py) +{ + *px = sprite.hotPhys.x; + *py = sprite.hotPhys.y; +} + +#ifdef PANORAMIX +_X_EXPORT int +XineramaGetCursorScreen() +{ + if(!noPanoramiXExtension) { + return sprite.screen->myNum; + } else { + return 0; + } +} +#endif /* PANORAMIX */ + +#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ + +static void +MonthChangedOrBadTime(register xEvent *xE) +{ + /* If the ddx/OS is careless about not processing timestamped events from + * different sources in sorted order, then it's possible for time to go + * backwards when it should not. Here we ensure a decent time. + */ + if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) + currentTime.months++; + else + XE_KBPTR.time = currentTime.milliseconds; +} + +#define NoticeTime(xE) { \ + if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ + MonthChangedOrBadTime(xE); \ + currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ + lastDeviceEventTime = currentTime; } + +void +NoticeEventTime(register xEvent *xE) +{ + if (!syncEvents.playingEvents) + NoticeTime(xE); +} + +/************************************************************************** + * The following procedures deal with synchronous events * + **************************************************************************/ + +void +EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) +{ + register QdEventPtr tail = *syncEvents.pendtail; + register QdEventPtr qe; + xEvent *qxE; + + NoticeTime(xE); + +#ifdef XKB + /* Fix for key repeating bug. */ + if (device->key != NULL && device->key->xkbInfo != NULL && + xE->u.u.type == KeyRelease) + AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail); +#endif + + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* The RECORD spec says that the root window field of motion events + * must be valid. At this point, it hasn't been filled in yet, so + * we do it here. The long expression below is necessary to get + * the current root window; the apparently reasonable alternative + * GetCurrentRootWindow()->drawable.id doesn't give you the right + * answer on the first motion event after a screen change because + * the data that GetCurrentRootWindow relies on hasn't been + * updated yet. + */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + if (xE->u.u.type == MotionNotify) + { +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + } +#endif + sprite.hotPhys.x = XE_KBPTR.rootX; + sprite.hotPhys.y = XE_KBPTR.rootY; + /* do motion compression */ + if (tail && + (tail->event->u.u.type == MotionNotify) && + (tail->pScreen == sprite.hotPhys.pScreen)) + { + tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; + tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.time = XE_KBPTR.time; + tail->months = currentTime.months; + return; + } + } + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + if (!qe) + return; + qe->next = (QdEventPtr)NULL; + qe->device = device; + qe->pScreen = sprite.hotPhys.pScreen; + qe->months = currentTime.months; + qe->event = (xEvent *)(qe + 1); + qe->evcount = count; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + *qxE = *xE; + if (tail) + syncEvents.pendtail = &tail->next; + *syncEvents.pendtail = qe; +} + +static void +PlayReleasedEvents(void) +{ + register QdEventPtr *prev, qe; + register DeviceIntPtr dev; + + prev = &syncEvents.pending; + while ( (qe = *prev) ) + { + if (!qe->device->sync.frozen) + { + *prev = qe->next; + if (*syncEvents.pendtail == *prev) + syncEvents.pendtail = prev; + if (qe->event->u.u.type == MotionNotify) + CheckVirtualMotion(qe, NullWindow); + syncEvents.time.months = qe->months; + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + (*qe->device->public.processInputProc)(qe->event, qe->device, + qe->evcount); + xfree(qe); + for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + ; + if (!dev) + break; + /* Playing the event may have unfrozen another device. */ + /* So to play it safe, restart at the head of the queue */ + prev = &syncEvents.pending; + } + else + prev = &qe->next; + } +} + +static void +FreezeThaw(register DeviceIntPtr dev, Bool frozen) +{ + dev->sync.frozen = frozen; + if (frozen) + dev->public.processInputProc = dev->public.enqueueInputProc; + else + dev->public.processInputProc = dev->public.realInputProc; +} + +void +ComputeFreezes() +{ + register DeviceIntPtr replayDev = syncEvents.replayDev; + register int i; + WindowPtr w; + register xEvent *xE; + int count; + GrabPtr grab; + register DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + return; + syncEvents.playingEvents = TRUE; + if (replayDev) + { + xE = replayDev->sync.event; + count = replayDev->sync.evcount; + syncEvents.replayDev = (DeviceIntPtr)NULL; + + w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < spriteTraceGood; i++) + { + if (syncEvents.replayWin == spriteTrace[i]) + { + if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, + replayDev, count); + } + goto playmore; + } + } + /* must not still be in the same stack */ + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } +playmore: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->sync.frozen) + { + PlayReleasedEvents(); + break; + } + } + syncEvents.playingEvents = FALSE; + /* the following may have been skipped during replay, so do it now */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(); +} + +#ifdef RANDR +void +ScreenRestructured (ScreenPtr pScreen) +{ + GrabPtr grab; + + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) +{ + register GrabPtr grab = thisDev->grab; + register DeviceIntPtr dev; + + if (thisMode == GrabModeSync) + thisDev->sync.state = FROZEN_NO_EVENT; + else + { /* free both if same client owns both */ + thisDev->sync.state = THAWED; + if (thisDev->sync.other && + (CLIENT_BITS(thisDev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + thisDev->sync.other = NullGrab; + } + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev != thisDev) + { + if (otherMode == GrabModeSync) + dev->sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->sync.other && + (CLIENT_BITS(dev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->sync.other = NullGrab; + } + } + } + ComputeFreezes(); +} + +void +ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab, + TimeStamp time, Bool autoGrab) +{ + WindowPtr oldWin = (mouse->grab) ? mouse->grab->window + : sprite.win; + + if (grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + } + DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + mouse->valuator->motionHintWindow = NullWindow; + if (syncEvents.playingEvents) + mouse->grabTime = syncEvents.time; + else + mouse->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; + mouse->activeGrab = *grab; + mouse->grab = &mouse->activeGrab; + mouse->fromPassiveGrab = autoGrab; + PostNewCursor(); + CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); +} + +void +DeactivatePointerGrab(register DeviceIntPtr mouse) +{ + register GrabPtr grab = mouse->grab; + register DeviceIntPtr dev; + + mouse->valuator->motionHintWindow = NullWindow; + mouse->grab = NullGrab; + mouse->sync.state = NOT_GRABBED; + mouse->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + if (grab->confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + PostNewCursor(); + if (grab->cursor) + FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); +} + +void +ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) +{ + WindowPtr oldWin; + + if (keybd->grab) + oldWin = keybd->grab->window; + else if (keybd->focus) + oldWin = keybd->focus->win; + else + oldWin = sprite.win; + if (oldWin == FollowKeyboardWin) + oldWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (syncEvents.playingEvents) + keybd->grabTime = syncEvents.time; + else + keybd->grabTime = time; + keybd->activeGrab = *grab; + keybd->grab = &keybd->activeGrab; + keybd->fromPassiveGrab = passive; + CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); +} + +void +DeactivateKeyboardGrab(register DeviceIntPtr keybd) +{ + register GrabPtr grab = keybd->grab; + register DeviceIntPtr dev; + register WindowPtr focusWin = keybd->focus ? keybd->focus->win + : sprite.win; + + if (focusWin == FollowKeyboardWin) + focusWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + keybd->grab = NullGrab; + keybd->sync.state = NOT_GRABBED; + keybd->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); +} + +void +AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) +{ + Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; + TimeStamp grabTime; + register DeviceIntPtr dev; + + thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisSynced = FALSE; + otherGrabbed = FALSE; + othersFrozen = TRUE; + grabTime = thisDev->grabTime; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + { + if (!(thisGrabbed || otherGrabbed) || + (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) + grabTime = dev->grabTime; + otherGrabbed = TRUE; + if (thisDev->sync.other == dev->grab) + thisSynced = TRUE; + if (dev->sync.state < FROZEN) + othersFrozen = FALSE; + } + else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + othersFrozen = FALSE; + } + if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + return; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, grabTime) == EARLIER)) + return; + switch (newState) + { + case THAWED: /* Async */ + if (thisGrabbed) + thisDev->sync.state = THAWED; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + break; + case FREEZE_NEXT_EVENT: /* Sync */ + if (thisGrabbed) + { + thisDev->sync.state = FREEZE_NEXT_EVENT; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + } + break; + case THAWED_BOTH: /* AsyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case NOT_GRABBED: /* Replay */ + if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + { + if (thisSynced) + thisDev->sync.other = NullGrab; + syncEvents.replayDev = thisDev; + syncEvents.replayWin = thisDev->grab->window; + (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayDev = (DeviceIntPtr)NULL; + } + break; + case THAW_OTHERS: /* AsyncOthers */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + } +} + +int +ProcAllowEvents(register ClientPtr client) +{ + TimeStamp time; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + REQUEST(xAllowEventsReq); + + REQUEST_SIZE_MATCH(xAllowEventsReq); + time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) + { + case ReplayPointer: + AllowSome(client, time, mouse, NOT_GRABBED); + break; + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + break; + case AsyncPointer: + AllowSome(client, time, mouse, THAWED); + break; + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED); + break; + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + break; + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED); + break; + case SyncBoth: + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncBoth: + AllowSome(client, time, keybd, THAWED_BOTH); + break; + default: + client->errorValue = stuff->mode; + return BadValue; + } + return Success; +} + +void +ReleaseActiveGrabs(ClientPtr client) +{ + register DeviceIntPtr dev; + Bool done; + + /* XXX CloseDownClient should remove passive grabs before + * releasing active grabs. + */ + do { + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + { + (*dev->DeactivateGrab)(dev); + done = FALSE; + } + } + } while (!done); +} + +/************************************************************************** + * The following procedures deal with delivering events * + **************************************************************************/ + +_X_EXPORT int +TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, + Mask filter, GrabPtr grab) +{ + int i; + int type; + +#ifdef DEBUG + if (debug_events) ErrorF( + "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); +#endif + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) + return -1; /* don't send, but notify caller */ + type = pEvents->u.u.type; + if (type == MotionNotify) + { + if (mask & PointerMotionHintMask) + { + if (WID(inputInfo.pointer->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); + fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n"); +#endif + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } + } +#ifdef XINPUT + else + { + if ((type == DeviceMotionNotify) && + MaybeSendDeviceMotionNotifyHint + ((deviceKeyButtonPointer*)pEvents, mask) != 0) + return 1; + } +#endif + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + { +#ifdef SMART_SCHEDULE + if (client->smart_priority < SMART_MAX_PRIORITY) + client->smart_priority++; +#endif + SetCriticalOutputPending(); + } + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG + if (debug_events) ErrorF( " delivered\n"); +#endif + return 1; + } + else + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 0; + } +} + +int +DeliverEventsToWindow(register WindowPtr pWin, xEvent *pEvents, int count, + Mask filter, GrabPtr grab, int mskidx) +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + register InputClients *other; + ClientPtr client = NullClient; + Mask deliveryMask = 0; /* If a grab occurs due to a button press, then + this mask is the mask of the grab. */ + int type = pEvents->u.u.type; + + /* CantBeFiltered means only window owner gets the event */ + if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + { + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) + return 0; + if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + } else + nondeliveries--; + } + } + if (filter != CantBeFiltered) + { + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + if ( (attempt = TryClientEvents(rClient(other), pEvents, count, + other->mask[mskidx], filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } + if ((type == ButtonPress) && deliveries && (!grab)) + { + GrabRec tempGrab; + + tempGrab.device = inputInfo.pointer; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, + currentTime, TRUE); + } + else if ((type == MotionNotify) && deliveries) + inputInfo.pointer->valuator->motionHintWindow = pWin; +#ifdef XINPUT + else + { + if (((type == DeviceMotionNotify) +#ifdef XKB + || (type == DeviceButtonPress) +#endif + ) && deliveries) + CheckDeviceGrabAndHintWindow (pWin, type, + (deviceKeyButtonPointer*) pEvents, + grab, client, deliveryMask); + } +#endif + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* If the event goes to dontClient, don't send it and return 0. if + send works, return 1 or if send didn't work, return 2. + Only works for core events. +*/ + +#ifdef PANORAMIX +static int +XineramaTryClientEventsResult( + ClientPtr client, + GrabPtr grab, + Mask mask, + Mask filter +){ + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) return -1; + else return 1; + } + return 0; +} +#endif + +int +MaybeDeliverEventsToClient(register WindowPtr pWin, xEvent *pEvents, + int count, Mask filter, ClientPtr dontClient) +{ + register OtherClients *other; + + + if (pWin->eventMask & filter) + { + if (wClient(pWin) == dontClient) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + wClient(pWin), NullGrab, pWin->eventMask, filter); +#endif + return TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, NullGrab); + } + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & filter) + { + if (SameClient(other, dontClient)) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + rClient(other), NullGrab, other->mask, filter); +#endif + return TryClientEvents(rClient(other), pEvents, count, + other->mask, filter, NullGrab); + } + } + return 2; +} + +static void +FixUpEventFromWindow( + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild) +{ + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.event = pWin->drawable.id; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + XE_KBPTR.sameScreen = xTrue; + XE_KBPTR.child = child; + XE_KBPTR.eventX = + XE_KBPTR.rootX - pWin->drawable.x; + XE_KBPTR.eventY = + XE_KBPTR.rootY - pWin->drawable.y; + } + else + { + XE_KBPTR.sameScreen = xFalse; + XE_KBPTR.child = None; + XE_KBPTR.eventX = 0; + XE_KBPTR.eventY = 0; + } +} + +int +DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab, + register WindowPtr stopAt, DeviceIntPtr dev, int count) +{ + Window child = None; + int type = xE->u.u.type; + Mask filter = filters[type]; + int deliveries = 0; + + if (type & EXTENSION_EVENT_BASE) + { + register OtherInputMasks *inputMasks; + int mskidx = dev->id; + + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) + return 0; + while (pWin) + { + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, mskidx); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + if (pWin) + inputMasks = wOtherInputMasks(pWin); + } + } + else + { + if (!(filter & pWin->deliverableEvents)) + return 0; + while (pWin) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, 0); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + } + } + return 0; +} + +/* not useful for events that propagate up the tree or extension events */ +_X_EXPORT int +DeliverEvents(register WindowPtr pWin, register xEvent *xE, int count, + register WindowPtr otherParent) +{ + Mask filter; + int deliveries; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return count; +#endif + + if (!count) + return 0; + filter = filters[xE->u.u.type]; + if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) + xE->u.destroyNotify.event = pWin->drawable.id; + if (filter != StructureAndSubMask) + return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + NullGrab, 0); + if (pWin->parent) + { + xE->u.destroyNotify.event = pWin->parent->drawable.id; + deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + SubstructureNotifyMask, NullGrab, + 0); + if (xE->u.u.type == ReparentNotify) + { + xE->u.destroyNotify.event = otherParent->drawable.id; + deliveries += DeliverEventsToWindow(otherParent, xE, count, + SubstructureNotifyMask, + NullGrab, 0); + } + } + return deliveries; +} + + +static Bool +PointInBorderSize(WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(POINT_IN_REGION(sprite.screen, + &sprite.windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + &box)) + return TRUE; + } + } +#endif + return FALSE; +} + +static WindowPtr +XYToWindow(int x, int y) +{ + register WindowPtr pWin; + BoxRec box; + + spriteTraceGood = 1; /* root window still there */ + pWin = ROOT->firstChild; + while (pWin) + { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + if (spriteTraceGood >= spriteTraceSize) + { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = (WindowPtr *)xrealloc( + spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + spriteTrace[spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return spriteTrace[spriteTraceGood-1]; +} + +static Bool +CheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaCheckMotion(xE); +#endif + + if (xE && !syncEvents.playingEvents) + { + if (sprite.hot.pScreen != sprite.hotPhys.pScreen) + { + sprite.hot.pScreen = sprite.hotPhys.pScreen; + ROOT = WindowTable[sprite.hot.pScreen->myNum]; + } + sprite.hot.x = XE_KBPTR.rootX; + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); +#endif +#ifdef XEVIE + xeviehot.x = sprite.hot.x; + xeviehot.y = sprite.hot.y; +#endif + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + (*sprite.hotPhys.pScreen->SetCursorPosition)( + sprite.hotPhys.pScreen, + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + +#ifdef XEVIE + xeviewin = +#endif + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); +#ifdef notyet + if (!(sprite.win->deliverableEvents & + Motion_Filter(inputInfo.pointer->button)) + !syncEvents.playingEvents) + { + /* XXX Do PointerNonInterestBox here */ + } +#endif + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + +_X_EXPORT void +WindowsRestructured() +{ + (void) CheckMotion((xEvent *)NULL); +} + +#ifdef PANORAMIX +/* This was added to support reconfiguration under Xdmx. The problem is + * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin + * other than 0,0, the information in the private sprite structure must + * be updated accordingly, or XYToWindow (and other routines) will not + * compute correctly. */ +void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) +{ + GrabPtr grab; + + if (noPanoramiXExtension) return; + + sprite.hot.x -= xoff; + sprite.hot.y -= yoff; + + sprite.hotPhys.x -= xoff; + sprite.hotPhys.y -= yoff; + + sprite.hotLimits.x1 -= xoff; + sprite.hotLimits.y1 -= yoff; + sprite.hotLimits.x2 -= xoff; + sprite.hotLimits.y2 -= yoff; + + if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1)) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff); + if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2)) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff); + + /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +DefineInitialRootWindow(register WindowPtr win) +{ + register ScreenPtr pScreen = win->drawable.pScreen; + + sprite.hotPhys.pScreen = pScreen; + sprite.hotPhys.x = pScreen->width / 2; + sprite.hotPhys.y = pScreen->height / 2; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = win; + sprite.current = wCursor (win); + sprite.current->refcnt++; + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) ( + pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); + (*pScreen->DisplayCursor) (pScreen, sprite.current); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; + sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; + sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + sprite.physLimits = sprite.hotLimits; + sprite.confineWin = NullWindow; +#ifdef SHAPE + sprite.hotShape = NullRegion; +#endif + sprite.screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_NULL(pScreen, &sprite.Reg1); + REGION_NULL(pScreen, &sprite.Reg2); + } +#endif +} + +/* + * This does not take any shortcuts, and even ignores its argument, since + * it does not happen very often, and one has to walk up the tree since + * this might be a newly instantiated cursor for an intermediate window + * between the one the pointer is in and the one that the last cursor was + * instantiated from. + */ +void +WindowHasNewCursor(WindowPtr pWin) +{ + PostNewCursor(); +} + +_X_EXPORT void +NewCurrentScreen(ScreenPtr newScreen, int x, int y) +{ + sprite.hotPhys.x = x; + sprite.hotPhys.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + panoramiXdataPtr[0].x; + sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + panoramiXdataPtr[0].y; + if (newScreen != sprite.screen) { + sprite.screen = newScreen; + /* Make sure we tell the DDX to update its copy of the screen */ + if(sprite.confineWin) + XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + else + XineramaConfineCursorToWindow(WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get + told of the pointer warp so we reposition it here */ + if(!syncEvents.playingEvents) + (*sprite.screen->SetCursorPosition)(sprite.screen, + sprite.hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x, + sprite.hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + } + } else +#endif + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + +#ifdef PANORAMIX + +static Bool +XineramaPointInWindowIsVisible( + WindowPtr pWin, + int x, + int y +) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + int i, xoff, yoff; + + if (!pWin->realized) return FALSE; + + if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + if(!XineramaSetWindowPntrs(pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; + + for(i = 1; i < PanoramiXNumScreens; i++) { + pWin = sprite.windows[i]; + pScreen = pWin->drawable.pScreen; + x = xoff - panoramiXdataPtr[i].x; + y = yoff - panoramiXdataPtr[i].y; + + if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box))) + return TRUE; + + } + + return FALSE; +} + +static int +XineramaWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + + REQUEST(xWarpPointerReq); + + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if(source == WindowTable[0]) { + winX -= panoramiXdataPtr[0].x; + winY -= panoramiXdataPtr[0].y; + } + if (x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !XineramaPointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) { + x = dest->drawable.x; + y = dest->drawable.y; + if(dest == WindowTable[0]) { + x -= panoramiXdataPtr[0].x; + y -= panoramiXdataPtr[0].y; + } + } + + x += stuff->dstX; + y += stuff->dstY; + + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); + + XineramaSetCursorPosition(x, y, TRUE); + + return Success; +} + +#endif + + +int +ProcWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(xWarpPointerReq); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaWarpPointer(client); +#endif + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if (source->drawable.pScreen != sprite.hotPhys.pScreen || + x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !PointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } else + newScreen = sprite.hotPhys.pScreen; + + x += stuff->dstX; + y += stuff->dstY; + + if (x < 0) + x = 0; + else if (x >= newScreen->width) + x = newScreen->width - 1; + if (y < 0) + y = 0; + else if (y >= newScreen->height) + y = newScreen->height - 1; + + if (newScreen == sprite.hotPhys.pScreen) + { + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; +#if defined(SHAPE) + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) + { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +static Bool +BorderSizeNotEmpty(WindowPtr pWin) +{ + if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + return TRUE; + } + } +#endif + return FALSE; +} + +/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a + passive grab set on the window to be activated. */ + +static Bool +CheckPassiveGrabsOnWindow( + WindowPtr pWin, + register DeviceIntPtr device, + register xEvent *xE, + int count) +{ + register GrabPtr grab = wPassiveGrabs(pWin); + GrabRec tempGrab; + register xEvent *dxE; + + if (!grab) + return FALSE; + tempGrab.window = pWin; + tempGrab.device = device; + tempGrab.type = xE->u.u.type; + tempGrab.detail.exact = xE->u.u.detail; + tempGrab.detail.pMask = NULL; + tempGrab.modifiersDetail.pMask = NULL; + for (; grab; grab = grab->next) + { +#ifdef XKB + DeviceIntPtr gdev; + XkbSrvInfoPtr xkbi; + + gdev= grab->modifierDevice; + xkbi= gdev->key->xkbInfo; +#endif + tempGrab.modifierDevice = grab->modifierDevice; + if ((device == grab->modifierDevice) && + ((xE->u.u.type == KeyPress) +#if defined(XINPUT) && defined(XKB) + || (xE->u.u.type == DeviceKeyPress) +#endif + )) + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); +#else + grab->modifierDevice->key->prev_state; +#endif + else + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); +#else + grab->modifierDevice->key->state; +#endif + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + BorderSizeNotEmpty(grab->confineTo)))) + { +#ifdef XACE + if (!XaceHook(XACE_DEVICE_ACCESS, wClient(pWin), device, FALSE)) + return FALSE; +#endif +#ifdef XKB + if (!noXkbExtension) { + XE_KBPTR.state &= 0x1f00; + XE_KBPTR.state |= + tempGrab.modifiersDetail.exact&(~0x1f00); + } +#endif + (*device->ActivateGrab)(device, grab, currentTime, TRUE); + + FixUpEventFromWindow(xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), xE, count, + filters[xE->u.u.type], + filters[xE->u.u.type], grab); + + if (device->sync.state == FROZEN_NO_EVENT) + { + if (device->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + device->sync.event = (xEvent *)xrealloc(device->sync.event, + count* + sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + device->sync.evcount = count; + for (dxE = device->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + device->sync.state = FROZEN_WITH_EVENT; + } + return TRUE; + } + } + return FALSE; +} + +/** +"CheckDeviceGrabs" handles both keyboard and pointer events that may cause +a passive grab to be activated. If the event is a keyboard event, the +ancestors of the focus window are traced down and tried to see if they have +any passive grabs to be activated. If the focus window itself is reached and +it's descendants contain they pointer, the ancestors of the window that the +pointer is in are then traced down starting at the focus window, otherwise no +grabs are activated. If the event is a pointer event, the ancestors of the +window that the pointer is in are traced down starting at the root until +CheckPassiveGrabs causes a passive grab to activate or all the windows are +tried. PRH +*/ + +Bool +CheckDeviceGrabs(register DeviceIntPtr device, register xEvent *xE, + int checkFirst, int count) +{ + register int i; + register WindowPtr pWin = NULL; + register FocusClassPtr focus = device->focus; + + if (((xE->u.u.type == ButtonPress) +#if defined(XINPUT) && defined(XKB) + || (xE->u.u.type == DeviceButtonPress) +#endif + ) && (device->button->buttonsDown != 1)) + return FALSE; + + i = checkFirst; + + if (focus) + { + for (; i < focus->traceGood; i++) + { + pWin = focus->trace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + if ((focus->win == NoneWin) || + (i >= spriteTraceGood) || + ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + return FALSE; + } + + for (; i < spriteTraceGood; i++) + { + pWin = spriteTrace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + return FALSE; +} + +void +DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) +{ + WindowPtr focus = keybd->focus->win; + int mskidx = 0; + + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + if (!focus) + return; + if (focus == PointerRootWin) + { + DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); + return; + } + if ((focus == window) || IsParent(focus, window)) + { + if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) + return; + } + /* just deliver it to the focus window */ + FixUpEventFromWindow(xE, focus, None, FALSE); + if (xE->u.u.type & EXTENSION_EVENT_BASE) + mskidx = keybd->id; + (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], + NullGrab, mskidx); +} + +void +DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev, + Bool deactivateGrab, int count) +{ + register GrabPtr grab = thisDev->grab; + int deliveries = 0; + register DeviceIntPtr dev; + register xEvent *dxE; + + if (grab->ownerEvents) + { + WindowPtr focus; + + if (thisDev->focus) + { + focus = thisDev->focus->win; + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + } + else + focus = PointerRootWin; + if (focus == PointerRootWin) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, + thisDev, count); + else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + thisDev, count); + else if (focus) + deliveries = DeliverDeviceEvents(focus, xE, grab, focus, + thisDev, count); + } + if (!deliveries) + { + FixUpEventFromWindow(xE, grab->window, None, TRUE); + deliveries = TryClientEvents(rClient(grab), xE, count, + (Mask)grab->eventMask, + filters[xE->u.u.type], grab); + if (deliveries && (xE->u.u.type == MotionNotify +#ifdef XINPUT + || xE->u.u.type == DeviceMotionNotify +#endif + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify +#ifdef XINPUT + && xE->u.u.type != DeviceMotionNotify +#endif + )) + switch (thisDev->sync.state) + { + case FREEZE_BOTH_NEXT_EVENT: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + FreezeThaw(dev, TRUE); + if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(dev->grab->resource) == + CLIENT_BITS(thisDev->grab->resource))) + dev->sync.state = FROZEN_NO_EVENT; + else + dev->sync.other = thisDev->grab; + } + /* fall through */ + case FREEZE_NEXT_EVENT: + thisDev->sync.state = FROZEN_WITH_EVENT; + FreezeThaw(thisDev, TRUE); + if (thisDev->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + count*sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + thisDev->sync.evcount = count; + for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + break; + } +} + +void +#ifdef XKB +CoreProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count) +#else +ProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count) +#endif +{ + int key, bit; + register BYTE *kptr; + register int i; + register CARD8 modifiers; + register CARD16 mask; + GrabPtr grab = keybd->grab; + Bool deactivateGrab = FALSE; + register KeyClassPtr keyc = keybd->key; +#ifdef XEVIE + static Window rootWin = 0; + + if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type])) { + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + if((xE->u.u.type == KeyPress && (*kptr & bit)) || + (xE->u.u.type == KeyRelease && !(*kptr & bit))) + {} else { +#ifdef XKB + if(!noXkbExtension) + xevieKBEventSent = 1; +#endif + if(!xevieKBEventSent) + { + xeviekb = keybd; + if(!rootWin) { + rootWin = GetCurrentRootWindow()->drawable.id; + } + xE->u.keyButtonPointer.event = xeviewin->drawable.id; + xE->u.keyButtonPointer.root = rootWin; + xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild-> +drawable.id:0; + xE->u.keyButtonPointer.rootX = xeviehot.x; + xE->u.keyButtonPointer.rootY = xeviehot.y; + xE->u.keyButtonPointer.state = keyc->state; + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); +#ifdef XKB + if(noXkbExtension) +#endif + return; + } else { + xevieKBEventSent = 0; + } + } + } +#endif + + if (!syncEvents.playingEvents) + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } +#ifdef XEVIE + /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */ + if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type] +#ifdef XKB + && !noXkbExtension +#endif + ))) +#endif + XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + modifiers = keyc->modifierMap[key]; +#if defined(XKB) && defined(XEVIE) + if(!noXkbExtension && !xeviegrabState && + xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type])) { + switch(xE->u.u.type) { + case KeyPress: *kptr &= ~bit; break; + case KeyRelease: *kptr |= bit; break; + } + } +#endif + +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("CoreProcessKbdEvent: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->u.u.type = KeyRelease; + (*keybd->public.processInputProc)(xE, keybd, count); + xE->u.u.type = KeyPress; + /* release can have side effects, don't fall through */ + (*keybd->public.processInputProc)(xE, keybd, count); + } + return; + } + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + keyc->modifierKeyCount[i]++; + keyc->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) + { + keybd->activatingKey = key; + return; + } + break; + case KeyRelease: + if (!(*kptr & bit)) /* guard against duplicates */ + return; + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) { + /* This key affects modifier "i" */ + if (--keyc->modifierKeyCount[i] <= 0) { + keyc->state &= ~mask; + keyc->modifierKeyCount[i] = 0; + } + modifiers &= ~mask; + } + } + if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + deactivateGrab = TRUE; + break; + default: + FatalError("Impossible keyboard event"); + } + if (grab) + DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); + else + DeliverFocusedEvent(keybd, xE, sprite.win, count); + if (deactivateGrab) + (*keybd->DeactivateGrab)(keybd); + +#ifdef XACE + XaceHook(XACE_KEY_AVAIL, xE, keybd, count); +#endif +} + +#ifdef XKB +/* This function is used to set the key pressed or key released state - + this is only used when the pressing of keys does not cause + CoreProcessKeyEvent to be called, as in for example Mouse Keys. +*/ +void +FixKeyState (register xEvent *xE, register DeviceIntPtr keybd) +{ + int key, bit; + register BYTE *kptr; + register KeyClassPtr keyc = keybd->key; + + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("FixKeyState: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + *kptr |= bit; + break; + case KeyRelease: + *kptr &= ~bit; + break; + default: + FatalError("Impossible keyboard event"); + } +} +#endif + +void +#ifdef XKB +CoreProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count) +#else +ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count) +#endif +{ + register GrabPtr grab = mouse->grab; + Bool deactivateGrab = FALSE; + register ButtonClassPtr butc = mouse->button; +#ifdef XKB + XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo; +#endif +#ifdef XEVIE + if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState && + (xevieMask & xevieFilters[xE->u.u.type])) { + if(xevieEventSent) + xevieEventSent = 0; + else { + xeviemouse = mouse; + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); + return; + } + } +#endif + + if (!syncEvents.playingEvents) + NoticeTime(xE) + XE_KBPTR.state = (butc->state | ( +#ifdef XKB + (noXkbExtension ? + inputInfo.keyboard->key->state : + xkbi->state.grab_mods) +#else + inputInfo.keyboard->key->state +#endif + )); + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* see comment in EnqueueEvents regarding the next three lines */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + if (xE->u.u.type != MotionNotify) + { + register int key; + register BYTE *kptr; + int bit; + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + + key = xE->u.u.detail; + kptr = &butc->down[key >> 3]; + bit = 1 << (key & 7); + switch (xE->u.u.type) + { + case ButtonPress: + mouse->valuator->motionHintWindow = NullWindow; + if (!(*kptr & bit)) + butc->buttonsDown++; + butc->motionMask = ButtonMotionMask; + *kptr |= bit; + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state |= (Button1Mask >> 1) << xE->u.u.detail; + filters[MotionNotify] = Motion_Filter(butc); + if (!grab) + if (CheckDeviceGrabs(mouse, xE, 0, count)) + return; + break; + case ButtonRelease: + mouse->valuator->motionHintWindow = NullWindow; + if (*kptr & bit) + --butc->buttonsDown; + if (!butc->buttonsDown) + butc->motionMask = 0; + *kptr &= ~bit; + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); + filters[MotionNotify] = Motion_Filter(butc); + if (!butc->state && mouse->fromPassiveGrab) + deactivateGrab = TRUE; + break; + default: + FatalError("bogus pointer event from ddx"); + } + } + else if (!CheckMotion(xE)) + return; + if (grab) + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + else + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + if (deactivateGrab) + (*mouse->DeactivateGrab)(mouse); +} + +#define AtMostOneClient \ + (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) + +void +RecalculateDeliverableEvents(pWin) + register WindowPtr pWin; +{ + register OtherClients *others; + register WindowPtr pChild; + + pChild = pWin; + while (1) + { + if (pChild->optional) + { + pChild->optional->otherEventMasks = 0; + for (others = wOtherClients(pChild); others; others = others->next) + { + pChild->optional->otherEventMasks |= others->mask; + } + } + pChild->deliverableEvents = pChild->eventMask| + wOtherEventMasks(pChild); + if (pChild->parent) + pChild->deliverableEvents |= + (pChild->parent->deliverableEvents & + ~wDontPropagateMask(pChild) & PropagateMask); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +/** + * + * \param value must conform to DeleteType + */ +int +OtherClientGone(pointer value, XID id) +{ + register OtherClientsPtr other, prev; + register WindowPtr pWin = (WindowPtr)value; + + prev = 0; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + { + if (!(pWin->optional->otherClients = other->next)) + CheckWindowOptionalNeed (pWin); + } + xfree(other); + RecalculateDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on event list"); + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} + +int +EventSelectForWindow(register WindowPtr pWin, register ClientPtr client, Mask mask) +{ + Mask check; + OtherClients * others; + + if (mask & ~AllEventMasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & AtMostOneClient); + if (check & (pWin->eventMask|wOtherEventMasks(pWin))) + { /* It is illegal for two different + clients to select on any of the + events for AtMostOneClient. However, + it is OK, for some client to + continue selecting on one of those + events. */ + if ((wClient(pWin) != client) && (check & pWin->eventMask)) + return BadAccess; + for (others = wOtherClients (pWin); others; others = others->next) + { + if (!SameClient(others, client) && (check & others->mask)) + return BadAccess; + } + } + if (wClient (pWin) == client) + { + check = pWin->eventMask; +#ifdef SGIMISC + pWin->eventMask = + (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask); +#else + pWin->eventMask = mask; +#endif + } + else + { + for (others = wOtherClients (pWin); others; others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask; +#ifdef SGIMISC + mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask); +#endif + if (mask == 0) + { + FreeResource(others->resource, RT_NONE); + return Success; + } + else + others->mask = mask; + goto maskSet; + } + } + check = 0; + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!others) + return BadAlloc; + others->mask = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->otherClients; + pWin->optional->otherClients = others; + if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) + return BadAlloc; + } +maskSet: + if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && + (mask & PointerMotionHintMask) && + !(check & PointerMotionHintMask) && + !inputInfo.pointer->grab) + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + RecalculateDeliverableEvents(pWin); + return Success; +} + +int +EventSuppressForWindow(register WindowPtr pWin, register ClientPtr client, + Mask mask, Bool *checkOptional) +{ + register int i, free; + + if (mask & ~PropagateMask) + { + client->errorValue = mask; + return BadValue; + } + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + if (!mask) + i = 0; + else + { + for (i = DNPMCOUNT, free = 0; --i > 0; ) + { + if (!DontPropagateRefCnts[i]) + free = i; + else if (mask == DontPropagateMasks[i]) + break; + } + if (!i && free) + { + i = free; + DontPropagateMasks[i] = mask; + } + } + if (i || !mask) + { + pWin->dontPropagate = i; + if (i) + DontPropagateRefCnts[i]++; + if (pWin->optional) + { + pWin->optional->dontPropagateMask = mask; + *checkOptional = TRUE; + } + } + else + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]++; + return BadAlloc; + } + pWin->dontPropagate = 0; + pWin->optional->dontPropagateMask = mask; + } + RecalculateDeliverableEvents(pWin); + return Success; +} + +static WindowPtr +CommonAncestor( + register WindowPtr a, + register WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + +static void +EnterLeaveEvent( + int type, + int mode, + int detail, + register WindowPtr pWin, + Window child) +{ + xEvent event; + register DeviceIntPtr keybd = inputInfo.keyboard; + WindowPtr focus; + register DeviceIntPtr mouse = inputInfo.pointer; + register GrabPtr grab = mouse->grab; + Mask mask; + + if ((pWin == mouse->valuator->motionHintWindow) && + (detail != NotifyInferior)) + mouse->valuator->motionHintWindow = NullWindow; + if (grab) + { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } + else + { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } + if (mask & filters[type]) + { + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = sprite.hot.x; + event.u.enterLeave.rootY = sprite.hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(&event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; +#ifdef XKB + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + event.u.enterLeave.state = keybd->key->state | mouse->button->state; + event.u.enterLeave.mode = mode; + focus = keybd->focus->win; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], + NullGrab, 0); + } + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + +#ifdef XACE + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (!XaceHook(XACE_DEVICE_ACCESS, client, keybd, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + ke.type = KeymapNotify; + if (grab) + (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, + KeymapStateMask, grab); + else + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +static void +EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + EnterNotifies(ancestor, parent, mode, detail); + EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); +} + +static void +LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) +{ + register WindowPtr pWin; + + if (ancestor == child) + return; + for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + { + EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); + child = pWin; + } +} + +static void +DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) +{ + if (fromWin == toWin) + return; + if (IsParent(fromWin, toWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); + EnterNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + } + else if (IsParent(toWin, fromWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); + LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + } + else + { /* neither fromWin nor toWin is descendent of the other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); + LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + } +} + +static void +FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin) +{ + xEvent event; + +#ifdef XINPUT + if (dev != inputInfo.keyboard) + { + DeviceFocusEvent(dev, type, mode, detail, pWin); + return; + } +#endif + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; +#ifdef XACE + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (!XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + + /* + * recursive because it is easier + * no-op if child not descended from ancestor + */ +static Bool +FocusInEvents( + DeviceIntPtr dev, + WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, + int mode, int detail, + Bool doAncestor) +{ + if (child == NullWindow) + return ancestor == NullWindow; + if (ancestor == child) + { + if (doAncestor) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, + doAncestor)) + { + if (child != skipChild) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + return FALSE; +} + +/* dies horribly if ancestor is not an ancestor of child */ +static void +FocusOutEvents( + DeviceIntPtr dev, + WindowPtr child, WindowPtr ancestor, + int mode, int detail, + Bool doAncestor) +{ + register WindowPtr pWin; + + for (pWin = child; pWin != ancestor; pWin = pWin->parent) + FocusEvent(dev, FocusOut, mode, detail, pWin); + if (doAncestor) + FocusEvent(dev, FocusOut, mode, detail, ancestor); +} + +void +DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + + if (fromWin == toWin) + return; + out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + + if ((toWin == NullWindow) || (toWin == PointerRootWin)) + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); + else +#endif + for (i=0; i<screenInfo.numScreens; i++) + FocusEvent(dev, FocusOut, mode, out, WindowTable[i]); + } + else + { + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer, + FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + /* next call catches the root too, if the screen changed */ + FocusOutEvents(dev, fromWin->parent, NullWindow, mode, + NotifyNonlinearVirtual, FALSE); + } + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); + else +#endif + for (i=0; i<screenInfo.numScreens; i++) + FocusEvent(dev, FocusIn, mode, in, WindowTable[i]); + if (toWin == PointerRootWin) + (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode, + NotifyPointer, TRUE); + } + else + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); + else +#endif + for (i=0; i<screenInfo.numScreens; i++) + FocusEvent(dev, FocusOut, mode, out, WindowTable[i]); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + NotifyNonlinearVirtual, TRUE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + NotifyPointer, FALSE); + } + else + { + if (IsParent(toWin, fromWin)) + { + FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); + FocusOutEvents(dev, fromWin->parent, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); + if ((IsParent(toWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(fromWin, sprite.win)) && + (!IsParent(sprite.win, fromWin))) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + else + if (IsParent(fromWin, toWin)) + { + if ((IsParent(fromWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(toWin, sprite.win)) && + (!IsParent(sprite.win, toWin))) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); + (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); + } + else + { + /* neither fromWin or toWin is child of other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + if (fromWin->parent != NullWindow) + FocusOutEvents(dev, fromWin->parent, common, mode, + NotifyNonlinearVirtual, FALSE); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, common, toWin, toWin, mode, + NotifyNonlinearVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + } + } +} + +int +SetInputFocus( + ClientPtr client, + DeviceIntPtr dev, + Window focusID, + CARD8 revertTo, + Time ctime, + Bool followOK) +{ + register FocusClassPtr focus; + register WindowPtr focusWin; + int mode; + TimeStamp time; + + UpdateCurrentTime(); + if ((revertTo != RevertToParent) && + (revertTo != RevertToPointerRoot) && + (revertTo != RevertToNone) && + ((revertTo != RevertToFollowKeyboard) || !followOK)) + { + client->errorValue = revertTo; + return BadValue; + } + time = ClientTimeToServerTime(ctime); + if ((focusID == None) || (focusID == PointerRoot)) + focusWin = (WindowPtr)(long)focusID; + else if ((focusID == FollowKeyboard) && followOK) + focusWin = inputInfo.keyboard->focus->win; + else if (!(focusWin = SecurityLookupWindow(focusID, client, + SecurityReadAccess))) + return BadWindow; + else + { + /* It is a match error to try to set the input focus to an + unviewable window. */ + + if(!focusWin->realized) + return(BadMatch); + } + focus = dev->focus; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, focus->time) == EARLIER)) + return Success; + mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + if (focus->win == FollowKeyboardWin) + DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + else + DoFocusEvents(dev, focus->win, focusWin, mode); + focus->time = time; + focus->revert = revertTo; + if (focusID == FollowKeyboard) + focus->win = FollowKeyboardWin; + else + focus->win = focusWin; + if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) + focus->traceGood = 0; + else + { + int depth = 0; + register WindowPtr pWin; + + for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; + if (depth > focus->traceSize) + { + focus->traceSize = depth+1; + Must_have_memory = TRUE; /* XXX */ + focus->trace = (WindowPtr *)xrealloc(focus->trace, + focus->traceSize * + sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + focus->traceGood = depth; + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + focus->trace[depth] = pWin; + } + return Success; +} + +int +ProcSetInputFocus(client) + ClientPtr client; +{ + REQUEST(xSetInputFocusReq); + + REQUEST_SIZE_MATCH(xSetInputFocusReq); +#ifdef XACE + if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE)) + return Success; +#endif + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(ClientPtr client) +{ + xGetInputFocusReply rep; + /* REQUEST(xReq); */ + FocusClassPtr focus = inputInfo.keyboard->focus; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else rep.focus = focus->win->drawable.id; + rep.revertTo = focus->revert; + WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); + return Success; +} + +int +ProcGrabPointer(ClientPtr client) +{ + xGrabPointerReply rep; + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + WindowPtr pWin, confineTo; + CursorPtr cursor, oldCursor; + REQUEST(xGrabPointerReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xGrabPointerReq); + UpdateCurrentTime(); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + /* at this point, some sort of reply is guaranteed. */ + time = ClientTimeToServerTime(stuff->time); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + grab = device->grab; + if ((grab) && !SameClient(grab, client)) + rep.status = AlreadyGrabbed; + else if ((!pWin->realized) || + (confineTo && + !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + rep.status = GrabNotViewable; + else if (device->sync.frozen && + device->sync.other && !SameClient(device->sync.other, client)) + rep.status = GrabFrozen; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + rep.status = GrabInvalidTime; + else + { + GrabRec tempGrab; + + oldCursor = NullCursor; + if (grab) + { + if (grab->confineTo && !confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + oldCursor = grab->cursor; + } + tempGrab.cursor = cursor; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = stuff->ownerEvents; + tempGrab.eventMask = stuff->eventMask; + tempGrab.confineTo = confineTo; + tempGrab.window = pWin; + tempGrab.keyboardMode = stuff->keyboardMode; + tempGrab.pointerMode = stuff->pointerMode; + tempGrab.device = device; + (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + if (oldCursor) + FreeCursor (oldCursor, (Cursor)0); + rep.status = GrabSuccess; + } + WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); + return Success; +} + +int +ProcChangeActivePointerGrab(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.pointer; + register GrabPtr grab = device->grab; + CursorPtr newCursor, oldCursor; + REQUEST(xChangeActivePointerGrabReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + if (stuff->cursor == None) + newCursor = NullCursor; + else + { + newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!newCursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + if (!grab) + return Success; + if (!SameClient(grab, client)) + return Success; + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; + grab->cursor = newCursor; + if (newCursor) + newCursor->refcnt++; + PostNewCursor(); + if (oldCursor) + FreeCursor(oldCursor, (Cursor)0); + grab->eventMask = stuff->eventMask; + return Success; +} + +int +ProcUngrabPointer(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +GrabDevice(register ClientPtr client, register DeviceIntPtr dev, + unsigned this_mode, unsigned other_mode, Window grabWindow, + unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status) +{ + register WindowPtr pWin; + register GrabPtr grab; + TimeStamp time; + + UpdateCurrentTime(); + if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) + { + client->errorValue = this_mode; + return BadValue; + } + if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) + { + client->errorValue = other_mode; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + time = ClientTimeToServerTime(ctime); + grab = dev->grab; + if (grab && !SameClient(grab, client)) + *status = AlreadyGrabbed; + else if (!pWin->realized) + *status = GrabNotViewable; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + *status = GrabInvalidTime; + else if (dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) + *status = GrabFrozen; + else + { + GrabRec tempGrab; + + tempGrab.window = pWin; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = ownerEvents; + tempGrab.keyboardMode = this_mode; + tempGrab.pointerMode = other_mode; + tempGrab.eventMask = mask; + tempGrab.device = dev; + (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + *status = GrabSuccess; + } + return Success; +} + +int +ProcGrabKeyboard(ClientPtr client) +{ + xGrabKeyboardReply rep; + REQUEST(xGrabKeyboardReq); + int result; + + REQUEST_SIZE_MATCH(xGrabKeyboardReq); +#ifdef XACE + if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE)) + { + result = Success; + rep.status = AlreadyGrabbed; + } + else +#endif + result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status); + if (result != Success) + return result; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); + return Success; +} + +int +ProcUngrabKeyboard(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.keyboard; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +ProcQueryPointer(ClientPtr client) +{ + xQueryPointerReply rep; + WindowPtr pWin, t; + REQUEST(xResourceReq); + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mask = mouse->button->state | inputInfo.keyboard->key->state; + rep.length = 0; + rep.root = (ROOT)->drawable.id; + rep.rootX = sprite.hot.x; + rep.rootY = sprite.hot.y; + rep.child = None; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = sprite.hot.x - pWin->drawable.x; + rep.winY = sprite.hot.y - pWin->drawable.y; + for (t = sprite.win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } + else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.rootX += panoramiXdataPtr[0].x; + rep.rootY += panoramiXdataPtr[0].y; + if(stuff->id == rep.root) { + rep.winX += panoramiXdataPtr[0].x; + rep.winY += panoramiXdataPtr[0].y; + } + } +#endif + + WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); + + return(Success); +} + +void +InitEvents() +{ + int i; + + sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; + inputInfo.numDevices = 0; + inputInfo.devices = (DeviceIntPtr)NULL; + inputInfo.off_devices = (DeviceIntPtr)NULL; + inputInfo.keyboard = (DeviceIntPtr)NULL; + inputInfo.pointer = (DeviceIntPtr)NULL; + if (spriteTraceSize == 0) + { + spriteTraceSize = 32; + spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = NullWindow; + sprite.current = NullCursor; + sprite.hotLimits.x1 = 0; + sprite.hotLimits.y1 = 0; + sprite.hotLimits.x2 = 0; + sprite.hotLimits.y2 = 0; + sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; + syncEvents.replayWin = NullWindow; + while (syncEvents.pending) + { + QdEventPtr next = syncEvents.pending->next; + xfree(syncEvents.pending); + syncEvents.pending = next; + } + syncEvents.pendtail = &syncEvents.pending; + syncEvents.playingEvents = FALSE; + syncEvents.time.months = 0; + syncEvents.time.milliseconds = 0; /* hardly matters */ + currentTime.months = 0; + currentTime.milliseconds = GetTimeInMillis(); + lastDeviceEventTime = currentTime; + for (i = 0; i < DNPMCOUNT; i++) + { + DontPropagateMasks[i] = 0; + DontPropagateRefCnts[i] = 0; + } +} + +void +CloseDownEvents(void) +{ + xfree(spriteTrace); + spriteTrace = NULL; + spriteTraceSize = 0; +} + +int +ProcSendEvent(ClientPtr client) +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + REQUEST(xSendEventReq); + + REQUEST_SIZE_MATCH(xSendEventReq); + + /* The client's event type must be a core event type or one defined by an + extension. */ + + if ( ! ((stuff->event.u.u.type > X_Reply && + stuff->event.u.u.type < LASTEvent) || + (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && + stuff->event.u.u.type < (unsigned)lastEvent))) + { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + if (stuff->event.u.u.type == ClientMessage && + stuff->event.u.u.detail != 8 && + stuff->event.u.u.detail != 16 && + stuff->event.u.u.detail != 32) + { + client->errorValue = stuff->event.u.u.detail; + return BadValue; + } + if (stuff->eventMask & ~AllEventMasks) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + + if (stuff->destination == PointerWindow) + pWin = sprite.win; + else if (stuff->destination == InputFocus) + { + WindowPtr inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = ROOT; + + if (IsParent(inputFocus, sprite.win)) + { + effectiveFocus = inputFocus; + pWin = sprite.win; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = SecurityLookupWindow(stuff->destination, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) + { + client->errorValue = stuff->propagate; + return BadValue; + } + stuff->event.u.u.type |= 0x80; + if (stuff->propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0)) + return Success; + if (pWin == effectiveFocus) + return Success; + stuff->eventMask &= ~wDontPropagateMask(pWin); + if (!stuff->eventMask) + break; + } + } + else + (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0); + return Success; +} + +int +ProcUngrabKey(ClientPtr client) +{ + REQUEST(xUngrabKeyReq); + WindowPtr pWin; + GrabRec tempGrab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xUngrabKeyReq); + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + tempGrab.resource = client->clientAsMask; + tempGrab.device = keybd; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = KeyPress; + tempGrab.detail.exact = stuff->key; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +int +ProcGrabKey(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xGrabKeyReq); + GrabPtr grab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xGrabKeyReq); + if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) + { + client->errorValue = stuff->ownerEvents; + return(BadValue); + } + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, keybd, pWin, + (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, + (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, + keybd, stuff->modifiers, KeyPress, stuff->key, + NullWindow, NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + + +int +ProcGrabButton(ClientPtr client) +{ + WindowPtr pWin, confineTo; + REQUEST(xGrabButtonReq); + CursorPtr cursor; + GrabPtr grab; + + REQUEST_SIZE_MATCH(xGrabButtonReq); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + + + grab = CreateGrab(client->index, inputInfo.pointer, pWin, + (Mask)stuff->eventMask, (Bool)stuff->ownerEvents, + (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode, + inputInfo.keyboard, stuff->modifiers, ButtonPress, + stuff->button, confineTo, cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcUngrabButton(ClientPtr client) +{ + REQUEST(xUngrabButtonReq); + WindowPtr pWin; + GrabRec tempGrab; + + REQUEST_SIZE_MATCH(xUngrabButtonReq); + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + tempGrab.resource = client->clientAsMask; + tempGrab.device = inputInfo.pointer; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = ButtonPress; + tempGrab.detail.exact = stuff->button; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +void +DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) +{ + WindowPtr parent; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + FocusClassPtr focus = keybd->focus; + OtherClientsPtr oc; + GrabPtr passive; + + + /* Deactivate any grabs performed on this window, before making any + input focus changes. */ + + if (mouse->grab && + ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) + (*mouse->DeactivateGrab)(mouse); + + /* Deactivating a keyboard grab should cause focus events. */ + + if (keybd->grab && (keybd->grab->window == pWin)) + (*keybd->DeactivateGrab)(keybd); + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized +/* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ +#ifdef NOTDEF + || clients[CLIENT_ID(parent->drawable.id)]->clientGone +#endif + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + + if (mouse->valuator->motionHintWindow == pWin) + mouse->valuator->motionHintWindow = NullWindow; + + if (freeResources) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + while ( (oc = wOtherClients(pWin)) ) + FreeResource(oc->resource, RT_NONE); + while ( (passive = wPassiveGrabs(pWin)) ) + FreeResource(passive->resource, RT_NONE); + } +#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); +#endif +} + +/** + * Call this whenever some window at or below pWin has changed geometry + */ +_X_EXPORT void +CheckCursorConfinement(WindowPtr pWin) +{ + GrabPtr grab = inputInfo.pointer->grab; + WindowPtr confineTo; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; +#endif + + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(confineTo)) + (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(confineTo, TRUE, TRUE); + } +} + +Mask +EventMaskForClient(WindowPtr pWin, ClientPtr client) +{ + register OtherClientsPtr other; + + if (wClient (pWin) == client) + return pWin->eventMask; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (SameClient(other, client)) + return other->mask; + } + return 0; +} + +int +ProcRecolorCursor(ClientPtr client) +{ + CursorPtr pCursor; + int nscr; + ScreenPtr pscr; + Bool displayed; + REQUEST(xRecolorCursorReq); + + REQUEST_SIZE_MATCH(xRecolorCursorReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityWriteAccess); + if ( !pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + + pCursor->foreRed = stuff->foreRed; + pCursor->foreGreen = stuff->foreGreen; + pCursor->foreBlue = stuff->foreBlue; + + pCursor->backRed = stuff->backRed; + pCursor->backGreen = stuff->backGreen; + pCursor->backBlue = stuff->backBlue; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; +#ifdef PANORAMIX + if(!noPanoramiXExtension) + displayed = (pscr == sprite.screen); + else +#endif + displayed = (pscr == sprite.hotPhys.pScreen); + ( *pscr->RecolorCursor)(pscr, pCursor, + (pCursor == sprite.current) && displayed); + } + return (Success); +} + +_X_EXPORT void +WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) +{ +#ifdef PANORAMIX + xEvent eventCopy; +#endif + xEvent eventTo, *eventFrom; + int i; + +#ifdef XKB + if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) + return; +#endif + +#ifdef PANORAMIX + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + { + switch(events->u.u.type) { + case MotionNotify: + case ButtonPress: + case ButtonRelease: + case KeyPress: + case KeyRelease: + case EnterNotify: + case LeaveNotify: + /* + When multiple clients want the same event DeliverEventsToWindow + passes the same event structure multiple times so we can't + modify the one passed to us + */ + count = 1; /* should always be 1 */ + memcpy(&eventCopy, events, sizeof(xEvent)); + eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) + { + eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; + } + events = &eventCopy; + break; + default: break; + } + } +#endif + + if (EventCallback) + { + EventInfoRec eventinfo; + eventinfo.client = pClient; + eventinfo.events = events; + eventinfo.count = count; + CallCallbacks(&EventCallback, (pointer)&eventinfo); + } + if(pClient->swapped) + { + for(i = 0; i < count; i++) + { + eventFrom = &events[i]; + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[eventFrom->u.u.type & 0177]) + (eventFrom, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } + } + else + { + (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + } +} diff --git a/xserver/dix/extension.c b/xserver/dix/extension.c new file mode 100644 index 000000000..f58c73138 --- /dev/null +++ b/xserver/dix/extension.c @@ -0,0 +1,484 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "dispatch.h" +#ifdef XACE +#include "xace.h" +#endif + +#define EXTENSION_BASE 128 +#define EXTENSION_EVENT_BASE 64 +#define LAST_EVENT 128 +#define LAST_ERROR 255 + +ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS]; + +static ExtensionEntry **extensions = (ExtensionEntry **)NULL; + +int lastEvent = EXTENSION_EVENT_BASE; +static int lastError = FirstExtensionError; +static unsigned int NumExtensions = 0; + +extern int extensionPrivateLen; +extern unsigned *extensionPrivateSizes; +extern unsigned totalExtensionSize; + +static void +InitExtensionPrivates(ExtensionEntry *ext) +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalExtensionSize == sizeof(ExtensionEntry)) + ppriv = (DevUnion *)NULL; + else + ppriv = (DevUnion *)(ext + 1); + + ext->devPrivates = ppriv; + sizes = extensionPrivateSizes; + ptr = (char *)(ppriv + extensionPrivateLen); + for (i = extensionPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } +} + +_X_EXPORT ExtensionEntry * +AddExtension(char *name, int NumEvents, int NumErrors, + int (*MainProc)(ClientPtr c1), + int (*SwappedMainProc)(ClientPtr c2), + void (*CloseDownProc)(ExtensionEntry *e), + unsigned short (*MinorOpcodeProc)(ClientPtr c3)) +{ + int i; + register ExtensionEntry *ext, **newexts; + + if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + return((ExtensionEntry *) NULL); + if ((lastEvent + NumEvents > LAST_EVENT) || + (unsigned)(lastError + NumErrors > LAST_ERROR)) + return((ExtensionEntry *) NULL); + + ext = (ExtensionEntry *) xalloc(totalExtensionSize); + if (!ext) + return((ExtensionEntry *) NULL); + bzero(ext, totalExtensionSize); + InitExtensionPrivates(ext); + ext->name = (char *)xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **)NULL; + if (!ext->name) + { + xfree(ext); + return((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) xrealloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) + { + xfree(ext->name); + xfree(ext); + return((ExtensionEntry *) NULL); + } + NumExtensions++; + extensions = newexts; + extensions[i] = ext; + ext->index = i; + ext->base = i + EXTENSION_BASE; + ext->CloseDown = CloseDownProc; + ext->MinorOpcode = MinorOpcodeProc; + ProcVector[i + EXTENSION_BASE] = MainProc; + SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; + if (NumEvents) + { + ext->eventBase = lastEvent; + ext->eventLast = lastEvent + NumEvents; + lastEvent += NumEvents; + } + else + { + ext->eventBase = 0; + ext->eventLast = 0; + } + if (NumErrors) + { + ext->errorBase = lastError; + ext->errorLast = lastError + NumErrors; + lastError += NumErrors; + } + else + { + ext->errorBase = 0; + ext->errorLast = 0; + } + + return(ext); +} + +_X_EXPORT Bool AddExtensionAlias(char *alias, ExtensionEntry *ext) +{ + char *name; + char **aliases; + + aliases = (char **)xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *)xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; + return TRUE; +} + +static int +FindExtension(char *extname, int len) +{ + int i, j; + + for (i=0; i<NumExtensions; i++) + { + if ((strlen(extensions[i]->name) == len) && + !strncmp(extname, extensions[i]->name, len)) + break; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + if ((strlen(extensions[i]->aliases[j]) == len) && + !strncmp(extname, extensions[i]->aliases[j], len)) + break; + } + if (j >= 0) break; + } + return ((i == NumExtensions) ? -1 : i); +} + +/* + * CheckExtension returns the extensions[] entry for the requested + * extension name. Maybe this could just return a Bool instead? + */ +_X_EXPORT ExtensionEntry * +CheckExtension(const char *extname) +{ + int n; + + n = FindExtension((char*)extname, strlen(extname)); + if (n != -1) + return extensions[n]; + else + return NULL; +} + +/* + * Added as part of Xace. + */ +ExtensionEntry * +GetExtensionEntry(int major) +{ + if (major < EXTENSION_BASE) + return NULL; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return NULL; + return extensions[major]; +} + +_X_EXPORT void +DeclareExtensionSecurity(char *extname, Bool secure) +{ +#ifdef XACE + int i = FindExtension(extname, strlen(extname)); + if (i >= 0) + XaceHook(XACE_DECLARE_EXT_SECURE, extensions[i], secure); +#endif +} + +_X_EXPORT unsigned short +StandardMinorOpcode(ClientPtr client) +{ + return ((xReq *)client->requestBuffer)->data; +} + +_X_EXPORT unsigned short +MinorOpcodeOfRequest(ClientPtr client) +{ + unsigned char major; + + major = ((xReq *)client->requestBuffer)->reqType; + if (major < EXTENSION_BASE) + return 0; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return 0; + return (*extensions[major]->MinorOpcode)(client); +} + +void +CloseDownExtensions() +{ + register int i,j; + + for (i = NumExtensions - 1; i >= 0; i--) + { + (* extensions[i]->CloseDown)(extensions[i]); + NumExtensions = i; + xfree(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + xfree(extensions[i]->aliases[j]); + xfree(extensions[i]->aliases); + xfree(extensions[i]); + } + xfree(extensions); + extensions = (ExtensionEntry **)NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i=0; i<MAXSCREENS; i++) + { + register ScreenProcEntry *spentry = &AuxillaryScreenProcs[i]; + + while (spentry->num) + { + spentry->num--; + xfree(spentry->procList[spentry->num].name); + } + xfree(spentry->procList); + spentry->procList = (ProcEntryPtr)NULL; + } +} + + +int +ProcQueryExtension(ClientPtr client) +{ + xQueryExtensionReply reply; + int i; + REQUEST(xQueryExtensionReq); + + REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); + + reply.type = X_Reply; + reply.length = 0; + reply.major_opcode = 0; + reply.sequenceNumber = client->sequence; + + if ( ! NumExtensions ) + reply.present = xFalse; + else + { + i = FindExtension((char *)&stuff[1], stuff->nbytes); + if (i < 0 +#ifdef XACE + /* call callbacks to find out whether to show extension */ + || !XaceHook(XACE_EXT_ACCESS, client, extensions[i]) +#endif + ) + reply.present = xFalse; + else + { + reply.present = xTrue; + reply.major_opcode = extensions[i]->base; + reply.first_event = extensions[i]->eventBase; + reply.first_error = extensions[i]->errorBase; + } + } + WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); + return(client->noClientException); +} + +int +ProcListExtensions(ClientPtr client) +{ + xListExtensionsReply reply; + char *bufptr, *buffer; + int total_length = 0; + + REQUEST_SIZE_MATCH(xReq); + + reply.type = X_Reply; + reply.nExtensions = 0; + reply.length = 0; + reply.sequenceNumber = client->sequence; + buffer = NULL; + + if ( NumExtensions ) + { + register int i, j; + + for (i=0; i<NumExtensions; i++) + { +#ifdef XACE + /* call callbacks to find out whether to show extension */ + if (!XaceHook(XACE_EXT_ACCESS, client, extensions[i])) + continue; +#endif + total_length += strlen(extensions[i]->name) + 1; + reply.nExtensions += 1 + extensions[i]->num_aliases; + for (j = extensions[i]->num_aliases; --j >= 0;) + total_length += strlen(extensions[i]->aliases[j]) + 1; + } + reply.length = (total_length + 3) >> 2; + buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); + if (!buffer) + return(BadAlloc); + for (i=0; i<NumExtensions; i++) + { + int len; +#ifdef XACE + if (!XaceHook(XACE_EXT_ACCESS, client, extensions[i])) + continue; +#endif + *bufptr++ = len = strlen(extensions[i]->name); + memmove(bufptr, extensions[i]->name, len); + bufptr += len; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + *bufptr++ = len = strlen(extensions[i]->aliases[j]); + memmove(bufptr, extensions[i]->aliases[j], len); + bufptr += len; + } + } + } + WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); + if (reply.length) + { + WriteToClient(client, total_length, buffer); + DEALLOCATE_LOCAL(buffer); + } + return(client->noClientException); +} + + +ExtensionLookupProc +LookupProc(char *name, GCPtr pGC) +{ + register int i; + register ScreenProcEntry *spentry; + spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum]; + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + return(spentry->procList[i].proc); + } + return (ExtensionLookupProc)NULL; +} + +Bool +RegisterProc(char *name, GC *pGC, ExtensionLookupProc proc) +{ + return RegisterScreenProc(name, pGC->pScreen, proc); +} + +Bool +RegisterScreenProc(char *name, ScreenPtr pScreen, ExtensionLookupProc proc) +{ + register ScreenProcEntry *spentry; + register ProcEntryPtr procEntry = (ProcEntryPtr)NULL; + char *newname; + int i; + + spentry = &AuxillaryScreenProcs[pScreen->myNum]; + /* first replace duplicates */ + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + { + procEntry = &spentry->procList[i]; + break; + } + } + if (procEntry) + procEntry->proc = proc; + else + { + newname = (char *)xalloc(strlen(name)+1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + xrealloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num+1)); + if (!procEntry) + { + xfree(newname); + return FALSE; + } + spentry->procList = procEntry; + procEntry += spentry->num; + procEntry->name = newname; + strcpy(newname, name); + procEntry->proc = proc; + spentry->num++; + } + return TRUE; +} diff --git a/xserver/dix/ffs.c b/xserver/dix/ffs.c new file mode 100644 index 000000000..e25d715dd --- /dev/null +++ b/xserver/dix/ffs.c @@ -0,0 +1,36 @@ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- +ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization from +The Open Group. + +*/ + +int +ffs(int i) +{ + int j; + for (j = 1; (i & 1) == 0; j++) + i >>= 1; + return j; +} diff --git a/xserver/dix/gc.c b/xserver/dix/gc.c new file mode 100644 index 000000000..ed6bf26db --- /dev/null +++ b/xserver/dix/gc.c @@ -0,0 +1,1286 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "resource.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "region.h" + +#include "dix.h" +#include <assert.h> + +extern XID clientErrorValue; +extern FontPtr defaultFont; + +static Bool CreateDefaultTile(GCPtr pGC); + +unsigned char DefaultDash[2] = {4, 4}; + +_X_EXPORT void +ValidateGC(DrawablePtr pDraw, GC *pGC) +{ + (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); + pGC->stateChanges = 0; + pGC->serialNumber = pDraw->serialNumber; +} + + +/* dixChangeGC(client, pGC, mask, pC32, pUnion) + * + * This function was created as part of the Security extension + * implementation. The client performing the gc change must be passed so + * that access checks can be performed on any tiles, stipples, or fonts + * that are specified. ddxen can call this too; they should normally + * pass NullClient for the client since any access checking should have + * already been done at a higher level. + * + * Since we had to create a new function anyway, we decided to change the + * way the list of gc values is passed to eliminate the compiler warnings + * caused by the DoChangeGC interface. You can pass the values via pC32 + * or pUnion, but not both; one of them must be NULL. If you don't need + * to pass any pointers, you can use either one: + * + * example calling dixChangeGC using pC32 parameter + * + * CARD32 v[2]; + * v[0] = foreground; + * v[1] = background; + * dixChangeGC(client, pGC, GCForeground|GCBackground, v, NULL); + * + * example calling dixChangeGC using pUnion parameter; + * same effect as above + * + * ChangeGCVal v[2]; + * v[0].val = foreground; + * v[1].val = background; + * dixChangeGC(client, pGC, GCForeground|GCBackground, NULL, v); + * + * However, if you need to pass a pointer to a pixmap or font, you MUST + * use the pUnion parameter. + * + * example calling dixChangeGC passing pointers in the value list + * v[1].ptr is a pointer to a pixmap + * + * ChangeGCVal v[2]; + * v[0].val = FillTiled; + * v[1].ptr = pPixmap; + * dixChangeGC(client, pGC, GCFillStyle|GCTile, NULL, v); + * + * Note: we could have gotten by with just the pUnion parameter, but on + * 64 bit machines that would have forced us to copy the value list that + * comes in the ChangeGC request. + * + * Ideally, we'd change all the DoChangeGC calls to dixChangeGC, but this + * is far too many changes to consider at this time, so we've only + * changed the ones that caused compiler warnings. New code should use + * dixChangeGC. + * + * dpw + */ + +#define NEXTVAL(_type, _var) { \ + if (pC32) _var = (_type)*pC32++; \ + else { \ + _var = (_type)(pUnion->val); pUnion++; \ + } \ + } + +#define NEXT_PTR(_type, _var) { \ + assert(pUnion); _var = (_type)pUnion->ptr; pUnion++; } + +_X_EXPORT int +dixChangeGC(ClientPtr client, register GC *pGC, register BITS32 mask, CARD32 *pC32, ChangeGCValPtr pUnion) +{ + register BITS32 index2; + register int error = 0; + PixmapPtr pPixmap; + BITS32 maskQ; + + assert( (pC32 && !pUnion) || (!pC32 && pUnion) ); + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + + maskQ = mask; /* save these for when we walk the GCque */ + while (mask && !error) + { + index2 = (BITS32) lowbit (mask); + mask &= ~index2; + pGC->stateChanges |= index2; + switch (index2) + { + case GCFunction: + { + CARD8 newalu; + NEXTVAL(CARD8, newalu); + if (newalu <= GXset) + pGC->alu = newalu; + else + { + clientErrorValue = newalu; + error = BadValue; + } + break; + } + case GCPlaneMask: + NEXTVAL(unsigned long, pGC->planemask); + break; + case GCForeground: + NEXTVAL(unsigned long, pGC->fgPixel); + /* + * this is for CreateGC + */ + if (!pGC->tileIsPixel && !pGC->tile.pixmap) + { + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = pGC->fgPixel; + } + break; + case GCBackground: + NEXTVAL(unsigned long, pGC->bgPixel); + break; + case GCLineWidth: /* ??? line width is a CARD16 */ + NEXTVAL(CARD16, pGC->lineWidth); + break; + case GCLineStyle: + { + unsigned int newlinestyle; + NEXTVAL(unsigned int, newlinestyle); + if (newlinestyle <= LineDoubleDash) + pGC->lineStyle = newlinestyle; + else + { + clientErrorValue = newlinestyle; + error = BadValue; + } + break; + } + case GCCapStyle: + { + unsigned int newcapstyle; + NEXTVAL(unsigned int, newcapstyle); + if (newcapstyle <= CapProjecting) + pGC->capStyle = newcapstyle; + else + { + clientErrorValue = newcapstyle; + error = BadValue; + } + break; + } + case GCJoinStyle: + { + unsigned int newjoinstyle; + NEXTVAL(unsigned int, newjoinstyle); + if (newjoinstyle <= JoinBevel) + pGC->joinStyle = newjoinstyle; + else + { + clientErrorValue = newjoinstyle; + error = BadValue; + } + break; + } + case GCFillStyle: + { + unsigned int newfillstyle; + NEXTVAL(unsigned int, newfillstyle); + if (newfillstyle <= FillOpaqueStippled) + pGC->fillStyle = newfillstyle; + else + { + clientErrorValue = newfillstyle; + error = BadValue; + } + break; + } + case GCFillRule: + { + unsigned int newfillrule; + NEXTVAL(unsigned int, newfillrule); + if (newfillrule <= WindingRule) + pGC->fillRule = newfillrule; + else + { + clientErrorValue = newfillrule; + error = BadValue; + } + break; + } + case GCTile: + { + XID newpix = 0; + if (pUnion) + { + NEXT_PTR(PixmapPtr, pPixmap); + } + else + { + NEXTVAL(XID, newpix); + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + newpix, RT_PIXMAP, SecurityReadAccess); + } + if (pPixmap) + { + if ((pPixmap->drawable.depth != pGC->depth) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + pPixmap->refcnt++; + if (!pGC->tileIsPixel) + (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = pPixmap; + } + } + else + { + clientErrorValue = newpix; + error = BadPixmap; + } + break; + } + case GCStipple: + { + XID newstipple = 0; + if (pUnion) + { + NEXT_PTR(PixmapPtr, pPixmap); + } + else + { + NEXTVAL(XID, newstipple) + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + newstipple, RT_PIXMAP, SecurityReadAccess); + } + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + pPixmap->refcnt++; + if (pGC->stipple) + (* pGC->pScreen->DestroyPixmap)(pGC->stipple); + pGC->stipple = pPixmap; + } + } + else + { + clientErrorValue = newstipple; + error = BadPixmap; + } + break; + } + case GCTileStipXOrigin: + NEXTVAL(INT16, pGC->patOrg.x); + break; + case GCTileStipYOrigin: + NEXTVAL(INT16, pGC->patOrg.y); + break; + case GCFont: + { + FontPtr pFont; + XID newfont = 0; + if (pUnion) + { + NEXT_PTR(FontPtr, pFont); + } + else + { + NEXTVAL(XID, newfont) + pFont = (FontPtr)SecurityLookupIDByType(client, newfont, + RT_FONT, SecurityReadAccess); + } + if (pFont) + { + pFont->refcnt++; + if (pGC->font) + CloseFont(pGC->font, (Font)0); + pGC->font = pFont; + } + else + { + clientErrorValue = newfont; + error = BadFont; + } + break; + } + case GCSubwindowMode: + { + unsigned int newclipmode; + NEXTVAL(unsigned int, newclipmode); + if (newclipmode <= IncludeInferiors) + pGC->subWindowMode = newclipmode; + else + { + clientErrorValue = newclipmode; + error = BadValue; + } + break; + } + case GCGraphicsExposures: + { + unsigned int newge; + NEXTVAL(unsigned int, newge); + if (newge <= xTrue) + pGC->graphicsExposures = newge; + else + { + clientErrorValue = newge; + error = BadValue; + } + break; + } + case GCClipXOrigin: + NEXTVAL(INT16, pGC->clipOrg.x); + break; + case GCClipYOrigin: + NEXTVAL(INT16, pGC->clipOrg.y); + break; + case GCClipMask: + { + Pixmap pid = 0; + int clipType = 0; + + if (pUnion) + { + NEXT_PTR(PixmapPtr, pPixmap); + } + else + { + NEXTVAL(Pixmap, pid) + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, RT_PIXMAP, SecurityReadAccess); + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + else if (!pUnion && (pid != None)) + { + clientErrorValue = pid; + error = BadPixmap; + } + if(error == Success) + { + (*pGC->funcs->ChangeClip)(pGC, clipType, + (pointer)pPixmap, 0); + } + break; + } + case GCDashOffset: + NEXTVAL(INT16, pGC->dashOffset); + break; + case GCDashList: + { + CARD8 newdash; + NEXTVAL(CARD8, newdash); + if (newdash == 4) + { + if (pGC->dash != DefaultDash) + { + xfree(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + } + } + else if (newdash != 0) + { + unsigned char *dash; + + dash = (unsigned char *)xalloc(2 * sizeof(unsigned char)); + if (dash) + { + if (pGC->dash != DefaultDash) + xfree(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = dash; + dash[0] = newdash; + dash[1] = newdash; + } + else + error = BadAlloc; + } + else + { + clientErrorValue = newdash; + error = BadValue; + } + break; + } + case GCArcMode: + { + unsigned int newarcmode; + NEXTVAL(unsigned int, newarcmode); + if (newarcmode <= ArcPieSlice) + pGC->arcMode = newarcmode; + else + { + clientErrorValue = newarcmode; + error = BadValue; + } + break; + } + default: + clientErrorValue = maskQ; + error = BadValue; + break; + } + } /* end while mask && !error */ + + if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) + { + if (!CreateDefaultTile (pGC)) + { + pGC->fillStyle = FillSolid; + error = BadAlloc; + } + } + (*pGC->funcs->ChangeGC)(pGC, maskQ); + return error; +} + +#undef NEXTVAL +#undef NEXT_PTR + +/* Publically defined entry to ChangeGC. Just calls dixChangeGC and tells + * it that all of the entries are constants or IDs */ +_X_EXPORT int +ChangeGC(register GC *pGC, register BITS32 mask, XID *pval) +{ + return (dixChangeGC(NullClient, pGC, mask, pval, NULL)); +} + +/* DoChangeGC(pGC, mask, pval, fPointer) + mask is a set of bits indicating which values to change. + pval contains an appropriate value for each mask. + fPointer is true if the values for tiles, stipples, fonts or clipmasks + are pointers instead of IDs. Note: if you are passing pointers you + MUST declare the array of values as type pointer! Other data types + may not be large enough to hold pointers on some machines. Yes, + this means you have to cast to (XID *) when you pass the array to + DoChangeGC. Similarly, if you are not passing pointers (fPointer = 0) you + MUST declare the array as type XID (not unsigned long!), or again the wrong + size data type may be used. To avoid this cruftiness, use dixChangeGC + above. + + if there is an error, the value is marked as changed + anyway, which is probably wrong, but infrequent. + +NOTE: + all values sent over the protocol for ChangeGC requests are +32 bits long +*/ +_X_EXPORT int +DoChangeGC(register GC *pGC, register BITS32 mask, XID *pval, int fPointer) +{ + if (fPointer) + /* XXX might be a problem on 64 bit big-endian servers */ + return dixChangeGC(NullClient, pGC, mask, NULL, (ChangeGCValPtr)pval); + else + return dixChangeGC(NullClient, pGC, mask, pval, NULL); +} + + +/* CreateGC(pDrawable, mask, pval, pStatus) + creates a default GC for the given drawable, using mask to fill + in any non-default values. + Returns a pointer to the new GC on success, NULL otherwise. + returns status of non-default fields in pStatus +BUG: + should check for failure to create default tile + +*/ + +static GCPtr +AllocateGC(ScreenPtr pScreen) +{ + GCPtr pGC; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pGC = (GCPtr)xalloc(pScreen->totalGCSize); + if (pGC) + { + ppriv = (DevUnion *)(pGC + 1); + pGC->devPrivates = ppriv; + sizes = pScreen->GCPrivateSizes; + ptr = (char *)(ppriv + pScreen->GCPrivateLen); + for (i = pScreen->GCPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pGC; +} + +_X_EXPORT GCPtr +CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus) +{ + register GCPtr pGC; + + pGC = AllocateGC(pDrawable->pScreen); + if (!pGC) + { + *pStatus = BadAlloc; + return (GCPtr)NULL; + } + + pGC->pScreen = pDrawable->pScreen; + pGC->depth = pDrawable->depth; + pGC->alu = GXcopy; /* dst <- src */ + pGC->planemask = ~0; + pGC->serialNumber = GC_CHANGE_SERIAL_BIT; + pGC->funcs = 0; + + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcPieSlice; + if (mask & GCForeground) + { + /* + * magic special case -- ChangeGC checks for this condition + * and snags the Foreground value to create a pseudo default-tile + */ + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = NullPixmap; + } + else + { + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + } + + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = TRUE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + pGC->clientClipType = CT_NONE; + pGC->clientClip = (pointer)NULL; + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + pGC->dashOffset = 0; + pGC->lastWinOrg.x = 0; + pGC->lastWinOrg.y = 0; + + /* use the default font and stipple */ + pGC->font = defaultFont; + defaultFont->refcnt++; + pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; + pGC->stipple->refcnt++; + + pGC->stateChanges = (1 << (GCLastBit+1)) - 1; + if (!(*pGC->pScreen->CreateGC)(pGC)) + *pStatus = BadAlloc; + else if (mask) + *pStatus = ChangeGC(pGC, mask, pval); + else + *pStatus = Success; + if (*pStatus != Success) + { + if (!pGC->tileIsPixel && !pGC->tile.pixmap) + pGC->tileIsPixel = TRUE; /* undo special case */ + FreeGC(pGC, (XID)0); + pGC = (GCPtr)NULL; + } + + return (pGC); +} + +static Bool +CreateDefaultTile (GCPtr pGC) +{ + XID tmpval[3]; + PixmapPtr pTile; + GCPtr pgcScratch; + xRectangle rect; + CARD16 w, h; + + w = 1; + h = 1; + (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); + pTile = (PixmapPtr) + (*pGC->pScreen->CreatePixmap)(pGC->pScreen, + w, h, pGC->depth); + pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); + if (!pTile || !pgcScratch) + { + if (pTile) + (*pTile->drawable.pScreen->DestroyPixmap)(pTile); + if (pgcScratch) + FreeScratchGC(pgcScratch); + return FALSE; + } + tmpval[0] = GXcopy; + tmpval[1] = pGC->tile.pixel; + tmpval[2] = FillSolid; + (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle, + tmpval); + ValidateGC((DrawablePtr)pTile, pgcScratch); + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); + /* Always remember to free the scratch graphics context after use. */ + FreeScratchGC(pgcScratch); + + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = pTile; + return TRUE; +} + +_X_EXPORT int +CopyGC(register GC *pgcSrc, register GC *pgcDst, register BITS32 mask) +{ + register BITS32 index2; + BITS32 maskQ; + int error = 0; + + if (pgcSrc == pgcDst) + return Success; + pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; + pgcDst->stateChanges |= mask; + maskQ = mask; + while (mask) + { + index2 = (BITS32) lowbit (mask); + mask &= ~index2; + switch (index2) + { + case GCFunction: + pgcDst->alu = pgcSrc->alu; + break; + case GCPlaneMask: + pgcDst->planemask = pgcSrc->planemask; + break; + case GCForeground: + pgcDst->fgPixel = pgcSrc->fgPixel; + break; + case GCBackground: + pgcDst->bgPixel = pgcSrc->bgPixel; + break; + case GCLineWidth: + pgcDst->lineWidth = pgcSrc->lineWidth; + break; + case GCLineStyle: + pgcDst->lineStyle = pgcSrc->lineStyle; + break; + case GCCapStyle: + pgcDst->capStyle = pgcSrc->capStyle; + break; + case GCJoinStyle: + pgcDst->joinStyle = pgcSrc->joinStyle; + break; + case GCFillStyle: + pgcDst->fillStyle = pgcSrc->fillStyle; + break; + case GCFillRule: + pgcDst->fillRule = pgcSrc->fillRule; + break; + case GCTile: + { + if (EqualPixUnion(pgcDst->tileIsPixel, + pgcDst->tile, + pgcSrc->tileIsPixel, + pgcSrc->tile)) + { + break; + } + if (!pgcDst->tileIsPixel) + (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); + pgcDst->tileIsPixel = pgcSrc->tileIsPixel; + pgcDst->tile = pgcSrc->tile; + if (!pgcDst->tileIsPixel) + pgcDst->tile.pixmap->refcnt++; + break; + } + case GCStipple: + { + if (pgcDst->stipple == pgcSrc->stipple) + break; + if (pgcDst->stipple) + (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); + pgcDst->stipple = pgcSrc->stipple; + if (pgcDst->stipple) + pgcDst->stipple->refcnt ++; + break; + } + case GCTileStipXOrigin: + pgcDst->patOrg.x = pgcSrc->patOrg.x; + break; + case GCTileStipYOrigin: + pgcDst->patOrg.y = pgcSrc->patOrg.y; + break; + case GCFont: + if (pgcDst->font == pgcSrc->font) + break; + if (pgcDst->font) + CloseFont(pgcDst->font, (Font)0); + if ((pgcDst->font = pgcSrc->font) != NullFont) + (pgcDst->font)->refcnt++; + break; + case GCSubwindowMode: + pgcDst->subWindowMode = pgcSrc->subWindowMode; + break; + case GCGraphicsExposures: + pgcDst->graphicsExposures = pgcSrc->graphicsExposures; + break; + case GCClipXOrigin: + pgcDst->clipOrg.x = pgcSrc->clipOrg.x; + break; + case GCClipYOrigin: + pgcDst->clipOrg.y = pgcSrc->clipOrg.y; + break; + case GCClipMask: + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + break; + case GCDashOffset: + pgcDst->dashOffset = pgcSrc->dashOffset; + break; + case GCDashList: + if (pgcSrc->dash == DefaultDash) + { + if (pgcDst->dash != DefaultDash) + { + xfree(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = pgcSrc->dash; + } + } + else + { + unsigned char *dash; + unsigned int i; + + dash = (unsigned char *)xalloc(pgcSrc->numInDashList * + sizeof(unsigned char)); + if (dash) + { + if (pgcDst->dash != DefaultDash) + xfree(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = dash; + for (i=0; i<pgcSrc->numInDashList; i++) + dash[i] = pgcSrc->dash[i]; + } + else + error = BadAlloc; + } + break; + case GCArcMode: + pgcDst->arcMode = pgcSrc->arcMode; + break; + default: + clientErrorValue = maskQ; + error = BadValue; + break; + } + } + if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) + { + if (!CreateDefaultTile (pgcDst)) + { + pgcDst->fillStyle = FillSolid; + error = BadAlloc; + } + } + (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); + return error; +} + +/** + * does the diX part of freeing the characteristics in the GC. + * + * \param value must conform to DeleteType + */ +_X_EXPORT int +FreeGC(pointer value, XID gid) +{ + GCPtr pGC = (GCPtr)value; + + CloseFont(pGC->font, (Font)0); + (* pGC->funcs->DestroyClip)(pGC); + + if (!pGC->tileIsPixel) + (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); + if (pGC->stipple) + (* pGC->pScreen->DestroyPixmap)(pGC->stipple); + + (*pGC->funcs->DestroyGC) (pGC); + if (pGC->dash != DefaultDash) + xfree(pGC->dash); + xfree(pGC); + return(Success); +} + +void +SetGCMask(GCPtr pGC, Mask selectMask, Mask newDataMask) +{ + pGC->stateChanges = (~selectMask & pGC->stateChanges) | + (selectMask & newDataMask); + if (selectMask & newDataMask) + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; +} + + + +/* CreateScratchGC(pScreen, depth) + like CreateGC, but doesn't do the default tile or stipple, +since we can't create them without already having a GC. any code +using the tile or stipple has to set them explicitly anyway, +since the state of the scratch gc is unknown. This is OK +because ChangeGC() has to be able to deal with NULL tiles and +stipples anyway (in case the CreateGC() call has provided a +value for them -- we can't set the default tile until the +client-supplied attributes are installed, since the fgPixel +is what fills the default tile. (maybe this comment should +go with CreateGC() or ChangeGC().) +*/ + +_X_EXPORT GCPtr +CreateScratchGC(ScreenPtr pScreen, unsigned depth) +{ + register GCPtr pGC; + + pGC = AllocateGC(pScreen); + if (!pGC) + return (GCPtr)NULL; + + pGC->pScreen = pScreen; + pGC->depth = depth; + pGC->alu = GXcopy; /* dst <- src */ + pGC->planemask = ~0; + pGC->serialNumber = 0; + + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcPieSlice; + pGC->font = defaultFont; + if ( pGC->font) /* necessary, because open of default font could fail */ + pGC->font->refcnt++; + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = TRUE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + pGC->clientClipType = CT_NONE; + pGC->dashOffset = 0; + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + pGC->lastWinOrg.x = 0; + pGC->lastWinOrg.y = 0; + + pGC->stateChanges = (1 << (GCLastBit+1)) - 1; + if (!(*pScreen->CreateGC)(pGC)) + { + FreeGC(pGC, (XID)0); + pGC = (GCPtr)NULL; + } + return pGC; +} + +void +FreeGCperDepth(int screenNum) +{ + register int i; + register ScreenPtr pScreen; + GCPtr *ppGC; + + pScreen = screenInfo.screens[screenNum]; + ppGC = pScreen->GCperDepth; + + for (i = 0; i <= pScreen->numDepths; i++) + (void)FreeGC(ppGC[i], (XID)0); + pScreen->rgf = ~0L; +} + + +Bool +CreateGCperDepth(int screenNum) +{ + register int i; + register ScreenPtr pScreen; + DepthPtr pDepth; + GCPtr *ppGC; + + pScreen = screenInfo.screens[screenNum]; + pScreen->rgf = 0; + ppGC = pScreen->GCperDepth; + /* do depth 1 separately because it's not included in list */ + if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) + return FALSE; + ppGC[0]->graphicsExposures = FALSE; + /* Make sure we don't overflow GCperDepth[] */ + if( pScreen->numDepths > MAXFORMATS ) + return FALSE; + + pDepth = pScreen->allowedDepths; + for (i=0; i<pScreen->numDepths; i++, pDepth++) + { + if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) + { + for (; i >= 0; i--) + (void)FreeGC(ppGC[i], (XID)0); + return FALSE; + } + ppGC[i+1]->graphicsExposures = FALSE; + } + return TRUE; +} + +Bool +CreateDefaultStipple(int screenNum) +{ + register ScreenPtr pScreen; + XID tmpval[3]; + xRectangle rect; + CARD16 w, h; + GCPtr pgcScratch; + + pScreen = screenInfo.screens[screenNum]; + + w = 16; + h = 16; + (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); + if (!(pScreen->PixmapPerDepth[0] = + (*pScreen->CreatePixmap)(pScreen, w, h, 1))) + return FALSE; + /* fill stipple with 1 */ + tmpval[0] = GXcopy; tmpval[1] = 1; tmpval[2] = FillSolid; + pgcScratch = GetScratchGC(1, pScreen); + if (!pgcScratch) + { + (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); + return FALSE; + } + (void)ChangeGC(pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); + ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], + pgcScratch, 1, &rect); + FreeScratchGC(pgcScratch); + return TRUE; +} + +void +FreeDefaultStipple(int screenNum) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); +} + +_X_EXPORT int +SetDashes(register GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) +{ + register long i; + register unsigned char *p, *indash; + BITS32 maskQ = 0; + + i = ndash; + p = pdash; + while (i--) + { + if (!*p++) + { + /* dash segment must be > 0 */ + clientErrorValue = 0; + return BadValue; + } + } + + if (ndash & 1) + p = (unsigned char *)xalloc(2 * ndash * sizeof(unsigned char)); + else + p = (unsigned char *)xalloc(ndash * sizeof(unsigned char)); + if (!p) + return BadAlloc; + + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + if (offset != pGC->dashOffset) + { + pGC->dashOffset = offset; + pGC->stateChanges |= GCDashOffset; + maskQ |= GCDashOffset; + } + + if (pGC->dash != DefaultDash) + xfree(pGC->dash); + pGC->numInDashList = ndash; + pGC->dash = p; + if (ndash & 1) + { + pGC->numInDashList += ndash; + indash = pdash; + i = ndash; + while (i--) + *p++ = *indash++; + } + while(ndash--) + *p++ = *pdash++; + pGC->stateChanges |= GCDashList; + maskQ |= GCDashList; + + if (pGC->funcs->ChangeGC) + (*pGC->funcs->ChangeGC) (pGC, maskQ); + return Success; +} + +_X_EXPORT int +VerifyRectOrder(int nrects, xRectangle *prects, int ordering) +{ + register xRectangle *prectP, *prectN; + register int i; + + switch(ordering) + { + case Unsorted: + return CT_UNSORTED; + case YSorted: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if(prectN->y < prectP->y) + return -1; + } + return CT_YSORTED; + case YXSorted: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if((prectN->y < prectP->y) || + ( (prectN->y == prectP->y) && + (prectN->x < prectP->x) ) ) + return -1; + } + return CT_YXSORTED; + case YXBanded: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if((prectN->y != prectP->y && + prectN->y < prectP->y + (int) prectP->height) || + ((prectN->y == prectP->y) && + (prectN->height != prectP->height || + prectN->x < prectP->x + (int) prectP->width))) + return -1; + } + return CT_YXBANDED; + } + return -1; +} + +_X_EXPORT int +SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, + xRectangle *prects, int ordering) +{ + int newct, size; + xRectangle *prectsNew; + + newct = VerifyRectOrder(nrects, prects, ordering); + if (newct < 0) + return(BadMatch); + size = nrects * sizeof(xRectangle); + prectsNew = (xRectangle *) xalloc(size); + if (!prectsNew && size) + return BadAlloc; + + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + pGC->clipOrg.x = xOrigin; + pGC->stateChanges |= GCClipXOrigin; + + pGC->clipOrg.y = yOrigin; + pGC->stateChanges |= GCClipYOrigin; + + if (size) + memmove((char *)prectsNew, (char *)prects, size); + (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); + if (pGC->funcs->ChangeGC) + (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); + return Success; +} + + +/* + sets reasonable defaults + if we can get a pre-allocated one, use it and mark it as used. + if we can't, create one out of whole cloth (The Velveteen GC -- if + you use it often enough it will become real.) +*/ +_X_EXPORT GCPtr +GetScratchGC(register unsigned depth, register ScreenPtr pScreen) +{ + register int i; + register GCPtr pGC; + + for (i=0; i<=pScreen->numDepths; i++) + if ( pScreen->GCperDepth[i]->depth == depth && + !(pScreen->rgf & (1L << (i+1))) + ) + { + pScreen->rgf |= (1L << (i+1)); + pGC = (pScreen->GCperDepth[i]); + + pGC->alu = GXcopy; + pGC->planemask = ~0; + pGC->serialNumber = 0; + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcChord; + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = FALSE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + if (pGC->clientClipType != CT_NONE) + (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); + pGC->stateChanges = (1 << (GCLastBit+1)) - 1; + return pGC; + } + /* if we make it this far, need to roll our own */ + pGC = CreateScratchGC(pScreen, depth); + if (pGC) + pGC->graphicsExposures = FALSE; + return pGC; +} + +/* + if the gc to free is in the table of pre-existing ones, +mark it as available. + if not, free it for real +*/ +_X_EXPORT void +FreeScratchGC(register GCPtr pGC) +{ + register ScreenPtr pScreen = pGC->pScreen; + register int i; + + for (i=0; i<=pScreen->numDepths; i++) + { + if ( pScreen->GCperDepth[i] == pGC) + { + pScreen->rgf &= ~(1L << (i+1)); + return; + } + } + (void)FreeGC(pGC, (GContext)0); +} diff --git a/xserver/dix/globals.c b/xserver/dix/globals.c new file mode 100644 index 000000000..f86c6026d --- /dev/null +++ b/xserver/dix/globals.c @@ -0,0 +1,161 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#include <X11/Xmd.h> +#include "misc.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "input.h" +#include "dixfont.h" +#include "site.h" +#include "dixstruct.h" +#include "os.h" + +_X_EXPORT ScreenInfo screenInfo; +KeybdCtrl defaultKeyboardControl = { + DEFAULT_KEYBOARD_CLICK, + DEFAULT_BELL, + DEFAULT_BELL_PITCH, + DEFAULT_BELL_DURATION, + DEFAULT_AUTOREPEAT, + DEFAULT_AUTOREPEATS, + DEFAULT_LEDS, + 0}; + +PtrCtrl defaultPointerControl = { + DEFAULT_PTR_NUMERATOR, + DEFAULT_PTR_DENOMINATOR, + DEFAULT_PTR_THRESHOLD, + 0}; + +_X_EXPORT ClientPtr *clients; +_X_EXPORT ClientPtr serverClient; +_X_EXPORT int currentMaxClients; /* current size of clients array */ +_X_EXPORT long maxBigRequestSize = MAX_BIG_REQUEST_SIZE; + +_X_EXPORT WindowPtr *WindowTable; + +_X_EXPORT unsigned long globalSerialNumber = 0; +_X_EXPORT unsigned long serverGeneration = 0; + +/* these next four are initialized in main.c */ +_X_EXPORT CARD32 ScreenSaverTime; +CARD32 ScreenSaverInterval; +_X_EXPORT int ScreenSaverBlanking; +int ScreenSaverAllowExposures; + +#ifdef DPMSExtension +# ifndef DEFAULT_STANDBY_TIME +# define DEFAULT_STANDBY_TIME DEFAULT_SCREEN_SAVER_TIME * 2 +# endif +# ifndef DEFAULT_SUSPEND_TIME +# define DEFAULT_SUSPEND_TIME DEFAULT_SCREEN_SAVER_TIME * 3 +# endif +# ifndef DEFAULT_OFF_TIME +# define DEFAULT_OFF_TIME DEFAULT_SCREEN_SAVER_TIME * 4 +# endif +# ifndef DEFAULT_DPMS_ENABLED +# define DEFAULT_DPMS_ENABLED TRUE +# endif +CARD32 defaultDPMSStandbyTime = DEFAULT_STANDBY_TIME; +CARD32 defaultDPMSSuspendTime = DEFAULT_SUSPEND_TIME; +CARD32 defaultDPMSOffTime = DEFAULT_OFF_TIME; +_X_EXPORT CARD16 DPMSPowerLevel = 0; +_X_EXPORT Bool defaultDPMSEnabled = DEFAULT_DPMS_ENABLED; +_X_EXPORT Bool DPMSEnabledSwitch = FALSE; /* these denote the DPMS command */ +_X_EXPORT Bool DPMSDisabledSwitch = FALSE; /* lind switch states */ +_X_EXPORT Bool DPMSCapableFlag = FALSE; +_X_EXPORT CARD32 DPMSStandbyTime; +_X_EXPORT CARD32 DPMSSuspendTime; +_X_EXPORT CARD32 DPMSOffTime; +_X_EXPORT Bool DPMSEnabled; +#endif + +CARD32 defaultScreenSaverTime = DEFAULT_SCREEN_SAVER_TIME; +CARD32 defaultScreenSaverInterval = DEFAULT_SCREEN_SAVER_INTERVAL; +int defaultScreenSaverBlanking = DEFAULT_SCREEN_SAVER_BLANKING; +int defaultScreenSaverAllowExposures = DEFAULT_SCREEN_SAVER_EXPOSURES; +#ifndef NOLOGOHACK +int logoScreenSaver = DEFAULT_LOGO_SCREEN_SAVER; +#endif + +#ifdef SCREENSAVER +Bool screenSaverSuspended = FALSE; +#endif + +char *defaultFontPath = COMPILEDDEFAULTFONTPATH; +char *defaultTextFont = COMPILEDDEFAULTFONT; +char *defaultCursorFont = COMPILEDCURSORFONT; +char *rgbPath = RGB_DB; +char *defaultDisplayClass = COMPILEDDISPLAYCLASS; +FontPtr defaultFont; /* not declared in dix.h to avoid including font.h in + every compilation of dix code */ +Bool loadableFonts = FALSE; +CursorPtr rootCursor; +Bool blackRoot=FALSE; +Bool whiteRoot=FALSE; +ClientPtr requestingClient; /* XXX this should be obsolete now, remove? */ + +_X_EXPORT TimeStamp currentTime; +_X_EXPORT TimeStamp lastDeviceEventTime; + +_X_EXPORT int defaultColorVisualClass = -1; +_X_EXPORT int monitorResolution = 0; + +_X_EXPORT char *display; + +CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND; +int argcGlobal; +char **argvGlobal; + +DDXPointRec dixScreenOrigins[MAXSCREENS]; diff --git a/xserver/dix/glyphcurs.c b/xserver/dix/glyphcurs.c new file mode 100644 index 000000000..c1c545fa9 --- /dev/null +++ b/xserver/dix/glyphcurs.c @@ -0,0 +1,193 @@ +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 "misc.h" +#include <X11/fonts/fontstruct.h> +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "resource.h" +#include "dix.h" +#include "cursorstr.h" +#include "opaque.h" +#include "servermd.h" + + +/* + get the bits out of the font in a portable way. to avoid +dealing with padding and such-like, we draw the glyph into +a bitmap, then read the bits out with GetImage, which +uses server-natural format. + since all screens return the same bitmap format, we'll just use +the first one we find. + the character origin lines up with the hotspot in the +cursor metrics. +*/ + +int +ServerBitsFromGlyph(FontPtr pfont, unsigned ch, register CursorMetricPtr cm, unsigned char **ppbits) +{ + register ScreenPtr pScreen; + register GCPtr pGC; + xRectangle rect; + PixmapPtr ppix; + long nby; + char *pbits; + ChangeGCVal gcval[3]; + unsigned char char2b[2]; + + /* turn glyph index into a protocol-format char2b */ + char2b[0] = (unsigned char)(ch >> 8); + char2b[1] = (unsigned char)(ch & 0xff); + + pScreen = screenInfo.screens[0]; + nby = BitmapBytePad(cm->width) * (long)cm->height; + pbits = (char *)xalloc(nby); + if (!pbits) + return BadAlloc; + /* zeroing the (pad) bits seems to help some ddx cursor handling */ + bzero(pbits, nby); + + ppix = (PixmapPtr)(*pScreen->CreatePixmap)(pScreen, cm->width, + cm->height, 1); + pGC = GetScratchGC(1, pScreen); + if (!ppix || !pGC) + { + if (ppix) + (*pScreen->DestroyPixmap)(ppix); + if (pGC) + FreeScratchGC(pGC); + xfree(pbits); + return BadAlloc; + } + + rect.x = 0; + rect.y = 0; + rect.width = cm->width; + rect.height = cm->height; + + /* fill the pixmap with 0 */ + gcval[0].val = GXcopy; + gcval[1].val = 0; + gcval[2].ptr = (pointer)pfont; + dixChangeGC(NullClient, pGC, GCFunction | GCForeground | GCFont, + NULL, gcval); + ValidateGC((DrawablePtr)ppix, pGC); + (*pGC->ops->PolyFillRect)((DrawablePtr)ppix, pGC, 1, &rect); + + /* draw the glyph */ + gcval[0].val = 1; + dixChangeGC(NullClient, pGC, GCForeground, NULL, gcval); + ValidateGC((DrawablePtr)ppix, pGC); + (*pGC->ops->PolyText16)((DrawablePtr)ppix, pGC, cm->xhot, cm->yhot, + 1, (unsigned short *)char2b); + (*pScreen->GetImage)((DrawablePtr)ppix, 0, 0, cm->width, cm->height, + XYPixmap, 1, pbits); + *ppbits = (unsigned char *)pbits; + FreeScratchGC(pGC); + (*pScreen->DestroyPixmap)(ppix); + return Success; +} + + +Bool +CursorMetricsFromGlyph(register FontPtr pfont, unsigned ch, register CursorMetricPtr cm) +{ + CharInfoPtr pci; + unsigned long nglyphs; + CARD8 chs[2]; + FontEncoding encoding; + + chs[0] = ch >> 8; + chs[1] = ch; + encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit; + if (encoding == Linear16Bit) + { + if (ch < pfont->info.firstCol || pfont->info.lastCol < ch) + return FALSE; + } + else + { + if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0]) + return FALSE; + if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1]) + return FALSE; + } + (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci); + if (nglyphs == 0) + return FALSE; + cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + cm->height = pci->metrics.descent + pci->metrics.ascent; + if (pci->metrics.leftSideBearing > 0) + { + cm->width += pci->metrics.leftSideBearing; + cm->xhot = 0; + } + else + { + cm->xhot = -pci->metrics.leftSideBearing; + if (pci->metrics.rightSideBearing < 0) + cm->width -= pci->metrics.rightSideBearing; + } + if (pci->metrics.ascent < 0) + { + cm->height -= pci->metrics.ascent; + cm->yhot = 0; + } + else + { + cm->yhot = pci->metrics.ascent; + if (pci->metrics.descent < 0) + cm->height -= pci->metrics.descent; + } + return TRUE; +} diff --git a/xserver/dix/grabs.c b/xserver/dix/grabs.c new file mode 100644 index 000000000..0c2b05e89 --- /dev/null +++ b/xserver/dix/grabs.c @@ -0,0 +1,436 @@ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#include "misc.h" +#define NEED_EVENTS +#include <X11/Xproto.h> +#include "windowstr.h" +#include "inputstr.h" +#include "cursorstr.h" +#include "dixgrabs.h" + +#define BITMASK(i) (((Mask)1) << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +GrabPtr +CreateGrab( + int client, + DeviceIntPtr device, + WindowPtr window, + Mask eventMask, + Bool ownerEvents, Bool keyboardMode, Bool pointerMode, + DeviceIntPtr modDevice, + unsigned short modifiers, + int type, + KeyCode keybut, /* key or button */ + WindowPtr confineTo, + CursorPtr cursor) +{ + GrabPtr grab; + + grab = (GrabPtr)xalloc(sizeof(GrabRec)); + if (!grab) + return (GrabPtr)NULL; + grab->resource = FakeClientID(client); + grab->device = device; + grab->coreGrab = ((device == inputInfo.keyboard) || + (device == inputInfo.pointer)); + grab->window = window; + grab->eventMask = eventMask; + grab->ownerEvents = ownerEvents; + grab->keyboardMode = keyboardMode; + grab->pointerMode = pointerMode; + grab->modifiersDetail.exact = modifiers; + grab->modifiersDetail.pMask = NULL; + grab->modifierDevice = modDevice; + grab->coreMods = ((modDevice == inputInfo.keyboard) || + (modDevice == inputInfo.pointer)); + grab->type = type; + grab->detail.exact = keybut; + grab->detail.pMask = NULL; + grab->confineTo = confineTo; + grab->cursor = cursor; + if (cursor) + cursor->refcnt++; + return grab; + +} + +static void +FreeGrab(GrabPtr pGrab) +{ + if (pGrab->modifiersDetail.pMask != NULL) + xfree(pGrab->modifiersDetail.pMask); + + if (pGrab->detail.pMask != NULL) + xfree(pGrab->detail.pMask); + + if (pGrab->cursor) + FreeCursor(pGrab->cursor, (Cursor)0); + + xfree(pGrab); +} + +int +DeletePassiveGrab(pointer value, XID id) +{ + register GrabPtr g, prev; + GrabPtr pGrab = (GrabPtr)value; + + /* it is OK if the grab isn't found */ + prev = 0; + for (g = (wPassiveGrabs (pGrab->window)); g; g = g->next) + { + if (pGrab == g) + { + if (prev) + prev->next = g->next; + else + if (!(pGrab->window->optional->passiveGrabs = g->next)) + CheckWindowOptionalNeed (pGrab->window); + break; + } + prev = g; + } + FreeGrab(pGrab); + return Success; +} + +static Mask * +DeleteDetailFromMask(Mask *pDetailMask, unsigned short detail) +{ + register Mask *mask; + register int i; + + mask = (Mask *)xalloc(sizeof(Mask) * MasksPerDetailMask); + if (mask) + { + if (pDetailMask) + for (i = 0; i < MasksPerDetailMask; i++) + mask[i]= pDetailMask[i]; + else + for (i = 0; i < MasksPerDetailMask; i++) + mask[i]= ~0L; + BITCLEAR(mask, detail); + } + return mask; +} + +static Bool +IsInGrabMask( + DetailRec firstDetail, + DetailRec secondDetail, + unsigned short exception) +{ + if (firstDetail.exact == exception) + { + if (firstDetail.pMask == NULL) + return TRUE; + + /* (at present) never called with two non-null pMasks */ + if (secondDetail.exact == exception) + return FALSE; + + if (GETBIT(firstDetail.pMask, secondDetail.exact)) + return TRUE; + } + + return FALSE; +} + +static Bool +IdenticalExactDetails( + unsigned short firstExact, + unsigned short secondExact, + unsigned short exception) +{ + if ((firstExact == exception) || (secondExact == exception)) + return FALSE; + + if (firstExact == secondExact) + return TRUE; + + return FALSE; +} + +static Bool +DetailSupersedesSecond( + DetailRec firstDetail, + DetailRec secondDetail, + unsigned short exception) +{ + if (IsInGrabMask(firstDetail, secondDetail, exception)) + return TRUE; + + if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact, + exception)) + return TRUE; + + return FALSE; +} + +static Bool +GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab) +{ + if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail, + pSecondGrab->modifiersDetail, + (unsigned short)AnyModifier)) + return FALSE; + + if (DetailSupersedesSecond(pFirstGrab->detail, + pSecondGrab->detail, (unsigned short)AnyKey)) + return TRUE; + + return FALSE; +} + +Bool +GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab) +{ + if ((pFirstGrab->device != pSecondGrab->device) || + (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) || + (pFirstGrab->type != pSecondGrab->type)) + return FALSE; + + if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) || + GrabSupersedesSecond(pSecondGrab, pFirstGrab)) + return TRUE; + + if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail, + (unsigned short)AnyKey) + && + DetailSupersedesSecond(pFirstGrab->modifiersDetail, + pSecondGrab->modifiersDetail, + (unsigned short)AnyModifier)) + return TRUE; + + if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail, + (unsigned short)AnyKey) + && + DetailSupersedesSecond(pSecondGrab->modifiersDetail, + pFirstGrab->modifiersDetail, + (unsigned short)AnyModifier)) + return TRUE; + + return FALSE; +} + +int +AddPassiveGrabToList(GrabPtr pGrab) +{ + GrabPtr grab; + + for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next) + { + if (GrabMatchesSecond(pGrab, grab)) + { + if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource)) + { + FreeGrab(pGrab); + return BadAccess; + } + } + } + + if (!pGrab->window->optional && !MakeWindowOptional (pGrab->window)) + { + FreeGrab(pGrab); + return BadAlloc; + } + pGrab->next = pGrab->window->optional->passiveGrabs; + pGrab->window->optional->passiveGrabs = pGrab; + if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab)) + return Success; + return BadAlloc; +} + +/* the following is kinda complicated, because we need to be able to back out + * if any allocation fails + */ + +Bool +DeletePassiveGrabFromList(GrabPtr pMinuendGrab) +{ + register GrabPtr grab; + GrabPtr *deletes, *adds; + Mask ***updates, **details; + int i, ndels, nadds, nups; + Bool ok; + +#define UPDATE(mask,exact) \ + if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \ + ok = FALSE; \ + else \ + updates[nups++] = &(mask) + + i = 0; + for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next) + i++; + if (!i) + return TRUE; + deletes = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr)); + adds = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr)); + updates = (Mask ***)ALLOCATE_LOCAL(i * sizeof(Mask **)); + details = (Mask **)ALLOCATE_LOCAL(i * sizeof(Mask *)); + if (!deletes || !adds || !updates || !details) + { + if (details) DEALLOCATE_LOCAL(details); + if (updates) DEALLOCATE_LOCAL(updates); + if (adds) DEALLOCATE_LOCAL(adds); + if (deletes) DEALLOCATE_LOCAL(deletes); + return FALSE; + } + ndels = nadds = nups = 0; + ok = TRUE; + for (grab = wPassiveGrabs(pMinuendGrab->window); + grab && ok; + grab = grab->next) + { + if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) || + !GrabMatchesSecond(grab, pMinuendGrab)) + continue; + if (GrabSupersedesSecond(pMinuendGrab, grab)) + { + deletes[ndels++] = grab; + } + else if ((grab->detail.exact == AnyKey) + && (grab->modifiersDetail.exact != AnyModifier)) + { + UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); + } + else if ((grab->modifiersDetail.exact == AnyModifier) + && (grab->detail.exact != AnyKey)) + { + UPDATE(grab->modifiersDetail.pMask, + pMinuendGrab->modifiersDetail.exact); + } + else if ((pMinuendGrab->detail.exact != AnyKey) + && (pMinuendGrab->modifiersDetail.exact != AnyModifier)) + { + GrabPtr pNewGrab; + + UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); + + pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device, + grab->window, (Mask)grab->eventMask, + (Bool)grab->ownerEvents, + (Bool)grab->keyboardMode, + (Bool)grab->pointerMode, + grab->modifierDevice, + AnyModifier, (int)grab->type, + pMinuendGrab->detail.exact, + grab->confineTo, grab->cursor); + if (!pNewGrab) + ok = FALSE; + else if (!(pNewGrab->modifiersDetail.pMask = + DeleteDetailFromMask(grab->modifiersDetail.pMask, + pMinuendGrab->modifiersDetail.exact)) + || + (!pNewGrab->window->optional && + !MakeWindowOptional(pNewGrab->window))) + { + FreeGrab(pNewGrab); + ok = FALSE; + } + else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB, + (pointer)pNewGrab)) + ok = FALSE; + else + adds[nadds++] = pNewGrab; + } + else if (pMinuendGrab->detail.exact == AnyKey) + { + UPDATE(grab->modifiersDetail.pMask, + pMinuendGrab->modifiersDetail.exact); + } + else + { + UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); + } + } + + if (!ok) + { + for (i = 0; i < nadds; i++) + FreeResource(adds[i]->resource, RT_NONE); + for (i = 0; i < nups; i++) + xfree(details[i]); + } + else + { + for (i = 0; i < ndels; i++) + FreeResource(deletes[i]->resource, RT_NONE); + for (i = 0; i < nadds; i++) + { + grab = adds[i]; + grab->next = grab->window->optional->passiveGrabs; + grab->window->optional->passiveGrabs = grab; + } + for (i = 0; i < nups; i++) + { + xfree(*updates[i]); + *updates[i] = details[i]; + } + } + DEALLOCATE_LOCAL(details); + DEALLOCATE_LOCAL(updates); + DEALLOCATE_LOCAL(adds); + DEALLOCATE_LOCAL(deletes); + return ok; + +#undef UPDATE +} diff --git a/xserver/dix/initatoms.c b/xserver/dix/initatoms.c new file mode 100644 index 000000000..a5972afd6 --- /dev/null +++ b/xserver/dix/initatoms.c @@ -0,0 +1,84 @@ +/* THIS IS A GENERATED FILE + * + * Do not change! Changing this file implies a protocol change! + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xatom.h> +#include "misc.h" +#include "dix.h" +void MakePredeclaredAtoms() +{ + if (MakeAtom("PRIMARY", 7, 1) != XA_PRIMARY) AtomError(); + if (MakeAtom("SECONDARY", 9, 1) != XA_SECONDARY) AtomError(); + if (MakeAtom("ARC", 3, 1) != XA_ARC) AtomError(); + if (MakeAtom("ATOM", 4, 1) != XA_ATOM) AtomError(); + if (MakeAtom("BITMAP", 6, 1) != XA_BITMAP) AtomError(); + if (MakeAtom("CARDINAL", 8, 1) != XA_CARDINAL) AtomError(); + if (MakeAtom("COLORMAP", 8, 1) != XA_COLORMAP) AtomError(); + if (MakeAtom("CURSOR", 6, 1) != XA_CURSOR) AtomError(); + if (MakeAtom("CUT_BUFFER0", 11, 1) != XA_CUT_BUFFER0) AtomError(); + if (MakeAtom("CUT_BUFFER1", 11, 1) != XA_CUT_BUFFER1) AtomError(); + if (MakeAtom("CUT_BUFFER2", 11, 1) != XA_CUT_BUFFER2) AtomError(); + if (MakeAtom("CUT_BUFFER3", 11, 1) != XA_CUT_BUFFER3) AtomError(); + if (MakeAtom("CUT_BUFFER4", 11, 1) != XA_CUT_BUFFER4) AtomError(); + if (MakeAtom("CUT_BUFFER5", 11, 1) != XA_CUT_BUFFER5) AtomError(); + if (MakeAtom("CUT_BUFFER6", 11, 1) != XA_CUT_BUFFER6) AtomError(); + if (MakeAtom("CUT_BUFFER7", 11, 1) != XA_CUT_BUFFER7) AtomError(); + if (MakeAtom("DRAWABLE", 8, 1) != XA_DRAWABLE) AtomError(); + if (MakeAtom("FONT", 4, 1) != XA_FONT) AtomError(); + if (MakeAtom("INTEGER", 7, 1) != XA_INTEGER) AtomError(); + if (MakeAtom("PIXMAP", 6, 1) != XA_PIXMAP) AtomError(); + if (MakeAtom("POINT", 5, 1) != XA_POINT) AtomError(); + if (MakeAtom("RECTANGLE", 9, 1) != XA_RECTANGLE) AtomError(); + if (MakeAtom("RESOURCE_MANAGER", 16, 1) != XA_RESOURCE_MANAGER) AtomError(); + if (MakeAtom("RGB_COLOR_MAP", 13, 1) != XA_RGB_COLOR_MAP) AtomError(); + if (MakeAtom("RGB_BEST_MAP", 12, 1) != XA_RGB_BEST_MAP) AtomError(); + if (MakeAtom("RGB_BLUE_MAP", 12, 1) != XA_RGB_BLUE_MAP) AtomError(); + if (MakeAtom("RGB_DEFAULT_MAP", 15, 1) != XA_RGB_DEFAULT_MAP) AtomError(); + if (MakeAtom("RGB_GRAY_MAP", 12, 1) != XA_RGB_GRAY_MAP) AtomError(); + if (MakeAtom("RGB_GREEN_MAP", 13, 1) != XA_RGB_GREEN_MAP) AtomError(); + if (MakeAtom("RGB_RED_MAP", 11, 1) != XA_RGB_RED_MAP) AtomError(); + if (MakeAtom("STRING", 6, 1) != XA_STRING) AtomError(); + if (MakeAtom("VISUALID", 8, 1) != XA_VISUALID) AtomError(); + if (MakeAtom("WINDOW", 6, 1) != XA_WINDOW) AtomError(); + if (MakeAtom("WM_COMMAND", 10, 1) != XA_WM_COMMAND) AtomError(); + if (MakeAtom("WM_HINTS", 8, 1) != XA_WM_HINTS) AtomError(); + if (MakeAtom("WM_CLIENT_MACHINE", 17, 1) != XA_WM_CLIENT_MACHINE) AtomError(); + if (MakeAtom("WM_ICON_NAME", 12, 1) != XA_WM_ICON_NAME) AtomError(); + if (MakeAtom("WM_ICON_SIZE", 12, 1) != XA_WM_ICON_SIZE) AtomError(); + if (MakeAtom("WM_NAME", 7, 1) != XA_WM_NAME) AtomError(); + if (MakeAtom("WM_NORMAL_HINTS", 15, 1) != XA_WM_NORMAL_HINTS) AtomError(); + if (MakeAtom("WM_SIZE_HINTS", 13, 1) != XA_WM_SIZE_HINTS) AtomError(); + if (MakeAtom("WM_ZOOM_HINTS", 13, 1) != XA_WM_ZOOM_HINTS) AtomError(); + if (MakeAtom("MIN_SPACE", 9, 1) != XA_MIN_SPACE) AtomError(); + if (MakeAtom("NORM_SPACE", 10, 1) != XA_NORM_SPACE) AtomError(); + if (MakeAtom("MAX_SPACE", 9, 1) != XA_MAX_SPACE) AtomError(); + if (MakeAtom("END_SPACE", 9, 1) != XA_END_SPACE) AtomError(); + if (MakeAtom("SUPERSCRIPT_X", 13, 1) != XA_SUPERSCRIPT_X) AtomError(); + if (MakeAtom("SUPERSCRIPT_Y", 13, 1) != XA_SUPERSCRIPT_Y) AtomError(); + if (MakeAtom("SUBSCRIPT_X", 11, 1) != XA_SUBSCRIPT_X) AtomError(); + if (MakeAtom("SUBSCRIPT_Y", 11, 1) != XA_SUBSCRIPT_Y) AtomError(); + if (MakeAtom("UNDERLINE_POSITION", 18, 1) != XA_UNDERLINE_POSITION) AtomError(); + if (MakeAtom("UNDERLINE_THICKNESS", 19, 1) != XA_UNDERLINE_THICKNESS) AtomError(); + if (MakeAtom("STRIKEOUT_ASCENT", 16, 1) != XA_STRIKEOUT_ASCENT) AtomError(); + if (MakeAtom("STRIKEOUT_DESCENT", 17, 1) != XA_STRIKEOUT_DESCENT) AtomError(); + if (MakeAtom("ITALIC_ANGLE", 12, 1) != XA_ITALIC_ANGLE) AtomError(); + if (MakeAtom("X_HEIGHT", 8, 1) != XA_X_HEIGHT) AtomError(); + if (MakeAtom("QUAD_WIDTH", 10, 1) != XA_QUAD_WIDTH) AtomError(); + if (MakeAtom("WEIGHT", 6, 1) != XA_WEIGHT) AtomError(); + if (MakeAtom("POINT_SIZE", 10, 1) != XA_POINT_SIZE) AtomError(); + if (MakeAtom("RESOLUTION", 10, 1) != XA_RESOLUTION) AtomError(); + if (MakeAtom("COPYRIGHT", 9, 1) != XA_COPYRIGHT) AtomError(); + if (MakeAtom("NOTICE", 6, 1) != XA_NOTICE) AtomError(); + if (MakeAtom("FONT_NAME", 9, 1) != XA_FONT_NAME) AtomError(); + if (MakeAtom("FAMILY_NAME", 11, 1) != XA_FAMILY_NAME) AtomError(); + if (MakeAtom("FULL_NAME", 9, 1) != XA_FULL_NAME) AtomError(); + if (MakeAtom("CAP_HEIGHT", 10, 1) != XA_CAP_HEIGHT) AtomError(); + if (MakeAtom("WM_CLASS", 8, 1) != XA_WM_CLASS) AtomError(); + if (MakeAtom("WM_TRANSIENT_FOR", 16, 1) != XA_WM_TRANSIENT_FOR) AtomError(); +} diff --git a/xserver/dix/main.c b/xserver/dix/main.c new file mode 100644 index 000000000..f3cde189c --- /dev/null +++ b/xserver/dix/main.c @@ -0,0 +1,792 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $TOG: main.c /main/86 1998/02/09 14:20:03 kaleb $ */ + +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xos.h> /* for unistd.h */ +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "extension.h" +#include "colormap.h" +#include "colormapst.h" +#include "cursorstr.h" +#include <X11/fonts/font.h> +#include "opaque.h" +#include "servermd.h" +#include "site.h" +#include "dixfont.h" +#include "extnsionst.h" +#ifdef XPRINT +#include "DiPrint.h" +#endif +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#else +#include "dixevents.h" /* InitEvents() */ +#include "dispatch.h" /* InitProcVectors() */ +#endif + +#ifdef DPMSExtension +#define DPMS_SERVER +#include <X11/extensions/dpms.h> +#include "dpmsproc.h" +#endif + +extern int InitClientPrivates(ClientPtr client); + +extern void Dispatch(void); + +char *ConnectionInfo; +xConnSetupPrefix connSetupPrefix; + +extern FontPtr defaultFont; +extern int screenPrivateCount; + +extern void InitProcVectors(void); +extern Bool CreateGCperDepthArray(void); + +#ifndef PANORAMIX +static +#endif +Bool CreateConnectionBlock(void); + +static void FreeScreen(ScreenPtr); + +_X_EXPORT PaddingInfo PixmapWidthPaddingInfo[33]; + +int connBlockScreenStart; + +static int restart = 0; + +_X_EXPORT void +NotImplemented(xEvent *from, xEvent *to) +{ + FatalError("Not implemented"); +} + +/* + * Dummy entry for ReplySwapVector[] + */ + +void +ReplyNotSwappd( + ClientPtr pClient , + int size , + void * pbuf + ) +{ + FatalError("Not implemented"); +} + +/* + * This array encodes the answer to the question "what is the log base 2 + * of the number of pixels that fit in a scanline pad unit?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int answer[6][4] = { + /* pad pad pad pad*/ + /* 8 16 32 64 */ + + { 3, 4, 5 , 6 }, /* 1 bit per pixel */ + { 1, 2, 3 , 4 }, /* 4 bits per pixel */ + { 0, 1, 2 , 3 }, /* 8 bits per pixel */ + { ~0, 0, 1 , 2 }, /* 16 bits per pixel */ + { ~0, ~0, 0 , 1 }, /* 24 bits per pixel */ + { ~0, ~0, 0 , 1 } /* 32 bits per pixel */ +}; + +/* + * This array gives the answer to the question "what is the first index for + * the answer array above given the number of bits per pixel?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int indexForBitsPerPixel[ 33 ] = { + ~0, 0, ~0, ~0, /* 1 bit per pixel */ + 1, ~0, ~0, ~0, /* 4 bits per pixel */ + 2, ~0, ~0, ~0, /* 8 bits per pixel */ + ~0,~0, ~0, ~0, + 3, ~0, ~0, ~0, /* 16 bits per pixel */ + ~0,~0, ~0, ~0, + 4, ~0, ~0, ~0, /* 24 bits per pixel */ + ~0,~0, ~0, ~0, + 5 /* 32 bits per pixel */ +}; + +/* + * This array gives the bytesperPixel value for cases where the number + * of bits per pixel is a multiple of 8 but not a power of 2. + */ +static int answerBytesPerPixel[ 33 ] = { + ~0, 0, ~0, ~0, /* 1 bit per pixel */ + 0, ~0, ~0, ~0, /* 4 bits per pixel */ + 0, ~0, ~0, ~0, /* 8 bits per pixel */ + ~0,~0, ~0, ~0, + 0, ~0, ~0, ~0, /* 16 bits per pixel */ + ~0,~0, ~0, ~0, + 3, ~0, ~0, ~0, /* 24 bits per pixel */ + ~0,~0, ~0, ~0, + 0 /* 32 bits per pixel */ +}; + +/* + * This array gives the answer to the question "what is the second index for + * the answer array above given the number of bits per scanline pad unit?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int indexForScanlinePad[ 65 ] = { + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 3 /* 64 bits per scanline pad unit */ +}; + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +int +main(int argc, char *argv[], char *envp[]) +{ + int i, j, k, error; + char *xauthfile; + HWEventQueueType alwaysCheckForInput[2]; + + display = "0"; + + InitGlobals(); +#ifdef XPRINT + PrinterInitGlobals(); +#endif + + /* Quartz support on Mac OS X requires that the Cocoa event loop be in + * the main thread. This allows the X server main to be called again + * from another thread. */ +#if defined(__DARWIN__) && defined(DARWIN_WITH_QUARTZ) + DarwinHandleGUI(argc, argv, envp); +#endif + + /* Notice if we're restarted. Probably this is because we jumped through + * an uninitialized pointer */ + if (restart) + FatalError("server restarted. Jumped through uninitialized pointer?\n"); + else + restart = 1; + + CheckUserParameters(argc, argv, envp); + + CheckUserAuthorization(); + +#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS + ExpandCommandLine(&argc, &argv); +#endif + + InitConnectionLimits(); + + /* These are needed by some routines which are called from interrupt + * handlers, thus have no direct calling path back to main and thus + * can't be passed argc, argv as parameters */ + argcGlobal = argc; + argvGlobal = argv; + /* prep X authority file from environment; this can be overriden by a + * command line option */ + xauthfile = getenv("XAUTHORITY"); + if (xauthfile) InitAuthorization (xauthfile); + ProcessCommandLine(argc, argv); + + alwaysCheckForInput[0] = 0; + alwaysCheckForInput[1] = 1; + while(1) + { + serverGeneration++; + ScreenSaverTime = defaultScreenSaverTime; + ScreenSaverInterval = defaultScreenSaverInterval; + ScreenSaverBlanking = defaultScreenSaverBlanking; + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; +#ifdef DPMSExtension + DPMSStandbyTime = defaultDPMSStandbyTime; + DPMSSuspendTime = defaultDPMSSuspendTime; + DPMSOffTime = defaultDPMSOffTime; + DPMSEnabled = defaultDPMSEnabled; + DPMSPowerLevel = 0; +#endif + InitBlockAndWakeupHandlers(); + /* Perform any operating system dependent initializations you'd like */ + OsInit(); + if(serverGeneration == 1) + { + CreateWellKnownSockets(); + InitProcVectors(); + clients = (ClientPtr *)xalloc(MAXCLIENTS * sizeof(ClientPtr)); + if (!clients) + FatalError("couldn't create client array"); + for (i=1; i<MAXCLIENTS; i++) + clients[i] = NullClient; + serverClient = (ClientPtr)xalloc(sizeof(ClientRec)); + if (!serverClient) + FatalError("couldn't create server client"); + InitClient(serverClient, 0, (pointer)NULL); + } + else + ResetWellKnownSockets (); + clients[0] = serverClient; + currentMaxClients = 1; + + if (!InitClientResources(serverClient)) /* for root resources */ + FatalError("couldn't init server resources"); + + SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]); + screenInfo.arraySize = MAXSCREENS; + screenInfo.numScreens = 0; + screenInfo.numVideoScreens = -1; + WindowTable = (WindowPtr *)xalloc(MAXSCREENS * sizeof(WindowPtr)); + if (!WindowTable) + FatalError("couldn't create root window table"); + + /* + * Just in case the ddx doesnt supply a format for depth 1 (like qvss). + */ + j = indexForBitsPerPixel[ 1 ]; + k = indexForScanlinePad[ BITMAP_SCANLINE_PAD ]; + PixmapWidthPaddingInfo[1].padRoundUp = BITMAP_SCANLINE_PAD-1; + PixmapWidthPaddingInfo[1].padPixelsLog2 = answer[j][k]; + j = indexForBitsPerPixel[8]; /* bits per byte */ + PixmapWidthPaddingInfo[1].padBytesLog2 = answer[j][k]; + PixmapWidthPaddingInfo[1].bitsPerPixel = 1; + + InitAtoms(); + InitEvents(); + InitGlyphCaching(); + ResetExtensionPrivates(); + ResetClientPrivates(); + ResetScreenPrivates(); + ResetWindowPrivates(); + ResetGCPrivates(); +#ifdef PIXPRIV + ResetPixmapPrivates(); +#endif + ResetColormapPrivates(); + ResetFontPrivateIndex(); + ResetDevicePrivateIndex(); + InitCallbackManager(); + InitVisualWrap(); + InitOutput(&screenInfo, argc, argv); +#ifdef XPRINT + PrinterInitOutput(&screenInfo, argc, argv); +#endif + + if (screenInfo.numScreens < 1) + FatalError("no screens found"); + if (screenInfo.numVideoScreens < 0) + screenInfo.numVideoScreens = screenInfo.numScreens; + InitExtensions(argc, argv); + if (!InitClientPrivates(serverClient)) + FatalError("failed to allocate serverClient devprivates"); + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + if (!CreateScratchPixmapsForScreen(i)) + FatalError("failed to create scratch pixmaps"); + if (pScreen->CreateScreenResources && + !(*pScreen->CreateScreenResources)(pScreen)) + FatalError("failed to create screen resources"); + if (!CreateGCperDepth(i)) + FatalError("failed to create scratch GCs"); + if (!CreateDefaultStipple(i)) + FatalError("failed to create default stipple"); + if (!CreateRootWindow(pScreen)) + FatalError("failed to create root window"); + } + InitInput(argc, argv); + if (InitAndStartDevices() != Success) + FatalError("failed to initialize core devices"); + + InitFonts(); + if (loadableFonts) { + SetFontPath(0, 0, (unsigned char *)defaultFontPath, &error); + } else { + if (SetDefaultFontPath(defaultFontPath) != Success) + ErrorF("failed to set default font path '%s'", + defaultFontPath); + } + if (!SetDefaultFont(defaultTextFont)) + FatalError("could not open default font '%s'", defaultTextFont); + if (!(rootCursor = CreateRootCursor(defaultCursorFont, 0))) + FatalError("could not open default cursor font '%s'", + defaultCursorFont); +#ifdef DPMSExtension + /* check all screens, looking for DPMS Capabilities */ + DPMSCapableFlag = DPMSSupported(); + if (!DPMSCapableFlag) + DPMSEnabled = FALSE; +#endif + +#ifdef PANORAMIX + /* + * Consolidate window and colourmap information for each screen + */ + if (!noPanoramiXExtension) + PanoramiXConsolidate(); +#endif + + for (i = 0; i < screenInfo.numScreens; i++) + InitRootWindow(WindowTable[i]); + DefineInitialRootWindow(WindowTable[0]); + SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + if (!PanoramiXCreateConnectionBlock()) + FatalError("could not create connection block info"); + } else +#endif + { + if (!CreateConnectionBlock()) + FatalError("could not create connection block info"); + } + + Dispatch(); + + /* Now free up whatever must be freed */ + if (screenIsSaved == SCREEN_SAVER_ON) + SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset); + FreeScreenSaverTimer(); + CloseDownExtensions(); + +#ifdef PANORAMIX + { + Bool remember_it = noPanoramiXExtension; + noPanoramiXExtension = TRUE; + FreeAllResources(); + noPanoramiXExtension = remember_it; + } +#else + FreeAllResources(); +#endif + + CloseDownDevices(); + for (i = screenInfo.numScreens - 1; i >= 0; i--) + { + FreeScratchPixmapsForScreen(i); + FreeGCperDepth(i); + FreeDefaultStipple(i); + (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]); + FreeScreen(screenInfo.screens[i]); + screenInfo.numScreens = i; + } + CloseDownEvents(); + xfree(WindowTable); + WindowTable = NULL; + FreeFonts(); + + FreeAuditTimer(); + + xfree(serverClient->devPrivates); + serverClient->devPrivates = NULL; + + if (dispatchException & DE_TERMINATE) + { + CloseWellKnownConnections(); + } + + OsCleanup((dispatchException & DE_TERMINATE) != 0); + + if (dispatchException & DE_TERMINATE) + { + ddxGiveUp(); + break; + } + + xfree(ConnectionInfo); + ConnectionInfo = NULL; + } + return(0); +} + +static int VendorRelease = VENDOR_RELEASE; +static char *VendorString = VENDOR_STRING; + +void +SetVendorRelease(int release) +{ + VendorRelease = release; +} + +void +SetVendorString(char *string) +{ + VendorString = string; +} + +static int padlength[4] = {0, 3, 2, 1}; + +#ifndef PANORAMIX +static +#endif +Bool +CreateConnectionBlock() +{ + xConnSetup setup; + xWindowRoot root; + xDepth depth; + xVisualType visual; + xPixmapFormat format; + unsigned long vid; + int i, j, k, + lenofblock, + sizesofar = 0; + char *pBuf; + + + /* Leave off the ridBase and ridMask, these must be sent with + connection */ + + setup.release = VendorRelease; + /* + * per-server image and bitmap parameters are defined in Xmd.h + */ + setup.imageByteOrder = screenInfo.imageByteOrder; + + setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit; + setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad; + + setup.bitmapBitOrder = screenInfo.bitmapBitOrder; + setup.motionBufferSize = NumMotionEvents(); + setup.numRoots = screenInfo.numScreens; + setup.nbytesVendor = strlen(VendorString); + setup.numFormats = screenInfo.numPixmapFormats; + setup.maxRequestSize = MAX_REQUEST_SIZE; + QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode); + + lenofblock = sizeof(xConnSetup) + + ((setup.nbytesVendor + 3) & ~3) + + (setup.numFormats * sizeof(xPixmapFormat)) + + (setup.numRoots * sizeof(xWindowRoot)); + ConnectionInfo = (char *) xalloc(lenofblock); + if (!ConnectionInfo) + return FALSE; + + memmove(ConnectionInfo, (char *)&setup, sizeof(xConnSetup)); + sizesofar = sizeof(xConnSetup); + pBuf = ConnectionInfo + sizeof(xConnSetup); + + memmove(pBuf, VendorString, (int)setup.nbytesVendor); + sizesofar += setup.nbytesVendor; + pBuf += setup.nbytesVendor; + i = padlength[setup.nbytesVendor & 3]; + sizesofar += i; + while (--i >= 0) + *pBuf++ = 0; + + for (i=0; i<screenInfo.numPixmapFormats; i++) + { + format.depth = screenInfo.formats[i].depth; + format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel; + format.scanLinePad = screenInfo.formats[i].scanlinePad; + memmove(pBuf, (char *)&format, sizeof(xPixmapFormat)); + pBuf += sizeof(xPixmapFormat); + sizesofar += sizeof(xPixmapFormat); + } + + connBlockScreenStart = sizesofar; + for (i=0; i<screenInfo.numScreens; i++) + { + ScreenPtr pScreen; + DepthPtr pDepth; + VisualPtr pVisual; + + pScreen = screenInfo.screens[i]; + root.windowId = WindowTable[i]->drawable.id; + root.defaultColormap = pScreen->defColormap; + root.whitePixel = pScreen->whitePixel; + root.blackPixel = pScreen->blackPixel; + root.currentInputMask = 0; /* filled in when sent */ + root.pixWidth = pScreen->width; + root.pixHeight = pScreen->height; + root.mmWidth = pScreen->mmWidth; + root.mmHeight = pScreen->mmHeight; + root.minInstalledMaps = pScreen->minInstalledCmaps; + root.maxInstalledMaps = pScreen->maxInstalledCmaps; + root.rootVisualID = pScreen->rootVisual; + root.backingStore = pScreen->backingStoreSupport; + root.saveUnders = pScreen->saveUnderSupport != NotUseful; + root.rootDepth = pScreen->rootDepth; + root.nDepths = pScreen->numDepths; + memmove(pBuf, (char *)&root, sizeof(xWindowRoot)); + sizesofar += sizeof(xWindowRoot); + pBuf += sizeof(xWindowRoot); + + pDepth = pScreen->allowedDepths; + for(j = 0; j < pScreen->numDepths; j++, pDepth++) + { + lenofblock += sizeof(xDepth) + + (pDepth->numVids * sizeof(xVisualType)); + pBuf = (char *)xrealloc(ConnectionInfo, lenofblock); + if (!pBuf) + { + xfree(ConnectionInfo); + return FALSE; + } + ConnectionInfo = pBuf; + pBuf += sizesofar; + depth.depth = pDepth->depth; + depth.nVisuals = pDepth->numVids; + memmove(pBuf, (char *)&depth, sizeof(xDepth)); + pBuf += sizeof(xDepth); + sizesofar += sizeof(xDepth); + for(k = 0; k < pDepth->numVids; k++) + { + vid = pDepth->vids[k]; + for (pVisual = pScreen->visuals; + pVisual->vid != vid; + pVisual++) + ; + visual.visualID = vid; + visual.class = pVisual->class; + visual.bitsPerRGB = pVisual->bitsPerRGBValue; + visual.colormapEntries = pVisual->ColormapEntries; + visual.redMask = pVisual->redMask; + visual.greenMask = pVisual->greenMask; + visual.blueMask = pVisual->blueMask; + memmove(pBuf, (char *)&visual, sizeof(xVisualType)); + pBuf += sizeof(xVisualType); + sizesofar += sizeof(xVisualType); + } + } + } + connSetupPrefix.success = xTrue; + connSetupPrefix.length = lenofblock/4; + connSetupPrefix.majorVersion = X_PROTOCOL; + connSetupPrefix.minorVersion = X_PROTOCOL_REVISION; + return TRUE; +} + +/* + grow the array of screenRecs if necessary. + call the device-supplied initialization procedure +with its screen number, a pointer to its ScreenRec, argc, and argv. + return the number of successfully installed screens. + +*/ + +int +AddScreen( + Bool (* pfnInit)( + int /*index*/, + ScreenPtr /*pScreen*/, + int /*argc*/, + char ** /*argv*/ + ), + int argc, + char **argv) +{ + + int i; + int scanlinepad, format, depth, bitsPerPixel, j, k; + ScreenPtr pScreen; +#ifdef DEBUG + void (**jNI) (); +#endif /* DEBUG */ + + i = screenInfo.numScreens; + if (i == MAXSCREENS) + return -1; + + pScreen = (ScreenPtr) xcalloc(1, sizeof(ScreenRec)); + if (!pScreen) + return -1; + + pScreen->devPrivates = (DevUnion *)xcalloc(sizeof(DevUnion), + screenPrivateCount); + if (!pScreen->devPrivates && screenPrivateCount) + { + xfree(pScreen); + return -1; + } + pScreen->myNum = i; + pScreen->WindowPrivateLen = 0; + pScreen->WindowPrivateSizes = (unsigned *)NULL; + pScreen->totalWindowSize = + ((sizeof(WindowRec) + sizeof(long) - 1) / sizeof(long)) * sizeof(long); + pScreen->GCPrivateLen = 0; + pScreen->GCPrivateSizes = (unsigned *)NULL; + pScreen->totalGCSize = + ((sizeof(GC) + sizeof(long) - 1) / sizeof(long)) * sizeof(long); +#ifdef PIXPRIV + pScreen->PixmapPrivateLen = 0; + pScreen->PixmapPrivateSizes = (unsigned *)NULL; + pScreen->totalPixmapSize = BitmapBytePad(sizeof(PixmapRec)*8); +#endif + pScreen->ClipNotify = 0; /* for R4 ddx compatibility */ + pScreen->CreateScreenResources = 0; + +#ifdef DEBUG + for (jNI = &pScreen->QueryBestSize; + jNI < (void (**) ()) &pScreen->SendGraphicsExpose; + jNI++) + *jNI = NotImplemented; +#endif /* DEBUG */ + + /* + * This loop gets run once for every Screen that gets added, + * but thats ok. If the ddx layer initializes the formats + * one at a time calling AddScreen() after each, then each + * iteration will make it a little more accurate. Worst case + * we do this loop N * numPixmapFormats where N is # of screens. + * Anyway, this must be called after InitOutput and before the + * screen init routine is called. + */ + for (format=0; format<screenInfo.numPixmapFormats; format++) + { + depth = screenInfo.formats[format].depth; + bitsPerPixel = screenInfo.formats[format].bitsPerPixel; + scanlinepad = screenInfo.formats[format].scanlinePad; + j = indexForBitsPerPixel[ bitsPerPixel ]; + k = indexForScanlinePad[ scanlinepad ]; + PixmapWidthPaddingInfo[ depth ].padPixelsLog2 = answer[j][k]; + PixmapWidthPaddingInfo[ depth ].padRoundUp = + (scanlinepad/bitsPerPixel) - 1; + j = indexForBitsPerPixel[ 8 ]; /* bits per byte */ + PixmapWidthPaddingInfo[ depth ].padBytesLog2 = answer[j][k]; + PixmapWidthPaddingInfo[ depth ].bitsPerPixel = bitsPerPixel; + if (answerBytesPerPixel[bitsPerPixel]) + { + PixmapWidthPaddingInfo[ depth ].notPower2 = 1; + PixmapWidthPaddingInfo[ depth ].bytesPerPixel = + answerBytesPerPixel[bitsPerPixel]; + } + else + { + PixmapWidthPaddingInfo[ depth ].notPower2 = 0; + } + } + + /* This is where screen specific stuff gets initialized. Load the + screen structure, call the hardware, whatever. + This is also where the default colormap should be allocated and + also pixel values for blackPixel, whitePixel, and the cursor + Note that InitScreen is NOT allowed to modify argc, argv, or + any of the strings pointed to by argv. They may be passed to + multiple screens. + */ + pScreen->rgf = ~0L; /* there are no scratch GCs yet*/ + WindowTable[i] = NullWindow; + screenInfo.screens[i] = pScreen; + screenInfo.numScreens++; + if (!(*pfnInit)(i, pScreen, argc, argv)) + { + FreeScreen(pScreen); + screenInfo.numScreens--; + return -1; + } + return i; +} + +static void +FreeScreen(ScreenPtr pScreen) +{ + xfree(pScreen->WindowPrivateSizes); + xfree(pScreen->GCPrivateSizes); +#ifdef PIXPRIV + xfree(pScreen->PixmapPrivateSizes); +#endif + xfree(pScreen->devPrivates); + xfree(pScreen); +} diff --git a/xserver/dix/pixmap.c b/xserver/dix/pixmap.c new file mode 100644 index 000000000..a5b7b064d --- /dev/null +++ b/xserver/dix/pixmap.c @@ -0,0 +1,151 @@ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include "scrnintstr.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "site.h" + + +/* + * Scratch pixmap management and device independent pixmap allocation + * function. + */ + + +/* callable by ddx */ +_X_EXPORT PixmapPtr +GetScratchPixmapHeader(ScreenPtr pScreen, int width, int height, int depth, + int bitsPerPixel, int devKind, pointer pPixData) +{ + PixmapPtr pPixmap = pScreen->pScratchPixmap; + + if (pPixmap) + pScreen->pScratchPixmap = NULL; + else + /* width and height of 0 means don't allocate any pixmap data */ + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth); + + if (pPixmap) { + if ((*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + bitsPerPixel, devKind, pPixData)) + return pPixmap; + (*pScreen->DestroyPixmap)(pPixmap); + } + return NullPixmap; +} + + +/* callable by ddx */ +_X_EXPORT void +FreeScratchPixmapHeader(PixmapPtr pPixmap) +{ + if (pPixmap) + { + ScreenPtr pScreen = pPixmap->drawable.pScreen; + + pPixmap->devPrivate.ptr = NULL; /* lest ddx chases bad ptr */ + if (pScreen->pScratchPixmap) + (*pScreen->DestroyPixmap)(pPixmap); + else + pScreen->pScratchPixmap = pPixmap; + } +} + + +Bool +CreateScratchPixmapsForScreen(int scrnum) +{ + /* let it be created on first use */ + screenInfo.screens[scrnum]->pScratchPixmap = NULL; + return TRUE; +} + + +void +FreeScratchPixmapsForScreen(int scrnum) +{ + FreeScratchPixmapHeader(screenInfo.screens[scrnum]->pScratchPixmap); +} + + +/* callable by ddx */ +_X_EXPORT PixmapPtr +AllocatePixmap(ScreenPtr pScreen, int pixDataSize) +{ + PixmapPtr pPixmap; +#ifdef PIXPRIV + char *ptr; + DevUnion *ppriv; + unsigned *sizes; + unsigned size; + int i; + + if (pScreen->totalPixmapSize > ((size_t)-1) - pixDataSize) + return NullPixmap; + + pPixmap = (PixmapPtr)xalloc(pScreen->totalPixmapSize + pixDataSize); + if (!pPixmap) + return NullPixmap; + ppriv = (DevUnion *)(pPixmap + 1); + pPixmap->devPrivates = ppriv; + sizes = pScreen->PixmapPrivateSizes; + ptr = (char *)(ppriv + pScreen->PixmapPrivateLen); + for (i = pScreen->PixmapPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ((size = *sizes) != 0) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } +#else + pPixmap = (PixmapPtr)xalloc(sizeof(PixmapRec) + pixDataSize); +#endif + +#ifdef _XSERVER64 + if (pPixmap) { + pPixmap->drawable.pad0 = 0; + pPixmap->drawable.pad1 = 0; + } +#endif + + return pPixmap; +} diff --git a/xserver/dix/privates.c b/xserver/dix/privates.c new file mode 100644 index 000000000..b20a1dbf0 --- /dev/null +++ b/xserver/dix/privates.c @@ -0,0 +1,456 @@ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include "scrnintstr.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "servermd.h" +#include "site.h" +#include "inputstr.h" +#include "extnsionst.h" + +/* + * See the Wrappers and devPrivates section in "Definition of the + * Porting Layer for the X v11 Sample Server" (doc/Server/ddx.tbl.ms) + * for information on how to use devPrivates. + */ + +/* + * extension private machinery + */ + +static int extensionPrivateCount; +int extensionPrivateLen; +unsigned *extensionPrivateSizes; +unsigned totalExtensionSize; + +void +ResetExtensionPrivates() +{ + extensionPrivateCount = 0; + extensionPrivateLen = 0; + xfree(extensionPrivateSizes); + extensionPrivateSizes = (unsigned *)NULL; + totalExtensionSize = + ((sizeof(ExtensionEntry) + sizeof(long) - 1) / sizeof(long)) * sizeof(long); +} + +_X_EXPORT int +AllocateExtensionPrivateIndex() +{ + return extensionPrivateCount++; +} + +_X_EXPORT Bool +AllocateExtensionPrivate(int index2, unsigned amount) +{ + unsigned oldamount; + + /* Round up sizes for proper alignment */ + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= extensionPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(extensionPrivateSizes, + (index2 + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (extensionPrivateLen <= index2) + { + nsizes[extensionPrivateLen++] = 0; + totalExtensionSize += sizeof(DevUnion); + } + extensionPrivateSizes = nsizes; + } + oldamount = extensionPrivateSizes[index2]; + if (amount > oldamount) + { + extensionPrivateSizes[index2] = amount; + totalExtensionSize += (amount - oldamount); + } + return TRUE; +} + +/* + * client private machinery + */ + +static int clientPrivateCount; +int clientPrivateLen; +unsigned *clientPrivateSizes; +unsigned totalClientSize; + +void +ResetClientPrivates() +{ + clientPrivateCount = 0; + clientPrivateLen = 0; + xfree(clientPrivateSizes); + clientPrivateSizes = (unsigned *)NULL; + totalClientSize = + ((sizeof(ClientRec) + sizeof(long) - 1) / sizeof(long)) * sizeof(long); +} + +_X_EXPORT int +AllocateClientPrivateIndex() +{ + return clientPrivateCount++; +} + +_X_EXPORT Bool +AllocateClientPrivate(int index2, unsigned amount) +{ + unsigned oldamount; + + /* Round up sizes for proper alignment */ + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= clientPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(clientPrivateSizes, + (index2 + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (clientPrivateLen <= index2) + { + nsizes[clientPrivateLen++] = 0; + totalClientSize += sizeof(DevUnion); + } + clientPrivateSizes = nsizes; + } + oldamount = clientPrivateSizes[index2]; + if (amount > oldamount) + { + clientPrivateSizes[index2] = amount; + totalClientSize += (amount - oldamount); + } + return TRUE; +} + +/* + * screen private machinery + */ + +int screenPrivateCount; + +void +ResetScreenPrivates() +{ + screenPrivateCount = 0; +} + +/* this can be called after some screens have been created, + * so we have to worry about resizing existing devPrivates + */ +_X_EXPORT int +AllocateScreenPrivateIndex() +{ + int idx; + int i; + ScreenPtr pScreen; + DevUnion *nprivs; + + idx = screenPrivateCount++; + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + nprivs = (DevUnion *)xrealloc(pScreen->devPrivates, + screenPrivateCount * sizeof(DevUnion)); + if (!nprivs) + { + screenPrivateCount--; + return -1; + } + /* Zero the new private */ + bzero(&nprivs[idx], sizeof(DevUnion)); + pScreen->devPrivates = nprivs; + } + return idx; +} + + +/* + * window private machinery + */ + +static int windowPrivateCount; + +void +ResetWindowPrivates() +{ + windowPrivateCount = 0; +} + +_X_EXPORT int +AllocateWindowPrivateIndex() +{ + return windowPrivateCount++; +} + +_X_EXPORT Bool +AllocateWindowPrivate(register ScreenPtr pScreen, int index2, unsigned amount) +{ + unsigned oldamount; + + /* Round up sizes for proper alignment */ + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= pScreen->WindowPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(pScreen->WindowPrivateSizes, + (index2 + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (pScreen->WindowPrivateLen <= index2) + { + nsizes[pScreen->WindowPrivateLen++] = 0; + pScreen->totalWindowSize += sizeof(DevUnion); + } + pScreen->WindowPrivateSizes = nsizes; + } + oldamount = pScreen->WindowPrivateSizes[index2]; + if (amount > oldamount) + { + pScreen->WindowPrivateSizes[index2] = amount; + pScreen->totalWindowSize += (amount - oldamount); + } + return TRUE; +} + + +/* + * gc private machinery + */ + +static int gcPrivateCount; + +void +ResetGCPrivates() +{ + gcPrivateCount = 0; +} + +_X_EXPORT int +AllocateGCPrivateIndex() +{ + return gcPrivateCount++; +} + +_X_EXPORT Bool +AllocateGCPrivate(register ScreenPtr pScreen, int index2, unsigned amount) +{ + unsigned oldamount; + + /* Round up sizes for proper alignment */ + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= pScreen->GCPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(pScreen->GCPrivateSizes, + (index2 + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (pScreen->GCPrivateLen <= index2) + { + nsizes[pScreen->GCPrivateLen++] = 0; + pScreen->totalGCSize += sizeof(DevUnion); + } + pScreen->GCPrivateSizes = nsizes; + } + oldamount = pScreen->GCPrivateSizes[index2]; + if (amount > oldamount) + { + pScreen->GCPrivateSizes[index2] = amount; + pScreen->totalGCSize += (amount - oldamount); + } + return TRUE; +} + + +/* + * pixmap private machinery + */ +#ifdef PIXPRIV +static int pixmapPrivateCount; + +void +ResetPixmapPrivates() +{ + pixmapPrivateCount = 0; +} + +_X_EXPORT int +AllocatePixmapPrivateIndex() +{ + return pixmapPrivateCount++; +} + +_X_EXPORT Bool +AllocatePixmapPrivate(register ScreenPtr pScreen, int index2, unsigned amount) +{ + unsigned oldamount; + + /* Round up sizes for proper alignment */ + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= pScreen->PixmapPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(pScreen->PixmapPrivateSizes, + (index2 + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (pScreen->PixmapPrivateLen <= index2) + { + nsizes[pScreen->PixmapPrivateLen++] = 0; + pScreen->totalPixmapSize += sizeof(DevUnion); + } + pScreen->PixmapPrivateSizes = nsizes; + } + oldamount = pScreen->PixmapPrivateSizes[index2]; + if (amount > oldamount) + { + pScreen->PixmapPrivateSizes[index2] = amount; + pScreen->totalPixmapSize += (amount - oldamount); + } + pScreen->totalPixmapSize = BitmapBytePad(pScreen->totalPixmapSize * 8); + return TRUE; +} +#endif + + +/* + * colormap private machinery + */ + +int colormapPrivateCount; + +void +ResetColormapPrivates() +{ + colormapPrivateCount = 0; +} + + +_X_EXPORT int +AllocateColormapPrivateIndex (InitCmapPrivFunc initPrivFunc) +{ + int index; + int i; + ColormapPtr pColormap; + DevUnion *privs; + + index = colormapPrivateCount++; + + for (i = 0; i < screenInfo.numScreens; i++) + { + /* + * AllocateColormapPrivateIndex may be called after the + * default colormap has been created on each screen! + * + * We must resize the devPrivates array for the default + * colormap on each screen, making room for this new private. + * We also call the initialization function 'initPrivFunc' on + * the new private allocated for each default colormap. + */ + + ScreenPtr pScreen = screenInfo.screens[i]; + + pColormap = (ColormapPtr) LookupIDByType ( + pScreen->defColormap, RT_COLORMAP); + + if (pColormap) + { + privs = (DevUnion *) xrealloc (pColormap->devPrivates, + colormapPrivateCount * sizeof(DevUnion)); + if (!privs) { + colormapPrivateCount--; + return -1; + } + bzero(&privs[index], sizeof(DevUnion)); + pColormap->devPrivates = privs; + if (!(*initPrivFunc)(pColormap,index)) + { + colormapPrivateCount--; + return -1; + } + } + } + + return index; +} + +/* + * device private machinery + */ + +static int devicePrivateIndex = 0; + +_X_EXPORT int +AllocateDevicePrivateIndex() +{ + return devicePrivateIndex++; +} + +_X_EXPORT Bool +AllocateDevicePrivate(DeviceIntPtr device, int index) +{ + if (device->nPrivates < ++index) { + DevUnion *nprivs = (DevUnion *) xrealloc(device->devPrivates, + index * sizeof(DevUnion)); + if (!nprivs) + return FALSE; + device->devPrivates = nprivs; + bzero(&nprivs[device->nPrivates], sizeof(DevUnion) + * (index - device->nPrivates)); + device->nPrivates = index; + return TRUE; + } else { + return TRUE; + } +} + +void +ResetDevicePrivateIndex(void) +{ + devicePrivateIndex = 0; +} diff --git a/xserver/dix/property.c b/xserver/dix/property.c new file mode 100644 index 000000000..da983838f --- /dev/null +++ b/xserver/dix/property.c @@ -0,0 +1,683 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/Xproto.h> +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#include "dispatch.h" +#include "swaprep.h" +#ifdef XACE +#include "xace.h" +#endif + +/***************************************************************** + * Property Stuff + * + * ChangeProperty, DeleteProperty, GetProperties, + * ListProperties + * + * Properties below to windows. A allocate slots each time + * a property is added. No fancy searching done. + * + *****************************************************************/ + +#ifdef notdef +static void +PrintPropertys(WindowPtr pWin) +{ + PropertyPtr pProp; + register int j; + + pProp = pWin->userProps; + while (pProp) + { + ErrorF( "%x %x\n", pProp->propertyName, pProp->type); + ErrorF("property format: %d\n", pProp->format); + ErrorF("property data: \n"); + for (j=0; j<(pProp->format/8)*pProp->size; j++) + ErrorF("%c\n", pProp->data[j]); + pProp = pProp->next; + } +} +#endif + +int +ProcRotateProperties(ClientPtr client) +{ + int i, j, delta; + REQUEST(xRotatePropertiesReq); + WindowPtr pWin; + register Atom * atoms; + PropertyPtr * props; /* array of pointer */ + PropertyPtr pProp; + xEvent event; + + REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!stuff->nAtoms) + return(Success); + atoms = (Atom *) & stuff[1]; + props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr)); + if (!props) + return(BadAlloc); + for (i = 0; i < stuff->nAtoms; i++) + { +#ifdef XACE + char action = XaceHook(XACE_PROPERTY_ACCESS, client, pWin, atoms[i], + SecurityReadAccess|SecurityWriteAccess); +#endif + if (!ValidAtom(atoms[i]) +#ifdef XACE + || (SecurityErrorOperation == action) +#endif + ) + { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } +#ifdef XACE + if (SecurityIgnoreOperation == action) + { + DEALLOCATE_LOCAL(props); + return Success; + } +#endif + for (j = i + 1; j < stuff->nAtoms; j++) + if (atoms[j] == atoms[i]) + { + DEALLOCATE_LOCAL(props); + return BadMatch; + } + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == atoms[i]) + goto found; + pProp = pProp->next; + } + DEALLOCATE_LOCAL(props); + return BadMatch; +found: + props[i] = pProp; + } + delta = stuff->nPositions; + + /* If the rotation is a complete 360 degrees, then moving the properties + around and generating PropertyNotify events should be skipped. */ + + if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) + { + while (delta < 0) /* faster if abs value is small */ + delta += stuff->nAtoms; + for (i = 0; i < stuff->nAtoms; i++) + { + /* Generate a PropertyNotify event for each property whose value + is changed in the order in which they appear in the request. */ + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = props[i]->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + + props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; + } + } + DEALLOCATE_LOCAL(props); + return Success; +} + +int +ProcChangeProperty(ClientPtr client) +{ + WindowPtr pWin; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + REQUEST(xChangePropertyReq); + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) + { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) + { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); + + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if (!ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + +#ifdef XACE + switch (XaceHook(XACE_PROPERTY_ACCESS, client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + return Success; + } +#endif + + err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format, + (int)mode, len, (pointer)&stuff[1], TRUE); + if (err != Success) + return err; + else + return client->noClientException; +} + +_X_EXPORT int +ChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format, + int mode, unsigned long len, pointer value, + Bool sendevent) +{ + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) /* just add to list */ + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + return(BadAlloc); + pProp = (PropertyPtr)xalloc(sizeof(PropertyRec)); + if (!pProp) + return(BadAlloc); + data = (pointer)xalloc(totalSize); + if (!data && len) + { + xfree(pProp); + return(BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (len) + memmove((char *)data, (char *)value, totalSize); + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } + else + { + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return(BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return(BadMatch); + if (mode == PropModeReplace) + { + if (totalSize != pProp->size * (pProp->format >> 3)) + { + data = (pointer)xrealloc(pProp->data, totalSize); + if (!data && len) + return(BadAlloc); + pProp->data = data; + } + if (len) + memmove((char *)pProp->data, (char *)value, totalSize); + pProp->size = len; + pProp->type = type; + pProp->format = format; + } + else if (len == 0) + { + /* do nothing */ + } + else if (mode == PropModeAppend) + { + data = (pointer)xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + pProp->data = data; + memmove(&((char *)data)[pProp->size * sizeInBytes], + (char *)value, + totalSize); + pProp->size += len; + } + else if (mode == PropModePrepend) + { + data = (pointer)xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + memmove(&((char *)data)[totalSize], (char *)pProp->data, + (int)(pProp->size * sizeInBytes)); + memmove((char *)data, (char *)value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + return(Success); +} + +int +DeleteProperty(WindowPtr pWin, Atom propName) +{ + PropertyPtr pProp, prevProp; + xEvent event; + + if (!(pProp = wUserProps (pWin))) + return(Success); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == propName) + break; + prevProp = pProp; + pProp = pProp->next; + } + if (pProp) + { + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + { + prevProp->next = pProp->next; + } + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} + +void +DeleteAllWindowProperties(WindowPtr pWin) +{ + PropertyPtr pProp, pNextProp; + xEvent event; + + pProp = wUserProps (pWin); + while (pProp) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + pNextProp = pProp->next; + xfree(pProp->data); + xfree(pProp); + pProp = pNextProp; + } +} + +static int +NullPropertyReply( + ClientPtr client, + ATOM propertyType, + int format, + xGetPropertyReply *reply) +{ + reply->nItems = 0; + reply->length = 0; + reply->bytesAfter = 0; + reply->propertyType = propertyType; + reply->format = format; + WriteReplyToClient(client, sizeof(xGenericReply), reply); + return(client->noClientException); +} + +/***************** + * GetProperty + * If type Any is specified, returns the property from the specified + * window regardless of its type. If a type is specified, returns the + * property only if its type equals the specified type. + * If delete is True and a property is returned, the property is also + * deleted from the window and a PropertyNotify event is generated on the + * window. + *****************/ + +int +ProcGetProperty(ClientPtr client) +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + WindowPtr pWin; + xGetPropertyReply reply; + REQUEST(xGetPropertyReq); + + REQUEST_SIZE_MATCH(xGetPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) + { + client->errorValue = stuff->delete; + return(BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) + return NullPropertyReply(client, None, 0, &reply); + +#ifdef XACE + { + Mask access_mode = SecurityReadAccess; + + if (stuff->delete) + access_mode |= SecurityDestroyAccess; + switch(XaceHook(XACE_PROPERTY_ACCESS, client, pWin, stuff->property, + access_mode)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return NullPropertyReply(client, pProp->type, pProp->format, + &reply); + } + } +#endif + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) + ) + { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + return(Success); + } + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.length = (len + 3) >> 2; + reply.nItems = len / (pProp->format / 8 ); + reply.propertyType = pProp->type; + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + if (len) + { + switch (reply.format) { + case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; + case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; + default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; + } + WriteSwappedDataToClient(client, len, + (char *)pProp->data + ind); + } + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* delete the Property */ + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(client->noClientException); +} + +int +ProcListProperties(ClientPtr client) +{ + Atom *pAtoms = NULL, *temppAtoms; + xListPropertiesReply xlpr; + int numProps = 0; + WindowPtr pWin; + PropertyPtr pProp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pProp = wUserProps (pWin); + while (pProp) + { + pProp = pProp->next; + numProps++; + } + if (numProps) + if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom)))) + return(BadAlloc); + + xlpr.type = X_Reply; + xlpr.nProperties = numProps; + xlpr.length = (numProps * sizeof(Atom)) >> 2; + xlpr.sequenceNumber = client->sequence; + pProp = wUserProps (pWin); + temppAtoms = pAtoms; + while (pProp) + { + *temppAtoms++ = pProp->propertyName; + pProp = pProp->next; + } + WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); + if (numProps) + { + client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + DEALLOCATE_LOCAL(pAtoms); + } + return(client->noClientException); +} + +int +ProcDeleteProperty(register ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xDeletePropertyReq); + int result; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return (BadAtom); + } + +#ifdef XACE + switch(XaceHook(XACE_PROPERTY_ACCESS, client, pWin, stuff->property, + SecurityDestroyAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return Success; + } +#endif + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} diff --git a/xserver/dix/resource.c b/xserver/dix/resource.c new file mode 100644 index 000000000..b2d01c8f3 --- /dev/null +++ b/xserver/dix/resource.c @@ -0,0 +1,903 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +********************************************************/ +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $TOG: resource.c /main/41 1998/02/09 14:20:31 kaleb $ */ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, CreateNewResourceClass, InitClientResources, + * FakeClientID, AddResource, FreeResource, FreeClientResources, + * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange + */ + +/* + * A resource ID is a 32 bit quantity, the upper 2 bits of which are + * off-limits for client-visible resources. The next 8 bits are + * used as client ID, and the low 22 bits come from the client. + * A resource ID is "hashed" by extracting and xoring subfields + * (varying with the size of the hash table). + * + * It is sometimes necessary for the server to create an ID that looks + * like it belongs to a client. This ID, however, must not be one + * the client actually can create, or we have the potential for conflict. + * The 31st bit of the ID is reserved for the server's use for this + * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to + * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a + * resource "owned" by the client. + */ + +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include "misc.h" +#include "os.h" +#include "resource.h" +#include "dixstruct.h" +#include "opaque.h" +#include "windowstr.h" +#include "dixfont.h" +#include "colormap.h" +#include "inputstr.h" +#include "dixevents.h" +#include "dixgrabs.h" +#include "cursor.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef XACE +#include "xace.h" +#endif +#include <assert.h> + +static void RebuildTable( + int /*client*/ +); + +#define SERVER_MINID 32 + +#define INITBUCKETS 64 +#define INITHASHSIZE 6 +#define MAXHASHSIZE 11 + +typedef struct _Resource { + struct _Resource *next; + XID id; + RESTYPE type; + pointer value; +} ResourceRec, *ResourcePtr; +#define NullResource ((ResourcePtr)NULL) + +typedef struct _ClientResource { + ResourcePtr *resources; + int elements; + int buckets; + int hashsize; /* log(2)(buckets) */ + XID fakeID; + XID endFakeID; + XID expectID; +} ClientResourceRec; + +_X_EXPORT RESTYPE lastResourceType; +static RESTYPE lastResourceClass; +_X_EXPORT RESTYPE TypeMask; + +static DeleteType *DeleteFuncs = (DeleteType *)NULL; + +#ifdef XResExtension + +_X_EXPORT Atom * ResourceNames = NULL; + +_X_EXPORT void RegisterResourceName (RESTYPE type, char *name) +{ + ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE); +} + +#endif + +_X_EXPORT RESTYPE +CreateNewResourceType(DeleteType deleteFunc) +{ + RESTYPE next = lastResourceType + 1; + DeleteType *funcs; + + if (next & lastResourceClass) + return 0; + funcs = (DeleteType *)xrealloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + +#ifdef XResExtension + { + Atom *newnames; + newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom)); + if(!newnames) + return 0; + ResourceNames = newnames; + ResourceNames[next] = 0; + } +#endif + + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +_X_EXPORT RESTYPE +CreateNewResourceClass() +{ + RESTYPE next = lastResourceClass >> 1; + + if (next & lastResourceType) + return 0; + lastResourceClass = next; + TypeMask = next - 1; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(ClientPtr client) +{ + register int i, j; + + if (client == serverClient) + { + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + xfree(DeleteFuncs); + DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * + sizeof(DeleteType)); + if (!DeleteFuncs) + return FALSE; + DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; + DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; + DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; + DeleteFuncs[RT_GC & TypeMask] = FreeGC; + DeleteFuncs[RT_FONT & TypeMask] = CloseFont; + DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; + DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; + DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; + DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; + DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + +#ifdef XResExtension + if(ResourceNames) + xfree(ResourceNames); + ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom)); + if(!ResourceNames) + return FALSE; +#endif + } + clientTable[i = client->index].resources = + (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); + if (!clientTable[i].resources) + return FALSE; + clientTable[i].buckets = INITBUCKETS; + clientTable[i].elements = 0; + clientTable[i].hashsize = INITHASHSIZE; + /* Many IDs allocated from the server client are visible to clients, + * so we don't use the SERVER_BIT for them, but we have to start + * past the magic value constants used in the protocol. For normal + * clients, we can start from zero, with SERVER_BIT set. + */ + clientTable[i].fakeID = client->clientAsMask | + (client->index ? SERVER_BIT : SERVER_MINID); + clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; + clientTable[i].expectID = client->clientAsMask; + for (j=0; j<INITBUCKETS; j++) + { + clientTable[i].resources[j] = NullResource; + } + return TRUE; +} + + +static int +Hash(int client, register XID id) +{ + id &= RESOURCE_ID_MASK; + switch (clientTable[client].hashsize) + { + case 6: + return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12)))); + case 7: + return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); + case 8: + return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); + case 9: + return ((int)(0x1FF & (id ^ (id>>9)))); + case 10: + return ((int)(0x3FF & (id ^ (id>>10)))); + case 11: + return ((int)(0x7FF & (id ^ (id>>11)))); + } + return -1; +} + +static XID +AvailableID( + register int client, + register XID id, + register XID maxid, + register XID goodid) +{ + register ResourcePtr res; + + if ((goodid >= id) && (goodid <= maxid)) + return goodid; + for (; id <= maxid; id++) + { + res = clientTable[client].resources[Hash(client, id)]; + while (res && (res->id != id)) + res = res->next; + if (!res) + return id; + } + return 0; +} + +_X_EXPORT void +GetXIDRange(int client, Bool server, XID *minp, XID *maxp) +{ + register XID id, maxid; + register ResourcePtr *resp; + register ResourcePtr res; + register int i; + XID goodid; + + id = (Mask)client << CLIENTOFFSET; + if (server) + id |= client ? SERVER_BIT : SERVER_MINID; + maxid = id | RESOURCE_ID_MASK; + goodid = 0; + for (resp = clientTable[client].resources, i = clientTable[client].buckets; + --i >= 0;) + { + for (res = *resp++; res; res = res->next) + { + if ((res->id < id) || (res->id > maxid)) + continue; + if (((res->id - id) >= (maxid - res->id)) ? + (goodid = AvailableID(client, id, res->id - 1, goodid)) : + !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) + maxid = res->id - 1; + else + id = res->id + 1; + } + } + if (id > maxid) + id = maxid = 0; + *minp = id; + *maxp = maxid; +} + +/** + * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. + * This function tries to find count unused XIDs for the given client. It + * puts the IDs in the array pids and returns the number found, which should + * almost always be the number requested. + * + * The circumstances that lead to a call to this function are very rare. + * Xlib must run out of IDs while trying to generate a request that wants + * multiple ID's, like the Multi-buffering CreateImageBuffers request. + * + * No rocket science in the implementation; just iterate over all + * possible IDs for the given client and pick the first count IDs + * that aren't in use. A more efficient algorithm could probably be + * invented, but this will be used so rarely that this should suffice. + */ + +_X_EXPORT unsigned int +GetXIDList(ClientPtr pClient, unsigned count, XID *pids) +{ + unsigned int found = 0; + XID id = pClient->clientAsMask; + XID maxid; + + maxid = id | RESOURCE_ID_MASK; + while ( (found < count) && (id <= maxid) ) + { + if (!LookupIDByClass(id, RC_ANY)) + { + pids[found++] = id; + } + id++; + } + return found; +} + +/* + * Return the next usable fake client ID. + * + * Normally this is just the next one in line, but if we've used the last + * in the range, we need to find a new range of safe IDs to avoid + * over-running another client. + */ + +_X_EXPORT XID +FakeClientID(register int client) +{ + XID id, maxid; + + id = clientTable[client].fakeID++; + if (id != clientTable[client].endFakeID) + return id; + GetXIDRange(client, TRUE, &id, &maxid); + if (!id) { + if (!client) + FatalError("FakeClientID: server internal ids exhausted\n"); + MarkClientException(clients[client]); + id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); + maxid = id | RESOURCE_ID_MASK; + } + clientTable[client].fakeID = id + 1; + clientTable[client].endFakeID = maxid + 1; + return id; +} + +_X_EXPORT Bool +AddResource(XID id, RESTYPE type, pointer value) +{ + int client; + register ClientResourceRec *rrec; + register ResourcePtr res, *head; + + client = CLIENT_ID(id); + rrec = &clientTable[client]; + if (!rrec->buckets) + { + ErrorF("AddResource(%lx, %lx, %lx), client=%d \n", + (unsigned long)id, type, (unsigned long)value, client); + FatalError("client not in use\n"); + } + if ((rrec->elements >= 4*rrec->buckets) && + (rrec->hashsize < MAXHASHSIZE)) + RebuildTable(client); + head = &rrec->resources[Hash(client, id)]; + res = (ResourcePtr)xalloc(sizeof(ResourceRec)); + if (!res) + { + (*DeleteFuncs[type & TypeMask])(value, id); + return FALSE; + } + res->next = *head; + res->id = id; + res->type = type; + res->value = value; + *head = res; + rrec->elements++; + if (!(id & SERVER_BIT) && (id >= rrec->expectID)) + rrec->expectID = id + 1; + return TRUE; +} + +static void +RebuildTable(int client) +{ + register int j; + register ResourcePtr res, next; + ResourcePtr **tails, *resources; + register ResourcePtr **tptr, *rptr; + + /* + * For now, preserve insertion order, since some ddx layers depend + * on resources being free in the opposite order they are added. + */ + + j = 2 * clientTable[client].buckets; + tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); + if (!tails) + return; + resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); + if (!resources) + { + DEALLOCATE_LOCAL(tails); + return; + } + for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) + { + *rptr = NullResource; + *tptr = rptr; + } + clientTable[client].hashsize++; + for (j = clientTable[client].buckets, + rptr = clientTable[client].resources; + --j >= 0; + rptr++) + { + for (res = *rptr; res; res = next) + { + next = res->next; + res->next = NullResource; + tptr = &tails[Hash(client, res->id)]; + **tptr = res; + *tptr = &res->next; + } + } + DEALLOCATE_LOCAL(tails); + clientTable[client].buckets *= 2; + xfree(clientTable[client].resources); + clientTable[client].resources = resources; +} + +_X_EXPORT void +FreeResource(XID id, RESTYPE skipDeleteFuncType) +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + register int *eltptr; + int elements; + Bool gotOne = FALSE; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id) + { + RESTYPE rtype = res->type; + *prev = res->next; + elements = --*eltptr; + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + if (rtype != skipDeleteFuncType) + (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ + gotOne = TRUE; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } + if (!gotOne) + ErrorF("Freeing resource id=%lX which isn't there.\n", + (unsigned long)id); +} + + +_X_EXPORT void +FreeResourceByType(XID id, RESTYPE type, Bool skipFree) +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id && res->type == type) + { + *prev = res->next; + if (type & RC_CACHED) + FlushClientCaches(res->id); + if (!skipFree) + (*DeleteFuncs[type & TypeMask])(res->value, res->id); + xfree(res); + break; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } +} + +/* + * Change the value associated with a resource id. Caller + * is responsible for "doing the right thing" with the old + * data + */ + +_X_EXPORT Bool +ChangeResourceValue (XID id, RESTYPE rtype, pointer value) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + res->value = value; + return TRUE; + } + } + return FALSE; +} + +/* Note: if func adds or deletes resources, then func can get called + * more than once for some resources. If func adds new resources, + * func might or might not get called for them. func cannot both + * add and delete an equal number of resources! + */ + +_X_EXPORT void +FindClientResourcesByType( + ClientPtr client, + RESTYPE type, + FindResType func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + if (!type || this->type == type) { + elements = *eltptr; + (*func)(this->value, this->id, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } + } +} + +_X_EXPORT void +FindAllClientResources( + ClientPtr client, + FindAllRes func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + elements = *eltptr; + (*func)(this->value, this->id, this->type, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } +} + + +pointer +LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata +){ + ResourcePtr *resources; + ResourcePtr this; + int i; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + for (i = 0; i < clientTable[client->index].buckets; i++) { + for (this = resources[i]; this; this = this->next) { + if (!type || this->type == type) { + if((*func)(this->value, this->id, cdata)) + return this->value; + } + } + } + return NULL; +} + + +void +FreeClientNeverRetainResources(ClientPtr client) +{ + ResourcePtr *resources; + ResourcePtr this; + ResourcePtr *prev; + int j; + + if (!client) + return; + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + prev = &resources[j]; + while ( (this = *prev) ) + { + RESTYPE rtype = this->type; + if (rtype & RC_NEVERRETAIN) + { + *prev = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(ClientPtr client) +{ + register ResourcePtr *resources; + register ResourcePtr this; + int j; + + /* This routine shouldn't be called with a null client, but just in + case ... */ + + if (!client) + return; + + HandleSaveSet(client); + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + /* It may seem silly to update the head of this resource list as + we delete the members, since the entire list will be deleted any way, + but there are some resource deletion functions "FreeClientPixels" for + one which do a LookupID on another resource id (a Colormap id in this + case), so the resource list must be kept valid up to the point that + it is deleted, so every time we delete a resource, we must update the + head, just like in FreeResource. I hope that this doesn't slow down + mass deletion appreciably. PRH */ + + ResourcePtr *head; + + head = &resources[j]; + + for (this = *head; this; this = *head) + { + RESTYPE rtype = this->type; + *head = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + } + xfree(clientTable[client->index].resources); + clientTable[client->index].resources = NULL; + clientTable[client->index].buckets = 0; +} + +void +FreeAllResources() +{ + int i; + + for (i = currentMaxClients; --i >= 0; ) + { + if (clientTable[i].buckets) + FreeClientResources(clients[i]); + } +} + +_X_EXPORT Bool +LegalNewID(XID id, register ClientPtr client) +{ + +#ifdef PANORAMIX + XID minid, maxid; + + if (!noPanoramiXExtension) { + minid = client->clientAsMask | (client->index ? + SERVER_BIT : SERVER_MINID); + maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; + if ((id >= minid) && (id <= maxid)) + return TRUE; + } +#endif /* PANORAMIX */ + return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && + ((clientTable[client->index].expectID <= id) || + !LookupIDByClass(id, RC_ANY))); +} + +/* SecurityLookupIDByType and SecurityLookupIDByClass: + * These are the heart of the resource ID security system. They take + * two additional arguments compared to the old LookupID functions: + * the client doing the lookup, and the access mode (see resource.h). + * The resource is returned if it exists and the client is allowed access, + * else NULL is returned. + */ + +_X_EXPORT pointer +SecurityLookupIDByType(ClientPtr client, XID id, RESTYPE rtype, Mask mode) +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + retval = res->value; + break; + } + } +#ifdef XACE + if (retval && client && + !XaceHook(XACE_RESOURCE_ACCESS, client, id, rtype, mode, retval)) + retval = NULL; +#endif + return retval; +} + + +_X_EXPORT pointer +SecurityLookupIDByClass(ClientPtr client, XID id, RESTYPE classes, Mask mode) +{ + int cid; + register ResourcePtr res = NULL; + pointer retval = NULL; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + { + retval = res->value; + break; + } + } +#ifdef XACE + if (retval && client && + !XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type, mode, retval)) + retval = NULL; +#endif + return retval; +} + +/* We can't replace the LookupIDByType and LookupIDByClass functions with + * macros because of compatibility with loadable servers. + */ + +_X_EXPORT pointer +LookupIDByType(XID id, RESTYPE rtype) +{ + return SecurityLookupIDByType(NullClient, id, rtype, + SecurityUnknownAccess); +} + +_X_EXPORT pointer +LookupIDByClass(XID id, RESTYPE classes) +{ + return SecurityLookupIDByClass(NullClient, id, classes, + SecurityUnknownAccess); +} diff --git a/xserver/dix/strcasecmp.c b/xserver/dix/strcasecmp.c new file mode 100644 index 000000000..58f0961e6 --- /dev/null +++ b/xserver/dix/strcasecmp.c @@ -0,0 +1,48 @@ +/************************************************************ + 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 <ctype.h> +#include "dix.h" + +#ifdef NEED_STRCASECMP +int +xstrcasecmp(char *str1,char *str2) +{ + const u_char *us1 = (const u_char *)str1, *us2 = (const u_char *)str2; + + while (tolower(*us1) == tolower(*us2)) { + if (*us1++ == '\0') + return (0); + us2++; + } + + return (tolower(*us1) - tolower(*us2)); +} +#endif diff --git a/xserver/dix/swaprep.c b/xserver/dix/swaprep.c new file mode 100644 index 000000000..08ae6eb1a --- /dev/null +++ b/xserver/dix/swaprep.c @@ -0,0 +1,1299 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include <X11/fonts/fontstruct.h> +#include "scrnintstr.h" +#include "swaprep.h" +#include "globals.h" + +static void SwapFontInfo(xQueryFontReply *pr); + +static void SwapCharInfo(xCharInfo *pInfo); + +static void SwapFont(xQueryFontReply *pr, Bool hasGlyphs); + +/** + * Thanks to Jack Palevich for testing and subsequently rewriting all this + * + * \param size size in bytes + */ +_X_EXPORT void +Swap32Write(ClientPtr pClient, int size, register CARD32 *pbuf) +{ + register int i; + register char n; + + size >>= 2; + for(i = 0; i < size; i++) + /* brackets are mandatory here, because "swapl" macro expands + to several statements */ + { + swapl(&pbuf[i], n); + } + (void)WriteToClient(pClient, size << 2, (char *) pbuf); +} + +/** + * + * \param size size in bytes + */ +_X_EXPORT void +CopySwap32Write(ClientPtr pClient, int size, CARD32 *pbuf) +{ + int bufsize = size; + CARD32 *pbufT; + register CARD32 *from, *to, *fromLast, *toLast; + CARD32 tmpbuf[1]; + + /* Allocate as big a buffer as we can... */ + while (!(pbufT = (CARD32 *) ALLOCATE_LOCAL(bufsize))) + { + bufsize >>= 1; + if (bufsize == 4) + { + pbufT = tmpbuf; + break; + } + } + + /* convert lengths from # of bytes to # of longs */ + size >>= 2; + bufsize >>= 2; + + from = pbuf; + fromLast = from + size; + while (from < fromLast) { + int nbytes; + to = pbufT; + toLast = to + min (bufsize, fromLast - from); + nbytes = (toLast - to) << 2; + while (to < toLast) { + /* can't write "cpswapl(*from++, *to++)" because cpswapl is a macro + that evaulates its args more than once */ + cpswapl(*from, *to); + from++; + to++; + } + (void)WriteToClient (pClient, nbytes, (char *) pbufT); + } + + if (pbufT != tmpbuf) + DEALLOCATE_LOCAL ((char *) pbufT); +} + +/** + * + * \param size size in bytes + */ +void +CopySwap16Write(ClientPtr pClient, int size, short *pbuf) +{ + int bufsize = size; + short *pbufT; + register short *from, *to, *fromLast, *toLast; + short tmpbuf[2]; + + /* Allocate as big a buffer as we can... */ + while (!(pbufT = (short *) ALLOCATE_LOCAL(bufsize))) + { + bufsize >>= 1; + if (bufsize == 4) + { + pbufT = tmpbuf; + break; + } + } + + /* convert lengths from # of bytes to # of shorts */ + size >>= 1; + bufsize >>= 1; + + from = pbuf; + fromLast = from + size; + while (from < fromLast) { + int nbytes; + to = pbufT; + toLast = to + min (bufsize, fromLast - from); + nbytes = (toLast - to) << 1; + while (to < toLast) { + /* can't write "cpswaps(*from++, *to++)" because cpswaps is a macro + that evaulates its args more than once */ + cpswaps(*from, *to); + from++; + to++; + } + (void)WriteToClient (pClient, nbytes, (char *) pbufT); + } + + if (pbufT != tmpbuf) + DEALLOCATE_LOCAL ((char *) pbufT); +} + + +/* Extra-small reply */ +void +SGenericReply(ClientPtr pClient, int size, xGenericReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +/* Extra-large reply */ +void +SGetWindowAttributesReply(ClientPtr pClient, int size, + xGetWindowAttributesReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->visualID, n); + swaps(&pRep->class, n); + swapl(&pRep->backingBitPlanes, n); + swapl(&pRep->backingPixel, n); + swapl(&pRep->colormap, n); + swapl(&pRep->allEventMasks, n); + swapl(&pRep->yourEventMask, n); + swaps(&pRep->doNotPropagateMask, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetGeometryReply(ClientPtr pClient, int size, xGetGeometryReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->root, n); + swaps(&pRep->x, n); + swaps(&pRep->y, n); + swaps(&pRep->width, n); + swaps(&pRep->height, n); + swaps(&pRep->borderWidth, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryTreeReply(ClientPtr pClient, int size, xQueryTreeReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->root, n); + swapl(&pRep->parent, n); + swaps(&pRep->nChildren, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SInternAtomReply(ClientPtr pClient, int size, xInternAtomReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->atom, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetAtomNameReply(ClientPtr pClient, int size, xGetAtomNameReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nameLength, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + + +void +SGetPropertyReply(ClientPtr pClient, int size, xGetPropertyReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->propertyType, n); + swapl(&pRep->bytesAfter, n); + swapl(&pRep->nItems, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SListPropertiesReply(ClientPtr pClient, int size, xListPropertiesReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nProperties, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetSelectionOwnerReply(ClientPtr pClient, int size, + xGetSelectionOwnerReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->owner, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + + +void +SQueryPointerReply(ClientPtr pClient, int size, xQueryPointerReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->root, n); + swapl(&pRep->child, n); + swaps(&pRep->rootX, n); + swaps(&pRep->rootY, n); + swaps(&pRep->winX, n); + swaps(&pRep->winY, n); + swaps(&pRep->mask, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SwapTimecoord(xTimecoord* pCoord) +{ + register char n; + + swapl(&pCoord->time, n); + swaps(&pCoord->x, n); + swaps(&pCoord->y, n); +} + +void +SwapTimeCoordWrite(ClientPtr pClient, int size, xTimecoord *pRep) +{ + int i, n; + xTimecoord *pRepT; + + n = size / sizeof(xTimecoord); + pRepT = pRep; + for(i = 0; i < n; i++) + { + SwapTimecoord(pRepT); + pRepT++; + } + (void)WriteToClient(pClient, size, (char *) pRep); + +} +void +SGetMotionEventsReply(ClientPtr pClient, int size, xGetMotionEventsReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->nEvents, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +STranslateCoordsReply(ClientPtr pClient, int size, xTranslateCoordsReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->child, n); + swaps(&pRep->dstX, n); + swaps(&pRep->dstY, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetInputFocusReply(ClientPtr pClient, int size, xGetInputFocusReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->focus, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +/* extra long reply */ +void +SQueryKeymapReply(ClientPtr pClient, int size, xQueryKeymapReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +static void +SwapCharInfo(xCharInfo *pInfo) +{ + register char n; + + swaps(&pInfo->leftSideBearing, n); + swaps(&pInfo->rightSideBearing, n); + swaps(&pInfo->characterWidth, n); + swaps(&pInfo->ascent, n); + swaps(&pInfo->descent, n); + swaps(&pInfo->attributes, n); +} + +static void +SwapFontInfo(xQueryFontReply *pr) +{ + register char n; + + swaps(&pr->minCharOrByte2, n); + swaps(&pr->maxCharOrByte2, n); + swaps(&pr->defaultChar, n); + swaps(&pr->nFontProps, n); + swaps(&pr->fontAscent, n); + swaps(&pr->fontDescent, n); + SwapCharInfo( &pr->minBounds); + SwapCharInfo( &pr->maxBounds); + swapl(&pr->nCharInfos, n); +} + +static void +SwapFont(xQueryFontReply *pr, Bool hasGlyphs) +{ + unsigned i; + xCharInfo * pxci; + unsigned nchars, nprops; + char *pby; + register char n; + + swaps(&pr->sequenceNumber, n); + swapl(&pr->length, n); + nchars = pr->nCharInfos; + nprops = pr->nFontProps; + SwapFontInfo(pr); + pby = (char *) &pr[1]; + /* Font properties are an atom and either an int32 or a CARD32, so + * they are always 2 4 byte values */ + for(i = 0; i < nprops; i++) + { + swapl(pby, n); + pby += 4; + swapl(pby, n); + pby += 4; + } + if (hasGlyphs) + { + pxci = (xCharInfo *)pby; + for(i = 0; i< nchars; i++, pxci++) + SwapCharInfo(pxci); + } +} + +void +SQueryFontReply(ClientPtr pClient, int size, xQueryFontReply *pRep) +{ + SwapFont(pRep, TRUE); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryTextExtentsReply(ClientPtr pClient, int size, xQueryTextExtentsReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->fontAscent, n); + swaps(&pRep->fontDescent, n); + swaps(&pRep->overallAscent, n); + swaps(&pRep->overallDescent, n); + swapl(&pRep->overallWidth, n); + swapl(&pRep->overallLeft, n); + swapl(&pRep->overallRight, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SListFontsReply(ClientPtr pClient, int size, xListFontsReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nFonts, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SListFontsWithInfoReply(ClientPtr pClient, int size, + xListFontsWithInfoReply *pRep) +{ + SwapFont((xQueryFontReply *)pRep, FALSE); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetFontPathReply(ClientPtr pClient, int size, xGetFontPathReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nPaths, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetImageReply(ClientPtr pClient, int size, xGetImageReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->visual, n); + (void)WriteToClient(pClient, size, (char *) pRep); + /* Fortunately, image doesn't need swapping */ +} + +void +SListInstalledColormapsReply(ClientPtr pClient, int size, + xListInstalledColormapsReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nColormaps, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocColorReply(pClient, size, pRep) + ClientPtr pClient; + int size; + xAllocColorReply *pRep; +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->red, n); + swaps(&pRep->green, n); + swaps(&pRep->blue, n); + swapl(&pRep->pixel, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocNamedColorReply(ClientPtr pClient, int size, xAllocNamedColorReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->pixel, n); + swaps(&pRep->exactRed, n); + swaps(&pRep->exactGreen, n); + swaps(&pRep->exactBlue, n); + swaps(&pRep->screenRed, n); + swaps(&pRep->screenGreen, n); + swaps(&pRep->screenBlue, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocColorCellsReply(ClientPtr pClient, int size, xAllocColorCellsReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nPixels, n); + swaps(&pRep->nMasks, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + + +void +SAllocColorPlanesReply(ClientPtr pClient, int size, xAllocColorPlanesReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nPixels, n); + swapl(&pRep->redMask, n); + swapl(&pRep->greenMask, n); + swapl(&pRep->blueMask, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SwapRGB(xrgb *prgb) +{ + register char n; + + swaps(&prgb->red, n); + swaps(&prgb->green, n); + swaps(&prgb->blue, n); +} + +void +SQColorsExtend(ClientPtr pClient, int size, xrgb *prgb) +{ + int i, n; + xrgb *prgbT; + + n = size / sizeof(xrgb); + prgbT = prgb; + for(i = 0; i < n; i++) + { + SwapRGB(prgbT); + prgbT++; + } + (void)WriteToClient(pClient, size, (char *) prgb); +} + +void +SQueryColorsReply(ClientPtr pClient, int size, xQueryColorsReply* pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nColors, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SLookupColorReply(ClientPtr pClient, int size, xLookupColorReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->exactRed, n); + swaps(&pRep->exactGreen, n); + swaps(&pRep->exactBlue, n); + swaps(&pRep->screenRed, n); + swaps(&pRep->screenGreen, n); + swaps(&pRep->screenBlue, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryBestSizeReply(ClientPtr pClient, int size, xQueryBestSizeReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->width, n); + swaps(&pRep->height, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SListExtensionsReply(ClientPtr pClient, int size, xListExtensionsReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetKeyboardMappingReply(ClientPtr pClient, int size, + xGetKeyboardMappingReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetPointerMappingReply(ClientPtr pClient, int size, + xGetPointerMappingReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetModifierMappingReply(ClientPtr pClient, int size, + xGetModifierMappingReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetKeyboardControlReply(ClientPtr pClient, int size, xGetKeyboardControlReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->ledMask, n); + swaps(&pRep->bellPitch, n); + swaps(&pRep->bellDuration, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetPointerControlReply(ClientPtr pClient, int size, xGetPointerControlReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->accelNumerator, n); + swaps(&pRep->accelDenominator, n); + swaps(&pRep->threshold, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetScreenSaverReply(ClientPtr pClient, int size, xGetScreenSaverReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swaps(&pRep->timeout, n); + swaps(&pRep->interval, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + +void +SLHostsExtend(ClientPtr pClient, int size, char *buf) +{ + char *bufT = buf; + char *endbuf = buf + size; + while (bufT < endbuf) { + xHostEntry *host = (xHostEntry *) bufT; + int len = host->length; + register char n; + swaps (&host->length, n); + bufT += sizeof (xHostEntry) + (((len + 3) >> 2) << 2); + } + (void)WriteToClient (pClient, size, buf); +} + +void +SListHostsReply(ClientPtr pClient, int size, xListHostsReply *pRep) +{ + register char n; + + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swaps(&pRep->nHosts, n); + (void)WriteToClient(pClient, size, (char *) pRep); +} + + + +void +SErrorEvent(xError *from, xError *to) +{ + to->type = X_Error; + to->errorCode = from->errorCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->resourceID, to->resourceID); + cpswaps(from->minorCode, to->minorCode); + to->majorCode = from->majorCode; +} + +void +SKeyButtonPtrEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.keyButtonPointer.time, + to->u.keyButtonPointer.time); + cpswapl(from->u.keyButtonPointer.root, + to->u.keyButtonPointer.root); + cpswapl(from->u.keyButtonPointer.event, + to->u.keyButtonPointer.event); + cpswapl(from->u.keyButtonPointer.child, + to->u.keyButtonPointer.child); + cpswaps(from->u.keyButtonPointer.rootX, + to->u.keyButtonPointer.rootX); + cpswaps(from->u.keyButtonPointer.rootY, + to->u.keyButtonPointer.rootY); + cpswaps(from->u.keyButtonPointer.eventX, + to->u.keyButtonPointer.eventX); + cpswaps(from->u.keyButtonPointer.eventY, + to->u.keyButtonPointer.eventY); + cpswaps(from->u.keyButtonPointer.state, + to->u.keyButtonPointer.state); + to->u.keyButtonPointer.sameScreen = + from->u.keyButtonPointer.sameScreen; +} + +void +SEnterLeaveEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.enterLeave.time, to->u.enterLeave.time); + cpswapl(from->u.enterLeave.root, to->u.enterLeave.root); + cpswapl(from->u.enterLeave.event, to->u.enterLeave.event); + cpswapl(from->u.enterLeave.child, to->u.enterLeave.child); + cpswaps(from->u.enterLeave.rootX, to->u.enterLeave.rootX); + cpswaps(from->u.enterLeave.rootY, to->u.enterLeave.rootY); + cpswaps(from->u.enterLeave.eventX, to->u.enterLeave.eventX); + cpswaps(from->u.enterLeave.eventY, to->u.enterLeave.eventY); + cpswaps(from->u.enterLeave.state, to->u.enterLeave.state); + to->u.enterLeave.mode = from->u.enterLeave.mode; + to->u.enterLeave.flags = from->u.enterLeave.flags; +} + +void +SFocusEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.focus.window, to->u.focus.window); + to->u.focus.mode = from->u.focus.mode; +} + +void +SExposeEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.expose.window, to->u.expose.window); + cpswaps(from->u.expose.x, to->u.expose.x); + cpswaps(from->u.expose.y, to->u.expose.y); + cpswaps(from->u.expose.width, to->u.expose.width); + cpswaps(from->u.expose.height, to->u.expose.height); + cpswaps(from->u.expose.count, to->u.expose.count); +} + +void +SGraphicsExposureEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.graphicsExposure.drawable, + to->u.graphicsExposure.drawable); + cpswaps(from->u.graphicsExposure.x, + to->u.graphicsExposure.x); + cpswaps(from->u.graphicsExposure.y, + to->u.graphicsExposure.y); + cpswaps(from->u.graphicsExposure.width, + to->u.graphicsExposure.width); + cpswaps(from->u.graphicsExposure.height, + to->u.graphicsExposure.height); + cpswaps(from->u.graphicsExposure.minorEvent, + to->u.graphicsExposure.minorEvent); + cpswaps(from->u.graphicsExposure.count, + to->u.graphicsExposure.count); + to->u.graphicsExposure.majorEvent = + from->u.graphicsExposure.majorEvent; +} + +void +SNoExposureEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.noExposure.drawable, to->u.noExposure.drawable); + cpswaps(from->u.noExposure.minorEvent, to->u.noExposure.minorEvent); + to->u.noExposure.majorEvent = from->u.noExposure.majorEvent; +} + +void +SVisibilityEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.visibility.window, to->u.visibility.window); + to->u.visibility.state = from->u.visibility.state; +} + +void +SCreateNotifyEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.createNotify.window, to->u.createNotify.window); + cpswapl(from->u.createNotify.parent, to->u.createNotify.parent); + cpswaps(from->u.createNotify.x, to->u.createNotify.x); + cpswaps(from->u.createNotify.y, to->u.createNotify.y); + cpswaps(from->u.createNotify.width, to->u.createNotify.width); + cpswaps(from->u.createNotify.height, to->u.createNotify.height); + cpswaps(from->u.createNotify.borderWidth, + to->u.createNotify.borderWidth); + to->u.createNotify.override = from->u.createNotify.override; +} + +void +SDestroyNotifyEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.destroyNotify.event, to->u.destroyNotify.event); + cpswapl(from->u.destroyNotify.window, to->u.destroyNotify.window); +} + +void +SUnmapNotifyEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.unmapNotify.event, to->u.unmapNotify.event); + cpswapl(from->u.unmapNotify.window, to->u.unmapNotify.window); + to->u.unmapNotify.fromConfigure = from->u.unmapNotify.fromConfigure; +} + +void +SMapNotifyEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.mapNotify.event, to->u.mapNotify.event); + cpswapl(from->u.mapNotify.window, to->u.mapNotify.window); + to->u.mapNotify.override = from->u.mapNotify.override; +} + +void +SMapRequestEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.mapRequest.parent, to->u.mapRequest.parent); + cpswapl(from->u.mapRequest.window, to->u.mapRequest.window); +} + +void +SReparentEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.reparent.event, to->u.reparent.event); + cpswapl(from->u.reparent.window, to->u.reparent.window); + cpswapl(from->u.reparent.parent, to->u.reparent.parent); + cpswaps(from->u.reparent.x, to->u.reparent.x); + cpswaps(from->u.reparent.y, to->u.reparent.y); + to->u.reparent.override = from->u.reparent.override; +} + +void +SConfigureNotifyEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.configureNotify.event, + to->u.configureNotify.event); + cpswapl(from->u.configureNotify.window, + to->u.configureNotify.window); + cpswapl(from->u.configureNotify.aboveSibling, + to->u.configureNotify.aboveSibling); + cpswaps(from->u.configureNotify.x, to->u.configureNotify.x); + cpswaps(from->u.configureNotify.y, to->u.configureNotify.y); + cpswaps(from->u.configureNotify.width, to->u.configureNotify.width); + cpswaps(from->u.configureNotify.height, + to->u.configureNotify.height); + cpswaps(from->u.configureNotify.borderWidth, + to->u.configureNotify.borderWidth); + to->u.configureNotify.override = from->u.configureNotify.override; +} + +void +SConfigureRequestEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; /* actually stack-mode */ + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.configureRequest.parent, + to->u.configureRequest.parent); + cpswapl(from->u.configureRequest.window, + to->u.configureRequest.window); + cpswapl(from->u.configureRequest.sibling, + to->u.configureRequest.sibling); + cpswaps(from->u.configureRequest.x, to->u.configureRequest.x); + cpswaps(from->u.configureRequest.y, to->u.configureRequest.y); + cpswaps(from->u.configureRequest.width, + to->u.configureRequest.width); + cpswaps(from->u.configureRequest.height, + to->u.configureRequest.height); + cpswaps(from->u.configureRequest.borderWidth, + to->u.configureRequest.borderWidth); + cpswaps(from->u.configureRequest.valueMask, + to->u.configureRequest.valueMask); +} + + +void +SGravityEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.gravity.event, to->u.gravity.event); + cpswapl(from->u.gravity.window, to->u.gravity.window); + cpswaps(from->u.gravity.x, to->u.gravity.x); + cpswaps(from->u.gravity.y, to->u.gravity.y); +} + +void +SResizeRequestEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.resizeRequest.window, to->u.resizeRequest.window); + cpswaps(from->u.resizeRequest.width, to->u.resizeRequest.width); + cpswaps(from->u.resizeRequest.height, to->u.resizeRequest.height); +} + +void +SCirculateEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.circulate.event, to->u.circulate.event); + cpswapl(from->u.circulate.window, to->u.circulate.window); + cpswapl(from->u.circulate.parent, to->u.circulate.parent); + to->u.circulate.place = from->u.circulate.place; +} + +void +SPropertyEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.property.window, to->u.property.window); + cpswapl(from->u.property.atom, to->u.property.atom); + cpswapl(from->u.property.time, to->u.property.time); + to->u.property.state = from->u.property.state; +} + +void +SSelectionClearEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.selectionClear.time, to->u.selectionClear.time); + cpswapl(from->u.selectionClear.window, to->u.selectionClear.window); + cpswapl(from->u.selectionClear.atom, to->u.selectionClear.atom); +} + +void +SSelectionRequestEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.selectionRequest.time, to->u.selectionRequest.time); + cpswapl(from->u.selectionRequest.owner, + to->u.selectionRequest.owner); + cpswapl(from->u.selectionRequest.requestor, + to->u.selectionRequest.requestor); + cpswapl(from->u.selectionRequest.selection, + to->u.selectionRequest.selection); + cpswapl(from->u.selectionRequest.target, + to->u.selectionRequest.target); + cpswapl(from->u.selectionRequest.property, + to->u.selectionRequest.property); +} + +void +SSelectionNotifyEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.selectionNotify.time, to->u.selectionNotify.time); + cpswapl(from->u.selectionNotify.requestor, + to->u.selectionNotify.requestor); + cpswapl(from->u.selectionNotify.selection, + to->u.selectionNotify.selection); + cpswapl(from->u.selectionNotify.target, + to->u.selectionNotify.target); + cpswapl(from->u.selectionNotify.property, + to->u.selectionNotify.property); +} + +void +SColormapEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.colormap.window, to->u.colormap.window); + cpswapl(from->u.colormap.colormap, to->u.colormap.colormap); + to->u.colormap.new = from->u.colormap.new; + to->u.colormap.state = from->u.colormap.state; +} + +void +SMappingEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + to->u.mappingNotify.request = from->u.mappingNotify.request; + to->u.mappingNotify.firstKeyCode = + from->u.mappingNotify.firstKeyCode; + to->u.mappingNotify.count = from->u.mappingNotify.count; +} + +void +SClientMessageEvent(xEvent *from, xEvent *to) +{ + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; /* actually format */ + cpswaps(from->u.u.sequenceNumber, to->u.u.sequenceNumber); + cpswapl(from->u.clientMessage.window, to->u.clientMessage.window); + cpswapl(from->u.clientMessage.u.l.type, + to->u.clientMessage.u.l.type); + switch (from->u.u.detail) { + case 8: + memmove(to->u.clientMessage.u.b.bytes, + from->u.clientMessage.u.b.bytes,20); + break; + case 16: + cpswaps(from->u.clientMessage.u.s.shorts0, + to->u.clientMessage.u.s.shorts0); + cpswaps(from->u.clientMessage.u.s.shorts1, + to->u.clientMessage.u.s.shorts1); + cpswaps(from->u.clientMessage.u.s.shorts2, + to->u.clientMessage.u.s.shorts2); + cpswaps(from->u.clientMessage.u.s.shorts3, + to->u.clientMessage.u.s.shorts3); + cpswaps(from->u.clientMessage.u.s.shorts4, + to->u.clientMessage.u.s.shorts4); + cpswaps(from->u.clientMessage.u.s.shorts5, + to->u.clientMessage.u.s.shorts5); + cpswaps(from->u.clientMessage.u.s.shorts6, + to->u.clientMessage.u.s.shorts6); + cpswaps(from->u.clientMessage.u.s.shorts7, + to->u.clientMessage.u.s.shorts7); + cpswaps(from->u.clientMessage.u.s.shorts8, + to->u.clientMessage.u.s.shorts8); + cpswaps(from->u.clientMessage.u.s.shorts9, + to->u.clientMessage.u.s.shorts9); + break; + case 32: + cpswapl(from->u.clientMessage.u.l.longs0, + to->u.clientMessage.u.l.longs0); + cpswapl(from->u.clientMessage.u.l.longs1, + to->u.clientMessage.u.l.longs1); + cpswapl(from->u.clientMessage.u.l.longs2, + to->u.clientMessage.u.l.longs2); + cpswapl(from->u.clientMessage.u.l.longs3, + to->u.clientMessage.u.l.longs3); + cpswapl(from->u.clientMessage.u.l.longs4, + to->u.clientMessage.u.l.longs4); + break; + } +} + +void +SKeymapNotifyEvent(xEvent *from, xEvent *to) +{ + /* Keymap notify events are special; they have no + sequence number field, and contain entirely 8-bit data */ + *to = *from; +} + +_X_EXPORT void +SwapConnSetupInfo( + char *pInfo, + char *pInfoT +) +{ + int i, j, k; + xConnSetup *pConnSetup = (xConnSetup *)pInfo; + xDepth *depth; + xWindowRoot *root; + + SwapConnSetup(pConnSetup, (xConnSetup *)pInfoT); + pInfo += sizeof(xConnSetup); + pInfoT += sizeof(xConnSetup); + + /* Copy the vendor string */ + i = (pConnSetup->nbytesVendor + 3) & ~3; + memcpy(pInfoT, pInfo, i); + pInfo += i; + pInfoT += i; + + /* The Pixmap formats don't need to be swapped, just copied. */ + i = sizeof(xPixmapFormat) * pConnSetup->numFormats; + memcpy(pInfoT, pInfo, i); + pInfo += i; + pInfoT += i; + + for(i = 0; i < pConnSetup->numRoots; i++) + { + root = (xWindowRoot*)pInfo; + SwapWinRoot(root, (xWindowRoot *)pInfoT); + pInfo += sizeof(xWindowRoot); + pInfoT += sizeof(xWindowRoot); + + for(j = 0; j < root->nDepths; j++) + { + depth = (xDepth*)pInfo; + ((xDepth *)pInfoT)->depth = depth->depth; + cpswaps(depth->nVisuals, ((xDepth *)pInfoT)->nVisuals); + pInfo += sizeof(xDepth); + pInfoT += sizeof(xDepth); + for(k = 0; k < depth->nVisuals; k++) + { + SwapVisual((xVisualType *)pInfo, (xVisualType *)pInfoT); + pInfo += sizeof(xVisualType); + pInfoT += sizeof(xVisualType); + } + } + } +} + + +void +WriteSConnectionInfo(ClientPtr pClient, unsigned long size, char *pInfo) +{ + char *pInfoTBase; + + pInfoTBase = (char *) ALLOCATE_LOCAL(size); + if (!pInfoTBase) + { + pClient->noClientException = -1; + return; + } + SwapConnSetupInfo(pInfo, pInfoTBase); + (void)WriteToClient(pClient, (int)size, (char *) pInfoTBase); + DEALLOCATE_LOCAL(pInfoTBase); +} + +void +SwapConnSetup(xConnSetup *pConnSetup, xConnSetup *pConnSetupT) +{ + cpswapl(pConnSetup->release, pConnSetupT->release); + cpswapl(pConnSetup->ridBase, pConnSetupT->ridBase); + cpswapl(pConnSetup->ridMask, pConnSetupT->ridMask); + cpswapl(pConnSetup->motionBufferSize, pConnSetupT->motionBufferSize); + cpswaps(pConnSetup->nbytesVendor, pConnSetupT->nbytesVendor); + cpswaps(pConnSetup->maxRequestSize, pConnSetupT->maxRequestSize); + pConnSetupT->minKeyCode = pConnSetup->minKeyCode; + pConnSetupT->maxKeyCode = pConnSetup->maxKeyCode; + pConnSetupT->numRoots = pConnSetup->numRoots; + pConnSetupT->numFormats = pConnSetup->numFormats; + pConnSetupT->imageByteOrder = pConnSetup->imageByteOrder; + pConnSetupT->bitmapBitOrder = pConnSetup->bitmapBitOrder; + pConnSetupT->bitmapScanlineUnit = pConnSetup->bitmapScanlineUnit; + pConnSetupT->bitmapScanlinePad = pConnSetup->bitmapScanlinePad; +} + +void +SwapWinRoot(xWindowRoot *pRoot, xWindowRoot *pRootT) +{ + cpswapl(pRoot->windowId, pRootT->windowId); + cpswapl(pRoot->defaultColormap, pRootT->defaultColormap); + cpswapl(pRoot->whitePixel, pRootT->whitePixel); + cpswapl(pRoot->blackPixel, pRootT->blackPixel); + cpswapl(pRoot->currentInputMask, pRootT->currentInputMask); + cpswaps(pRoot->pixWidth, pRootT->pixWidth); + cpswaps(pRoot->pixHeight, pRootT->pixHeight); + cpswaps(pRoot->mmWidth, pRootT->mmWidth); + cpswaps(pRoot->mmHeight, pRootT->mmHeight); + cpswaps(pRoot->minInstalledMaps, pRootT->minInstalledMaps); + cpswaps(pRoot->maxInstalledMaps, pRootT->maxInstalledMaps); + cpswapl(pRoot->rootVisualID, pRootT->rootVisualID); + pRootT->backingStore = pRoot->backingStore; + pRootT->saveUnders = pRoot->saveUnders; + pRootT->rootDepth = pRoot->rootDepth; + pRootT->nDepths = pRoot->nDepths; +} + +void +SwapVisual(xVisualType *pVis, xVisualType *pVisT) +{ + cpswapl(pVis->visualID, pVisT->visualID); + pVisT->class = pVis->class; + pVisT->bitsPerRGB = pVis->bitsPerRGB; + cpswaps(pVis->colormapEntries, pVisT->colormapEntries); + cpswapl(pVis->redMask, pVisT->redMask); + cpswapl(pVis->greenMask, pVisT->greenMask); + cpswapl(pVis->blueMask, pVisT->blueMask); +} + +_X_EXPORT void +SwapConnSetupPrefix(xConnSetupPrefix *pcspFrom, xConnSetupPrefix *pcspTo) +{ + pcspTo->success = pcspFrom->success; + pcspTo->lengthReason = pcspFrom->lengthReason; + cpswaps(pcspFrom->majorVersion, pcspTo->majorVersion); + cpswaps(pcspFrom->minorVersion, pcspTo->minorVersion); + cpswaps(pcspFrom->length, pcspTo->length); +} + +void +WriteSConnSetupPrefix(ClientPtr pClient, xConnSetupPrefix *pcsp) +{ + xConnSetupPrefix cspT; + + SwapConnSetupPrefix(pcsp, &cspT); + (void)WriteToClient(pClient, sizeof(cspT), (char *) &cspT); +} diff --git a/xserver/dix/swapreq.c b/xserver/dix/swapreq.c new file mode 100644 index 000000000..a6a211515 --- /dev/null +++ b/xserver/dix/swapreq.c @@ -0,0 +1,1100 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#define NEED_EVENTS +#include <X11/Xproto.h> +#include <X11/Xprotostr.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" /* for SendEvent */ +#include "swapreq.h" + +/* Thanks to Jack Palevich for testing and subsequently rewriting all this */ + +/* Byte swap a list of longs */ +_X_EXPORT void +SwapLongs (register CARD32 *list, register unsigned long count) +{ + register char n; + + while (count >= 8) { + swapl(list+0, n); + swapl(list+1, n); + swapl(list+2, n); + swapl(list+3, n); + swapl(list+4, n); + swapl(list+5, n); + swapl(list+6, n); + swapl(list+7, n); + list += 8; + count -= 8; + } + if (count != 0) { + do { + swapl(list, n); + list++; + } while (--count != 0); + } +} + +/* Byte swap a list of shorts */ +_X_EXPORT void +SwapShorts (register short *list, register unsigned long count) +{ + register char n; + + while (count >= 16) { + swaps(list+0, n); + swaps(list+1, n); + swaps(list+2, n); + swaps(list+3, n); + swaps(list+4, n); + swaps(list+5, n); + swaps(list+6, n); + swaps(list+7, n); + swaps(list+8, n); + swaps(list+9, n); + swaps(list+10, n); + swaps(list+11, n); + swaps(list+12, n); + swaps(list+13, n); + swaps(list+14, n); + swaps(list+15, n); + list += 16; + count -= 16; + } + if (count != 0) { + do { + swaps(list, n); + list++; + } while (--count != 0); + } +} + +/* The following is used for all requests that have + no fields to be swapped (except "length") */ +int +SProcSimpleReq(register ClientPtr client) +{ + register char n; + + REQUEST(xReq); + swaps(&stuff->length, n); + return(*ProcVector[stuff->reqType])(client); +} + +/* The following is used for all requests that have + only a single 32-bit field to be swapped, coming + right after the "length" field */ +int +SProcResourceReq(register ClientPtr client) +{ + register char n; + + REQUEST(xResourceReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xResourceReq); /* not EXACT */ + swapl(&stuff->id, n); + return(*ProcVector[stuff->reqType])(client); +} + +int +SProcCreateWindow(register ClientPtr client) +{ + register char n; + + REQUEST(xCreateWindowReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + swapl(&stuff->wid, n); + swapl(&stuff->parent, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swaps(&stuff->borderWidth, n); + swaps(&stuff->class, n); + swapl(&stuff->visual, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_CreateWindow])(client)); +} + +int +SProcChangeWindowAttributes(register ClientPtr client) +{ + register char n; + + REQUEST(xChangeWindowAttributesReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + swapl(&stuff->window, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + return((* ProcVector[X_ChangeWindowAttributes])(client)); +} + +int +SProcReparentWindow(register ClientPtr client) +{ + register char n; + REQUEST(xReparentWindowReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xReparentWindowReq); + swapl(&stuff->window, n); + swapl(&stuff->parent, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return((* ProcVector[X_ReparentWindow])(client)); +} + +int +SProcConfigureWindow(register ClientPtr client) +{ + register char n; + REQUEST(xConfigureWindowReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + swapl(&stuff->window, n); + swaps(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_ConfigureWindow])(client)); + +} + + +int +SProcInternAtom(register ClientPtr client) +{ + register char n; + REQUEST(xInternAtomReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xInternAtomReq); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_InternAtom])(client)); +} + +int +SProcChangeProperty(register ClientPtr client) +{ + register char n; + REQUEST(xChangePropertyReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + switch ( stuff->format ) { + case 8 : + break; + case 16: + SwapRestS(stuff); + break; + case 32: + SwapRestL(stuff); + break; + } + return((* ProcVector[X_ChangeProperty])(client)); +} + +int +SProcDeleteProperty(register ClientPtr client) +{ + register char n; + REQUEST(xDeletePropertyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDeletePropertyReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + return((* ProcVector[X_DeleteProperty])(client)); + +} + +int +SProcGetProperty(register ClientPtr client) +{ + register char n; + REQUEST(xGetPropertyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetPropertyReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + return((* ProcVector[X_GetProperty])(client)); +} + +int +SProcSetSelectionOwner(register ClientPtr client) +{ + register char n; + REQUEST(xSetSelectionOwnerReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + swapl(&stuff->window, n); + swapl(&stuff->selection, n); + swapl(&stuff->time, n); + return((* ProcVector[X_SetSelectionOwner])(client)); +} + +int +SProcConvertSelection(register ClientPtr client) +{ + register char n; + REQUEST(xConvertSelectionReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xConvertSelectionReq); + swapl(&stuff->requestor, n); + swapl(&stuff->selection, n); + swapl(&stuff->target, n); + swapl(&stuff->property, n); + swapl(&stuff->time, n); + return((* ProcVector[X_ConvertSelection])(client)); +} + +int +SProcSendEvent(register ClientPtr client) +{ + register char n; + xEvent eventT; + EventSwapPtr proc; + REQUEST(xSendEventReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSendEventReq); + swapl(&stuff->destination, n); + swapl(&stuff->eventMask, n); + + /* Swap event */ + proc = EventSwapVector[stuff->event.u.u.type & 0177]; + if (!proc || proc == NotImplemented) /* no swapping proc; invalid event type? */ + return (BadValue); + (*proc)(&stuff->event, &eventT); + stuff->event = eventT; + + return((* ProcVector[X_SendEvent])(client)); +} + +int +SProcGrabPointer(register ClientPtr client) +{ + register char n; + REQUEST(xGrabPointerReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGrabPointerReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->eventMask, n); + swapl(&stuff->confineTo, n); + swapl(&stuff->cursor, n); + swapl(&stuff->time, n); + return((* ProcVector[X_GrabPointer])(client)); +} + +int +SProcGrabButton(register ClientPtr client) +{ + register char n; + REQUEST(xGrabButtonReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGrabButtonReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->eventMask, n); + swapl(&stuff->confineTo, n); + swapl(&stuff->cursor, n); + swaps(&stuff->modifiers, n); + return((* ProcVector[X_GrabButton])(client)); +} + +int +SProcUngrabButton(register ClientPtr client) +{ + register char n; + REQUEST(xUngrabButtonReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xUngrabButtonReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + return((* ProcVector[X_UngrabButton])(client)); +} + +int +SProcChangeActivePointerGrab(register ClientPtr client) +{ + register char n; + REQUEST(xChangeActivePointerGrabReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + swapl(&stuff->cursor, n); + swapl(&stuff->time, n); + swaps(&stuff->eventMask, n); + return((* ProcVector[X_ChangeActivePointerGrab])(client)); +} + +int +SProcGrabKeyboard(register ClientPtr client) +{ + register char n; + REQUEST(xGrabKeyboardReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGrabKeyboardReq); + swapl(&stuff->grabWindow, n); + swapl(&stuff->time, n); + return((* ProcVector[X_GrabKeyboard])(client)); +} + +int +SProcGrabKey(register ClientPtr client) +{ + register char n; + REQUEST(xGrabKeyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGrabKeyReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + return((* ProcVector[X_GrabKey])(client)); +} + +int +SProcUngrabKey(register ClientPtr client) +{ + register char n; + REQUEST(xUngrabKeyReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xUngrabKeyReq); + swapl(&stuff->grabWindow, n); + swaps(&stuff->modifiers, n); + return((* ProcVector[X_UngrabKey])(client)); +} + +int +SProcGetMotionEvents(register ClientPtr client) +{ + register char n; + REQUEST(xGetMotionEventsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetMotionEventsReq); + swapl(&stuff->window, n); + swapl(&stuff->start, n); + swapl(&stuff->stop, n); + return((* ProcVector[X_GetMotionEvents])(client)); +} + +int +SProcTranslateCoords(register ClientPtr client) +{ + register char n; + REQUEST(xTranslateCoordsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + swapl(&stuff->srcWid, n); + swapl(&stuff->dstWid, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + return((* ProcVector[X_TranslateCoords])(client)); +} + +int +SProcWarpPointer(register ClientPtr client) +{ + register char n; + REQUEST(xWarpPointerReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xWarpPointerReq); + swapl(&stuff->srcWid, n); + swapl(&stuff->dstWid, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + return((* ProcVector[X_WarpPointer])(client)); +} + +int +SProcSetInputFocus(register ClientPtr client) +{ + register char n; + REQUEST(xSetInputFocusReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSetInputFocusReq); + swapl(&stuff->focus, n); + swapl(&stuff->time, n); + return((* ProcVector[X_SetInputFocus])(client)); +} + +int +SProcOpenFont(register ClientPtr client) +{ + register char n; + REQUEST(xOpenFontReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xOpenFontReq); + swapl(&stuff->fid, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_OpenFont])(client)); +} + +int +SProcListFonts(register ClientPtr client) +{ + register char n; + REQUEST(xListFontsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xListFontsReq); + swaps(&stuff->maxNames, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_ListFonts])(client)); +} + +int +SProcListFontsWithInfo(register ClientPtr client) +{ + register char n; + REQUEST(xListFontsWithInfoReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xListFontsWithInfoReq); + swaps(&stuff->maxNames, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_ListFontsWithInfo])(client)); +} + +int +SProcSetFontPath(register ClientPtr client) +{ + register char n; + REQUEST(xSetFontPathReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + swaps(&stuff->nFonts, n); + return((* ProcVector[X_SetFontPath])(client)); +} + +int +SProcCreatePixmap(register ClientPtr client) +{ + register char n; + REQUEST(xCreatePixmapReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCreatePixmapReq); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return((* ProcVector[X_CreatePixmap])(client)); +} + +int +SProcCreateGC(register ClientPtr client) +{ + register char n; + REQUEST(xCreateGCReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + swapl(&stuff->gc, n); + swapl(&stuff->drawable, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_CreateGC])(client)); +} + +int +SProcChangeGC(register ClientPtr client) +{ + register char n; + REQUEST(xChangeGCReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + swapl(&stuff->gc, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_ChangeGC])(client)); +} + +int +SProcCopyGC(register ClientPtr client) +{ + register char n; + REQUEST(xCopyGCReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCopyGCReq); + swapl(&stuff->srcGC, n); + swapl(&stuff->dstGC, n); + swapl(&stuff->mask, n); + return((* ProcVector[X_CopyGC])(client)); +} + +int +SProcSetDashes(register ClientPtr client) +{ + register char n; + REQUEST(xSetDashesReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSetDashesReq); + swapl(&stuff->gc, n); + swaps(&stuff->dashOffset, n); + swaps(&stuff->nDashes, n); + return((* ProcVector[X_SetDashes])(client)); + +} + +int +SProcSetClipRectangles(register ClientPtr client) +{ + register char n; + REQUEST(xSetClipRectanglesReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + swapl(&stuff->gc, n); + swaps(&stuff->xOrigin, n); + swaps(&stuff->yOrigin, n); + SwapRestS(stuff); + return((* ProcVector[X_SetClipRectangles])(client)); +} + +int +SProcClearToBackground(register ClientPtr client) +{ + register char n; + REQUEST(xClearAreaReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xClearAreaReq); + swapl(&stuff->window, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return((* ProcVector[X_ClearArea])(client)); +} + +int +SProcCopyArea(register ClientPtr client) +{ + register char n; + REQUEST(xCopyAreaReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCopyAreaReq); + swapl(&stuff->srcDrawable, n); + swapl(&stuff->dstDrawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return((* ProcVector[X_CopyArea])(client)); +} + +int +SProcCopyPlane(register ClientPtr client) +{ + register char n; + REQUEST(xCopyPlaneReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCopyPlaneReq); + swapl(&stuff->srcDrawable, n); + swapl(&stuff->dstDrawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->bitPlane, n); + return((* ProcVector[X_CopyPlane])(client)); +} + +/* The following routine is used for all Poly drawing requests + (except FillPoly, which uses a different request format) */ +int +SProcPoly(register ClientPtr client) +{ + register char n; + + REQUEST(xPolyPointReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + SwapRestS(stuff); + return((* ProcVector[stuff->reqType])(client)); +} + +/* cannot use SProcPoly for this one, because xFillPolyReq + is longer than xPolyPointReq, and we don't want to swap + the difference as shorts! */ +int +SProcFillPoly(register ClientPtr client) +{ + register char n; + + REQUEST(xFillPolyReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + SwapRestS(stuff); + return((* ProcVector[X_FillPoly])(client)); +} + +int +SProcPutImage(register ClientPtr client) +{ + register char n; + REQUEST(xPutImageReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + /* Image should already be swapped */ + return((* ProcVector[X_PutImage])(client)); + +} + +int +SProcGetImage(register ClientPtr client) +{ + register char n; + REQUEST(xGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + return((* ProcVector[X_GetImage])(client)); +} + +/* ProcPolyText used for both PolyText8 and PolyText16 */ + +int +SProcPolyText(register ClientPtr client) +{ + register char n; + REQUEST(xPolyTextReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return((* ProcVector[stuff->reqType])(client)); +} + +/* ProcImageText used for both ImageText8 and ImageText16 */ + +int +SProcImageText(register ClientPtr client) +{ + register char n; + REQUEST(xImageTextReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xImageTextReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return((* ProcVector[stuff->reqType])(client)); +} + +int +SProcCreateColormap(register ClientPtr client) +{ + register char n; + REQUEST(xCreateColormapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCreateColormapReq); + swapl(&stuff->mid, n); + swapl(&stuff->window, n); + swapl(&stuff->visual, n); + return((* ProcVector[X_CreateColormap])(client)); +} + + +int +SProcCopyColormapAndFree(register ClientPtr client) +{ + register char n; + REQUEST(xCopyColormapAndFreeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + swapl(&stuff->mid, n); + swapl(&stuff->srcCmap, n); + return((* ProcVector[X_CopyColormapAndFree])(client)); + +} + +int +SProcAllocColor(register ClientPtr client) +{ + register char n; + REQUEST(xAllocColorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xAllocColorReq); + swapl(&stuff->cmap, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + return((* ProcVector[X_AllocColor])(client)); +} + +int +SProcAllocNamedColor(register ClientPtr client) +{ + register char n; + + REQUEST(xAllocNamedColorReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xAllocNamedColorReq); + swapl(&stuff->cmap, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_AllocNamedColor])(client)); +} + +int +SProcAllocColorCells(register ClientPtr client) +{ + register char n; + REQUEST(xAllocColorCellsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + swapl(&stuff->cmap, n); + swaps(&stuff->colors, n); + swaps(&stuff->planes, n); + return((* ProcVector[X_AllocColorCells])(client)); +} + +int +SProcAllocColorPlanes(register ClientPtr client) +{ + register char n; + REQUEST(xAllocColorPlanesReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + swapl(&stuff->cmap, n); + swaps(&stuff->colors, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + return((* ProcVector[X_AllocColorPlanes])(client)); +} + +int +SProcFreeColors(register ClientPtr client) +{ + register char n; + REQUEST(xFreeColorsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + swapl(&stuff->cmap, n); + swapl(&stuff->planeMask, n); + SwapRestL(stuff); + return((* ProcVector[X_FreeColors])(client)); + +} + +_X_EXPORT void +SwapColorItem(xColorItem *pItem) +{ + register char n; + + swapl(&pItem->pixel, n); + swaps(&pItem->red, n); + swaps(&pItem->green, n); + swaps(&pItem->blue, n); +} + +int +SProcStoreColors(register ClientPtr client) +{ + register char n; + long count; + xColorItem *pItem; + + REQUEST(xStoreColorsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + swapl(&stuff->cmap, n); + pItem = (xColorItem *) &stuff[1]; + for(count = LengthRestB(stuff)/sizeof(xColorItem); --count >= 0; ) + SwapColorItem(pItem++); + return((* ProcVector[X_StoreColors])(client)); +} + +int +SProcStoreNamedColor (register ClientPtr client) +{ + register char n; + REQUEST(xStoreNamedColorReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xStoreNamedColorReq); + swapl(&stuff->cmap, n); + swapl(&stuff->pixel, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_StoreNamedColor])(client)); +} + +int +SProcQueryColors (register ClientPtr client) +{ + register char n; + REQUEST(xQueryColorsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + swapl(&stuff->cmap, n); + SwapRestL(stuff); + return((* ProcVector[X_QueryColors])(client)); +} + +int +SProcLookupColor (register ClientPtr client) +{ + register char n; + REQUEST(xLookupColorReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xLookupColorReq); + swapl(&stuff->cmap, n); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_LookupColor])(client)); +} + +int +SProcCreateCursor (register ClientPtr client) +{ + register char n; + REQUEST(xCreateCursorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCreateCursorReq); + swapl(&stuff->cid, n); + swapl(&stuff->source, n); + swapl(&stuff->mask, n); + swaps(&stuff->foreRed, n); + swaps(&stuff->foreGreen, n); + swaps(&stuff->foreBlue, n); + swaps(&stuff->backRed, n); + swaps(&stuff->backGreen, n); + swaps(&stuff->backBlue, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return((* ProcVector[X_CreateCursor])(client)); +} + +int +SProcCreateGlyphCursor (register ClientPtr client) +{ + register char n; + REQUEST(xCreateGlyphCursorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + swapl(&stuff->cid, n); + swapl(&stuff->source, n); + swapl(&stuff->mask, n); + swaps(&stuff->sourceChar, n); + swaps(&stuff->maskChar, n); + swaps(&stuff->foreRed, n); + swaps(&stuff->foreGreen, n); + swaps(&stuff->foreBlue, n); + swaps(&stuff->backRed, n); + swaps(&stuff->backGreen, n); + swaps(&stuff->backBlue, n); + return((* ProcVector[X_CreateGlyphCursor])(client)); +} + + +int +SProcRecolorCursor (register ClientPtr client) +{ + register char n; + REQUEST(xRecolorCursorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecolorCursorReq); + swapl(&stuff->cursor, n); + swaps(&stuff->foreRed, n); + swaps(&stuff->foreGreen, n); + swaps(&stuff->foreBlue, n); + swaps(&stuff->backRed, n); + swaps(&stuff->backGreen, n); + swaps(&stuff->backBlue, n); + return((* ProcVector[X_RecolorCursor])(client)); +} + +int +SProcQueryBestSize (register ClientPtr client) +{ + register char n; + REQUEST(xQueryBestSizeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return((* ProcVector[X_QueryBestSize])(client)); + +} + +int +SProcQueryExtension (register ClientPtr client) +{ + register char n; + REQUEST(xQueryExtensionReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xQueryExtensionReq); + swaps(&stuff->nbytes, n); + return((* ProcVector[X_QueryExtension])(client)); +} + +int +SProcChangeKeyboardMapping (register ClientPtr client) +{ + register char n; + REQUEST(xChangeKeyboardMappingReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); + SwapRestL(stuff); + return((* ProcVector[X_ChangeKeyboardMapping])(client)); +} + + +int +SProcChangeKeyboardControl (register ClientPtr client) +{ + register char n; + REQUEST(xChangeKeyboardControlReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return((* ProcVector[X_ChangeKeyboardControl])(client)); +} + +int +SProcChangePointerControl (register ClientPtr client) +{ + register char n; + REQUEST(xChangePointerControlReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xChangePointerControlReq); + swaps(&stuff->accelNum, n); + swaps(&stuff->accelDenum, n); + swaps(&stuff->threshold, n); + return((* ProcVector[X_ChangePointerControl])(client)); +} + + +int +SProcSetScreenSaver (register ClientPtr client) +{ + register char n; + REQUEST(xSetScreenSaverReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + swaps(&stuff->timeout, n); + swaps(&stuff->interval, n); + return((* ProcVector[X_SetScreenSaver])(client)); +} + +int +SProcChangeHosts (register ClientPtr client) +{ + register char n; + + REQUEST(xChangeHostsReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xChangeHostsReq); + swaps(&stuff->hostLength, n); + return((* ProcVector[X_ChangeHosts])(client)); + +} + +int SProcRotateProperties (register ClientPtr client) +{ + register char n; + REQUEST(xRotatePropertiesReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xRotatePropertiesReq); + swapl(&stuff->window, n); + swaps(&stuff->nAtoms, n); + swaps(&stuff->nPositions, n); + SwapRestL(stuff); + return ((* ProcVector[X_RotateProperties])(client)); +} + +int +SProcNoOperation(register ClientPtr client) +{ + register char n; + REQUEST(xReq); + swaps(&stuff->length, n); + return ((* ProcVector[X_NoOperation])(client)); +} + +void +SwapConnClientPrefix(xConnClientPrefix *pCCP) +{ + register char n; + + swaps(&pCCP->majorVersion, n); + swaps(&pCCP->minorVersion, n); + swaps(&pCCP->nbytesAuthProto, n); + swaps(&pCCP->nbytesAuthString, n); +} diff --git a/xserver/dix/tables.c b/xserver/dix/tables.c new file mode 100644 index 000000000..258ac0370 --- /dev/null +++ b/xserver/dix/tables.c @@ -0,0 +1,527 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xproto.h> +#include "windowstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "dixevents.h" +#include "dispatch.h" +#include "swaprep.h" +#include "swapreq.h" + +#ifdef K5AUTH +extern int + k5_stage1(), k5_stage2(), k5_stage3(), k5_bad(); +#endif + +int (* InitialVector[3]) ( + ClientPtr /* client */ + ) = +{ + 0, + ProcInitialConnection, + ProcEstablishConnection +}; + +_X_EXPORT int (* ProcVector[256]) ( + ClientPtr /* client */ + ) = +{ + ProcBadRequest, + ProcCreateWindow, + ProcChangeWindowAttributes, + ProcGetWindowAttributes, + ProcDestroyWindow, + ProcDestroySubwindows, /* 5 */ + ProcChangeSaveSet, + ProcReparentWindow, + ProcMapWindow, + ProcMapSubwindows, + ProcUnmapWindow, /* 10 */ + ProcUnmapSubwindows, + ProcConfigureWindow, + ProcCirculateWindow, + ProcGetGeometry, + ProcQueryTree, /* 15 */ + ProcInternAtom, + ProcGetAtomName, + ProcChangeProperty, + ProcDeleteProperty, + ProcGetProperty, /* 20 */ + ProcListProperties, + ProcSetSelectionOwner, + ProcGetSelectionOwner, + ProcConvertSelection, + ProcSendEvent, /* 25 */ + ProcGrabPointer, + ProcUngrabPointer, + ProcGrabButton, + ProcUngrabButton, + ProcChangeActivePointerGrab, /* 30 */ + ProcGrabKeyboard, + ProcUngrabKeyboard, + ProcGrabKey, + ProcUngrabKey, + ProcAllowEvents, /* 35 */ + ProcGrabServer, + ProcUngrabServer, + ProcQueryPointer, + ProcGetMotionEvents, + ProcTranslateCoords, /* 40 */ + ProcWarpPointer, + ProcSetInputFocus, + ProcGetInputFocus, + ProcQueryKeymap, + ProcOpenFont, /* 45 */ + ProcCloseFont, + ProcQueryFont, + ProcQueryTextExtents, + ProcListFonts, + ProcListFontsWithInfo, /* 50 */ + ProcSetFontPath, + ProcGetFontPath, + ProcCreatePixmap, + ProcFreePixmap, + ProcCreateGC, /* 55 */ + ProcChangeGC, + ProcCopyGC, + ProcSetDashes, + ProcSetClipRectangles, + ProcFreeGC, /* 60 */ + ProcClearToBackground, + ProcCopyArea, + ProcCopyPlane, + ProcPolyPoint, + ProcPolyLine, /* 65 */ + ProcPolySegment, + ProcPolyRectangle, + ProcPolyArc, + ProcFillPoly, + ProcPolyFillRectangle, /* 70 */ + ProcPolyFillArc, + ProcPutImage, + ProcGetImage, + ProcPolyText, + ProcPolyText, /* 75 */ + ProcImageText8, + ProcImageText16, + ProcCreateColormap, + ProcFreeColormap, + ProcCopyColormapAndFree, /* 80 */ + ProcInstallColormap, + ProcUninstallColormap, + ProcListInstalledColormaps, + ProcAllocColor, + ProcAllocNamedColor, /* 85 */ + ProcAllocColorCells, + ProcAllocColorPlanes, + ProcFreeColors, + ProcStoreColors, + ProcStoreNamedColor, /* 90 */ + ProcQueryColors, + ProcLookupColor, + ProcCreateCursor, + ProcCreateGlyphCursor, + ProcFreeCursor, /* 95 */ + ProcRecolorCursor, + ProcQueryBestSize, + ProcQueryExtension, + ProcListExtensions, + ProcChangeKeyboardMapping, /* 100 */ + ProcGetKeyboardMapping, + ProcChangeKeyboardControl, + ProcGetKeyboardControl, + ProcBell, + ProcChangePointerControl, /* 105 */ + ProcGetPointerControl, + ProcSetScreenSaver, + ProcGetScreenSaver, + ProcChangeHosts, + ProcListHosts, /* 110 */ + ProcChangeAccessControl, + ProcChangeCloseDownMode, + ProcKillClient, + ProcRotateProperties, + ProcForceScreenSaver, /* 115 */ + ProcSetPointerMapping, + ProcGetPointerMapping, + ProcSetModifierMapping, + ProcGetModifierMapping, + 0, /* 120 */ + 0, + 0, + 0, + 0, + 0, /* 125 */ + 0, + ProcNoOperation +}; + +int (* SwappedProcVector[256]) ( + ClientPtr /* client */ + ) = +{ + ProcBadRequest, + SProcCreateWindow, + SProcChangeWindowAttributes, + SProcResourceReq, /* GetWindowAttributes */ + SProcResourceReq, /* DestroyWindow */ + SProcResourceReq, /* 5 DestroySubwindows */ + SProcResourceReq, /* SProcChangeSaveSet, */ + SProcReparentWindow, + SProcResourceReq, /* MapWindow */ + SProcResourceReq, /* MapSubwindows */ + SProcResourceReq, /* 10 UnmapWindow */ + SProcResourceReq, /* UnmapSubwindows */ + SProcConfigureWindow, + SProcResourceReq, /* SProcCirculateWindow, */ + SProcResourceReq, /* GetGeometry */ + SProcResourceReq, /* 15 QueryTree */ + SProcInternAtom, + SProcResourceReq, /* SProcGetAtomName, */ + SProcChangeProperty, + SProcDeleteProperty, + SProcGetProperty, /* 20 */ + SProcResourceReq, /* SProcListProperties, */ + SProcSetSelectionOwner, + SProcResourceReq, /* SProcGetSelectionOwner, */ + SProcConvertSelection, + SProcSendEvent, /* 25 */ + SProcGrabPointer, + SProcResourceReq, /* SProcUngrabPointer, */ + SProcGrabButton, + SProcUngrabButton, + SProcChangeActivePointerGrab, /* 30 */ + SProcGrabKeyboard, + SProcResourceReq, /* SProcUngrabKeyboard, */ + SProcGrabKey, + SProcUngrabKey, + SProcResourceReq, /* 35 SProcAllowEvents, */ + SProcSimpleReq, /* SProcGrabServer, */ + SProcSimpleReq, /* SProcUngrabServer, */ + SProcResourceReq, /* SProcQueryPointer, */ + SProcGetMotionEvents, + SProcTranslateCoords, /*40 */ + SProcWarpPointer, + SProcSetInputFocus, + SProcSimpleReq, /* SProcGetInputFocus, */ + SProcSimpleReq, /* QueryKeymap, */ + SProcOpenFont, /* 45 */ + SProcResourceReq, /* SProcCloseFont, */ + SProcResourceReq, /* SProcQueryFont, */ + SProcResourceReq, /* SProcQueryTextExtents, */ + SProcListFonts, + SProcListFontsWithInfo, /* 50 */ + SProcSetFontPath, + SProcSimpleReq, /* GetFontPath, */ + SProcCreatePixmap, + SProcResourceReq, /* SProcFreePixmap, */ + SProcCreateGC, /* 55 */ + SProcChangeGC, + SProcCopyGC, + SProcSetDashes, + SProcSetClipRectangles, + SProcResourceReq, /* 60 SProcFreeGC, */ + SProcClearToBackground, + SProcCopyArea, + SProcCopyPlane, + SProcPoly, /* PolyPoint, */ + SProcPoly, /* 65 PolyLine */ + SProcPoly, /* PolySegment, */ + SProcPoly, /* PolyRectangle, */ + SProcPoly, /* PolyArc, */ + SProcFillPoly, + SProcPoly, /* 70 PolyFillRectangle */ + SProcPoly, /* PolyFillArc, */ + SProcPutImage, + SProcGetImage, + SProcPolyText, + SProcPolyText, /* 75 */ + SProcImageText, + SProcImageText, + SProcCreateColormap, + SProcResourceReq, /* SProcFreeColormap, */ + SProcCopyColormapAndFree, /* 80 */ + SProcResourceReq, /* SProcInstallColormap, */ + SProcResourceReq, /* SProcUninstallColormap, */ + SProcResourceReq, /* SProcListInstalledColormaps, */ + SProcAllocColor, + SProcAllocNamedColor, /* 85 */ + SProcAllocColorCells, + SProcAllocColorPlanes, + SProcFreeColors, + SProcStoreColors, + SProcStoreNamedColor, /* 90 */ + SProcQueryColors, + SProcLookupColor, + SProcCreateCursor, + SProcCreateGlyphCursor, + SProcResourceReq, /* 95 SProcFreeCursor, */ + SProcRecolorCursor, + SProcQueryBestSize, + SProcQueryExtension, + SProcSimpleReq, /* ListExtensions, */ + SProcChangeKeyboardMapping, /* 100 */ + SProcSimpleReq, /* GetKeyboardMapping, */ + SProcChangeKeyboardControl, + SProcSimpleReq, /* GetKeyboardControl, */ + SProcSimpleReq, /* Bell, */ + SProcChangePointerControl, /* 105 */ + SProcSimpleReq, /* GetPointerControl, */ + SProcSetScreenSaver, + SProcSimpleReq, /* GetScreenSaver, */ + SProcChangeHosts, + SProcSimpleReq, /* 110 ListHosts, */ + SProcSimpleReq, /* SProcChangeAccessControl, */ + SProcSimpleReq, /* SProcChangeCloseDownMode, */ + SProcResourceReq, /* SProcKillClient, */ + SProcRotateProperties, + SProcSimpleReq, /* 115 ForceScreenSaver */ + SProcSimpleReq, /* SetPointerMapping, */ + SProcSimpleReq, /* GetPointerMapping, */ + SProcSimpleReq, /* SetModifierMapping, */ + SProcSimpleReq, /* GetModifierMapping, */ + 0, /* 120 */ + 0, + 0, + 0, + 0, + 0, /* 125 */ + 0, + SProcNoOperation +}; + +_X_EXPORT EventSwapPtr EventSwapVector[128] = +{ + (EventSwapPtr)SErrorEvent, + NotImplemented, + SKeyButtonPtrEvent, + SKeyButtonPtrEvent, + SKeyButtonPtrEvent, + SKeyButtonPtrEvent, /* 5 */ + SKeyButtonPtrEvent, + SEnterLeaveEvent, + SEnterLeaveEvent, + SFocusEvent, + SFocusEvent, /* 10 */ + SKeymapNotifyEvent, + SExposeEvent, + SGraphicsExposureEvent, + SNoExposureEvent, + SVisibilityEvent, /* 15 */ + SCreateNotifyEvent, + SDestroyNotifyEvent, + SUnmapNotifyEvent, + SMapNotifyEvent, + SMapRequestEvent, /* 20 */ + SReparentEvent, + SConfigureNotifyEvent, + SConfigureRequestEvent, + SGravityEvent, + SResizeRequestEvent, /* 25 */ + SCirculateEvent, + SCirculateEvent, + SPropertyEvent, + SSelectionClearEvent, + SSelectionRequestEvent, /* 30 */ + SSelectionNotifyEvent, + SColormapEvent, + SClientMessageEvent, + SMappingEvent, +}; + + +_X_EXPORT ReplySwapPtr ReplySwapVector[256] = +{ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + (ReplySwapPtr)SGetWindowAttributesReply, + ReplyNotSwappd, + ReplyNotSwappd, /* 5 */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 10 */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + (ReplySwapPtr)SGetGeometryReply, + (ReplySwapPtr)SQueryTreeReply, /* 15 */ + (ReplySwapPtr)SInternAtomReply, + (ReplySwapPtr)SGetAtomNameReply, + ReplyNotSwappd, + ReplyNotSwappd, + (ReplySwapPtr)SGetPropertyReply, /* 20 */ + (ReplySwapPtr)SListPropertiesReply, + ReplyNotSwappd, + (ReplySwapPtr)SGetSelectionOwnerReply, + ReplyNotSwappd, + ReplyNotSwappd, /* 25 */ + (ReplySwapPtr)SGenericReply, /* SGrabPointerReply, */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 30 */ + (ReplySwapPtr)SGenericReply, /* SGrabKeyboardReply, */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 35 */ + ReplyNotSwappd, + ReplyNotSwappd, + (ReplySwapPtr)SQueryPointerReply, + (ReplySwapPtr)SGetMotionEventsReply, + (ReplySwapPtr)STranslateCoordsReply, /* 40 */ + ReplyNotSwappd, + ReplyNotSwappd, + (ReplySwapPtr)SGetInputFocusReply, + (ReplySwapPtr)SQueryKeymapReply, + ReplyNotSwappd, /* 45 */ + ReplyNotSwappd, + (ReplySwapPtr)SQueryFontReply, + (ReplySwapPtr)SQueryTextExtentsReply, + (ReplySwapPtr)SListFontsReply, + (ReplySwapPtr)SListFontsWithInfoReply, /* 50 */ + ReplyNotSwappd, + (ReplySwapPtr)SGetFontPathReply, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 55 */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 60 */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 65 */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 70 */ + ReplyNotSwappd, + ReplyNotSwappd, + (ReplySwapPtr)SGetImageReply, + ReplyNotSwappd, + ReplyNotSwappd, /* 75 */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 80 */ + ReplyNotSwappd, + ReplyNotSwappd, + (ReplySwapPtr)SListInstalledColormapsReply, + (ReplySwapPtr)SAllocColorReply, + (ReplySwapPtr)SAllocNamedColorReply, /* 85 */ + (ReplySwapPtr)SAllocColorCellsReply, + (ReplySwapPtr)SAllocColorPlanesReply, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 90 */ + (ReplySwapPtr)SQueryColorsReply, + (ReplySwapPtr)SLookupColorReply, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 95 */ + ReplyNotSwappd, + (ReplySwapPtr)SQueryBestSizeReply, + (ReplySwapPtr)SGenericReply, /* SQueryExtensionReply, */ + (ReplySwapPtr)SListExtensionsReply, + ReplyNotSwappd, /* 100 */ + (ReplySwapPtr)SGetKeyboardMappingReply, + ReplyNotSwappd, + (ReplySwapPtr)SGetKeyboardControlReply, + ReplyNotSwappd, + ReplyNotSwappd, /* 105 */ + (ReplySwapPtr)SGetPointerControlReply, + ReplyNotSwappd, + (ReplySwapPtr)SGetScreenSaverReply, + ReplyNotSwappd, + (ReplySwapPtr)SListHostsReply, /* 110 */ + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, /* 115 */ + (ReplySwapPtr)SGenericReply, /* SetPointerMapping */ + (ReplySwapPtr)SGetPointerMappingReply, + (ReplySwapPtr)SGenericReply, /* SetModifierMapping */ + (ReplySwapPtr)SGetModifierMappingReply, /* 119 */ + ReplyNotSwappd, /* 120 */ + ReplyNotSwappd, /* 121 */ + ReplyNotSwappd, /* 122 */ + ReplyNotSwappd, /* 123 */ + ReplyNotSwappd, /* 124 */ + ReplyNotSwappd, /* 125 */ + ReplyNotSwappd, /* 126 */ + ReplyNotSwappd, /* NoOperation */ + ReplyNotSwappd +}; + +#ifdef K5AUTH +int (*k5_Vector[256])() = +{ + k5_bad, + k5_stage1, + k5_bad, + k5_stage3 +}; +#endif diff --git a/xserver/dix/window.c b/xserver/dix/window.c new file mode 100644 index 000000000..3dfeda36e --- /dev/null +++ b/xserver/dix/window.c @@ -0,0 +1,3924 @@ +/* + +Copyright (c) 2006, Red Hat, Inc. + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Red Hat shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from Red Hat. + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +*/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "dixevents.h" +#include "globals.h" + +#ifdef XAPPGROUP +#include "appgroup.h" +#endif +#ifdef XACE +#include "xace.h" +#endif + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11}; +static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88}; + +_X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF; + +_X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +#if 0 +extern void DeleteWindowFromAnyEvents(); +extern Mask EventMaskForClient(); +extern void WindowHasNewCursor(); +extern void RecalculateDeliverableEvents(); +#endif + +static Bool TileScreenSaver(int i, int kind); + + +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#define BOXES_OVERLAP(b1, b2) \ + (!( ((b1)->x2 <= (b2)->x1) || \ + ( ((b1)->x1 >= (b2)->x2)) || \ + ( ((b1)->y2 <= (b2)->y1)) || \ + ( ((b1)->y1 >= (b2)->y2)) ) ) + +#define RedirectSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +_X_EXPORT int numSaveUndersViewable = 0; +_X_EXPORT int deltaSaveUndersViewable = 0; + +#ifdef DEBUG +/****** + * PrintWindowTree + * For debugging only + ******/ + +int +PrintChildren(WindowPtr p1, int indent) +{ + WindowPtr p2; + int i; + + while (p1) + { + p2 = p1->firstChild; + for (i=0; i<indent; i++) ErrorF( " "); + ErrorF( "%x\n", p1->drawable.id); + miPrintRegion(&p1->clipList); + PrintChildren(p2, indent+4); + p1 = p1->nextSib; + } +} + +PrintWindowTree() +{ + int i; + WindowPtr pWin, p1; + + for (i=0; i<screenInfo.numScreens; i++) + { + ErrorF( "WINDOW %d\n", i); + pWin = WindowTable[i]; + miPrintRegion(&pWin->clipList); + p1 = pWin->firstChild; + PrintChildren(p1, 4); + } +} +#endif + +_X_EXPORT int +TraverseTree(register WindowPtr pWin, VisitWindowProcPtr func, pointer data) +{ + register int result; + register WindowPtr pChild; + + if (!(pChild = pWin)) + return(WT_NOMATCH); + while (1) + { + result = (* func)(pChild, data); + if (result == WT_STOPWALKING) + return(WT_STOPWALKING); + if ((result == WT_WALKCHILDREN) && pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + return(WT_NOMATCH); +} + +/***** + * WalkTree + * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on + * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, + * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING + * exit WalkTree. Does depth-first traverse. + *****/ + +_X_EXPORT int +WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data) +{ + return(TraverseTree(WindowTable[pScreen->myNum], func, data)); +} + +/* hack for forcing backing store on all windows */ +int defaultBackingStore = NotUseful; +/* hack to force no backing store */ +Bool disableBackingStore = FALSE; +Bool enableBackingStore = FALSE; +/* hack to force no save unders */ +Bool disableSaveUnders = FALSE; + +static void +SetWindowToDefaults(register WindowPtr pWin) +{ + pWin->prevSib = NullWindow; + pWin->firstChild = NullWindow; + pWin->lastChild = NullWindow; + + pWin->valdata = (ValidatePtr)NULL; + pWin->optional = (WindowOptPtr)NULL; + pWin->cursorIsNone = TRUE; + + pWin->backingStore = NotUseful; + pWin->DIXsaveUnder = FALSE; + pWin->backStorage = (pointer) NULL; + + pWin->mapped = FALSE; /* off */ + pWin->realized = FALSE; /* off */ + pWin->viewable = FALSE; + pWin->visibility = VisibilityNotViewable; + pWin->overrideRedirect = FALSE; + pWin->saveUnder = FALSE; + + pWin->bitGravity = ForgetGravity; + pWin->winGravity = NorthWestGravity; + + pWin->eventMask = 0; + pWin->deliverableEvents = 0; + pWin->dontPropagate = 0; + pWin->forcedBS = FALSE; +#ifdef NEED_DBE_BUF_BITS + pWin->srcBuffer = DBE_FRONT_BUFFER; + pWin->dstBuffer = DBE_FRONT_BUFFER; +#endif +#ifdef COMPOSITE + pWin->redirectDraw = 0; +#endif +} + +static void +MakeRootTile(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + GCPtr pGC; + unsigned char back[128]; + int len = BitmapBytePad(sizeof(long)); + register unsigned char *from, *to; + register int i, j; + + pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4, + pScreen->rootDepth); + + pWin->backgroundState = BackgroundPixmap; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pWin->background.pixmap || !pGC) + FatalError("could not create root tile"); + + { + CARD32 attributes[2]; + + attributes[0] = pScreen->whitePixel; + attributes[1] = pScreen->blackPixel; + + (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); + } + + ValidateGC((DrawablePtr)pWin->background.pixmap, pGC); + + from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb; + to = back; + + for (i = 4; i > 0; i--, from++) + for (j = len; j > 0; j--) + *to++ = *from; + + (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1, + 0, 0, len, 4, 0, XYBitmap, (char *)back); + + FreeScratchGC(pGC); + +} + +WindowPtr +AllocateWindow(ScreenPtr pScreen) +{ + WindowPtr pWin; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pWin = (WindowPtr)xalloc(pScreen->totalWindowSize); + if (pWin) + { + ppriv = (DevUnion *)(pWin + 1); + pWin->devPrivates = ppriv; + sizes = pScreen->WindowPrivateSizes; + ptr = (char *)(ppriv + pScreen->WindowPrivateLen); + for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } +#if _XSERVER64 + pWin->drawable.pad0 = 0; + pWin->drawable.pad1 = 0; +#endif + } + return pWin; +} + +/***** + * CreateRootWindow + * Makes a window at initialization time for specified screen + *****/ + +Bool +CreateRootWindow(ScreenPtr pScreen) +{ + WindowPtr pWin; + BoxRec box; + PixmapFormatRec *format; + + pWin = AllocateWindow(pScreen); + if (!pWin) + return FALSE; + + savedScreenInfo[pScreen->myNum].pWindow = NULL; + savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + screenIsSaved = SCREEN_SAVER_OFF; + + WindowTable[pScreen->myNum] = pWin; + + pWin->drawable.pScreen = pScreen; + pWin->drawable.type = DRAWABLE_WINDOW; + + pWin->drawable.depth = pScreen->rootDepth; + for (format = screenInfo.formats; + format->depth != pScreen->rootDepth; + format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->parent = NullWindow; + SetWindowToDefaults(pWin); + + pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); + if (!pWin->optional) + return FALSE; + + pWin->optional->dontPropagateMask = 0; + pWin->optional->otherEventMasks = 0; + pWin->optional->otherClients = NULL; + pWin->optional->passiveGrabs = NULL; + pWin->optional->userProps = NULL; + pWin->optional->backingBitPlanes = ~0L; + pWin->optional->backingPixel = 0; +#ifdef SHAPE + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; + pWin->optional->inputShape = NULL; +#endif +#ifdef XINPUT + pWin->optional->inputMasks = NULL; +#endif + pWin->optional->colormap = pScreen->defColormap; + pWin->optional->visual = pScreen->rootVisual; + + pWin->nextSib = NullWindow; + + pWin->drawable.id = FakeClientID(0); + + pWin->origin.x = pWin->origin.y = 0; + pWin->drawable.height = pScreen->height; + pWin->drawable.width = pScreen->width; + pWin->drawable.x = pWin->drawable.y = 0; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderClip, &box, 1); + + pWin->drawable.class = InputOutput; + pWin->optional->visual = pScreen->rootVisual; + + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = pScreen->whitePixel; + + pWin->borderIsPixel = TRUE; + pWin->border.pixel = pScreen->blackPixel; + pWin->borderWidth = 0; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) + return FALSE; + + if (disableBackingStore) + pScreen->backingStoreSupport = NotUseful; + if (enableBackingStore) + pScreen->backingStoreSupport = Always; + +#ifdef DO_SAVE_UNDERS + if ((pScreen->backingStoreSupport != NotUseful) && + (pScreen->saveUnderSupport == NotUseful)) + { + /* + * If the screen has backing-store but no save-unders, let the + * clients know we can support save-unders using backing-store. + */ + pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; + } +#endif /* DO_SAVE_UNDERS */ + + if (disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + + return TRUE; +} + +void +InitRootWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + int backFlag = CWBorderPixel | CWCursor | CWBackingStore; + + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + + if (!blackRoot && !whiteRoot) { + MakeRootTile(pWin); + backFlag |= CWBackPixmap; + } + else { + if (blackRoot) + pWin->background.pixel = pScreen->blackPixel; + else + pWin->background.pixel = pScreen->whitePixel; + backFlag |= CWBackPixel; + } + + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, backFlag); + +#ifdef XACE + XaceHook(XACE_WINDOW_INIT, serverClient, pWin); +#endif + + MapWindow(pWin, serverClient); +} + +/* Set the region to the intersection of the rectangle and the + * window's winSize. The window is typically the parent of the + * window from which the region came. + */ + +void +ClippedRegionFromBox(register WindowPtr pWin, RegionPtr Rgn, + register int x, register int y, + register int w, register int h) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + + box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); + /* we do these calculations to avoid overflows */ + if (x > box.x1) + box.x1 = x; + if (y > box.y1) + box.y1 = y; + x += w; + if (x < box.x2) + box.x2 = x; + y += h; + if (y < box.y2) + box.y2 = y; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + REGION_RESET(pScreen, Rgn, &box); + REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); +} + +static RealChildHeadProc realChildHeadProc = NULL; + +void +RegisterRealChildHeadProc (RealChildHeadProc proc) +{ + realChildHeadProc = proc; +} + + +WindowPtr +RealChildHead(register WindowPtr pWin) +{ + if (realChildHeadProc) { + return realChildHeadProc (pWin); + } + + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow (pWin->drawable.pScreen->myNum))) + return (pWin->firstChild); + else + return (NullWindow); +} + +/***** + * CreateWindow + * Makes a window in response to client request + *****/ + +_X_EXPORT WindowPtr +CreateWindow(Window wid, register WindowPtr pParent, int x, int y, unsigned w, + unsigned h, unsigned bw, unsigned class, register Mask vmask, XID *vlist, + int depth, ClientPtr client, VisualID visual, int *error) +{ + register WindowPtr pWin; + WindowPtr pHead; + register ScreenPtr pScreen; + xEvent event; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + PixmapFormatRec *format; + register WindowOptPtr ancwopt; + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + *error = BadValue; + client->errorValue = class; + return NullWindow; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + { + *error = BadMatch; + return NullWindow; + } + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + { + *error = BadMatch; + return NullWindow; + } + + pScreen = pParent->drawable.pScreen; + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) { +#ifdef XAPPGROUP + VisualID ag_visual; + + if (client->appgroup && !pParent->parent && + (ag_visual = XagRootVisual (client))) + visual = ag_visual; + else +#endif + visual = ancwopt->visual; + } + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + { + *error = BadMatch; + return NullWindow; + } + } + + if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + *error = BadMatch; + return NullWindow; + } + + if (((vmask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + *error = BadMatch; + return NullWindow; + } + + pWin = AllocateWindow(pScreen); + if (!pWin) + { + *error = BadAlloc; + return NullWindow; + } + pWin->drawable = pParent->drawable; + pWin->drawable.depth = depth; + if (depth == pParent->drawable.depth) + pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; + else + { + for (format = screenInfo.formats; format->depth != depth; format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + } + if (class == InputOnly) + pWin->drawable.type = (short) UNDRAWABLE_WINDOW; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->drawable.id = wid; + pWin->drawable.class = class; + + pWin->parent = pParent; + SetWindowToDefaults(pWin); + + if (visual != ancwopt->visual) + { + if (!MakeWindowOptional (pWin)) + { + xfree (pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; +#ifdef XACE + /* can't let untrusted clients have background None windows; + * they make it too easy to steal window contents + */ + if (!XaceHook(XACE_BACKGRND_ACCESS, client, pWin)) + { + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0; + } + else +#endif + pWin->backgroundState = None; + + pWin->borderIsPixel = pParent->borderIsPixel; + pWin->border = pParent->border; + if (pWin->borderIsPixel == FALSE) + pWin->border.pixmap->refcnt++; + + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + pWin->drawable.width = w; + pWin->drawable.height = h; + pWin->drawable.x = pParent->drawable.x + x + (int)bw; + pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + /* set up clip list correctly for unobscured WindowPtr */ + REGION_NULL(pScreen, &pWin->clipList); + REGION_NULL(pScreen, &pWin->borderClip); + REGION_NULL(pScreen, &pWin->winSize); + REGION_NULL(pScreen, &pWin->borderSize); + +#ifdef XACE + XaceHook(XACE_WINDOW_INIT, client, pWin); +#endif + + pHead = RealChildHead(pParent); + if (pHead) + { + pWin->nextSib = pHead->nextSib; + if (pHead->nextSib) + pHead->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pHead->nextSib = pWin; + pWin->prevSib = pHead; + } + else + { + pWin->nextSib = pParent->firstChild; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + /* We SHOULD check for an error value here XXX */ + if (!(*pScreen->CreateWindow)(pWin)) + { + *error = BadAlloc; + DeleteWindow(pWin, None); + return NullWindow; + } + /* We SHOULD check for an error value here XXX */ + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + if (!(vmask & CWEventMask)) + RecalculateDeliverableEvents(pWin); + + if (vmask) + *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); + else + *error = Success; + + if (*error != Success) + { + DeleteWindow(pWin, None); + return NullWindow; + } + if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) + { + XID value = defaultBackingStore; + (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); + pWin->forcedBS = TRUE; + } + + if (SubSend(pParent)) + { + event.u.u.type = CreateNotify; + event.u.createNotify.window = wid; + event.u.createNotify.parent = pParent->drawable.id; + event.u.createNotify.x = x; + event.u.createNotify.y = y; + event.u.createNotify.width = w; + event.u.createNotify.height = h; + event.u.createNotify.borderWidth = bw; + event.u.createNotify.override = pWin->overrideRedirect; + DeliverEvents(pParent, &event, 1, NullWindow); + } + return pWin; +} + +static void +FreeWindowResources(register WindowPtr pWin) +{ + register ScreenPtr pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(pScreen, &pWin->clipList); + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_UNINIT(pScreen, &pWin->borderClip); + REGION_UNINIT(pScreen, &pWin->borderSize); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_DESTROY(pScreen, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_DESTROY(pScreen, wClipShape (pWin)); + if (wInputShape (pWin)) + REGION_DESTROY(pScreen, wInputShape (pWin)); +#endif + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + + DeleteAllWindowProperties(pWin); + /* We SHOULD check for an error value here XXX */ + (*pScreen->DestroyWindow)(pWin); + DisposeWindowOptional (pWin); +} + +static void +CrushTree(WindowPtr pWin) +{ + register WindowPtr pChild, pSib, pParent; + UnrealizeWindowProcPtr UnrealizeWindow; + xEvent event; + + if (!(pChild = pWin->firstChild)) + return; + UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; + while (1) + { + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (1) + { + pParent = pChild->parent; + if (SubStrSend(pChild, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pChild->drawable.id; + DeliverEvents(pChild, &event, 1, NullWindow); + } + FreeResource(pChild->drawable.id, RT_WINDOW); + pSib = pChild->nextSib; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder && pChild->viewable) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->realized) + { + pChild->realized = FALSE; + (*UnrealizeWindow)(pChild); + } + FreeWindowResources(pChild); + xfree(pChild); + if ( (pChild = pSib) ) + break; + pChild = pParent; + pChild->firstChild = NullWindow; + pChild->lastChild = NullWindow; + if (pChild == pWin) + return; + } + } +} + +/***** + * DeleteWindow + * Deletes child of window then window itself + * If wid is None, don't send any events + *****/ + +int +DeleteWindow(pointer value, XID wid) + { + register WindowPtr pParent; + register WindowPtr pWin = (WindowPtr)value; + xEvent event; + + UnmapWindow(pWin, FALSE); + + CrushTree(pWin); + + pParent = pWin->parent; + if (wid && pParent && SubStrSend(pWin, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pWin->drawable.id; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + FreeWindowResources(pWin); + if (pParent) + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + } + xfree(pWin); + return Success; +} + +void +DestroySubwindows(register WindowPtr pWin, ClientPtr client) +{ + /* XXX + * The protocol is quite clear that each window should be + * destroyed in turn, however, unmapping all of the first + * eliminates most of the calls to ValidateTree. So, + * this implementation is incorrect in that all of the + * UnmapNotifies occur before all of the DestroyNotifies. + * If you care, simply delete the call to UnmapSubwindows. + */ + UnmapSubwindows(pWin); + while (pWin->lastChild) + FreeResource(pWin->lastChild->drawable.id, RT_NONE); +} + +#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + +/***** + * ChangeWindowAttributes + * + * The value-mask specifies which attributes are to be changed; the + * value-list contains one value for each one bit in the mask, from least + * to most significant bit in the mask. + *****/ + +_X_EXPORT int +ChangeWindowAttributes(register WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) +{ + register Mask index2; + register XID *pVlist; + PixmapPtr pPixmap; + Pixmap pixID; + CursorPtr pCursor, pOldCursor; + Cursor cursorID; + WindowPtr pChild; + Colormap cmap; + ColormapPtr pCmap; + xEvent xE; + int result; + register ScreenPtr pScreen; + Mask vmaskCopy = 0; + register Mask tmask; + unsigned int val; + int error; + Bool checkOptional = FALSE; + Bool borderRelative = FALSE; + WindowPtr pLayerWin; + + if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + error = Success; + pScreen = pWin->drawable.pScreen; + pVlist = vlist; + tmask = vmask; + while (tmask) + { + index2 = (Mask) lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + pVlist++; + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pixID == None) + { +#ifdef XACE + /* can't let untrusted clients have background None windows */ + if (XaceHook(XACE_BACKGRND_ACCESS, client, pWin)) + { +#endif + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; +#ifdef XACE + } + else + { /* didn't change the background to None, so don't tell ddx */ + index2 = 0; + } +#endif + } + else if (pixID == ParentRelative) + { + if (pWin->parent && + pWin->drawable.depth != pWin->parent->drawable.depth) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = ParentRelative; + borderRelative = TRUE; + /* Note that the parent's backgroundTile's refcnt is NOT + * incremented. */ + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = (CARD32 ) *pVlist; + /* background pixel overrides background pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBackPixmap; + pVlist++; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + pVlist++; + if (pixID == CopyFromParent) + { + if (!pWin->parent || + (pWin->drawable.depth != pWin->parent->drawable.depth)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->border = pWin->parent->border; + if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) + { + index2 = CWBorderPixel; + } + else + { + pWin->parent->border.pixmap->refcnt++; + } + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = TRUE; + pWin->border.pixel = (CARD32) *pVlist; + /* border pixel overrides border pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBorderPixmap; + pVlist++; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->bitGravity = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->winGravity = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + pVlist++; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->backingStore = val; + pWin->forcedBS = FALSE; + break; + case CWBackingPlanes: + if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingBitPlanes = (CARD32) *pVlist; + if ((CARD32)*pVlist == (CARD32)~0L) + checkOptional = TRUE; + } + pVlist++; + break; + case CWBackingPixel: + if (pWin->optional || (CARD32) *pVlist) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingPixel = (CARD32) *pVlist; + if (!*pVlist) + checkOptional = TRUE; + } + pVlist++; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } +#ifdef DO_SAVE_UNDERS + if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && + DO_SAVE_UNDERS(pWin)) + { + /* + * Re-check all siblings and inferiors for obscurity or + * exposition (hee hee). + */ + if (pWin->saveUnder) + deltaSaveUndersViewable--; + else + deltaSaveUndersViewable++; + pWin->saveUnder = val; + + if (pWin->firstChild) + { + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, + pWin->nextSib); + } + else + { + if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pWin, + pWin->nextSib); + } + } + else + { + /* If we're changing the saveUnder attribute of the root + * window, all we do is set pWin->saveUnder so that + * GetWindowAttributes returns the right value. We don't + * do the "normal" save-under processing (as above). + * Hope that doesn't cause any problems. + */ + pWin->saveUnder = val; + } +#else + pWin->saveUnder = val; +#endif /* DO_SAVE_UNDERS */ + break; + case CWEventMask: + result = EventSelectForWindow(pWin, client, (Mask )*pVlist); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWDontPropagate: + result = EventSuppressForWindow(pWin, client, (Mask )*pVlist, + &checkOptional); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWOverrideRedirect: + val = (BOOL ) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->overrideRedirect = val; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pVlist++; + if (cmap == CopyFromParent) + { +#ifdef XAPPGROUP + Colormap ag_colormap; + ClientPtr win_owner; + + /* + * win_owner == client for CreateWindow, other clients + * can ChangeWindowAttributes + */ + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + + if ( win_owner && win_owner->appgroup && + !pWin->parent->parent && + (ag_colormap = XagDefaultColormap (win_owner))) + cmap = ag_colormap; + else +#endif + if (pWin->parent && + (!pWin->optional || + pWin->optional->visual == wVisual (pWin->parent))) + { + cmap = wColormap (pWin->parent); + } + else + cmap = None; + } + if (cmap == None) + { + error = BadMatch; + goto PatchUp; + } + pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap, + RT_COLORMAP, SecurityReadAccess); + if (!pCmap) + { + error = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != wVisual (pWin) || + pCmap->pScreen != pScreen) + { + error = BadMatch; + goto PatchUp; + } + if (cmap != wColormap (pWin)) + { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && cmap == wColormap (pWin->parent)) + checkOptional = TRUE; + + /* + * propagate the original colormap to any children + * inheriting it + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pWin->optional->colormap = cmap; + + /* + * check on any children now matching the new colormap + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional->colormap == cmap) + CheckWindowOptionalNeed (pChild); + } + + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pWin->drawable.id; + xE.u.colormap.colormap = cmap; + xE.u.colormap.new = xTrue; + xE.u.colormap.state = IsMapInstalled(cmap, pWin); + DeliverEvents(pWin, &xE, 1, NullWindow); + } + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + pVlist++; + /* + * install the new + */ + if ( cursorID == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr) None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID, + RT_CURSOR, SecurityReadAccess); + if (!pCursor) + { + error = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + } + + if (pCursor != wCursor (pWin)) + { + /* + * patch up child windows so they don't lose cursors. + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !pChild->cursorIsNone && + !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pOldCursor = 0; + if (pCursor == (CursorPtr) None) + { + pWin->cursorIsNone = TRUE; + if (pWin->optional) + { + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = (CursorPtr) None; + checkOptional = TRUE; + } + } else { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && pCursor == wCursor (pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = pCursor; + pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor + */ + + for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional && + (pChild->optional->cursor == pCursor)) + CheckWindowOptionalNeed (pChild); + } + } + + if (pWin->realized) + WindowHasNewCursor( pWin); + + /* Can't free cursor until here - old cursor + * is needed in WindowHasNewCursor + */ + if (pOldCursor) + FreeCursor (pOldCursor, (Cursor)0); + } + break; + default: + error = BadValue; + client->errorValue = vmask; + goto PatchUp; + } + vmaskCopy |= index2; + } +PatchUp: + if (checkOptional) + CheckWindowOptionalNeed (pWin); + + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); + + /* + If the border contents have changed, redraw the border. + Note that this has to be done AFTER pScreen->ChangeWindowAttributes + for the tile to be rotated, and the correct function selected. + */ + if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) + && pWin->viewable && HasBorder (pWin)) + { + RegionRec exposed; + + REGION_NULL(pScreen, &exposed); + REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER); + REGION_UNINIT(pScreen, &exposed); + } + return error; +} + + +/***** + * GetWindowAttributes + * Notice that this is different than ChangeWindowAttributes + *****/ + +void +GetWindowAttributes(register WindowPtr pWin, ClientPtr client, xGetWindowAttributesReply *wa) +{ + wa->type = X_Reply; + wa->bitGravity = pWin->bitGravity; + wa->winGravity = pWin->winGravity; + if (pWin->forcedBS && pWin->backingStore != Always) + wa->backingStore = NotUseful; + else + wa->backingStore = pWin->backingStore; + wa->length = (sizeof(xGetWindowAttributesReply) - + sizeof(xGenericReply)) >> 2; + wa->sequenceNumber = client->sequence; + wa->backingBitPlanes = wBackingBitPlanes (pWin); + wa->backingPixel = wBackingPixel (pWin); + wa->saveUnder = (BOOL)pWin->saveUnder; + wa->override = pWin->overrideRedirect; + if (!pWin->mapped) + wa->mapState = IsUnmapped; + else if (pWin->realized) + wa->mapState = IsViewable; + else + wa->mapState = IsUnviewable; + + wa->colormap = wColormap (pWin); + wa->mapInstalled = (wa->colormap == None) ? xFalse + : IsMapInstalled(wa->colormap, pWin); + + wa->yourEventMask = EventMaskForClient(pWin, client); + wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); + wa->doNotPropagateMask = wDontPropagateMask (pWin); + wa->class = pWin->drawable.class; + wa->visualID = wVisual (pWin); +} + + +_X_EXPORT WindowPtr +MoveWindowInStack(register WindowPtr pWin, register WindowPtr pNextSib) +{ + register WindowPtr pParent = pWin->parent; + WindowPtr pFirstChange = pWin; /* highest window where list changes */ + + if (pWin->nextSib != pNextSib) + { + WindowPtr pOldNextSib = pWin->nextSib; + + if (!pNextSib) /* move to bottom */ + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL + * and pWin->nextSib != pNextSib + * therefore pWin->nextSib != NULL */ + pFirstChange = pWin->nextSib; + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pParent->lastChild->nextSib = pWin; + pWin->prevSib = pParent->lastChild; + pWin->nextSib = NullWindow; + pParent->lastChild = pWin; + } + else if (pParent->firstChild == pNextSib) /* move to top */ + { + pFirstChange = pWin; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pParent->firstChild; + pWin->prevSib = (WindowPtr ) NULL; + pNextSib->prevSib = pWin; + pParent->firstChild = pWin; + } + else /* move in middle of list */ + { + WindowPtr pOldNext = pWin->nextSib; + + pFirstChange = NullWindow; + if (pParent->firstChild == pWin) + pFirstChange = pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) { + pFirstChange = pWin; + pParent->lastChild = pWin->prevSib; + } + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pNextSib; + pWin->prevSib = pNextSib->prevSib; + if (pNextSib->prevSib) + pNextSib->prevSib->nextSib = pWin; + pNextSib->prevSib = pWin; + if (!pFirstChange) { /* do we know it yet? */ + pFirstChange = pParent->firstChild; /* no, search from top */ + while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) + pFirstChange = pFirstChange->nextSib; + } + } + if(pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib); + } + +#ifdef ROOTLESS + /* + * In rootless mode we can't optimize away window restacks. + * There may be non-X windows around, so even if the window + * is in the correct position from X's point of view, + * the underlying window system may want to reorder it. + */ + else if (pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pWin->nextSib); +#endif + + return( pFirstChange ); +} + +_X_EXPORT RegionPtr +CreateUnclippedWinSize (register WindowPtr pWin) +{ + RegionPtr pRgn; + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + (int) pWin->drawable.width; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); + } +#endif + return pRgn; +} + +_X_EXPORT void +SetWinSize (register WindowPtr pWin) +{ +#ifdef COMPOSITE + if (pWin->redirectDraw) + { + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + pWin->drawable.width; + box.y2 = pWin->drawable.y + pWin->drawable.height; + REGION_RESET (pScreen, &pWin->winSize, &box); + } + else +#endif + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int)pWin->drawable.width, + (int)pWin->drawable.height); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wClipShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +#endif +} + +_X_EXPORT void +SetBorderSize (register WindowPtr pWin) +{ + int bw; + + if (HasBorder (pWin)) { + bw = wBorderWidth (pWin); +#ifdef COMPOSITE + if (pWin->redirectDraw) + { + BoxRec box; + + box.x1 = pWin->drawable.x - bw; + box.y1 = pWin->drawable.y - bw; + box.x2 = pWin->drawable.x + pWin->drawable.width + bw; + box.y2 = pWin->drawable.y + pWin->drawable.height + bw; + REGION_RESET (pScreen, &pWin->borderSize, &box); + } + else +#endif + ClippedRegionFromBox(pWin->parent, &pWin->borderSize, + pWin->drawable.x - bw, pWin->drawable.y - bw, + (int)(pWin->drawable.width + (bw<<1)), + (int)(pWin->drawable.height + (bw<<1))); +#ifdef SHAPE + if (wBoundingShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, + - pWin->drawable.y); + REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, + wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } +#endif + } else { + REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, + &pWin->winSize); + } +} + +/** + * + * \param x,y new window position + * \param oldx,oldy old window position + * \param destx,desty position relative to gravity + */ + +_X_EXPORT void +GravityTranslate (register int x, register int y, int oldx, int oldy, + int dw, int dh, unsigned gravity, + register int *destx, register int *desty) +{ + switch (gravity) { + case NorthGravity: + *destx = x + dw / 2; + *desty = y; + break; + case NorthEastGravity: + *destx = x + dw; + *desty = y; + break; + case WestGravity: + *destx = x; + *desty = y + dh / 2; + break; + case CenterGravity: + *destx = x + dw / 2; + *desty = y + dh / 2; + break; + case EastGravity: + *destx = x + dw; + *desty = y + dh / 2; + break; + case SouthWestGravity: + *destx = x; + *desty = y + dh; + break; + case SouthGravity: + *destx = x + dw / 2; + *desty = y + dh; + break; + case SouthEastGravity: + *destx = x + dw; + *desty = y + dh; + break; + case StaticGravity: + *destx = oldx; + *desty = oldy; + break; + default: + *destx = x; + *desty = y; + break; + } +} + +/* XXX need to retile border on each window with ParentRelative origin */ +_X_EXPORT void +ResizeChildrenWinSize(register WindowPtr pWin, int dx, int dy, int dw, int dh) +{ + register ScreenPtr pScreen; + register WindowPtr pSib, pChild; + Bool resized = (dw || dh); + + pScreen = pWin->drawable.pScreen; + + for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) + { + if (resized && (pSib->winGravity > NorthWestGravity)) + { + int cwsx, cwsy; + + cwsx = pSib->origin.x; + cwsy = pSib->origin.y; + GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, + pSib->winGravity, &cwsx, &cwsy); + if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) + { + xEvent event; + + event.u.u.type = GravityNotify; + event.u.gravity.window = pSib->drawable.id; + event.u.gravity.x = cwsx - wBorderWidth (pSib); + event.u.gravity.y = cwsy - wBorderWidth (pSib); + DeliverEvents (pSib, &event, 1, NullWindow); + pSib->origin.x = cwsx; + pSib->origin.y = cwsy; + } + } + pSib->drawable.x = pWin->drawable.x + pSib->origin.x; + pSib->drawable.y = pWin->drawable.y + pSib->origin.y; + SetWinSize (pSib); + SetBorderSize (pSib); + (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); + + if ( (pChild = pSib->firstChild) ) + { + while (1) + { + pChild->drawable.x = pChild->parent->drawable.x + + pChild->origin.x; + pChild->drawable.y = pChild->parent->drawable.y + + pChild->origin.y; + SetWinSize (pChild); + SetBorderSize (pChild); + (*pScreen->PositionWindow)(pChild, + pChild->drawable.x, pChild->drawable.y); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pSib)) + pChild = pChild->parent; + if (pChild == pSib) + break; + pChild = pChild->nextSib; + } + } + } +} + +#define GET_INT16(m, f) \ + if (m & mask) \ + { \ + f = (INT16) *pVlist;\ + pVlist++; \ + } +#define GET_CARD16(m, f) \ + if (m & mask) \ + { \ + f = (CARD16) *pVlist;\ + pVlist++;\ + } + +#define GET_CARD8(m, f) \ + if (m & mask) \ + { \ + f = (CARD8) *pVlist;\ + pVlist++;\ + } + +#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) + +#define IllegalInputOnlyConfigureMask (CWBorderWidth) + +/* + * IsSiblingAboveMe + * returns Above if pSib above pMe in stack or Below otherwise + */ + +static int +IsSiblingAboveMe( + register WindowPtr pMe, + register WindowPtr pSib) +{ + register WindowPtr pWin; + + pWin = pMe->parent->firstChild; + while (pWin) + { + if (pWin == pSib) + return(Above); + else if (pWin == pMe) + return(Below); + pWin = pWin->nextSib; + } + return(Below); +} + +static BoxPtr +WindowExtents( + register WindowPtr pWin, + register BoxPtr pBox) +{ + pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); + pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); + pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + return(pBox); +} + +#ifdef SHAPE +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +MakeBoundingRegion ( + register WindowPtr pWin, + BoxPtr pBox) +{ + RegionPtr pRgn; + ScreenPtr pScreen = pWin->drawable.pScreen; + + pRgn = REGION_CREATE(pScreen, pBox, 1); + if (wBoundingShape (pWin)) { + REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, + -pWin->origin.y); + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, + pWin->origin.y); + } + return pRgn; +} + +static Bool +ShapeOverlap ( + WindowPtr pWin, + BoxPtr pWinBox, + WindowPtr pSib, + BoxPtr pSibBox) +{ + RegionPtr pWinRgn, pSibRgn; + register ScreenPtr pScreen; + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pScreen = pWin->drawable.pScreen; + pWinRgn = MakeBoundingRegion (pWin, pWinBox); + pSibRgn = MakeBoundingRegion (pSib, pSibBox); + REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pSibRgn); + return ret; +} +#endif + +static Bool +AnyWindowOverlapsMe( + WindowPtr pWin, + WindowPtr pHead, + register BoxPtr box) +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +static Bool +IOverlapAnyWindow( + WindowPtr pWin, + register BoxPtr box) +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +/* + * WhereDoIGoInTheStack() + * Given pWin and pSib and the relationshipe smode, return + * the window that pWin should go ABOVE. + * If a pSib is specified: + * Above: pWin is placed just above pSib + * Below: pWin is placed just below pSib + * TopIf: if pSib occludes pWin, then pWin is placed + * at the top of the stack + * BottomIf: if pWin occludes pSib, then pWin is + * placed at the bottom of the stack + * Opposite: if pSib occludes pWin, then pWin is placed at the + * top of the stack, else if pWin occludes pSib, then + * pWin is placed at the bottom of the stack + * + * If pSib is NULL: + * Above: pWin is placed at the top of the stack + * Below: pWin is placed at the bottom of the stack + * TopIf: if any sibling occludes pWin, then pWin is placed at + * the top of the stack + * BottomIf: if pWin occludes any sibline, then pWin is placed at + * the bottom of the stack + * Opposite: if any sibling occludes pWin, then pWin is placed at + * the top of the stack, else if pWin occludes any + * sibling, then pWin is placed at the bottom of the stack + * + */ + +static WindowPtr +WhereDoIGoInTheStack( + register WindowPtr pWin, + register WindowPtr pSib, + short x, + short y, + unsigned short w, + unsigned short h, + int smode) +{ + BoxRec box; + register ScreenPtr pScreen; + WindowPtr pHead, pFirst; + + if ((pWin == pWin->parent->firstChild) && + (pWin == pWin->parent->lastChild)) + return((WindowPtr ) NULL); + pHead = RealChildHead(pWin->parent); + pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; + pScreen = pWin->drawable.pScreen; + box.x1 = x; + box.y1 = y; + box.x2 = x + (int)w; + box.y2 = y + (int)h; + switch (smode) + { + case Above: + if (pSib) + return(pSib); + else if (pWin == pFirst) + return(pWin->nextSib); + else + return(pFirst); + case Below: + if (pSib) + if (pSib->nextSib != pWin) + return(pSib->nextSib); + else + return(pWin->nextSib); + else + return NullWindow; + case TopIf: + if ((!pWin->mapped || (pSib && !pSib->mapped))) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Above) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return(pFirst); + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + return(pFirst); + else + return(pWin->nextSib); + case BottomIf: + if ((!pWin->mapped || (pSib && !pSib->mapped))) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Below) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return NullWindow; + else + return(pWin->nextSib); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return(pWin->nextSib); + case Opposite: + if ((!pWin->mapped || (pSib && !pSib->mapped))) + return(pWin->nextSib); + else if (pSib) + { + if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) + { + if (IsSiblingAboveMe(pWin, pSib) == Above) + return(pFirst); + else + return NullWindow; + } + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + { + /* If I'm occluded, I can't possibly be the first child + * if (pWin == pWin->parent->firstChild) + * return pWin->nextSib; + */ + return(pFirst); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return pWin->nextSib; + default: + { + ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode ); + return pWin->nextSib; + } + } +} + +static void +ReflectStackChange( + register WindowPtr pWin, + register WindowPtr pSib, + VTKind kind) +{ +/* Note that pSib might be NULL */ + + Bool WasViewable = (Bool)pWin->viewable; + Bool anyMarked; + WindowPtr pFirstChange; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* if this is a root window, can't be restacked */ + if (!pWin->parent) + return; + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + &pLayerWin); + if (pLayerWin != pWin) pFirstChange = pLayerWin; +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pWin->drawable.pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + +/***** + * ConfigureWindow + *****/ + +int +ConfigureWindow(register WindowPtr pWin, register Mask mask, XID *vlist, ClientPtr client) +{ +#define RESTACK_WIN 0 +#define MOVE_WIN 1 +#define RESIZE_WIN 2 +#define REBORDER_WIN 3 + register WindowPtr pSib = NullWindow; + register WindowPtr pParent = pWin->parent; + Window sibwid = 0; + Mask index2, tmask; + register XID *pVlist; + short x, y, beforeX, beforeY; + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, + bw = pWin->borderWidth; + int action, smode = Above; +#ifdef XAPPGROUP + ClientPtr win_owner; + ClientPtr ag_leader = NULL; +#endif + xEvent event; + + if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) + return(BadMatch); + + if ((mask & CWSibling) && !(mask & CWStackMode)) + return(BadMatch); + + pVlist = vlist; + + if (pParent) + { + x = pWin->drawable.x - pParent->drawable.x - (int)bw; + y = pWin->drawable.y - pParent->drawable.y - (int)bw; + } + else + { + x = pWin->drawable.x; + y = pWin->drawable.y; + } + beforeX = x; + beforeY = y; + action = RESTACK_WIN; + if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + action = MOVE_WIN; + } + /* or should be resized */ + else if (mask & (CWX | CWY | CWWidth | CWHeight)) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + GET_CARD16(CWWidth, w); + GET_CARD16 (CWHeight, h); + if (!w || !h) + { + client->errorValue = 0; + return BadValue; + } + action = RESIZE_WIN; + } + tmask = mask & ~ChangeMask; + while (tmask) + { + index2 = (Mask)lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBorderWidth: + GET_CARD16(CWBorderWidth, bw); + break; + case CWSibling: + sibwid = (Window ) *pVlist; + pVlist++; + pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid, + RT_WINDOW, SecurityReadAccess); + if (!pSib) + { + client->errorValue = sibwid; + return(BadWindow); + } + if (pSib->parent != pParent) + return(BadMatch); + if (pSib == pWin) + return(BadMatch); + break; + case CWStackMode: + GET_CARD8(CWStackMode, smode); + if ((smode != TopIf) && (smode != BottomIf) && + (smode != Opposite) && (smode != Above) && (smode != Below)) + { + client->errorValue = smode; + return(BadValue); + } + break; + default: + client->errorValue = mask; + return(BadValue); + } + } + /* root really can't be reconfigured, so just return */ + if (!pParent) + return Success; + + /* Figure out if the window should be moved. Doesnt + make the changes to the window if event sent */ + + if (mask & CWStackMode) + pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, + pParent->drawable.y + y, + w + (bw << 1), h + (bw << 1), smode); + else + pSib = pWin->nextSib; + +#ifdef XAPPGROUP + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = ConfigureRequest; + event.u.configureRequest.window = pWin->drawable.id; + if (mask & CWSibling) + event.u.configureRequest.sibling = sibwid; + else + event.u.configureRequest.sibling = None; + if (mask & CWStackMode) + event.u.u.detail = smode; + else + event.u.u.detail = Above; + event.u.configureRequest.x = x; + event.u.configureRequest.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureRequest.x += panoramiXdataPtr[0].x; + event.u.configureRequest.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.configureRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.configureRequest.parent = pParent->drawable.id; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + if (action == RESIZE_WIN) + { + Bool size_change = (w != pWin->drawable.width) + || (h != pWin->drawable.height); + if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) + { + xEvent eventT; + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = w; + eventT.u.resizeRequest.height = h; + if (MaybeDeliverEventsToClient(pWin, &eventT, 1, + ResizeRedirectMask, client) == 1) + { + /* if event is delivered, leave the actual size alone. */ + w = pWin->drawable.width; + h = pWin->drawable.height; + size_change = FALSE; + } + } + if (!size_change) + { + if (mask & (CWX | CWY)) + action = MOVE_WIN; + else if (mask & (CWStackMode | CWBorderWidth)) + action = RESTACK_WIN; + else /* really nothing to do */ + return(Success) ; + } + } + + if (action == RESIZE_WIN) + /* we've already checked whether there's really a size change */ + goto ActuallyDoSomething; + if ((mask & CWX) && (x != beforeX)) + goto ActuallyDoSomething; + if ((mask & CWY) && (y != beforeY)) + goto ActuallyDoSomething; + if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) + goto ActuallyDoSomething; + if (mask & CWStackMode) + { +#ifndef ROOTLESS + /* See above for why we always reorder in rootless mode. */ + if (pWin->nextSib != pSib) +#endif + goto ActuallyDoSomething; + } + return(Success); + +ActuallyDoSomething: + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + if (pSib) + event.u.configureNotify.aboveSibling = pSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = x; + event.u.configureNotify.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureNotify.x += panoramiXdataPtr[0].x; + event.u.configureNotify.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureNotify.width = w; + event.u.configureNotify.height = h; + event.u.configureNotify.borderWidth = bw; + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (mask & CWBorderWidth) + { + if (action == RESTACK_WIN) + { + action = MOVE_WIN; + pWin->borderWidth = bw; + } + else if ((action == MOVE_WIN) && + (beforeX + wBorderWidth (pWin) == x + (int)bw) && + (beforeY + wBorderWidth (pWin) == y + (int)bw)) + { + action = REBORDER_WIN; + (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); + } + else + pWin->borderWidth = bw; + } + if (action == MOVE_WIN) + (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, + (mask & CWBorderWidth) ? VTOther : VTMove); + else if (action == RESIZE_WIN) + (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + else if (mask & CWStackMode) + ReflectStackChange(pWin, pSib, VTOther); + + if (action != RESTACK_WIN) + CheckCursorConfinement(pWin); + return(Success); +#undef RESTACK_WIN +#undef MOVE_WIN +#undef RESIZE_WIN +#undef REBORDER_WIN +} + + +/****** + * + * CirculateWindow + * For RaiseLowest, raises the lowest mapped child (if any) that is + * obscured by another child to the top of the stack. For LowerHighest, + * lowers the highest mapped child (if any) that is obscuring another + * child to the bottom of the stack. Exposure processing is performed + * + ******/ + +int +CirculateWindow(WindowPtr pParent, int direction, ClientPtr client) +{ + register WindowPtr pWin, pHead, pFirst; + xEvent event; + BoxRec box; + + pHead = RealChildHead(pParent); + pFirst = pHead ? pHead->nextSib : pParent->firstChild; + if (direction == RaiseLowest) + { + for (pWin = pParent->lastChild; + (pWin != pHead) && + !(pWin->mapped && + AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); + pWin = pWin->prevSib) ; + if (pWin == pHead) + return Success; + } + else + { + for (pWin = pFirst; + pWin && + !(pWin->mapped && + IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); + pWin = pWin->nextSib) ; + if (!pWin) + return Success; + } + + event.u.circulate.window = pWin->drawable.id; + event.u.circulate.parent = pParent->drawable.id; + event.u.circulate.event = pParent->drawable.id; + if (direction == RaiseLowest) + event.u.circulate.place = PlaceOnTop; + else + event.u.circulate.place = PlaceOnBottom; + + if (RedirectSend(pParent)) + { + event.u.u.type = CirculateRequest; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + event.u.u.type = CirculateNotify; + DeliverEvents(pWin, &event, 1, NullWindow); + ReflectStackChange(pWin, + (direction == RaiseLowest) ? pFirst : NullWindow, + VTStack); + + return(Success); +} + +static int +CompareWIDs( + WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + Window *wid = (Window *)value; + + if (pWin->drawable.id == *wid) + return(WT_STOPWALKING); + else + return(WT_WALKCHILDREN); +} + +/***** + * ReparentWindow + *****/ + +int +ReparentWindow(register WindowPtr pWin, register WindowPtr pParent, + int x, int y, ClientPtr client) +{ + WindowPtr pPrev, pPriorParent; + Bool WasMapped = (Bool)(pWin->mapped); + xEvent event; + int bw = wBorderWidth (pWin); + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) + return(BadMatch); + if (!MakeWindowOptional(pWin)) + return(BadAlloc); + + if (WasMapped) + UnmapWindow(pWin, FALSE); + + event.u.u.type = ReparentNotify; + event.u.reparent.window = pWin->drawable.id; + event.u.reparent.parent = pParent->drawable.id; + event.u.reparent.x = x; + event.u.reparent.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pParent->parent) { + event.u.reparent.x += panoramiXdataPtr[0].x; + event.u.reparent.y += panoramiXdataPtr[0].y; + } +#endif + event.u.reparent.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, pParent); + + /* take out of sibling chain */ + + pPriorParent = pPrev = pWin->parent; + if (pPrev->firstChild == pWin) + pPrev->firstChild = pWin->nextSib; + if (pPrev->lastChild == pWin) + pPrev->lastChild = pWin->prevSib; + + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + + /* insert at begining of pParent */ + pWin->parent = pParent; + pPrev = RealChildHead(pParent); + if (pPrev) + { + pWin->nextSib = pPrev->nextSib; + if (pPrev->nextSib) + pPrev->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pPrev->nextSib = pWin; + pWin->prevSib = pPrev; + } + else + { + pWin->nextSib = pParent->firstChild; + pWin->prevSib = NullWindow; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.x = x + bw + pParent->drawable.x; + pWin->drawable.y = y + bw + pParent->drawable.y; + + /* clip to parent */ + SetWinSize (pWin); + SetBorderSize (pWin); + + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + CheckWindowOptionalNeed(pWin); + + if (WasMapped) + MapWindow(pWin, client); + RecalculateDeliverableEvents(pWin); + return(Success); +} + +static void +RealizeTree(WindowPtr pWin) +{ + register WindowPtr pChild; + RealizeWindowProcPtr Realize; + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) + { + if (pChild->mapped) + { + pChild->realized = TRUE; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable++; +#endif + pChild->viewable = (pChild->drawable.class == InputOutput); + (* Realize)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * MapWindow + * If some other client has selected SubStructureReDirect on the parent + * and override-redirect is xFalse, then a MapRequest event is generated, + * but the window remains unmapped. Otherwise, the window is mapped and a + * MapNotify event is generated. + *****/ + +_X_EXPORT int +MapWindow(register WindowPtr pWin, ClientPtr client) +{ + register ScreenPtr pScreen; + + register WindowPtr pParent; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (pWin->mapped) + return(Success); + +#ifdef XACE + /* general check for permission to map window */ + if (!XaceHook(XACE_MAP_ACCESS, client, pWin)) + return Success; +#endif + + pScreen = pWin->drawable.pScreen; + if ( (pParent = pWin->parent) ) + { + xEvent event; + Bool anyMarked; +#ifdef XAPPGROUP + ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ClientPtr ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.mapRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pParent->realized) + return(Success); + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + } + WindowsRestructured (); + } + else + { + RegionRec temp; + + pWin->mapped = TRUE; + pWin->realized = TRUE; /* for roots */ + pWin->viewable = pWin->drawable.class == InputOutput; + /* We SHOULD check for an error value here XXX */ + (*pScreen->RealizeWindow)(pWin); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pWin, 0, 0); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); + REGION_NULL(pScreen, &temp); + REGION_COPY(pScreen, &temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(pScreen, &temp); + } + + return(Success); +} + + +/***** + * MapSubwindows + * Performs a MapWindow all unmapped children of the window, in top + * to bottom stacking order. + *****/ + +void +MapSubwindows(register WindowPtr pParent, ClientPtr client) +{ + register WindowPtr pWin; + WindowPtr pFirstMapped = NullWindow; +#ifdef DO_SAVE_UNDERS + WindowPtr pFirstSaveUndered = NullWindow; +#endif + register ScreenPtr pScreen; + register Mask parentRedirect; + register Mask parentNotify; + xEvent event; + Bool anyMarked; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + pScreen = pParent->drawable.pScreen; + parentRedirect = RedirectSend(pParent); + parentNotify = SubSend(pParent); + anyMarked = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (!pWin->mapped) + { + if (parentRedirect && !pWin->overrideRedirect) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + continue; + } + + pWin->mapped = TRUE; + if (parentNotify || StrSend(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pFirstMapped) + pFirstMapped = pWin; + if (pParent->realized) + { + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = TRUE; + } +#endif /* DO_SAVE_UNDERS */ + } + } + } + } + + if (pFirstMapped) + { + pLayerWin = (*pScreen->GetLayerWindow)(pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, + pLayerWin, + (WindowPtr *)NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) + { +#ifdef DO_SAVE_UNDERS + if (pLayerWin->parent != pParent) + { + if (dosave || (DO_SAVE_UNDERS(pLayerWin))) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, + pLayerWin); + } + } + else if (dosave) + { + dosave = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (DO_SAVE_UNDERS(pWin)) + { + dosave |= (*pScreen->ChangeSaveUnder)(pWin, + pWin->nextSib); + if (dosave && !pFirstSaveUndered) + pFirstSaveUndered = pWin; + } + } + } +#endif /* DO_SAVE_UNDERS */ + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, + pFirstSaveUndered->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured (); + } +} + +static void +UnrealizeTree( + WindowPtr pWin, + Bool fromConfigure) +{ + register WindowPtr pChild; + UnrealizeWindowProcPtr Unrealize; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + + Unrealize = pWin->drawable.pScreen->UnrealizeWindow; + MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; + pChild = pWin; + while (1) + { + if (pChild->realized) + { + pChild->realized = FALSE; + pChild->visibility = VisibilityNotViewable; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) { + PanoramiXRes *win; + win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id, + XRT_WINDOW); + if(win) + win->u.win.visibility = VisibilityNotViewable; + } +#endif + (* Unrealize)(pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) + { +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->backStorage) + (*pChild->drawable.pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * UnmapWindow + * If the window is already unmapped, this request has no effect. + * Otherwise, the window is unmapped and an UnMapNotify event is + * generated. Cannot unmap a root window. + *****/ + +_X_EXPORT int +UnmapWindow(register WindowPtr pWin, Bool fromConfigure) +{ + register WindowPtr pParent; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + if ((!pWin->mapped) || (!(pParent = pWin->parent))) + return(Success); + if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pWin->drawable.id; + event.u.unmapNotify.fromConfigure = fromConfigure; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (wasViewable && !fromConfigure) + { + pWin->valdata = UnmapValData; + (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + } + pWin->mapped = FALSE; + if (wasRealized) + UnrealizeTree(pWin, fromConfigure); + if (wasViewable) + { + if (!fromConfigure) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); + } + } + pWin->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (!fromConfigure && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); + } + if (wasRealized && !fromConfigure) + WindowsRestructured (); + return(Success); +} + +/***** + * UnmapSubwindows + * Performs an UnmapWindow request with the specified mode on all mapped + * children of the window, in bottom to top stacking order. + *****/ + +void +UnmapSubwindows(register WindowPtr pWin) +{ + register WindowPtr pChild, pHead; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + Bool anyMarked = FALSE; + Mask parentNotify; + WindowPtr pLayerWin = NULL; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!pWin->firstChild) + return; + parentNotify = SubSend(pWin); + pHead = RealChildHead(pWin); + + if (wasViewable) + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (pChild->mapped) + { + if (parentNotify || StrSend(pChild)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pChild->drawable.id; + event.u.unmapNotify.fromConfigure = xFalse; + DeliverEvents(pChild, &event, 1, NullWindow); + } + if (pChild->viewable) + { + pChild->valdata = UnmapValData; + anyMarked = TRUE; + } + pChild->mapped = FALSE; + if (pChild->realized) + UnrealizeTree(pChild, FALSE); + if (wasViewable) + { +#ifdef DO_SAVE_UNDERS + pChild->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (pChild->backStorage) + (*pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + } + } + } + if (wasViewable) + { + if (anyMarked) + { + if (pLayerWin->parent == pWin) + (*pScreen->MarkWindow)(pWin); + else + { + WindowPtr ptmp; + (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + (*pScreen->MarkWindow)(pLayerWin->parent); + + /* Windows between pWin and pLayerWin may not have been marked */ + ptmp = pWin; + + while (ptmp != pLayerWin->parent) + { + (*pScreen->MarkWindow)(ptmp); + ptmp = ptmp->parent; + } + pHead = pWin->firstChild; + } + (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured (); +} + + +void +HandleSaveSet(register ClientPtr client) +{ + register WindowPtr pParent, pWin; + register int j; + + for (j=0; j<client->numSaved; j++) + { + pWin = SaveSetWindow(client->saveSet[j]); +#ifdef XFIXES + if (SaveSetToRoot(client->saveSet[j])) + pParent = WindowTable[pWin->drawable.pScreen->myNum]; + else +#endif + { + pParent = pWin->parent; + while (pParent && (wClient (pParent) == client)) + pParent = pParent->parent; + } + if (pParent) + { + if (pParent != pWin->parent) + { + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + if(!pWin->realized && pWin->mapped) + pWin->mapped = FALSE; + } +#ifdef XFIXES + if (SaveSetRemap (client->saveSet[j])) +#endif + MapWindow(pWin, client); + } + } + xfree(client->saveSet); + client->numSaved = 0; + client->saveSet = (SaveSetElt *)NULL; +} + +/** + * + * \param x,y in root + * \param box "return" value + */ +Bool +VisibleBoundingBoxFromPoint(register WindowPtr pWin, int x, int y, BoxPtr box) +{ + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box)) + return(TRUE); + return(FALSE); +} + +/** + * + * \param x,y in root + */ +Bool +PointInWindowIsVisible(register WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, + x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box))) + return(TRUE); + return(FALSE); +} + + +_X_EXPORT RegionPtr +NotClippedByChildren(register WindowPtr pWin) +{ + register ScreenPtr pScreen; + RegionPtr pReg; + + pScreen = pWin->drawable.pScreen; + pReg = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow (pWin->drawable.pScreen->myNum)) + { + REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); + } + return(pReg); +} + +_X_EXPORT void +SendVisibilityNotify(WindowPtr pWin) +{ + xEvent event; +#ifndef NO_XINERAMA_PORT + unsigned int visibility = pWin->visibility; +#endif +#ifdef PANORAMIX + /* This is not quite correct yet, but it's close */ + if(!noPanoramiXExtension) { + PanoramiXRes *win; + WindowPtr pWin2; + int i, Scrnum; + + Scrnum = pWin->drawable.pScreen->myNum; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum); + + if(!win || (win->u.win.visibility == visibility)) + return; + + switch(visibility) { + case VisibilityUnobscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility == VisibilityPartiallyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + case VisibilityPartiallyObscured: + if(Scrnum) { + pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW); + if (pWin2) pWin = pWin2; + } + break; + case VisibilityFullyObscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility != VisibilityFullyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + } + + win->u.win.visibility = visibility; + } +#endif + + event.u.u.type = VisibilityNotify; + event.u.visibility.window = pWin->drawable.id; + event.u.visibility.state = visibility; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +static WindowPtr windowDisableMapUnmapEvents; + +void +DisableMapUnmapEvents(WindowPtr pWin) +{ + assert (windowDisableMapUnmapEvents == NULL); + + windowDisableMapUnmapEvents = pWin; +} + +void +EnableMapUnmapEvents(WindowPtr pWin) +{ + assert (windowDisableMapUnmapEvents != NULL); + + windowDisableMapUnmapEvents = NULL; +} + +Bool +MapUnmapEventsEnabled(WindowPtr pWin) +{ + return pWin != windowDisableMapUnmapEvents; +} + +#define RANDOM_WIDTH 32 + +#ifndef NOLOGOHACK +static void DrawLogo( + WindowPtr pWin +); +#endif + +_X_EXPORT void +SaveScreens(int on, int mode) +{ + int i; + int what; + int type; + + if (on == SCREEN_SAVER_FORCER) + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + if (mode == ScreenSaverReset) + what = SCREEN_SAVER_OFF; + else + what = SCREEN_SAVER_ON; + type = what; + } + else + { + what = on; + type = what; + if (what == screenIsSaved) + type = SCREEN_SAVER_CYCLE; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + if (on == SCREEN_SAVER_FORCER) + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); + if (savedScreenInfo[i].ExternalScreenSaver) + { + if ((*savedScreenInfo[i].ExternalScreenSaver) + (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) + continue; + } + if (type == screenIsSaved) + continue; + switch (type) { + case SCREEN_SAVER_OFF: + if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + what); + } + else if (HasSaverWindow (i)) + { + savedScreenInfo[i].pWindow = NullWindow; + FreeResource(savedScreenInfo[i].wid, RT_NONE); + } + break; + case SCREEN_SAVER_CYCLE: + if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) + { + WindowPtr pWin = savedScreenInfo[i].pWindow; + /* make it look like screen saver is off, so that + * NotClippedByChildren will compute a clip list + * for the root window, so miPaintWindow works + */ + screenIsSaved = SCREEN_SAVER_OFF; +#ifndef NOLOGOHACK + if (logoScreenSaver) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); +#endif + (*pWin->drawable.pScreen->MoveWindow)(pWin, + (short)(-(rand() % RANDOM_WIDTH)), + (short)(-(rand() % RANDOM_WIDTH)), + pWin->nextSib, VTMove); +#ifndef NOLOGOHACK + if (logoScreenSaver) + DrawLogo(pWin); +#endif + screenIsSaved = SCREEN_SAVER_ON; + } + /* + * Call the DDX saver in case it wants to do something + * at cycle time + */ + else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + type); + } + break; + case SCREEN_SAVER_ON: + if (ScreenSaverBlanking != DontPreferBlanking) + { + if ((* screenInfo.screens[i]->SaveScreen) + (screenInfo.screens[i], what)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; + continue; + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_BLACK)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLACK; + continue; + } + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_TILED)) + { + savedScreenInfo[i].blanked = SCREEN_IS_TILED; + } + else + savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; + break; + } + } + screenIsSaved = what; + if (mode == ScreenSaverReset) + SetScreenSaverTimer(); +} + +static Bool +TileScreenSaver(int i, int kind) +{ + int j; + int result; + XID attributes[3]; + Mask mask; + WindowPtr pWin; + CursorMetricRec cm; + unsigned char *srcbits, *mskbits; + CursorPtr cursor; + XID cursorID = 0; + int attri; + + mask = 0; + attri = 0; + switch (kind) { + case SCREEN_IS_TILED: + switch (WindowTable[i]->backgroundState) { + case BackgroundPixel: + attributes[attri++] = WindowTable[i]->background.pixel; + mask |= CWBackPixel; + break; + case BackgroundPixmap: + attributes[attri++] = None; + mask |= CWBackPixmap; + break; + default: + break; + } + break; + case SCREEN_IS_BLACK: + attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; + mask |= CWBackPixel; + break; + } + mask |= CWOverrideRedirect; + attributes[attri++] = xTrue; + + /* + * create a blank cursor + */ + + cm.width=16; + cm.height=16; + cm.xhot=8; + cm.yhot=8; + srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + if (!srcbits || !mskbits) + { + xfree(srcbits); + xfree(mskbits); + cursor = 0; + } + else + { + for (j=0; j<BitmapBytePad(32)*16; j++) + srcbits[j] = mskbits[j] = 0x0; + cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0); + if (cursor) + { + cursorID = FakeClientID(0); + if (AddResource (cursorID, RT_CURSOR, (pointer) cursor)) + { + attributes[attri] = cursorID; + mask |= CWCursor; + } + else + cursor = 0; + } + else + { + xfree (srcbits); + xfree (mskbits); + } + } + + pWin = savedScreenInfo[i].pWindow = + CreateWindow(savedScreenInfo[i].wid, + WindowTable[i], + -RANDOM_WIDTH, -RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->width + RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, + 0, InputOutput, mask, attributes, 0, serverClient, + wVisual (WindowTable[i]), &result); + + if (cursor) + FreeResource (cursorID, RT_NONE); + + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, + (pointer)savedScreenInfo[i].pWindow)) + return FALSE; + + if (mask & CWBackPixmap) + { + MakeRootTile (pWin); + (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); + } + MapWindow(pWin, serverClient); +#ifndef NOLOGOHACK + if (kind == SCREEN_IS_TILED && logoScreenSaver) + DrawLogo(pWin); +#endif + return TRUE; +} + +/* + * FindWindowWithOptional + * + * search ancestors of the given window for an entry containing + * a WindowOpt structure. Assumptions: some parent will + * contain the structure. + */ + +_X_EXPORT WindowPtr +FindWindowWithOptional (register WindowPtr w) +{ + do + w = w->parent; + while (!w->optional); + return w; +} + +/* + * CheckWindowOptionalNeed + * + * check each optional entry in the given window to see if + * the value is satisfied by the default rules. If so, + * release the optional record + */ + +_X_EXPORT void +CheckWindowOptionalNeed (register WindowPtr w) +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (!w->parent) + return; + optional = w->optional; + if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) + return; + if (optional->otherEventMasks != 0) + return; + if (optional->otherClients != NULL) + return; + if (optional->passiveGrabs != NULL) + return; + if (optional->userProps != NULL) + return; + if (optional->backingBitPlanes != ~0L) + return; + if (optional->backingPixel != 0) + return; +#ifdef SHAPE + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; + if (optional->inputShape != NULL) + return; +#endif +#ifdef XINPUT + if (optional->inputMasks != NULL) + return; +#endif + parentOptional = FindWindowWithOptional(w)->optional; + if (optional->visual != parentOptional->visual) + return; + if (optional->cursor != None && + (optional->cursor != parentOptional->cursor || + w->parent->cursorIsNone)) + return; + if (optional->colormap != parentOptional->colormap) + return; + DisposeWindowOptional (w); +} + +/* + * MakeWindowOptional + * + * create an optional record and initialize it with the default + * values. + */ + +_X_EXPORT Bool +MakeWindowOptional (register WindowPtr pWin) +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); + if (!optional) + return FALSE; + optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; + optional->otherEventMasks = 0; + optional->otherClients = NULL; + optional->passiveGrabs = NULL; + optional->userProps = NULL; + optional->backingBitPlanes = ~0L; + optional->backingPixel = 0; +#ifdef SHAPE + optional->boundingShape = NULL; + optional->clipShape = NULL; + optional->inputShape = NULL; +#endif +#ifdef XINPUT + optional->inputMasks = NULL; +#endif + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) + { + optional->cursor = parentOptional->cursor; + optional->cursor->refcnt++; + } + else + { + optional->cursor = None; + } + optional->colormap = parentOptional->colormap; + pWin->optional = optional; + return TRUE; +} + +void +DisposeWindowOptional (register WindowPtr pWin) +{ + if (!pWin->optional) + return; + /* + * everything is peachy. Delete the optional record + * and clean up + */ + /* + * TOG changed this code to: + * + * if (pWin->cursorIsNone == FALSE) + * FreeCursor (pWin->optional->cursor, (Cursor)0); + * pWin->cursorIsNone = TRUE; + * + * This is blatently wrong; windows without optionals can have + * two different cursor values, either None or sharing their + * parents cursor. This difference is controlled by the + * cursorIsNone value; when TRUE, the window has no cursor, + * when false, it shares its cursor with its parent; TOG + * made it impossible for a window to have a cursor without + * an optional record. + */ + if (pWin->optional->cursor) + { + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->cursorIsNone = FALSE; + } + else + pWin->cursorIsNone = TRUE; + xfree (pWin->optional); + pWin->optional = NULL; +} + +#ifndef NOLOGOHACK +static void +DrawLogo(WindowPtr pWin) +{ + DrawablePtr pDraw; + ScreenPtr pScreen; + int x, y; + unsigned int width, height, size; + GC *pGC; + int thin, gap, d31; + DDXPointRec poly[4]; + ChangeGCVal fore[2], back[2]; + xrgb rgb[2]; + BITS32 fmask, bmask; + ColormapPtr cmap; + + pDraw = (DrawablePtr)pWin; + pScreen = pDraw->pScreen; + x = -pWin->origin.x; + y = -pWin->origin.y; + width = pScreen->width; + height = pScreen->height; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pGC) + return; + + if ((rand() % 100) <= 17) /* make the probability for white fairly low */ + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + if ((pWin->backgroundState == BackgroundPixel) && + (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { + Pixel querypixels[2]; + + querypixels[0] = fore[0].val; + querypixels[1] = pWin->background.pixel; + QueryColors(cmap, 2, querypixels, rgb); + if ((rgb[0].red == rgb[1].red) && + (rgb[0].green == rgb[1].green) && + (rgb[0].blue == rgb[1].blue)) { + if (fore[0].val == pScreen->blackPixel) + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + } + } + fore[1].val = FillSolid; + fmask = GCForeground|GCFillStyle; + if (pWin->backgroundState == BackgroundPixel) { + back[0].val = pWin->background.pixel; + back[1].val = FillSolid; + bmask = GCForeground|GCFillStyle; + } else { + back[0].val = 0; + back[1].val = 0; + dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, + NULL, back); + back[0].val = FillTiled; + back[1].ptr = pWin->background.pixmap; + bmask = GCFillStyle|GCTile; + } + + /* should be the same as the reference function XmuDrawLogo() */ + + size = width; + if (height < width) + size = height; + size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); + size &= ~1; + x += rand() % (width - size); + y += rand() % (height - size); + +/* + * Draw what will be the thin strokes. + * + * ----- + * / / + * / / + * / / + * / / + * /____/ + * d + * + * Point d is 9/44 (~1/5) of the way across. + */ + + thin = (size / 11); + if (thin < 1) thin = 1; + gap = (thin+3) / 4; + d31 = thin + thin + gap; + poly[0].x = x + size; poly[0].y = y; + poly[1].x = x + size-d31; poly[1].y = y; + poly[2].x = x + 0; poly[2].y = y + size; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for lower thin stroke. + * + * ------ + * / / + * / __ / + * / / / + * / / / + * /__/__/ + */ + + poly[0].x = x + d31/2; poly[0].y = y + size; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for upper thin stroke. + * + * ------ + * / / / + * /--/ / + * / / + * / / + * /_____/ + */ + + poly[0].x = x + size - d31/2; poly[0].y = y; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + size - d31; poly[3].y = y; + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Draw thick stroke. + * Point b is 1/4 of the way across. + * + * b + * ----- + * \ \ + * \ \ + * \ \ + * \ \ + * \____\ + */ + + poly[0].x = x; poly[0].y = y; + poly[1].x = x + size/4; poly[1].y = y; + poly[2].x = x + size; poly[2].y = y + size; + poly[3].x = x + size - size/4; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase to create gap. + * + * / + * / + * / + * / + * / + */ + + poly[0].x = x + size- thin; poly[0].y = y; + poly[1].x = x + size-( thin+gap); poly[1].y = y; + poly[2].x = x + thin; poly[2].y = y + size; + poly[3].x = x + thin + gap; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + + FreeScratchGC(pGC); +} + +#endif diff --git a/xserver/dix/xpstubs.c b/xserver/dix/xpstubs.c new file mode 100644 index 000000000..3276d9dfe --- /dev/null +++ b/xserver/dix/xpstubs.c @@ -0,0 +1,79 @@ +/* $XFree86$ */ +/* +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. +*/ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "misc.h" +#include <X11/fonts/font.h> +#ifdef XPRINT +#include "DiPrint.h" +#else +extern Bool XpClientIsBitmapClient(ClientPtr client); +extern Bool XpClientIsPrintClient(ClientPtr client, FontPathElementPtr fpe); +#endif + +Bool +XpClientIsBitmapClient( + ClientPtr client) +{ + return TRUE; +} + +Bool +XpClientIsPrintClient( + ClientPtr client, + FontPathElementPtr fpe) +{ + return FALSE; +} +#ifdef XPRINT +int +PrinterOptions( + int argc, + char **argv, + int i) +{ + return i; +} +void +PrinterInitOutput( + ScreenInfo *pScreenInfo, + int argc, + char **argv) +{ +} +void PrinterUseMsg(void) +{ +} +void PrinterInitGlobals(void) +{ +} +#endif /* XPRINT */ + |